diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c index f3a204d0..6cb37fe7 100644 --- a/drivers/atmodem/sim.c +++ b/drivers/atmodem/sim.c @@ -234,9 +234,9 @@ static void at_cnum_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; GAtResultIter iter; - ofono_numbers_cb_t cb = cbd->cb; + ofono_own_numbers_cb_t cb = cbd->cb; struct ofono_error error; - struct ofono_phone_number *numbers; + struct ofono_own_number *numbers; int count; const char *str; @@ -253,7 +253,7 @@ static void at_cnum_cb(gboolean ok, GAtResult *result, gpointer user_data) for (count = 0; g_at_result_iter_next(&iter, "+CNUM:"); count++); ofono_debug("Got %i elements", count); - numbers = g_try_new0(struct ofono_phone_number, count); + numbers = g_try_new0(struct ofono_own_number, count); if (!numbers) { DECLARE_FAILURE(e); cb(&e, 0, NULL, cbd->data); @@ -262,16 +262,30 @@ static void at_cnum_cb(gboolean ok, GAtResult *result, gpointer user_data) g_at_result_iter_init(&iter, result); - for (count = 0; g_at_result_iter_next(&iter, "+CNUM:"); count++) { + count = 0; + while (g_at_result_iter_next(&iter, "+CNUM")) { + /* Skip alnum */ g_at_result_iter_skip_next(&iter); if (!g_at_result_iter_next_string(&iter, &str)) continue; - g_strlcpy(numbers[count].number, str, + g_strlcpy(numbers[count].phone_number.number, + str[0] == '+' ? str+1 : str, OFONO_MAX_PHONE_NUMBER_LENGTH); - g_at_result_iter_next_number(&iter, &numbers[count].type); + g_at_result_iter_next_number(&iter, + &numbers[count].phone_number.type); + + numbers[count].speed = -1; + numbers[count].service = -1; + numbers[count].itc = -1; + + g_at_result_iter_skip_next(&iter); + g_at_result_iter_next_number(&iter, &numbers[count].service); + g_at_result_iter_next_number(&iter, &numbers[count].itc); + + count++; } cb(&error, count, numbers, cbd->data); @@ -279,8 +293,8 @@ static void at_cnum_cb(gboolean ok, GAtResult *result, gpointer user_data) g_free(numbers); } -static void at_read_msisdn(struct ofono_modem *modem, ofono_numbers_cb_t cb, - void *data) +static void at_read_msisdn(struct ofono_modem *modem, ofono_own_numbers_cb_t cb, + void *data) { struct at_data *at = ofono_modem_userdata(modem); struct cb_data *cbd = cb_data_new(modem, cb, data); diff --git a/src/common.h b/src/common.h index 90e245d9..1c0a7763 100644 --- a/src/common.h +++ b/src/common.h @@ -117,6 +117,15 @@ enum bearer_class { BEARER_CLASS_PAD = 128 }; +enum own_number_service_type { + OWN_NUMBER_SERVICE_TYPE_ASYNC = 0, + OWN_NUMBER_SERVICE_TYPE_SYNC = 1, + OWN_NUMBER_SERVICE_TYPE_PAD = 2, + OWN_NUMBER_SERVICE_TYPE_PACKET = 3, + OWN_NUMBER_SERVICE_TYPE_VOICE = 4, + OWN_NUMBER_SERVICE_TYPE_FAX = 5 +}; + enum call_forwarding_type { CALL_FORWARDING_TYPE_UNCONDITIONAL = 0, CALL_FORWARDING_TYPE_BUSY = 1, diff --git a/src/driver.h b/src/driver.h index bed53020..d6927db7 100644 --- a/src/driver.h +++ b/src/driver.h @@ -96,6 +96,14 @@ struct ofono_cw_condition { int cls; }; +/* 27.007 Section 7.1 Subscriber Number */ +struct ofono_own_number { + struct ofono_phone_number phone_number; + int speed; + int service; + int itc; +}; + /* Notification functions, the integer values here should map to * values obtained from the modem. The enumerations are the same * as the values for the fields found in 3GPP TS 27.007 @@ -165,8 +173,8 @@ typedef void (*ofono_sim_read_cb_t)(const struct ofono_error *error, typedef void (*ofono_imsi_cb_t)(const struct ofono_error *error, const char *imsi, void *data); -typedef void (*ofono_numbers_cb_t)(const struct ofono_error *error, int num, - const struct ofono_phone_number *numbers, void *data); +typedef void (*ofono_own_numbers_cb_t)(const struct ofono_error *error, int num, + const struct ofono_own_number *numbers, void *data); struct ofono_modem_attribute_ops { void (*query_manufacturer)(struct ofono_modem *modem, @@ -372,7 +380,7 @@ struct ofono_sim_ops { void (*read_imsi)(struct ofono_modem *modem, ofono_imsi_cb_t cb, void *data); void (*read_own_numbers)(struct ofono_modem *modem, - ofono_numbers_cb_t cb, void *data); + ofono_own_numbers_cb_t cb, void *data); }; int ofono_sim_manager_register(struct ofono_modem *modem, diff --git a/src/modem.c b/src/modem.c index a1233ca7..ad476e0c 100644 --- a/src/modem.c +++ b/src/modem.c @@ -35,6 +35,7 @@ #include "dbus-gsm.h" #include "modem.h" #include "driver.h" +#include "common.h" #include "cssn.h" #include "sim.h" diff --git a/src/sim.c b/src/sim.c index 76b1010d..32126023 100644 --- a/src/sim.c +++ b/src/sim.c @@ -48,13 +48,64 @@ struct sim_manager_data { int flags; DBusMessage *pending; char *imsi; - char **numbers; + GSList *own_numbers; char *spn; int dcbyte; GSList *update_spn_notify; }; +static char **own_numbers_by_type(GSList *own_numbers, int type) +{ + int nelem; + GSList *l; + struct ofono_own_number *num; + char **ret; + + if (!own_numbers) + return NULL; + + for (nelem = 0, l = own_numbers; l; l = l->next) { + num = l->data; + + if (num->service != type) + continue; + + nelem++; + } + + if (nelem == 0) { + if (g_slist_length(own_numbers) != 1) + return NULL; + + num = own_numbers->data; + + /* Generic case */ + if (num->service != -1) + return NULL; + + ret = g_new0(char *, 2); + + ret[0] = g_strdup(phone_number_to_string(&num->phone_number)); + + return ret; + } + + ret = g_new0(char *, nelem + 1); + + nelem = 0; + for (l = own_numbers; l; l = l->next) { + num = l->data; + + if (num->service != type) + continue; + + ret[nelem++] = g_strdup(phone_number_to_string(&num->phone_number)); + } + + return ret; +} + static struct sim_manager_data *sim_manager_create() { return g_try_new0(struct sim_manager_data, 1); @@ -70,9 +121,10 @@ static void sim_manager_destroy(gpointer userdata) data->imsi = NULL; } - if (data->numbers) { - dbus_gsm_free_string_array(data->numbers); - data->numbers = NULL; + if (data->own_numbers) { + g_slist_foreach(data->own_numbers, (GFunc)g_free, NULL); + g_slist_free(data->own_numbers); + data->own_numbers = NULL; } if (data->spn) { @@ -89,6 +141,7 @@ static DBusMessage *sim_get_properties(DBusConnection *conn, DBusMessage *reply; DBusMessageIter iter; DBusMessageIter dict; + char **own_voice; reply = dbus_message_new_method_return(msg); if (!reply) @@ -100,12 +153,22 @@ static DBusMessage *sim_get_properties(DBusConnection *conn, PROPERTIES_ARRAY_SIGNATURE, &dict); - dbus_gsm_dict_append(&dict, "IMSI", - DBUS_TYPE_STRING, &sim->imsi); - dbus_gsm_dict_append(&dict, "ServiceProvider", - DBUS_TYPE_STRING, &sim->spn); - dbus_gsm_dict_append_array(&dict, "OwnNumbers", - DBUS_TYPE_STRING, &sim->numbers); + if (sim->imsi) + dbus_gsm_dict_append(&dict, "SubscriberIdentity", + DBUS_TYPE_STRING, &sim->imsi); + + if (sim->spn) + dbus_gsm_dict_append(&dict, "ServiceProvider", + DBUS_TYPE_STRING, &sim->spn); + + own_voice = own_numbers_by_type(sim->own_numbers, + OWN_NUMBER_SERVICE_TYPE_VOICE); + + if (own_voice) { + dbus_gsm_dict_append_array(&dict, "VoiceSubscriberNumber", + DBUS_TYPE_STRING, &own_voice); + dbus_gsm_free_string_array(own_voice); + } dbus_message_iter_close_container(&iter, &dict); @@ -223,26 +286,30 @@ static gboolean sim_retrieve_imsi(void *user_data) } static void sim_own_number_cb(const struct ofono_error *error, int num, - const struct ofono_phone_number *phs, void *data) + const struct ofono_own_number *own, void *data) { struct ofono_modem *modem = data; struct sim_manager_data *sim = modem->sim_manager; - char **number_str; int i; if (error->type != OFONO_ERROR_TYPE_NO_ERROR) return; - sim->numbers = g_try_new0(char *, num + 1); - number_str = sim->numbers; - for (i = 0; i < num; i++) { - if (phs[i].number[0] == '\0') + struct ofono_own_number *ph; + + if (own[i].phone_number.number[0] == '\0') continue; - *number_str = g_strdup(phone_number_to_string(&phs[i])); - number_str++; + ph = g_new(struct ofono_own_number, 1); + + memcpy(ph, &own[i], sizeof(struct ofono_own_number)); + + sim->own_numbers = g_slist_prepend(sim->own_numbers, ph); } + + if (sim->own_numbers) + sim->own_numbers = g_slist_reverse(sim->own_numbers); } static gboolean sim_retrieve_own_number(void *user_data)