diff --git a/include/osmocore/gsm_utils.h b/include/osmocore/gsm_utils.h index 0aadd2e..2fe4af4 100644 --- a/include/osmocore/gsm_utils.h +++ b/include/osmocore/gsm_utils.h @@ -59,6 +59,8 @@ enum gsm_band gsm_band_parse(const char *mhz); int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length); int gsm_7bit_encode(uint8_t *result, const char *data); +uint8_t get_octet_len(const uint8_t sept_len); + int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm); int ms_pwr_dbm(enum gsm_band band, uint8_t lvl); diff --git a/src/gsm_utils.c b/src/gsm_utils.c index 31e3cd6..40d6fb6 100644 --- a/src/gsm_utils.c +++ b/src/gsm_utils.c @@ -73,17 +73,29 @@ static int gsm_septet_lookup(uint8_t ch) return -1; } +/* Warning, user_data_len indicates the amount of septets (characters), we need amount of octets occupied */ +/* compute the number of octets: */ +/* #octets = (#septets * 7 bit) / 8 bit */ +/* e.g. 47 non-extension characters needs 329 bits / 8 bit = 41,125 octets => we need 42 octets for 47 characters */ +uint8_t get_octet_len(const uint8_t sept_len){ + int octet_len = (sept_len * 7) / 8; + if ((sept_len * 7) % 8 != 0) + octet_len++; + + return octet_len; +} + /* GSM 03.38 6.2.1 Character unpacking */ int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t length) { int i = 0; - int l = 0; - int septet_l = (length * 8) / 7; + + // length is equal to the number of septets, therefore we don't need to calculate it + int septet_l = length; uint8_t *rtext = calloc(septet_l, sizeof(uint8_t)); uint8_t tmp; /* FIXME: We need to account for user data headers here */ - i += l; for (; i < septet_l; i++){ rtext[i] = ((user_data[(i * 7 + 7) >> 3] << @@ -155,6 +167,11 @@ int gsm_7bit_encode(uint8_t *result, const char *data) shift = 0; continue; } + // special end case. This is necessary if the last septet fits into the previous octet. E.g. 48 non-extension characters: ....ag ( a = 1100001, g = 1100111) + // result[40] = 100001 XX + // result[41] = 1100111 1 + if(shift == 7 && i + 1 == y) + break; cb = (rdata[i] & 0x7f) >> shift; if(i + 1 < y){ @@ -168,7 +185,13 @@ int gsm_7bit_encode(uint8_t *result, const char *data) } free(rdata); - return z; + + // we don't care about the number of octets, because they are not unique. E.g.: + // 1.) 46 non-extension characters + 1 extension character => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets + // 2.) 47 non-extension characters => (47 * 7 bit) / 8 bit = 41,125 = 42 octets + // 3.) 48 non-extension characters => (48 * 7 bit) / 8 bit = 42 octects + return y; + //return z; } /* determine power control level for given dBm value, as indicated