diff options
| -rw-r--r-- | include/osmocore/gsm48.h | 9 | ||||
| -rw-r--r-- | 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 <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 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 <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]; +}  | 
