diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c index 5f66a09c..520b3dbf 100644 --- a/drivers/atmodem/sim.c +++ b/drivers/atmodem/sim.c @@ -75,6 +75,7 @@ static const char *cuad_prefix[] = { "+CUAD:", NULL }; static const char *ccho_prefix[] = { "+CCHO:", NULL }; static const char *crla_prefix[] = { "+CRLA:", NULL }; static const char *cgla_prefix[] = { "+CGLA:", NULL }; +static const char *xcmscsc_prefix[] = { "+XCMSCSC:", NULL}; static const char *none_prefix[] = { NULL }; static void append_file_path(char *buf, const unsigned char *path, @@ -1160,6 +1161,7 @@ static void at_pin_retries_query(struct ofono_sim *sim, DBG(""); switch (sd->vendor) { + case OFONO_VENDOR_XMM: case OFONO_VENDOR_IFX: if (g_at_chat_send(sd->chat, "AT+XPINCNT", xpincnt_prefix, xpincnt_cb, cbd, g_free) > 0) @@ -1920,6 +1922,83 @@ static void at_logical_access(struct ofono_sim *sim, int session_id, CALLBACK_WITH_FAILURE(cb, NULL, 0, data); } +static void xcmscsc_query_cb(gboolean ok, GAtResult *result, gpointer user) +{ + struct ofono_sim *sim = user; + struct sim_data *sd = ofono_sim_get_data(sim); + GAtResultIter iter; + int active_slot; + + if (!ok) + goto done; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+XCMSCSC:")) + goto done; + + g_at_result_iter_skip_next(&iter); + g_at_result_iter_skip_next(&iter); + + g_at_result_iter_next_number(&iter, &active_slot); + + /* set active SIM slot */ + ofono_sim_set_active_card_slot(sim, active_slot + 1); + +done: + /* Query supported s */ + g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix, + at_clck_query_cb, sim, NULL); +} + +static void at_xcmscsc_test_cb(gboolean ok, GAtResult *result, gpointer user) +{ + struct ofono_sim *sim = user; + struct sim_data *sd = ofono_sim_get_data(sim); + GAtResultIter iter; + int card_slot_count; + + if (!ok) + goto done; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+XCMSCSC:")) + goto done; + + g_at_result_iter_skip_next(&iter); + g_at_result_iter_skip_next(&iter); + + if (!g_at_result_iter_open_list(&iter)) + goto done; + + g_at_result_iter_skip_next(&iter); + + if (!g_at_result_iter_next_number(&iter, &card_slot_count)) + goto done; + + /* Set num slots */ + ofono_sim_set_card_slot_count(sim, card_slot_count + 1); + + /* + * enable reporting of MSIM remap status information + * and enable automatic acceptance of MSIM Remap + * acknowledgement + */ + g_at_chat_send(sd->chat, "AT+XCMSRS=2", none_prefix, + NULL, NULL, NULL); + + /* Query active card slot */ + g_at_chat_send(sd->chat, "AT+XCMSCSC?", xcmscsc_prefix, + xcmscsc_query_cb, sim, NULL); + return; + +done: + /* Query supported s */ + g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix, + at_clck_query_cb, sim, NULL); +} + static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor, void *data) { @@ -1938,6 +2017,10 @@ static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor, if (at_clck_cpwd_fac[i]) sd->passwd_type_mask |= (1 << i); + if (sd->vendor == OFONO_VENDOR_XMM) + return g_at_chat_send(sd->chat, "AT+XCMSCSC=?", xcmscsc_prefix, + at_xcmscsc_test_cb, sim, NULL) ? 0 : -1; + /* Query supported s */ return g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix, at_clck_query_cb, sim, NULL) ? 0 : -1; @@ -1957,6 +2040,46 @@ static void at_sim_remove(struct ofono_sim *sim) g_free(sd); } +static void xcmscsc_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct cb_data *cbd = user_data; + ofono_sim_set_active_card_slot_cb_t cb = cbd->cb; + struct ofono_error error; + + decode_at_error(&error, g_at_result_final_response(result)); + + if (cb) + cb(&error, cbd->data); +} + +static void at_set_active_card_slot(struct ofono_sim *sim, unsigned int index, + ofono_sim_set_active_card_slot_cb_t cb, void *data) +{ + struct sim_data *sd = ofono_sim_get_data(sim); + struct cb_data *cbd = cb_data_new(cb, data); + char cmd[43]; + + if (sd->vendor != OFONO_VENDOR_XMM) { + struct ofono_error error; + error.type = OFONO_ERROR_TYPE_CME; + error.error = 4; + + cb(&error, data); + return; + } + + /* Enable single SIM mode for indicated card slot id */ + snprintf(cmd, sizeof(cmd), "AT+XCMSCSC=1,0,%u,1", index); + + if (g_at_chat_send(sd->chat, cmd, none_prefix, xcmscsc_cb, + cbd, g_free) > 0) + return; + + g_free(cbd); + CALLBACK_WITH_FAILURE(cb, data); +} + static const struct ofono_sim_driver driver = { .name = "atmodem", .probe = at_sim_probe, @@ -1982,7 +2105,8 @@ static const struct ofono_sim_driver driver = { .session_read_binary = at_session_read_binary, .session_read_record = at_session_read_record, .session_read_info = at_session_read_info, - .logical_access = at_logical_access + .logical_access = at_logical_access, + .set_active_card_slot = at_set_active_card_slot }; static const struct ofono_sim_driver driver_noef = {