import gsm48 utility functions from OpenBSC
authorHarald Welte <laforge@gnumonks.org>
Thu, 4 Mar 2010 09:53:03 +0000 (10:53 +0100)
committerHarald Welte <laforge@gnumonks.org>
Thu, 4 Mar 2010 09:53:03 +0000 (10:53 +0100)
* gsm48_generate_lai() gsm48_generate_mid_from_tmsi() gsm48_generate_mid_from_imsi()
* gsm48_cc_msg_names[]

include/osmocore/gsm48.h
src/gsm48.c

index d0cf09d..95963d5 100644 (file)
@@ -1,9 +1,16 @@
 #ifndef _OSMOCORE_GSM48_H
 
 #include <osmocore/tlv.h>
+#include <osmocore/protocol/gsm_04_08.h>
 
 extern const struct tlv_definition gsm48_att_tlvdef;
-extern const char *cc_state_names[];
+extern const char *cc_state_names[32];
+const char *gsm48_cc_msg_names[0x40];
 const char *rr_cause_name(uint8_t cause);
 
+void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
+                       uint16_t mnc, uint16_t lac);
+int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi);
+int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi);
+
 #endif
index 2ded209..ff989ea 100644 (file)
@@ -26,6 +26,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <arpa/inet.h>
+
 #include <osmocore/utils.h>
 #include <osmocore/tlv.h>
 #include <osmocore/gsm48.h>
@@ -93,7 +95,7 @@ static const char *rr_cause_names[] = {
        [GSM48_RR_CAUSE_PROT_ERROR_UNSPC]       = "Protocol error unspecified",
 };
 
-const char *cc_state_names[] = {
+const char *cc_state_names[32] = {
        "NULL",
        "INITIATED",
        "illegal state 2",
@@ -128,6 +130,73 @@ const char *cc_state_names[] = {
        "illegal state 31",
 };
 
+const char *gsm48_cc_msg_names[0x40] = {
+       "unknown 0x00",
+       "ALERTING",
+       "CALL_PROC",
+       "PROGRESS",
+       "ESTAB",
+       "SETUP",
+       "ESTAB_CONF",
+       "CONNECT",
+       "CALL_CONF",
+       "START_CC",
+       "unknown 0x0a",
+       "RECALL",
+       "unknown 0x0c",
+       "unknown 0x0d",
+       "EMERG_SETUP",
+       "CONNECT_ACK",
+       "USER_INFO",
+       "unknown 0x11",
+       "unknown 0x12",
+       "MODIFY_REJECT",
+       "unknown 0x14",
+       "unknown 0x15",
+       "unknown 0x16",
+       "MODIFY",
+       "HOLD",
+       "HOLD_ACK",
+       "HOLD_REJ",
+       "unknown 0x1b",
+       "RETR",
+       "RETR_ACK",
+       "RETR_REJ",
+       "MODIFY_COMPL",
+       "unknown 0x20",
+       "unknown 0x21",
+       "unknown 0x22",
+       "unknown 0x23",
+       "unknown 0x24",
+       "DISCONNECT",
+       "unknown 0x26",
+       "unknown 0x27",
+       "unknown 0x28",
+       "unknown 0x29",
+       "RELEASE_COMPL",
+       "unknown 0x2b",
+       "unknown 0x2c",
+       "RELEASE",
+       "unknown 0x2e",
+       "unknown 0x2f",
+       "unknown 0x30",
+       "STOP_DTMF",
+       "STOP_DTMF_ACK",
+       "unknown 0x33",
+       "STATUS_ENQ",
+       "START_DTMF",
+       "START_DTMF_ACK",
+       "START_DTMF_REJ",
+       "unknown 0x38",
+       "CONG_CTRL",
+       "FACILITY",
+       "unknown 0x3b",
+       "STATUS",
+       "unknown 0x3d",
+       "NOTIFY",
+       "unknown 0x3f",
+};
+
 static char strbuf[64];
 
 const char *rr_cause_name(uint8_t cause)
@@ -140,4 +209,75 @@ const char *rr_cause_name(uint8_t cause)
        return strbuf;
 }
 
+static void to_bcd(uint8_t *bcd, uint16_t val)
+{
+       bcd[2] = val % 10;
+       val = val / 10;
+       bcd[1] = val % 10;
+       val = val / 10;
+       bcd[0] = val % 10;
+       val = val / 10;
+}
+
+void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
+                       uint16_t mnc, uint16_t lac)
+{
+       uint8_t bcd[3];
+
+       to_bcd(bcd, mcc);
+       lai48->digits[0] = bcd[0] | (bcd[1] << 4);
+       lai48->digits[1] = bcd[2];
+
+       to_bcd(bcd, mnc);
+       /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
+#if 0
+       lai48->digits[1] |= bcd[2] << 4;
+       lai48->digits[2] = bcd[0] | (bcd[1] << 4);
+#else
+       lai48->digits[1] |= 0xf << 4;
+       lai48->digits[2] = bcd[1] | (bcd[2] << 4);
+#endif
+
+       lai48->lac = htons(lac);
+}
+
+int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi)
+{
+       uint32_t *tptr = (uint32_t *) &buf[3];
+
+       buf[0] = GSM48_IE_MOBILE_ID;
+       buf[1] = GSM48_TMSI_LEN;
+       buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
+       *tptr = htonl(tmsi);
+
+       return 7;
+}
+
+int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi)
+{
+       unsigned int length = strlen(imsi), i, off = 0;
+       uint8_t odd = (length & 0x1) == 1;
 
+       buf[0] = GSM48_IE_MOBILE_ID;
+       buf[2] = char2bcd(imsi[0]) << 4 | GSM_MI_TYPE_IMSI | (odd << 3);
+
+       /* if the length is even we will fill half of the last octet */
+       if (odd)
+               buf[1] = (length + 1) >> 1;
+       else
+               buf[1] = (length + 2) >> 1;
+
+       for (i = 1; i < buf[1]; ++i) {
+               uint8_t lower, upper;
+
+               lower = char2bcd(imsi[++off]);
+               if (!odd && off + 1 == length)
+                       upper = 0x0f;
+               else
+                       upper = char2bcd(imsi[++off]) & 0x0f;
+
+               buf[2 + i] = (upper << 4) | lower;
+       }
+
+       return 2 + buf[1];
+}