static void cind_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct slc_establish_data *sed = user_data; struct hfp_slc_info *info = sed->info; GAtResultIter iter; const char *str; int index; int min, max; if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CIND:")) goto error; index = 1; while (g_at_result_iter_open_list(&iter)) { if (!g_at_result_iter_next_string(&iter, &str)) goto error; if (!g_at_result_iter_open_list(&iter)) goto error; while (g_at_result_iter_next_range(&iter, &min, &max)) ; if (!g_at_result_iter_close_list(&iter)) goto error; if (!g_at_result_iter_close_list(&iter)) goto error; if (g_str_equal("service", str) == TRUE) info->cind_pos[HFP_INDICATOR_SERVICE] = index; else if (g_str_equal("call", str) == TRUE) info->cind_pos[HFP_INDICATOR_CALL] = index; else if (g_str_equal("callsetup", str) == TRUE) info->cind_pos[HFP_INDICATOR_CALLSETUP] = index; else if (g_str_equal("callheld", str) == TRUE) info->cind_pos[HFP_INDICATOR_CALLHELD] = index; else if (g_str_equal("signal", str) == TRUE) info->cind_pos[HFP_INDICATOR_SIGNAL] = index; else if (g_str_equal("roam", str) == TRUE) info->cind_pos[HFP_INDICATOR_ROAM] = index; else if (g_str_equal("battchg", str) == TRUE) info->cind_pos[HFP_INDICATOR_BATTCHG] = index; index += 1; } slc_establish_data_ref(sed); g_at_chat_send(info->chat, "AT+CIND?", cind_prefix, cind_status_cb, sed, slc_establish_data_unref); return; error: slc_failed(sed); }
static void at_cgdcont_test_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); GAtResultIter iter; int min, max; const char *pdp_type; gboolean found = FALSE; if (!ok) goto error; g_at_result_iter_init(&iter, result); while (!found && g_at_result_iter_next(&iter, "+CGDCONT:")) { gboolean in_list = FALSE; if (!g_at_result_iter_open_list(&iter)) continue; if (g_at_result_iter_next_range(&iter, &min, &max) == FALSE) continue; if (!g_at_result_iter_close_list(&iter)) continue; if (g_at_result_iter_open_list(&iter)) in_list = TRUE; if (!g_at_result_iter_next_string(&iter, &pdp_type)) continue; if (in_list && !g_at_result_iter_close_list(&iter)) continue; /* We look for IP PDPs */ if (g_str_equal(pdp_type, "IP")) found = TRUE; } if (found == FALSE) goto error; ofono_gprs_set_cid_range(gprs, min, max); g_at_chat_send(gd->chat, "AT+CGREG=?", cgreg_prefix, at_cgreg_test_cb, gprs, NULL); return; error: ofono_info("GPRS not supported on this device"); ofono_gprs_remove(gprs); }
static void at_csms_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_sms *sms = user_data; struct sms_data *data = ofono_sms_get_data(sms); gboolean cnma_supported = FALSE; GAtResultIter iter; int status_min, status_max; char buf[128]; if (!ok) return at_sms_not_supported(sms); g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CSMS:")) goto out; if (!g_at_result_iter_open_list(&iter)) goto out; while (g_at_result_iter_next_range(&iter, &status_min, &status_max)) if (status_min <= 1 && 1 <= status_max) cnma_supported = TRUE; DBG("CSMS query parsed successfully"); out: snprintf(buf, sizeof(buf), "AT+CSMS=%d", cnma_supported ? 1 : 0); g_at_chat_send(data->chat, buf, csms_prefix, at_csms_set_cb, sms, NULL); }
static void at_cmgf_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_sms *sms = user_data; struct sms_data *data = ofono_sms_get_data(sms); gboolean supported = FALSE; if (ok) { GAtResultIter iter; int mode; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CMGF:")) goto out; if (!g_at_result_iter_open_list(&iter)) goto out; /* Look for mode 0 (PDU mode) */ while (g_at_result_iter_next_number(&iter, &mode)) if (mode == 0) supported = TRUE; } out: if (!supported) return at_sms_not_supported(sms); g_at_chat_send(data->chat, "AT+CPMS=?", cpms_prefix, at_cpms_query_cb, sms, NULL); }
static void at_cgreg_test_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); gint range[2]; GAtResultIter iter; int cgreg1 = 0; int cgreg2 = 0; const char *cmd; if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CGREG:")) goto error; if (!g_at_result_iter_open_list(&iter)) goto error; while (g_at_result_iter_next_range(&iter, &range[0], &range[1])) { if (1 >= range[0] && 1 <= range[1]) cgreg1 = 1; if (2 >= range[0] && 2 <= range[1]) cgreg2 = 1; } g_at_result_iter_close_list(&iter); if (cgreg2) cmd = "AT+CGREG=2"; else if (cgreg1) cmd = "AT+CGREG=1"; else goto error; g_at_chat_send(gd->chat, cmd, none_prefix, NULL, NULL, NULL); g_at_chat_send(gd->chat, "AT+CGAUTO=0", none_prefix, NULL, NULL, NULL); /* ST-E modem does not support AT+CGEREP = 2,1 */ if (gd->vendor == OFONO_VENDOR_STE) g_at_chat_send(gd->chat, "AT+CGEREP=1,0", none_prefix, gprs_initialized, gprs, NULL); else g_at_chat_send(gd->chat, "AT+CGEREP=2,1", none_prefix, gprs_initialized, gprs, NULL); return; error: ofono_info("GPRS not supported on this device"); ofono_gprs_remove(gprs); }
static void chld_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct slc_establish_data *sed = user_data; struct hfp_slc_info *info = sed->info; unsigned int ag_mpty_feature = 0; GAtResultIter iter; const char *str; if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CHLD:")) goto error; if (!g_at_result_iter_open_list(&iter)) goto error; while (g_at_result_iter_next_unquoted_string(&iter, &str)) { if (!strcmp(str, "0")) ag_mpty_feature |= HFP_AG_CHLD_0; else if (!strcmp(str, "1")) ag_mpty_feature |= HFP_AG_CHLD_1; else if (!strcmp(str, "1x")) ag_mpty_feature |= HFP_AG_CHLD_1x; else if (!strcmp(str, "2")) ag_mpty_feature |= HFP_AG_CHLD_2; else if (!strcmp(str, "2x")) ag_mpty_feature |= HFP_AG_CHLD_2x; else if (!strcmp(str, "3")) ag_mpty_feature |= HFP_AG_CHLD_3; else if (!strcmp(str, "4")) ag_mpty_feature |= HFP_AG_CHLD_4; } if (!g_at_result_iter_close_list(&iter)) goto error; info->ag_mpty_features = ag_mpty_feature; if ((info->ag_features & HFP_AG_FEATURE_HF_INDICATORS) && (info->hf_features & HFP_HF_FEATURE_HF_INDICATORS)) { slc_establish_data_ref(sed); g_at_chat_send(info->chat, "AT+BIND=1", none_prefix, bind_set_cb, sed, slc_establish_data_unref); } else slc_established(sed); return; error: slc_failed(sed); }
static void at_creg_test_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; struct netreg_data *nd = ofono_netreg_get_data(netreg); gint range[2]; GAtResultIter iter; int creg1 = 0; int creg2 = 0; if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CREG:")) goto error; if (!g_at_result_iter_open_list(&iter)) goto error; while (g_at_result_iter_next_range(&iter, &range[0], &range[1])) { if (1 >= range[0] && 1 <= range[1]) creg1 = 1; if (2 >= range[0] && 2 <= range[1]) creg2 = 1; } g_at_result_iter_close_list(&iter); if (creg2) { g_at_chat_send(nd->chat, "AT+CREG=2", none_prefix, at_creg_set_cb, netreg, NULL); return; } if (creg1) { g_at_chat_send(nd->chat, "AT+CREG=1", none_prefix, at_creg_set_cb, netreg, NULL); return; } error: ofono_error("Unable to initialize Network Registration"); ofono_netreg_remove(netreg); }
static void bind_support_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct slc_establish_data *sed = user_data; struct hfp_slc_info *info = sed->info; GAtResultIter iter; int hf_indicator; if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+BIND:")) goto error; if (!g_at_result_iter_open_list(&iter)) goto error; while (g_at_result_iter_next_number(&iter, &hf_indicator)) { if (info->num_hf_indicators >= 20) goto error; ofono_info("AG supports the following HF indicator: %d", hf_indicator); info->hf_indicators[info->num_hf_indicators] = hf_indicator; info->num_hf_indicators += 1; } if (!g_at_result_iter_close_list(&iter)) goto error; slc_establish_data_ref(sed); g_at_chat_send(info->chat, "AT+BIND?", bind_prefix, bind_query_cb, sed, slc_establish_data_unref); return; error: slc_failed(sed); }
static void mbm_e2ipcfg_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs_context *gc = user_data; struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); GAtResultIter iter; int numdns = 0; int type; const char *str; const char *ip = NULL; const char *gateway = NULL; const char *dns[MAX_DNS + 1]; struct ofono_modem *modem; const char *interface; gboolean success = FALSE; if (!ok) goto out; g_at_result_iter_init(&iter, result); if (g_at_result_iter_next(&iter, "*E2IPCFG:") == FALSE) return; while (g_at_result_iter_open_list(&iter)) { if (g_at_result_iter_next_number(&iter, &type) == FALSE) break; if (g_at_result_iter_next_string(&iter, &str) == FALSE) break; switch (type) { case 1: ip = str; break; case 2: gateway = str; break; case 3: if (numdns < MAX_DNS) dns[numdns++] = str; break; default: break; } if (g_at_result_iter_close_list(&iter) == FALSE) break; } dns[numdns] = NULL; if (ip && gateway && numdns) success = TRUE; out: modem = ofono_gprs_context_get_modem(gc); interface = ofono_modem_get_string(modem, "NetworkInterface"); CALLBACK_WITH_SUCCESS(gcd->up_cb, interface, success, ip, STATIC_IP_NETMASK, gateway, success ? dns : NULL, gcd->cb_data); gcd->mbm_state = MBM_NONE; gcd->up_cb = NULL; gcd->cb_data = NULL; }
static void at_cnmi_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_sms *sms = user_data; struct sms_data *data = ofono_sms_get_data(sms); GAtResultIter iter; int cnmi_opts[5]; /* See 27.005 Section 3.4.1 */ int opt; int mode; gboolean supported = FALSE; char buf[128]; if (!ok) goto out; memset(cnmi_opts, 0, sizeof(cnmi_opts)); g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CNMI:")) goto out; for (opt = 0; opt < 5; opt++) { int min, max; if (!g_at_result_iter_open_list(&iter)) goto out; while (g_at_result_iter_next_range(&iter, &min, &max)) { for (mode = min; mode <= max; mode++) cnmi_opts[opt] |= 1 << mode; } if (!g_at_result_iter_close_list(&iter)) goto out; } if (build_cnmi_string(buf, cnmi_opts, data)) supported = TRUE; /* support for ack pdu is not working */ switch (data->vendor) { case OFONO_VENDOR_IFX: case OFONO_VENDOR_GOBI: case OFONO_VENDOR_HUAWEI: case OFONO_VENDOR_NOVATEL: case OFONO_VENDOR_OPTION_HSO: goto out; default: break; } if (data->cnma_enabled) construct_ack_pdu(data); out: if (!supported) return at_sms_not_supported(sms); g_at_chat_send(data->chat, buf, cnmi_prefix, at_cnmi_set_cb, sms, NULL); }
static void at_cpms_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_sms *sms = user_data; struct sms_data *data = ofono_sms_get_data(sms); gboolean supported = FALSE; if (ok) { int mem = 0; GAtResultIter iter; const char *store; gboolean me_supported[3]; gboolean sm_supported[3]; gboolean mt_supported[3]; memset(me_supported, 0, sizeof(me_supported)); memset(sm_supported, 0, sizeof(sm_supported)); memset(mt_supported, 0, sizeof(mt_supported)); g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CPMS:")) goto out; for (mem = 0; mem < 3; mem++) { if (!g_at_result_iter_open_list(&iter)) goto out; while (g_at_result_iter_next_string(&iter, &store)) { if (!strcmp(store, "ME")) me_supported[mem] = TRUE; else if (!strcmp(store, "SM")) sm_supported[mem] = TRUE; else if (!strcmp(store, "MT")) mt_supported[mem] = TRUE; } if (!g_at_result_iter_close_list(&iter)) goto out; } if (!sm_supported[2] && !me_supported[2] && !mt_supported[2]) goto out; if (sm_supported[0] && sm_supported[1]) { supported = TRUE; data->store = AT_UTIL_SMS_STORE_SM; } if (me_supported[0] && me_supported[1]) { supported = TRUE; data->store = AT_UTIL_SMS_STORE_ME; } /* This seems to be a special case, where the modem will * pick & route the SMS to any of the storages supported by * mem1 */ if (mt_supported[2] && (sm_supported[0] || me_supported[0])) data->incoming = AT_UTIL_SMS_STORE_MT; if (sm_supported[2]) data->incoming = AT_UTIL_SMS_STORE_SM; if (me_supported[2]) data->incoming = AT_UTIL_SMS_STORE_ME; } out: if (!supported) return at_sms_not_supported(sms); set_cmgf(sms); }
static void at_cgreg_test_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); gint range[2]; GAtResultIter iter; int cgreg1 = 0; int cgreg2 = 0; const char *cmd; if (!ok) goto error; g_at_result_iter_init(&iter, result); retry: if (!g_at_result_iter_next(&iter, "+CGREG:")) goto error; if (!g_at_result_iter_open_list(&iter)) goto retry; while (g_at_result_iter_next_range(&iter, &range[0], &range[1])) { if (1 >= range[0] && 1 <= range[1]) cgreg1 = 1; if (2 >= range[0] && 2 <= range[1]) cgreg2 = 1; } g_at_result_iter_close_list(&iter); if (cgreg2) cmd = "AT+CGREG=2"; else if (cgreg1) cmd = "AT+CGREG=1"; else goto error; g_at_chat_send(gd->chat, cmd, none_prefix, NULL, NULL, NULL); g_at_chat_send(gd->chat, "AT+CGAUTO=0", none_prefix, NULL, NULL, NULL); switch (gd->vendor) { case OFONO_VENDOR_MBM: /* Ericsson MBM and ST-E modems don't support AT+CGEREP=2,1 */ g_at_chat_send(gd->chat, "AT+CGEREP=1,0", none_prefix, gprs_initialized, gprs, NULL); break; case OFONO_VENDOR_NOKIA: /* Nokia data cards don't support AT+CGEREP=1,0 either */ g_at_chat_send(gd->chat, "AT+CGEREP=1", none_prefix, gprs_initialized, gprs, NULL); break; default: g_at_chat_send(gd->chat, "AT+CGEREP=2,1", none_prefix, gprs_initialized, gprs, NULL); break; } return; error: ofono_info("GPRS not supported on this device"); ofono_gprs_remove(gprs); }
static void mux_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct mux_setup_data *msd = user_data; struct mux_setup_data *nmsd; GAtResultIter iter; int min, max; int speed; char buf[64]; /* CMUX query not supported, abort */ if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CMUX:")) goto error; /* Mode */ if (!g_at_result_iter_open_list(&iter)) goto error; if (!g_at_result_iter_next_range(&iter, &min, &max)) goto error; if (!g_at_result_iter_close_list(&iter)) goto error; if (min <= 1 && 1 <= max) msd->mode = 1; else if (min <= 0 && 0 <= max) msd->mode = 0; else goto error; /* Subset */ if (!g_at_result_iter_open_list(&iter)) goto error; if (!g_at_result_iter_next_range(&iter, &min, &max)) goto error; if (!g_at_result_iter_close_list(&iter)) goto error; if (min > 0) goto error; /* Speed, pick highest */ if (g_at_result_iter_open_list(&iter)) { if (!g_at_result_iter_next_range(&iter, &min, &max)) goto error; if (!g_at_result_iter_close_list(&iter)) goto error; speed = max; } else { if (!g_at_result_iter_skip_next(&iter)) goto error; /* not available/used */ speed = -1; } /* Frame size, pick defaults */ if (!g_at_result_iter_open_list(&iter)) goto error; if (!g_at_result_iter_next_range(&iter, &min, &max)) goto error; if (!g_at_result_iter_close_list(&iter)) goto error; if (msd->mode == 0) { if (min > 31 || max < 31) goto error; msd->frame_size = 31; } else if (msd->mode == 1) { if (min > 64 || max < 64) goto error; msd->frame_size = 64; } else goto error; nmsd = g_memdup(msd, sizeof(struct mux_setup_data)); g_at_chat_ref(nmsd->chat); if (speed < 0) sprintf(buf, "AT+CMUX=%u,0,,%u", msd->mode, msd->frame_size); else sprintf(buf, "AT+CMUX=%u,0,%u,%u", msd->mode, speed, msd->frame_size); if (g_at_chat_send(msd->chat, buf, none_prefix, mux_setup_cb, nmsd, msd_free) > 0) return; msd_free(nmsd); error: msd->func(NULL, msd->user); if (msd->destroy) msd->destroy(msd->user); }
static void cops_list_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_netreg_operator_list_cb_t cb = cbd->cb; struct ofono_network_operator *list; GAtResultIter iter; int num = 0; struct ofono_error error; decode_at_error(&error, g_at_result_final_response(result)); if (!ok) { cb(&error, 0, NULL, cbd->data); return; } g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, "+COPS:")) { while (g_at_result_iter_skip_next(&iter)) num += 1; } DBG("Got %d elements", num); list = g_try_new0(struct ofono_network_operator, num); if (list == NULL) { CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data); return; } num = 0; g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, "+COPS:")) { int status, tech, plmn; const char *l, *s, *n; gboolean have_long = FALSE; while (1) { if (!g_at_result_iter_open_list(&iter)) break; if (!g_at_result_iter_next_number(&iter, &status)) break; list[num].status = status; if (!g_at_result_iter_next_string(&iter, &l)) break; if (strlen(l) > 0) { have_long = TRUE; strncpy(list[num].name, l, OFONO_MAX_OPERATOR_NAME_LENGTH); } if (!g_at_result_iter_next_string(&iter, &s)) break; if (strlen(s) > 0 && !have_long) strncpy(list[num].name, s, OFONO_MAX_OPERATOR_NAME_LENGTH); list[num].name[OFONO_MAX_OPERATOR_NAME_LENGTH] = '\0'; if (!g_at_result_iter_next_string(&iter, &n)) break; extract_mcc_mnc(n, list[num].mcc, list[num].mnc); if (!g_at_result_iter_next_number(&iter, &tech)) tech = ACCESS_TECHNOLOGY_GSM; list[num].tech = tech; if (!g_at_result_iter_next_number(&iter, &plmn)) plmn = 0; if (!g_at_result_iter_close_list(&iter)) break; num += 1; } } DBG("Got %d operators", num); { int i = 0; for (; i < num; i++) { DBG("Operator: %s, %s, %s, status: %d, %d", list[i].name, list[i].mcc, list[i].mnc, list[i].status, list[i].tech); } } cb(&error, num, list, cbd->data); g_free(list); }
static void cind_support_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; struct netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; const char *str; int index; int min = 0; int max = 0; int tmp_min, tmp_max, invalid; if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CIND:")) goto error; index = 1; /* * Telit encapsulates the CIND=? tokens with braces * so we need to skip them */ if (nd->vendor == OFONO_VENDOR_TELIT) g_at_result_iter_open_list(&iter); while (g_at_result_iter_open_list(&iter)) { /* Reset invalid default value for every token */ invalid = 99; if (!g_at_result_iter_next_string(&iter, &str)) goto error; if (!g_at_result_iter_open_list(&iter)) goto error; while (g_at_result_iter_next_range(&iter, &tmp_min, &tmp_max)) { if (tmp_min != tmp_max) { min = tmp_min; max = tmp_max; } else invalid = tmp_min; } if (!g_at_result_iter_close_list(&iter)) goto error; if (!g_at_result_iter_close_list(&iter)) goto error; if (g_str_equal("signal", str) == TRUE) { nd->signal_index = index; nd->signal_min = min; nd->signal_max = max; nd->signal_invalid = invalid; } index += 1; } if (nd->vendor == OFONO_VENDOR_TELIT) g_at_result_iter_close_list(&iter); if (nd->signal_index == 0) goto error; g_at_chat_send(nd->chat, "AT+CMER=3,0,0,1", NULL, NULL, NULL, NULL); g_at_chat_register(nd->chat, "+CIEV:", ciev_notify, FALSE, netreg, NULL); g_at_chat_register(nd->chat, "+CREG:", creg_notify, FALSE, netreg, NULL); ofono_netreg_register(netreg); return; error: ofono_error("This driver is not setup with Signal Strength reporting" " via CIND indications, please write proper netreg" " handling for this device"); ofono_netreg_remove(netreg); }