From 61e2bfc5f44267a7a3b0b25ff3ab922fca2a199c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 4 Mar 2010 10:53:03 +0100 Subject: import gsm48 utility functions from OpenBSC * gsm48_generate_lai() gsm48_generate_mid_from_tmsi() gsm48_generate_mid_from_imsi() * gsm48_cc_msg_names[] --- include/osmocore/gsm48.h | 9 ++- src/gsm48.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 2 deletions(-) diff --git a/include/osmocore/gsm48.h b/include/osmocore/gsm48.h index d0cf09d1..95963d59 100644 --- a/include/osmocore/gsm48.h +++ b/include/osmocore/gsm48.h @@ -1,9 +1,16 @@ #ifndef _OSMOCORE_GSM48_H #include +#include 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 diff --git a/src/gsm48.c b/src/gsm48.c index 2ded2095..ff989eaf 100644 --- a/src/gsm48.c +++ b/src/gsm48.c @@ -26,6 +26,8 @@ #include #include +#include + #include #include #include @@ -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]; +} -- cgit v1.2.3