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 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_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 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 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_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 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); }