aboutsummaryrefslogtreecommitdiffstats
path: root/src/gsm/gsm48.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2016-03-15 13:28:10 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-03-15 14:30:41 +0100
commitbdccc1b1444a8692697bd8a293cc89c90ef2d832 (patch)
tree3078de6f8ef1c7941ef1853b7b4447ce6969f8ce /src/gsm/gsm48.c
parentda7bf4d55a896034320aa4466b9644083093acd1 (diff)
gsm48: factor out MCC+MNC BCD parsing for re-use in UMTS
For 3G, I need a BCD composer/parser similar to gsm48_generate_lai()/ gsm48_decode_lai(). Those functions also handle a trivial extra member (lac) which I don't need in this way for 3G. So create new functions to take on the MCC+MNC BCD handling and call those from gsm48_generate_lai() and gsm48_decode_lai(). In this way, the 3G code in openbsc can use only the BCD functionality without code duplication.
Diffstat (limited to 'src/gsm/gsm48.c')
-rw-r--r--src/gsm/gsm48.c55
1 files changed, 34 insertions, 21 deletions
diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c
index 60937cb9..d0a22867 100644
--- a/src/gsm/gsm48.c
+++ b/src/gsm/gsm48.c
@@ -278,25 +278,50 @@ static void to_bcd(uint8_t *bcd, uint16_t val)
val = val / 10;
}
-void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
- uint16_t mnc, uint16_t lac)
+/* Convert given mcc and mnc to BCD and write to *bcd_dst, which must be an
+ * allocated buffer of (at least) 3 bytes length. */
+void gsm48_mcc_mnc_to_bcd(uint8_t *bcd_dst, uint16_t mcc, uint16_t mnc)
{
uint8_t bcd[3];
to_bcd(bcd, mcc);
- lai48->digits[0] = bcd[0] | (bcd[1] << 4);
- lai48->digits[1] = bcd[2];
+ bcd_dst[0] = bcd[0] | (bcd[1] << 4);
+ bcd_dst[1] = bcd[2];
to_bcd(bcd, mnc);
/* FIXME: do we need three-digit MNC? See Table 10.5.3 */
if (mnc > 99) {
- lai48->digits[1] |= bcd[2] << 4;
- lai48->digits[2] = bcd[0] | (bcd[1] << 4);
+ bcd_dst[1] |= bcd[2] << 4;
+ bcd_dst[2] = bcd[0] | (bcd[1] << 4);
+ } else {
+ bcd_dst[1] |= 0xf << 4;
+ bcd_dst[2] = bcd[1] | (bcd[2] << 4);
+ }
+}
+
+/* Convert given 3-byte BCD buffer to integers and write results to *mcc and
+ * *mnc. The first three BCD digits result in the MCC and the remaining ones in
+ * the MNC. */
+void gsm48_mcc_mnc_from_bcd(uint8_t *bcd_src, uint16_t *mcc, uint16_t *mnc)
+{
+ *mcc = (bcd_src[0] & 0x0f) * 100
+ + (bcd_src[0] >> 4) * 10
+ + (bcd_src[1] & 0x0f);
+
+ if ((bcd_src[1] & 0xf0) == 0xf0) {
+ *mnc = (bcd_src[2] & 0x0f) * 10
+ + (bcd_src[2] >> 4);
} else {
- lai48->digits[1] |= 0xf << 4;
- lai48->digits[2] = bcd[1] | (bcd[2] << 4);
+ *mnc = (bcd_src[2] & 0x0f) * 100
+ + (bcd_src[2] >> 4) * 10
+ + (bcd_src[1] >> 4);
}
+}
+void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
+ uint16_t mnc, uint16_t lac)
+{
+ gsm48_mcc_mnc_to_bcd(&lai48->digits[0], mcc, mnc);
lai48->lac = htons(lac);
}
@@ -304,20 +329,8 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
uint16_t *mnc, uint16_t *lac)
{
- *mcc = (lai->digits[0] & 0x0f) * 100
- + (lai->digits[0] >> 4) * 10
- + (lai->digits[1] & 0x0f);
-
- if ((lai->digits[1] & 0xf0) == 0xf0) {
- *mnc = (lai->digits[2] & 0x0f) * 10
- + (lai->digits[2] >> 4);
- } else {
- *mnc = (lai->digits[2] & 0x0f) * 100
- + (lai->digits[2] >> 4) * 10
- + (lai->digits[1] >> 4);
- }
+ gsm48_mcc_mnc_from_bcd(&lai->digits[0], mcc, mnc);
*lac = ntohs(lai->lac);
-
return 0;
}