From fd6898c72662bd06b116c8d97a4aca321d6c64d4 Mon Sep 17 00:00:00 2001 From: "Sicelo A. Mhlongo" Date: Sat, 25 Nov 2023 21:50:46 +0200 Subject: [PATCH] isimodem: parse extra details from REG_STATUS_IND Extract additional operator information available in REG_STATUS_IND messages. These include mnc, mnc, and different variations of operator name. Additionally, in case NET_OPER_NAME_READ_RESP is an error result, which happens with some operators, report the extracted information to core instead. --- drivers/isimodem/debug.c | 1 + drivers/isimodem/network-registration.c | 78 ++++++++++++++++++++++++- drivers/isimodem/network.h | 1 + 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/drivers/isimodem/debug.c b/drivers/isimodem/debug.c index 180557914..8edcd9726 100644 --- a/drivers/isimodem/debug.c +++ b/drivers/isimodem/debug.c @@ -1190,6 +1190,7 @@ const char *net_subblock_name(enum net_subblock value) _(NET_REGISTRATION_CONF1_INFO); _(NET_ROAMING_CONF1_INFO); _(NET_AVAIL_NETWORK_INFO_COMMON); + _(NET_REG_STATUS_IND_OPER_NAME); _(NET_OPER_NAME_INFO); } return "NET_"; diff --git a/drivers/isimodem/network-registration.c b/drivers/isimodem/network-registration.c index 7a0fcff2c..06a9d3488 100644 --- a/drivers/isimodem/network-registration.c +++ b/drivers/isimodem/network-registration.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -81,6 +82,8 @@ struct netreg_data { struct rat_info rat; GIsiVersion version; char nitz_name[OFONO_MAX_OPERATOR_NAME_LENGTH + 1]; + char mcc[OFONO_MAX_MCC_LENGTH + 1]; + char mnc[OFONO_MAX_MNC_LENGTH + 1]; }; static inline guint8 *mccmnc_to_bcd(const char *mcc, const char *mnc, @@ -194,6 +197,12 @@ static void reg_status_ind_cb(const GIsiMessage *msg, void *data) struct netreg_data *nd = ofono_netreg_get_data(netreg); GIsiSubBlockIter iter; + uint8_t len = 0; + uint8_t type = 0; + char *abbrev = NULL; + char *an = NULL; + char *fn = NULL; + if (netreg == NULL || nd == NULL) return; @@ -209,17 +218,67 @@ static void reg_status_ind_cb(const GIsiMessage *msg, void *data) case NET_REG_INFO_COMMON: if (!parse_common_info(&iter, &nd->reg)) - return; + break; + + /* Parse abbreviated operator name */ + if (!g_isi_sb_iter_get_byte(&iter, &len, 7)) + break; + + len *= 2; + + g_isi_sb_iter_get_alpha_tag(&iter, &abbrev, len, 8); break; case NET_GSM_REG_INFO: if (!parse_gsm_info(&iter, &nd->gsm)) - return; + break; + + /* Parse mcc and mnc */ + g_isi_sb_iter_get_oper_code(&iter, nd->mcc, + nd->mnc, 8); + break; + + case NET_REG_STATUS_IND_OPER_NAME: + + if (!g_isi_sb_iter_get_byte(&iter, &type, 2)) + break; + + if (!g_isi_sb_iter_get_byte(&iter, &len, 5)) + break; + + /* Name is UCS-2 encoded */ + len *= 2; + + switch (type) { + case 2: + /* + * Alternate full name, which is similar to + * long name, but may have less whitespace + */ + g_isi_sb_iter_get_alpha_tag(&iter, &an, len, 6); + break; + case 3: + /* Full name */ + g_isi_sb_iter_get_alpha_tag(&iter, &fn, len, 6); + break; + } + break; } } + if (fn && fn[0] != '\0') + l_strlcpy(nd->nitz_name, fn, sizeof(nd->nitz_name)); + else if (an && an[0] != '\0') + l_strlcpy(nd->nitz_name, an, sizeof(nd->nitz_name)); + else if (abbrev && abbrev[0] != '\0') + l_strlcpy(nd->nitz_name, abbrev, sizeof(nd->nitz_name)); + + g_free(an); + g_free(fn); + g_free(abbrev); + ofono_netreg_status_notify(netreg, isi_status_to_at_status(&nd->reg), nd->gsm.lac, nd->gsm.ci, isi_to_at_tech(&nd->rat, &nd->gsm)); @@ -459,6 +518,8 @@ static void name_get_resp_cb(const GIsiMessage *msg, void *data) { struct isi_cb_data *cbd = data; ofono_netreg_operator_cb_t cb = cbd->cb; + struct ofono_netreg *netreg = cbd->user; + struct netreg_data *nd = ofono_netreg_get_data(netreg); struct ofono_network_operator op; GIsiSubBlockIter iter; @@ -469,7 +530,7 @@ static void name_get_resp_cb(const GIsiMessage *msg, void *data) if (!check_response_status(msg, NET_OLD_OPER_NAME_READ_RESP) && !check_response_status(msg, NET_OPER_NAME_READ_RESP)) - goto error; + goto alt_method; for (g_isi_sb_iter_init(&iter, msg, 6); g_isi_sb_iter_is_valid(&iter); @@ -501,9 +562,20 @@ static void name_get_resp_cb(const GIsiMessage *msg, void *data) } } +success: CALLBACK_WITH_SUCCESS(cb, &op, cbd->data); return; +alt_method: + if (nd->nitz_name[0] == '\0' || nd->mcc[0] == '\0' || + nd->mnc[0] == '\0') + goto error; + + l_strlcpy(op.name, nd->nitz_name, sizeof(op.name)); + l_strlcpy(op.mcc, nd->mcc, sizeof(op.mcc)); + l_strlcpy(op.mnc, nd->mnc, sizeof(op.mnc)); + goto success; + error: CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); } diff --git a/drivers/isimodem/network.h b/drivers/isimodem/network.h index 7449a1d0b..3282b383b 100644 --- a/drivers/isimodem/network.h +++ b/drivers/isimodem/network.h @@ -90,6 +90,7 @@ enum net_subblock { NET_REGISTRATION_CONF1_INFO = 0x59, NET_ROAMING_CONF1_INFO = 0x5A, NET_AVAIL_NETWORK_INFO_COMMON = 0xE1, + NET_REG_STATUS_IND_OPER_NAME = 0xE3, NET_OPER_NAME_INFO = 0xE7, };