static gboolean at_util_parse_reg(GAtResult *result, const char *prefix, int *mode, int *status, int *lac, int *ci, int *tech) { GAtResultIter iter; int m, s; int l = -1, c = -1, t = -1; const char *str; g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, prefix)) { g_at_result_iter_next_number(&iter, &m); /* Sometimes we get an unsolicited CREG/CGREG here, skip it */ if (g_at_result_iter_next_number(&iter, &s) == FALSE) continue; if (g_at_result_iter_next_string(&iter, &str) == TRUE) l = strtol(str, NULL, 16); else goto out; if (g_at_result_iter_next_string(&iter, &str) == TRUE) c = strtol(str, NULL, 16); else goto out; g_at_result_iter_next_number(&iter, &t); out: if (mode) *mode = m; if (status) *status = s; if (lac) *lac = l; if (ci) *ci = c; if (tech) *tech = t; return TRUE; } return FALSE; }
static void mbm_etzv_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; struct netreg_data *nd = ofono_netreg_get_data(netreg); int year, mon, mday, hour, min, sec; const char *tz, *time, *timestamp; GAtResultIter iter; g_at_result_iter_init(&iter, result); if (g_at_result_iter_next(&iter, "*ETZV:") == FALSE) return; if (g_at_result_iter_next_string(&iter, &tz) == FALSE) return; if (g_at_result_iter_next_string(&iter, &time) == FALSE) time = NULL; if (g_at_result_iter_next_string(&iter, ×tamp) == FALSE) timestamp = NULL; DBG("tz %s time %s timestamp %s", tz, time, timestamp); if (time == NULL) { year = -1; mon = -1; mday = -1; hour = -1; min = -1; sec = -1; } else { if (sscanf(time, "%u/%u/%u,%u:%u:%u", &year, &mon, &mday, &hour, &min, &sec) != 6) return; } nd->time.utcoff = atoi(tz) * 15 * 60; nd->time.sec = sec; nd->time.min = min; nd->time.hour = hour; nd->time.mday = mday; nd->time.mon = mon; nd->time.year = year; ofono_netreg_time_notify(netreg, &nd->time); }
static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; struct netreg_data *nd = ofono_netreg_get_data(cbd->user); ofono_netreg_operator_cb_t cb = cbd->cb; struct ofono_network_operator op; GAtResultIter iter; int format, tech; const char *name; struct ofono_error error; decode_at_error(&error, g_at_result_final_response(result)); if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+COPS:")) goto error; g_at_result_iter_skip_next(&iter); ok = g_at_result_iter_next_number(&iter, &format); if (ok == FALSE || format != 0) goto error; if (g_at_result_iter_next_string(&iter, &name) == FALSE) goto error; /* Default to GSM */ if (g_at_result_iter_next_number(&iter, &tech) == FALSE) tech = ACCESS_TECHNOLOGY_GSM; strncpy(op.name, name, OFONO_MAX_OPERATOR_NAME_LENGTH); op.name[OFONO_MAX_OPERATOR_NAME_LENGTH] = '\0'; strncpy(op.mcc, nd->mcc, OFONO_MAX_MCC_LENGTH); op.mcc[OFONO_MAX_MCC_LENGTH] = '\0'; strncpy(op.mnc, nd->mnc, OFONO_MAX_MNC_LENGTH); op.mnc[OFONO_MAX_MNC_LENGTH] = '\0'; /* Set to current */ op.status = 2; op.tech = tech; DBG("cops_cb: %s, %s %s %d", name, nd->mcc, nd->mnc, tech); cb(&error, &op, cbd->data); g_free(cbd); return; error: cb(&error, NULL, cbd->data); g_free(cbd); }
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 gboolean at_util_parse_reg_unsolicited(GAtResult *result, const char *prefix, int *status, int *lac, int *ci, int *tech) { GAtResultIter iter; int s; int l = -1, c = -1, t = -1; const char *str; g_at_result_iter_init(&iter, result); if (g_at_result_iter_next(&iter, prefix) == FALSE) return FALSE; if (g_at_result_iter_next_number(&iter, &s) == FALSE) return FALSE; if (g_at_result_iter_next_string(&iter, &str) == TRUE) l = strtol(str, NULL, 16); else goto out; if (g_at_result_iter_next_string(&iter, &str) == TRUE) c = strtol(str, NULL, 16); else goto out; g_at_result_iter_next_number(&iter, &t); out: if (status) *status = s; if (lac) *lac = l; if (ci) *ci = c; if (tech) *tech = t; return TRUE; }
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 cops_numeric_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; struct netreg_data *nd = ofono_netreg_get_data(cbd->user); ofono_netreg_operator_cb_t cb = cbd->cb; GAtResultIter iter; const char *str; int format; int len; struct ofono_error error; decode_at_error(&error, g_at_result_final_response(result)); if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+COPS:")) goto error; g_at_result_iter_skip_next(&iter); ok = g_at_result_iter_next_number(&iter, &format); if (ok == FALSE || format != 2) goto error; if (g_at_result_iter_next_string(&iter, &str) == FALSE) goto error; len = strspn(str, "0123456789"); if (len != 5 && len != 6) goto error; extract_mcc_mnc(str, nd->mcc, nd->mnc); DBG("Cops numeric got mcc: %s, mnc: %s", nd->mcc, nd->mnc); ok = g_at_chat_send(nd->chat, "AT+COPS=3,0", none_prefix, NULL, NULL, NULL); if (ok) ok = g_at_chat_send(nd->chat, "AT+COPS?", cops_prefix, cops_cb, cbd, NULL); if (ok) return; error: cb(&error, NULL, cbd->data); g_free(cbd); }
static void xgendata_query(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; struct ifx_data *data = ofono_modem_get_data(modem); GAtResultIter iter; const char *gendata; DBG(""); if (!ok) goto error; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+XGENDATA:")) goto error; if (!g_at_result_iter_next_string(&iter, &gendata)) goto error; DBG("\n%s", gendata); /* switch to GSM character set instead of IRA */ g_at_chat_send(data->dlcs[AUX_DLC], "AT+CSCS=\"GSM\"", none_prefix, NULL, NULL, NULL); /* disable UART for power saving */ g_at_chat_send(data->dlcs[AUX_DLC], "AT+XPOW=0,0,0", none_prefix, NULL, NULL, NULL); data->have_sim = FALSE; /* notify that the modem is ready so that pre_sim gets called */ ofono_modem_set_powered(modem, TRUE); g_at_chat_register(data->dlcs[AUX_DLC], "+XSIM:", xsim_notify, FALSE, modem, NULL); /* enable XSIM and XLOCK notifications */ g_at_chat_send(data->dlcs[AUX_DLC], "AT+XSIMSTATE=1", none_prefix, NULL, NULL, NULL); g_at_chat_send(data->dlcs[AUX_DLC], "AT+XSIMSTATE?", xsimstate_prefix, xsimstate_query, modem, NULL); return; error: shutdown_device(data); ofono_modem_set_powered(modem, FALSE); }
static void uipaddr_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; const char *gw = NULL; const char *netmask = NULL; DBG("ok %d", ok); if (!ok) { CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); return; } g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, "+UIPADDR:")) { g_at_result_iter_skip_next(&iter); g_at_result_iter_skip_next(&iter); if (!g_at_result_iter_next_string(&iter, &gw)) break; if (!g_at_result_iter_next_string(&iter, &netmask)) break; } if (gw) ofono_gprs_context_set_ipv4_gateway(gc, gw); if (netmask) ofono_gprs_context_set_ipv4_netmask(gc, netmask); CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); }
static void ifx_xhomezr_notify(GAtResult *result, gpointer user_data) { //struct ofono_netreg *netreg = user_data; const char *label; GAtResultIter iter; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+XHOMEZR:")) return; if (!g_at_result_iter_next_string(&iter, &label)) return; ofono_info("Home zone: %s", label); }
static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_netreg_operator_cb_t cb = cbd->cb; struct ofono_network_operator op; GAtResultIter iter; int format; const char *name; struct ofono_error error; decode_at_error(&error, g_at_result_final_response(result)); if (!ok) { cb(&error, NULL, cbd->data); return; } g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+COPS:")) goto error; g_at_result_iter_skip_next(&iter); ok = g_at_result_iter_next_number(&iter, &format); if (ok == FALSE || format != 0) goto error; if (g_at_result_iter_next_string(&iter, &name) == FALSE) goto error; strncpy(op.name, name, HFP_MAX_OPERATOR_NAME_LENGTH); op.name[HFP_MAX_OPERATOR_NAME_LENGTH] = '\0'; op.mcc[0] = '\0'; op.mnc[0] = '\0'; op.status = 2; op.tech = -1; cb(&error, &op, cbd->data); return; error: CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); }
static void at_csca_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; GAtResultIter iter; ofono_sms_sca_query_cb_t cb = cbd->cb; struct ofono_error error; struct ofono_phone_number sca; const char *number; decode_at_error(&error, g_at_result_final_response(result)); if (!ok) { cb(&error, NULL, cbd->data); return; } g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CSCA:")) goto err; if (!g_at_result_iter_next_string(&iter, &number)) goto err; if (number[0] == '+') { number = number + 1; sca.type = 145; } else { sca.type = 129; } strncpy(sca.number, number, OFONO_MAX_PHONE_NUMBER_LENGTH); sca.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0'; g_at_result_iter_next_number(&iter, &sca.type); DBG("csca_query_cb: %s, %d", sca.number, sca.type); cb(&error, &sca, cbd->data); return; err: CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); }
static void at_cgdcont_read_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; struct gprs_data *gd = ofono_gprs_get_data(gprs); int activated_cid = gd->last_auto_context_id; const char *apn = NULL; GAtResultIter iter; DBG("ok %d", ok); if (!ok) { ofono_warn("Can't read CGDCONT contexts."); return; } g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, "+CGDCONT:")) { int read_cid; if (!g_at_result_iter_next_number(&iter, &read_cid)) break; if (read_cid != activated_cid) continue; /* ignore protocol */ g_at_result_iter_skip_next(&iter); g_at_result_iter_next_string(&iter, &apn); break; } if (apn) ofono_gprs_cid_activated(gprs, activated_cid, apn); else ofono_warn("cid %u: Received activated but no apn present", activated_cid); }
static void ifx_ctzv_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; struct netreg_data *nd = ofono_netreg_get_data(netreg); int year, mon, mday, hour, min, sec; const char *tz, *time; GAtResultIter iter; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CTZV:")) return; if (!g_at_result_iter_next_unquoted_string(&iter, &tz)) return; if (!g_at_result_iter_next_string(&iter, &time)) return; DBG("tz %s time %s", tz, time); if (sscanf(time, "%u/%u/%u,%u:%u:%u", &year, &mon, &mday, &hour, &min, &sec) != 6) return; nd->time.sec = sec; nd->time.min = min; nd->time.hour = hour; nd->time.mday = mday; nd->time.mon = mon; nd->time.year = 2000 + year; if (nd->nitz_timeout > 0) g_source_remove(nd->nitz_timeout); nd->nitz_timeout = g_timeout_add_seconds(1, notify_time, user_data); }
static void cssu_notify(GAtResult *result, gpointer user_data) { struct ofono_ssn *ssn = user_data; GAtResultIter iter; int code2; int index = -1; const char *num; struct ofono_phone_number ph; ph.number[0] = '\0'; ph.type = 129; g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CSSU:")) return; if (!g_at_result_iter_next_number(&iter, &code2)) return; /* This field is optional, if we can't read it, try to skip it */ if (!g_at_result_iter_next_number(&iter, &index) && !g_at_result_iter_skip_next(&iter)) goto out; if (!g_at_result_iter_next_string(&iter, &num)) goto out; strncpy(ph.number, num, OFONO_MAX_PHONE_NUMBER_LENGTH); if (!g_at_result_iter_next_number(&iter, &ph.type)) return; out: ofono_ssn_cssu_notify(ssn, code2, index, &ph); }
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); }
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 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 cgcontrdp_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; const char *laddrnetmask = NULL; const char *gw = NULL; const char *dns[3] = { NULL, NULL, NULL }; char buf[64]; DBG("ok %d", ok); if (!ok) { struct ofono_error error; decode_at_error(&error, g_at_result_final_response(result)); gcd->cb(&error, gcd->cb_data); return; } g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, "+CGCONTRDP:")) { /* skip cid, bearer_id, apn */ g_at_result_iter_skip_next(&iter); g_at_result_iter_skip_next(&iter); g_at_result_iter_skip_next(&iter); if (!g_at_result_iter_next_string(&iter, &laddrnetmask)) break; if (!g_at_result_iter_next_string(&iter, &gw)) break; if (!g_at_result_iter_next_string(&iter, &dns[0])) break; if (!g_at_result_iter_next_string(&iter, &dns[1])) break; } set_gprs_context_interface(gc); if (!laddrnetmask || set_address_and_netmask(gc, laddrnetmask) < 0) { CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); return; } if (gw) ofono_gprs_context_set_ipv4_gateway(gc, gw); if (dns[0]) ofono_gprs_context_set_ipv4_dns_servers(gc, dns); /* * Some older versions of Toby L2 need to issue AT+UIPADDR to get the * the correct gateway and netmask. The newer version will return an * empty ok reply. */ snprintf(buf, sizeof(buf), "AT+UIPADDR=%u", gcd->active_context); if (g_at_chat_send(gcd->chat, buf, uipaddr_prefix, uipaddr_cb, gc, NULL) > 0) return; /* Even if UIPADDR failed, we still have enough data. */ CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); }
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); }