diff options
author | Denis Kenzior <denkenz@gmail.com> | 2009-07-13 16:12:22 -0500 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2009-07-14 15:45:05 -0500 |
commit | 5ea1326b00d330fdb0ab3697f60a3143ff380c90 (patch) | |
tree | 78647f2eaf1c2679c50b8a10e7ed960632b231d8 | |
parent | f2440ebd82510d65478bb0d38bd937a212ad69bf (diff) | |
download | ofono-5ea1326b00d330fdb0ab3697f60a3143ff380c90.tar.bz2 |
Move SPDI to network.c
-rw-r--r-- | src/network.c | 68 | ||||
-rw-r--r-- | src/sim.c | 126 | ||||
-rw-r--r-- | src/sim.h | 2 | ||||
-rw-r--r-- | src/simutil.c | 92 | ||||
-rw-r--r-- | src/simutil.h | 9 |
5 files changed, 157 insertions, 140 deletions
diff --git a/src/network.c b/src/network.c index 629fc007..6ed30e10 100644 --- a/src/network.c +++ b/src/network.c @@ -66,6 +66,7 @@ struct network_registration_data { int signal_strength; char *spname; GSList *pnn_list; + struct sim_spdi *spdi; }; static void operator_list_callback(const struct ofono_error *error, int total, @@ -352,9 +353,12 @@ static char *get_operator_display_name(struct ofono_modem *modem) return name; } - home_or_spdi = - (netreg->status == NETWORK_REGISTRATION_STATUS_REGISTERED) || - ofono_operator_in_spdi(modem, netreg->current_operator); + if (netreg->status == NETWORK_REGISTRATION_STATUS_REGISTERED) + home_or_spdi = TRUE; + else + home_or_spdi = sim_spdi_lookup(netreg->spdi, + netreg->current_operator->mcc, + netreg->current_operator->mnc); if (home_or_spdi) if (netreg->flags & NETWORK_REGISTRATION_FLAG_HOME_SHOW_PLMN) @@ -1136,6 +1140,43 @@ static void sim_pnn_read_cb(struct ofono_modem *modem, int ok, } } +static void sim_spdi_read_cb(struct ofono_modem *modem, int ok, + enum ofono_sim_file_structure structure, + int length, int record, + const unsigned char *data, + int record_length, void *userdata) +{ + struct network_registration_data *netreg = modem->network_registration; + + if (!ok) + return; + + if (structure != OFONO_SIM_FILE_STRUCTURE_TRANSPARENT) + return; + + netreg->spdi = sim_spdi_new(data, length); + + if (!netreg->current_operator) + return; + + if (netreg->status == NETWORK_REGISTRATION_STATUS_ROAMING) { + DBusConnection *conn = dbus_gsm_connection(); + const char *operator; + + if (!sim_spdi_lookup(netreg->spdi, + netreg->current_operator->mcc, + netreg->current_operator->mnc)) + return; + + operator = get_operator_display_name(modem); + + dbus_gsm_signal_property_changed(conn, modem->path, + NETWORK_REGISTRATION_INTERFACE, + "Operator", DBUS_TYPE_STRING, + &operator); + } +} + static void sim_spn_read_cb(struct ofono_modem *modem, int ok, enum ofono_sim_file_structure structure, int length, int record, @@ -1143,8 +1184,6 @@ static void sim_spn_read_cb(struct ofono_modem *modem, int ok, int record_length, void *userdata) { struct network_registration_data *netreg = modem->network_registration; - DBusConnection *conn = dbus_gsm_connection(); - const char *operator; unsigned char dcbyte; char *spn; @@ -1183,21 +1222,26 @@ static void sim_spn_read_cb(struct ofono_modem *modem, int ok, return; } + netreg->spname = spn; + ofono_sim_read(modem, SIM_EFSPDI_FILEID, sim_spdi_read_cb, NULL); + if (dcbyte & SIM_EFSPN_DC_HOME_PLMN_BIT) netreg->flags |= NETWORK_REGISTRATION_FLAG_HOME_SHOW_PLMN; if (!(dcbyte & SIM_EFSPN_DC_ROAMING_SPN_BIT)) netreg->flags |= NETWORK_REGISTRATION_FLAG_ROAMING_SHOW_SPN; - if (!netreg->current_operator) - return; + if (netreg->current_operator) { + DBusConnection *conn = dbus_gsm_connection(); + const char *operator; - operator = get_operator_display_name(modem); + operator = get_operator_display_name(modem); - dbus_gsm_signal_property_changed(conn, modem->path, - NETWORK_REGISTRATION_INTERFACE, - "Operator", DBUS_TYPE_STRING, - &operator); + dbus_gsm_signal_property_changed(conn, modem->path, + NETWORK_REGISTRATION_INTERFACE, + "Operator", DBUS_TYPE_STRING, + &operator); + } } static void sim_ready(struct ofono_modem *modem) @@ -245,132 +245,6 @@ check: } } -struct sim_operator { - char mcc[OFONO_MAX_MCC_LENGTH + 1]; - char mnc[OFONO_MAX_MNC_LENGTH + 1]; -}; - -static void parse_mcc_mnc(struct sim_operator *oper, const guint8 *bcd) -{ - char *mcc = oper->mcc; - char *mnc = oper->mnc; - guint8 digit; - - digit = (bcd[0] >> 0) & 0xf; - if (digit != 0xf) - *mcc ++ = '0' + digit; - digit = (bcd[0] >> 4) & 0xf; - if (digit != 0xf) - *mcc ++ = '0' + digit; - digit = (bcd[1] >> 0) & 0xf; - if (digit != 0xf) - *mcc ++ = '0' + digit; - digit = (bcd[2] >> 0) & 0xf; - if (digit != 0xf) - *mnc ++ = '0' + digit; - digit = (bcd[2] >> 4) & 0xf; - if (digit != 0xf) - *mnc ++ = '0' + digit; - digit = (bcd[1] >> 4) & 0xf; - if (digit != 0xf) - *mnc ++ = '0' + digit; -} - -static struct sim_operator *sim_operator_alloc(const guint8 *bcd) -{ - struct sim_operator *spdi = g_new0(struct sim_operator, 1); - - parse_mcc_mnc(spdi, bcd); - - return spdi; -} - -static gint spdi_operator_compare(gconstpointer a, gconstpointer b) -{ - const struct sim_operator *opa = a; - const struct sim_operator *opb = b; - gint r; - - if ((r = strcmp(opa->mcc, opb->mcc))) - return r; - - return strcmp(opa->mnc, opb->mnc); -} - -gboolean ofono_operator_in_spdi(struct ofono_modem *modem, - const struct ofono_network_operator *op) -{ - struct sim_manager_data *sim = modem->sim_manager; - struct sim_operator spdi_op; - - if (!sim) - return FALSE; - - g_strlcpy(spdi_op.mcc, op->mcc, sizeof(spdi_op.mcc)); - g_strlcpy(spdi_op.mnc, op->mnc, sizeof(spdi_op.mnc)); - - return g_slist_find_custom(sim->spdi, - &spdi_op, spdi_operator_compare) != NULL; -} - -static void sim_spdi_read_cb(const struct ofono_error *error, - const unsigned char *spdidata, - int length, void *data) -{ - struct ofono_modem *modem = data; - struct sim_manager_data *sim = modem->sim_manager; - const guint8 *plmn_list; - GSList *l; - - if (error->type != OFONO_ERROR_TYPE_NO_ERROR || length <= 5) - return; - - plmn_list = ber_tlv_find_by_tag(spdidata, 0x80, length, &length); - if (!plmn_list) { - ofono_debug("Couldn't parse the EF-SPDI contents as a TLV"); - return; - } - - for (length /= 3; length --; plmn_list += 3) { - if ((plmn_list[0] & plmn_list[1] & plmn_list[2]) == 0xff) - continue; - - sim->spdi = g_slist_insert_sorted(sim->spdi, - sim_operator_alloc(plmn_list), - spdi_operator_compare); - } - - if (sim->spdi) - for (l = sim->update_spn_notify; l; l = l->next) - sim_spn_notify(modem, l->data); -} - -static void sim_spdi_info_cb(const struct ofono_error *error, int length, - enum ofono_sim_file_structure structure, - int dummy, void *data) -{ - struct ofono_modem *modem = data; - struct sim_manager_data *sim = modem->sim_manager; - - if (error->type != OFONO_ERROR_TYPE_NO_ERROR || length <= 5 || - structure != OFONO_SIM_FILE_STRUCTURE_TRANSPARENT) - return; - - sim->ops->read_file_transparent(modem, SIM_EFSPDI_FILEID, 0, length, - sim_spdi_read_cb, modem); -} - -static gboolean sim_retrieve_spdi(void *user_data) -{ - struct ofono_modem *modem = user_data; - struct sim_manager_data *sim = modem->sim_manager; - - sim->ops->read_file_info(modem, SIM_EFSPDI_FILEID, - sim_spdi_info_cb, modem); - - return FALSE; -} - struct opl_operator { struct sim_operator mcc_mnc; guint16 lac_tac_low; @@ -30,8 +30,6 @@ typedef void (*ofono_sim_file_read_cb_t)(struct ofono_modem *modem, int ok, void ofono_sim_manager_init(struct ofono_modem *modem); void ofono_sim_manager_exit(struct ofono_modem *modem); -gboolean ofono_operator_in_spdi(struct ofono_modem *modem, - const struct ofono_network_operator *op); const char *ofono_sim_get_imsi(struct ofono_modem *modem); int ofono_sim_ready_notify_register(struct ofono_modem *modem, diff --git a/src/simutil.c b/src/simutil.c index 253970bc..57d040b4 100644 --- a/src/simutil.c +++ b/src/simutil.c @@ -27,9 +27,15 @@ #include <glib.h> +#include "driver.h" #include "simutil.h" #include "util.h" +struct spdi_operator { + char mcc[OFONO_MAX_MCC_LENGTH + 1]; + char mnc[OFONO_MAX_MNC_LENGTH + 1]; +}; + /* Parse ASN.1 Basic Encoding Rules TLVs per ISO/IEC 7816 */ const guint8 *ber_tlv_find_by_tag(const guint8 *pdu, guint8 in_tag, int in_len, int *out_len) @@ -156,3 +162,89 @@ void sim_pnn_operator_free(struct sim_pnn_operator *oper) g_free(oper->shortname); g_free(oper->longname); } + +static void parse_mcc_mnc(const guint8 *bcd, char *mcc, char *mnc) +{ + guint8 digit; + + digit = (bcd[0] >> 0) & 0xf; + if (digit != 0xf) + *mcc ++ = '0' + digit; + digit = (bcd[0] >> 4) & 0xf; + if (digit != 0xf) + *mcc ++ = '0' + digit; + digit = (bcd[1] >> 0) & 0xf; + if (digit != 0xf) + *mcc ++ = '0' + digit; + digit = (bcd[2] >> 0) & 0xf; + if (digit != 0xf) + *mnc ++ = '0' + digit; + digit = (bcd[2] >> 4) & 0xf; + if (digit != 0xf) + *mnc ++ = '0' + digit; + digit = (bcd[1] >> 4) & 0xf; + if (digit != 0xf) + *mnc ++ = '0' + digit; +} + +static gint spdi_operator_compare(gconstpointer a, gconstpointer b) +{ + const struct spdi_operator *opa = a; + const struct spdi_operator *opb = b; + gint r; + + if (r = strcmp(opa->mcc, opb->mcc)) + return r; + + return strcmp(opa->mnc, opb->mnc); +} + +struct sim_spdi *sim_spdi_new(const guint8 *tlv, int length) +{ + const guint8 *plmn_list; + struct sim_spdi *spdi; + struct spdi_operator *oper; + int tlv_length; + + if (length <= 5) + return NULL; + + plmn_list = ber_tlv_find_by_tag(tlv, 0x80, length, &tlv_length); + + if (!plmn_list) + return NULL; + + spdi = g_new0(struct sim_spdi, 1); + + for (tlv_length /= 3; tlv_length--; plmn_list += 3) { + if ((plmn_list[0] & plmn_list[1] & plmn_list[2]) == 0xff) + continue; + + oper = g_new0(struct spdi_operator, 1); + + parse_mcc_mnc(plmn_list, oper->mcc, oper->mnc); + spdi->operators = g_slist_insert_sorted(spdi->operators, oper, + spdi_operator_compare); + } + + return spdi; +} + +gboolean sim_spdi_lookup(struct sim_spdi *spdi, + const char *mcc, const char *mnc) +{ + struct spdi_operator spdi_op; + + g_strlcpy(spdi_op.mcc, mcc, sizeof(spdi_op.mcc)); + g_strlcpy(spdi_op.mnc, mnc, sizeof(spdi_op.mnc)); + + return g_slist_find_custom(spdi->operators, &spdi_op, + spdi_operator_compare) != NULL; +} + +void sim_spdi_free(struct sim_spdi *spdi) +{ + g_slist_foreach(spdi->operators, (GFunc)g_free, NULL); + g_slist_free(spdi->operators); + g_free(spdi); +} diff --git a/src/simutil.h b/src/simutil.h index 92c956c7..eff2d99e 100644 --- a/src/simutil.h +++ b/src/simutil.h @@ -38,6 +38,10 @@ struct sim_pnn_operator { char *info; }; +struct sim_spdi { + GSList *operators; +}; + void sim_pnn_operator_free(struct sim_pnn_operator *oper); const guint8 *ber_tlv_find_by_tag(const guint8 *pdu, guint8 in_tag, @@ -45,3 +49,8 @@ const guint8 *ber_tlv_find_by_tag(const guint8 *pdu, guint8 in_tag, char *sim_network_name_parse(const unsigned char *buffer, int length, gboolean *add_ci); struct sim_pnn_operator *sim_pnn_operator_parse(const guint8 *tlv, int length); + +struct sim_spdi *sim_spdi_new(const guint8 *tlv, int length); +gboolean sim_spdi_lookup(struct sim_spdi *spdi, + const char *mcc, const char *mnc); +void sim_spdi_free(struct sim_spdi *spdi); |