static void ril_sim_update_binary(struct ofono_sim *sim, int fileid, int start, int length, const unsigned char *value, const unsigned char *path, unsigned int path_len, ofono_sim_write_cb_t cb, void *data) { struct sim_data *sd = ofono_sim_get_data(sim); struct cb_data *cbd = cb_data_new(cb, data, sd); char *hex_path; struct parcel rilp; char *hex_data; int p1, p2; DBG("file 0x%04x", fileid); hex_path = get_path(g_ril_vendor(sd->ril), sd->app_type, fileid, path, path_len); if (hex_path == NULL) { ofono_error("Couldn't build SIM read info request - NULL path"); goto error; } p1 = start >> 8; p2 = start & 0xff; hex_data = encode_hex(value, length, 0); parcel_init(&rilp); parcel_w_int32(&rilp, CMD_UPDATE_BINARY); parcel_w_int32(&rilp, fileid); parcel_w_string(&rilp, hex_path); parcel_w_int32(&rilp, p1); /* P1 */ parcel_w_int32(&rilp, p2); /* P2 */ parcel_w_int32(&rilp, length); /* P3 (Lc) */ parcel_w_string(&rilp, hex_data); /* data */ parcel_w_string(&rilp, NULL); /* pin2; only for FDN/BDN */ parcel_w_string(&rilp, sd->aid_str); /* AID (Application ID) */ /* sessionId, specific to latest MTK modems (harmless for older ones) */ if (g_ril_vendor(sd->ril) == OFONO_RIL_VENDOR_MTK) parcel_w_int32(&rilp, 0); g_ril_append_print_buf(sd->ril, "(cmd=0x%02X,efid=0x%04X,path=%s," "%d,%d,%d,%s,pin2=(null),aid=%s),", CMD_UPDATE_BINARY, fileid, hex_path, p1, p2, length, hex_data, sd->aid_str); g_free(hex_path); g_free(hex_data); if (g_ril_send(sd->ril, RIL_REQUEST_SIM_IO, &rilp, ril_file_write_cb, cbd, g_free) > 0) return; error: g_free(cbd); CALLBACK_WITH_FAILURE(cb, data); }
static void ril_sim_read_binary(struct ofono_sim *sim, int fileid, int start, int length, const unsigned char *path, unsigned int path_len, ofono_sim_read_cb_t cb, void *data) { struct sim_data *sd = ofono_sim_get_data(sim); struct cb_data *cbd = cb_data_new(cb, data, sd); char *hex_path; struct parcel rilp; DBG("file %04x", fileid); hex_path = get_path(g_ril_vendor(sd->ril), sd->app_type, fileid, path, path_len); if (hex_path == NULL) { ofono_error("Couldn't build SIM read info request - NULL path"); goto error; } parcel_init(&rilp); parcel_w_int32(&rilp, CMD_READ_BINARY); parcel_w_int32(&rilp, fileid); parcel_w_string(&rilp, hex_path); parcel_w_int32(&rilp, start >> 8); /* P1 */ parcel_w_int32(&rilp, start & 0xff); /* P2 */ parcel_w_int32(&rilp, length); /* P3 */ parcel_w_string(&rilp, NULL); /* data; only req'd for writes */ parcel_w_string(&rilp, NULL); /* pin2; only req'd for writes */ parcel_w_string(&rilp, sd->aid_str); /* sessionId, specific to latest MTK modems (harmless for older ones) */ if (g_ril_vendor(sd->ril) == OFONO_RIL_VENDOR_MTK) parcel_w_int32(&rilp, 0); g_ril_append_print_buf(sd->ril, "(cmd=0x%.2X,efid=0x%.4X,path=%s," "%d,%d,%d,(null),pin2=(null),aid=%s)", CMD_READ_BINARY, fileid, hex_path, start >> 8, start & 0xff, length, sd->aid_str); g_free(hex_path); if (g_ril_send(sd->ril, RIL_REQUEST_SIM_IO, &rilp, ril_file_io_cb, cbd, g_free) > 0) return; error: g_free(cbd); CALLBACK_WITH_FAILURE(cb, NULL, 0, data); }
static void set_data_reg_state(GRil *gril, struct reply_data_reg_state *reply, int i, const char *str) { unsigned val; char *endp; if (str == NULL || *str == '\0') goto no_val; val = (unsigned) strtoul(str, &endp, 10); if (*endp != '\0') goto no_val; switch (i) { case RDST_IX_MAXDC: /* * MTK modem does not return max_cids, string for this index * actually contains the maximum data bearer capability. */ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) reply->max_cids = MTK_MODEM_MAX_CIDS; else reply->max_cids = val; g_ril_append_print_buf(gril, "%s%u", print_buf, val); break; default: goto no_val; } return; no_val: g_ril_append_print_buf(gril, "%s%s", print_buf, str ? str : "(null)"); }
int g_ril_unsol_parse_connected(GRil *gril, const struct ril_msg *message) { struct parcel rilp; int size; int version; DBG(""); g_ril_init_parcel(message, &rilp); size = parcel_r_int32(&rilp); version = parcel_r_int32(&rilp); /* * For something that looks like a bug we get an extra int in mtk2 * modems. RIL version is the second integer in this case. This * happens when we get duplicated connected events, which should * not happen either. In these cases the first event has the right * size, but not those appearing after. */ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK2 && size > 1) version = parcel_r_int32(&rilp); if (rilp.malformed) { ofono_error("%s: malformed parcel", __func__); version = RIL_VERSION_UNSPECIFIED; } g_ril_append_print_buf(gril, "{size: %d, [%d]}", size, version); g_ril_print_unsol(gril, message); return version; }
void g_ril_request_set_initial_attach_apn(GRil *gril, const char *apn, int proto, const char *user, const char *passwd, const char *mccmnc, struct parcel *rilp) { const char *proto_str; const int auth_type = RIL_AUTH_ANY; parcel_init(rilp); parcel_w_string(rilp, apn); proto_str = ril_ofono_protocol_to_ril_string(proto); parcel_w_string(rilp, proto_str); parcel_w_int32(rilp, auth_type); parcel_w_string(rilp, user); parcel_w_string(rilp, passwd); g_ril_append_print_buf(gril, "(%s,%s,%s,%s,%s", apn, proto_str, ril_authtype_to_string(auth_type), user, passwd); if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) { parcel_w_string(rilp, mccmnc); g_ril_append_print_buf(gril, "%s,%s)", print_buf, mccmnc); } else { g_ril_append_print_buf(gril, "%s)", print_buf); } }
gboolean g_ril_request_sim_read_record(GRil *gril, const struct req_sim_read_record *req, struct parcel *rilp) { parcel_init(rilp); parcel_w_int32(rilp, CMD_READ_RECORD); parcel_w_int32(rilp, req->fileid); g_ril_append_print_buf(gril, "(cmd=0x%.2X,efid=0x%.4X,", CMD_READ_RECORD, req->fileid); if (set_path(gril, req->app_type, rilp, req->fileid, req->path, req->path_len) == FALSE) goto error; parcel_w_int32(rilp, req->record); /* P1 */ parcel_w_int32(rilp, 4); /* P2 */ parcel_w_int32(rilp, req->length); /* P3 */ parcel_w_string(rilp, NULL); /* data; only req'd for writes */ parcel_w_string(rilp, NULL); /* pin2; only req'd for writes */ parcel_w_string(rilp, req->aid_str); /* AID (Application ID) */ /* sessionId, specific to latest MTK modems (harmless for older ones) */ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) parcel_w_int32(rilp, 0); return TRUE; error: return FALSE; }
static void ril_ussd_notify(struct ril_msg *message, gpointer user_data) { struct ofono_ussd *ussd = user_data; struct ussd_data *ud = ofono_ussd_get_data(ussd); struct parcel rilp; int numstr; char *typestr; int type; char *str = NULL; gsize written; char *ucs2; g_ril_init_parcel(message, &rilp); numstr = parcel_r_int32(&rilp); if (numstr < 1) return; typestr = parcel_r_string(&rilp); if (typestr == NULL || *typestr == '\0') return; type = *typestr - '0'; g_free(typestr); if (numstr > 1) str = parcel_r_string(&rilp); g_ril_append_print_buf(ud->ril, "{%d,%s}", type, str); g_ril_print_unsol(ud->ril, message); /* To fix bug in MTK: USSD-Notify arrive with type 2 instead of 0 */ if (g_ril_vendor(ud->ril) == OFONO_RIL_VENDOR_MTK && str != NULL && type == 2) type = 0; if (str == NULL) { ofono_ussd_notify(ussd, type, 0, NULL, 0); return; } /* * With data coding scheme 0x48, we are saying that the ussd string is a * UCS-2 string, uncompressed, and with unspecified message class. For * the DCS coding, see 3gpp 23.038, sect. 5. */ ucs2 = g_convert(str, -1, "UCS-2BE//TRANSLIT", "UTF-8", NULL, &written, NULL); g_free(str); if (ucs2 == NULL) { ofono_error("%s: Error transcoding", __func__); return; } ofono_ussd_notify(ussd, type, 0x48, (unsigned char *) ucs2, written); g_free(ucs2); }
int g_ril_reply_parse_get_preferred_network_type(GRil *gril, const struct ril_msg *message) { struct parcel rilp; int numint, parcel_net_type, net_type; g_ril_init_parcel(message, &rilp); numint = parcel_r_int32(&rilp); if (numint != 1) { ofono_error("%s: Wrong format", __func__); goto error; } parcel_net_type = parcel_r_int32(&rilp); net_type = parcel_net_type; /* Try to translate special MTK settings */ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) { switch (net_type) { /* 4G preferred */ case MTK_PREF_NET_TYPE_LTE_GSM_WCDMA: case MTK_PREF_NET_TYPE_LTE_GSM_WCDMA_MMDC: case MTK_PREF_NET_TYPE_LTE_GSM_TYPE: case MTK_PREF_NET_TYPE_LTE_GSM_MMDC_TYPE: net_type = PREF_NET_TYPE_LTE_GSM_WCDMA; break; /* 3G or 2G preferred over LTE */ case MTK_PREF_NET_TYPE_GSM_WCDMA_LTE: case MTK_PREF_NET_TYPE_GSM_WCDMA_LTE_MMDC: net_type = PREF_NET_TYPE_GSM_WCDMA; break; } } if (net_type < 0 || net_type > PREF_NET_TYPE_LTE_ONLY) { ofono_error("%s: unknown network type", __func__); goto error; } if (rilp.malformed) { ofono_error("%s: malformed parcel", __func__); goto error; } g_ril_append_print_buf(gril, "{%d}", parcel_net_type); g_ril_print_response(gril, message); return net_type; error: return -1; }
gboolean g_ril_request_sim_write_binary(GRil *gril, const struct req_sim_write_binary *req, struct parcel *rilp) { char *hex_data; int p1, p2; parcel_init(rilp); parcel_w_int32(rilp, CMD_UPDATE_BINARY); parcel_w_int32(rilp, req->fileid); g_ril_append_print_buf(gril, "(cmd=0x%02X,efid=0x%04X,", CMD_UPDATE_BINARY, req->fileid); if (set_path(gril, req->app_type, rilp, req->fileid, req->path, req->path_len) == FALSE) goto error; p1 = req->start >> 8; p2 = req->start & 0xff; hex_data = encode_hex(req->data, req->length, 0); parcel_w_int32(rilp, p1); /* P1 */ parcel_w_int32(rilp, p2); /* P2 */ parcel_w_int32(rilp, req->length); /* P3 (Lc) */ parcel_w_string(rilp, hex_data); /* data */ parcel_w_string(rilp, NULL); /* pin2; only for FDN/BDN */ parcel_w_string(rilp, req->aid_str); /* AID (Application ID) */ /* sessionId, specific to latest MTK modems (harmless for older ones) */ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) parcel_w_int32(rilp, 0); g_ril_append_print_buf(gril, "%s%d,%d,%d,%s,pin2=(null),aid=%s)", print_buf, p1, p2, req->length, hex_data, req->aid_str); g_free(hex_data); return TRUE; error: return FALSE; }
gboolean g_ril_request_sim_read_info(GRil *gril, const struct req_sim_read_info *req, struct parcel *rilp) { parcel_init(rilp); parcel_w_int32(rilp, CMD_GET_RESPONSE); parcel_w_int32(rilp, req->fileid); g_ril_append_print_buf(gril, "(cmd=0x%.2X,efid=0x%.4X,", CMD_GET_RESPONSE, req->fileid); if (set_path(gril, req->app_type, rilp, req->fileid, req->path, req->path_len) == FALSE) goto error; parcel_w_int32(rilp, 0); /* P1 */ parcel_w_int32(rilp, 0); /* P2 */ /* * TODO: review parameters values used by Android. * The values of P1-P3 in this code were based on * values used by the atmodem driver impl. * * NOTE: * GET_RESPONSE_EF_SIZE_BYTES == 15; !255 */ parcel_w_int32(rilp, 15); /* P3 - max length */ parcel_w_string(rilp, NULL); /* data; only req'd for writes */ parcel_w_string(rilp, NULL); /* pin2; only req'd for writes */ parcel_w_string(rilp, req->aid_str); /* AID (Application ID) */ /* * sessionId, specific to latest MTK modems (harmless for older ones). * It looks like this field selects one or another SIM application, but * we use only one at a time so using zero here seems safe. */ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) parcel_w_int32(rilp, 0); return TRUE; error: return FALSE; }
static void ril_ussd_notify(struct ril_msg *message, gpointer user_data) { struct ofono_ussd *ussd = user_data; struct ussd_data *ud = ofono_ussd_get_data(ussd); struct unsol_ussd *unsol; enum ofono_ril_vendor vendor; unsol = g_ril_unsol_parse_ussd(ud->ril, message); if (unsol == NULL) { ofono_error("%s: Parsing error", __func__); return; } /* To fix bug in MTK: USSD-Notify arrive with type 2 instead of 0 */ vendor = g_ril_vendor(ud->ril); if ((vendor == OFONO_RIL_VENDOR_MTK || vendor == OFONO_RIL_VENDOR_MTK2) && unsol->message != NULL && unsol->type == 2) unsol->type = 0; /* * With data coding scheme 0x48, we are saying that the ussd string is a * UCS-2 string, uncompressed, and with unspecified message class. For * the DCS coding, see 3gpp 23.038, sect. 5. */ if (unsol->message != NULL) { gsize written; char *ucs2; ucs2 = g_convert(unsol->message, -1, "UCS-2BE//TRANSLIT", "UTF-8", NULL, &written, NULL); if (ucs2 != NULL) { ofono_ussd_notify(ussd, unsol->type, 0x48, (unsigned char *) ucs2, written); g_free(ucs2); } else { ofono_error("%s: Error transcoding", __func__); } } else { ofono_ussd_notify(ussd, unsol->type, 0, NULL, 0); } g_ril_unsol_free_ussd(unsol); }
static void set_reg_state(GRil *gril, struct reply_reg_state *reply, int i, const char *str) { int val; char *endp; int base; const char *strstate; if (str == NULL || *str == '\0') goto no_val; if (i == RST_IX_LAC || i == RST_IX_CID) base = 16; else base = 10; val = (int) strtol(str, &endp, base); if (*endp != '\0') goto no_val; switch (i) { case RST_IX_STATE: switch (val) { case RIL_REG_STATE_NOT_REGISTERED: case RIL_REG_STATE_REGISTERED: case RIL_REG_STATE_SEARCHING: case RIL_REG_STATE_DENIED: case RIL_REG_STATE_UNKNOWN: case RIL_REG_STATE_ROAMING: /* Only valid values for ofono */ strstate = registration_status_to_string(val); break; case RIL_REG_STATE_EMERGENCY_NOT_REGISTERED: case RIL_REG_STATE_EMERGENCY_SEARCHING: case RIL_REG_STATE_EMERGENCY_DENIED: case RIL_REG_STATE_EMERGENCY_UNKNOWN: /* Map to states valid for ofono core */ val -= RIL_REG_STATE_EMERGENCY_NOT_REGISTERED; strstate = str; break; default: val = NETWORK_REGISTRATION_STATUS_UNKNOWN; strstate = str; } reply->status = val; g_ril_append_print_buf(gril, "%s%s", print_buf, strstate); break; case RST_IX_LAC: reply->lac = val; g_ril_append_print_buf(gril, "%s0x%x", print_buf, val); break; case RST_IX_CID: reply->ci = val; g_ril_append_print_buf(gril, "%s0x%x", print_buf, val); break; case RST_IX_RAT: g_ril_append_print_buf(gril, "%s%s", print_buf, ril_radio_tech_to_string(val)); if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) { switch (val) { case MTK_RADIO_TECH_HSDPAP: case MTK_RADIO_TECH_HSDPAP_UPA: case MTK_RADIO_TECH_HSUPAP: case MTK_RADIO_TECH_HSUPAP_DPA: val = RADIO_TECH_HSPAP; break; case MTK_RADIO_TECH_DC_DPA: val = RADIO_TECH_HSDPA; break; case MTK_RADIO_TECH_DC_UPA: val = RADIO_TECH_HSUPA; break; case MTK_RADIO_TECH_DC_HSDPAP: case MTK_RADIO_TECH_DC_HSDPAP_UPA: case MTK_RADIO_TECH_DC_HSDPAP_DPA: case MTK_RADIO_TECH_DC_HSPAP: val = RADIO_TECH_HSPAP; break; } } reply->tech = val; break; default: goto no_val; } return; no_val: g_ril_append_print_buf(gril, "%s%s", print_buf, str ? str : "(null)"); }
int *g_ril_reply_parse_retries(GRil *gril, const struct ril_msg *message, enum ofono_sim_password_type passwd_type) { struct parcel rilp; int i, numint; int *retries = g_try_malloc0(sizeof(int) * OFONO_SIM_PASSWORD_INVALID); if (retries == NULL) { ofono_error("%s: out of memory", __func__); goto no_data; } for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; ++i) retries[i] = -1; g_ril_init_parcel(message, &rilp); /* maguro/infineon: no data is returned */ if (parcel_data_avail(&rilp) == 0) goto no_data; numint = parcel_r_int32(&rilp); switch (g_ril_vendor(gril)) { case OFONO_RIL_VENDOR_AOSP: case OFONO_RIL_VENDOR_QCOM_MSIM: /* * The number of retries is valid only when a wrong password has * been introduced in Nexus 4. TODO: check Nexus 5 behaviour. */ if (message->error == RIL_E_PASSWORD_INCORRECT) retries[passwd_type] = parcel_r_int32(&rilp); g_ril_append_print_buf(gril, "{%d}", retries[passwd_type]); break; case OFONO_RIL_VENDOR_MTK: /* * Some versions of MTK modem return just the retries for the * password just entered while others return the retries for all * passwords. */ if (numint == 1) { retries[passwd_type] = parcel_r_int32(&rilp); g_ril_append_print_buf(gril, "{%d}", retries[passwd_type]); } else if (numint == 4) { retries[OFONO_SIM_PASSWORD_SIM_PIN] = parcel_r_int32(&rilp); retries[OFONO_SIM_PASSWORD_SIM_PIN2] = parcel_r_int32(&rilp); retries[OFONO_SIM_PASSWORD_SIM_PUK] = parcel_r_int32(&rilp); retries[OFONO_SIM_PASSWORD_SIM_PUK2] = parcel_r_int32(&rilp); g_ril_append_print_buf(gril, "{pin %d, pin2 %d, puk %d, puk2 %d}", retries[OFONO_SIM_PASSWORD_SIM_PIN], retries[OFONO_SIM_PASSWORD_SIM_PIN2], retries[OFONO_SIM_PASSWORD_SIM_PUK], retries[OFONO_SIM_PASSWORD_SIM_PUK2]); } else { ofono_error("%s: wrong format", __func__); goto no_data; } break; case OFONO_RIL_VENDOR_INFINEON: ofono_error("%s: infineon type should not arrive here", __func__); g_assert(FALSE); break; } if (rilp.malformed) { ofono_error("%s: malformed parcel", __func__); goto no_data; } g_ril_print_response(gril, message); return retries; no_data: g_free(retries); return NULL; }
gboolean g_ril_request_setup_data_call(GRil *gril, const struct req_setup_data_call *req, struct parcel *rilp, struct ofono_error *error) { const gchar *protocol_str; gchar *tech_str; gchar *auth_str; gchar *profile_str; int num_param = SETUP_DATA_CALL_PARAMS; DBG(""); if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) num_param = SETUP_DATA_CALL_PARAMS + 1; /* * Radio technology to use: 0-CDMA, 1-GSM/UMTS, 2... * values > 2 are (RADIO_TECH + 2) */ if (req->tech < 1 || req->tech > (RADIO_TECH_GSM + 2)) { ofono_error("%s: Invalid tech value: %d", __func__, req->tech); goto error; } /* * TODO(OEM): This code doesn't currently support * OEM data profiles. If a use case exist, then * this code will need to be modified. */ switch (req->data_profile) { case RIL_DATA_PROFILE_DEFAULT: profile_str = DATA_PROFILE_DEFAULT_STR; break; case RIL_DATA_PROFILE_TETHERED: profile_str = DATA_PROFILE_TETHERED_STR; break; case RIL_DATA_PROFILE_IMS: profile_str = DATA_PROFILE_IMS_STR; break; case RIL_DATA_PROFILE_FOTA: profile_str = DATA_PROFILE_FOTA_STR; break; case RIL_DATA_PROFILE_CBS: profile_str = DATA_PROFILE_CBS_STR; break; case RIL_DATA_PROFILE_MTK_MMS: if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) { profile_str = DATA_PROFILE_MTK_MMS_STR; break; } default: ofono_error("%s, invalid data_profile value: %d", __func__, req->data_profile); goto error; } if (req->apn == NULL) goto error; if (req->auth_type > RIL_AUTH_BOTH) { ofono_error("%s: Invalid auth type: %d", __func__, req->auth_type); goto error; } protocol_str = ril_ofono_protocol_to_ril_string(req->protocol); if (protocol_str == NULL) { ofono_error("%s: Invalid protocol: %d", __func__, req->protocol); goto error; } parcel_init(rilp); parcel_w_int32(rilp, num_param); tech_str = g_strdup_printf("%d", req->tech); parcel_w_string(rilp, tech_str); parcel_w_string(rilp, profile_str); parcel_w_string(rilp, req->apn); parcel_w_string(rilp, req->username); parcel_w_string(rilp, req->password); auth_str = g_strdup_printf("%d", req->auth_type); parcel_w_string(rilp, auth_str); parcel_w_string(rilp, protocol_str); g_ril_append_print_buf(gril, "(%s,%s,%s,%s,%s,%s,%s", tech_str, profile_str, req->apn, req->username, req->password, auth_str, protocol_str); if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) { /* MTK request_cid parameter */ char cid_str[MAX_CID_DIGITS + 1]; snprintf(cid_str, sizeof(cid_str), "%u", req->req_cid); parcel_w_string(rilp, cid_str); g_ril_append_print_buf(gril, "%s,%s", print_buf, cid_str); } g_ril_append_print_buf(gril, "%s)", print_buf); g_free(tech_str); g_free(auth_str); OFONO_NO_ERROR(error); return TRUE; error: OFONO_EINVAL(error); return FALSE; }
struct reply_avail_ops *g_ril_reply_parse_avail_ops(GRil *gril, const struct ril_msg *message) { struct parcel rilp; struct reply_operator *operator; struct reply_avail_ops *reply = NULL; unsigned int num_ops, num_strings; unsigned int i; int strings_per_opt; if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) strings_per_opt = 5; else strings_per_opt = 4; /* * Minimum message length is 4: * - array size */ if (message->buf_len < 4) { ofono_error("%s: invalid QUERY_AVAIL_NETWORKS reply: " "size too small (< 4): %d ", __func__, (int) message->buf_len); goto error; } g_ril_init_parcel(message, &rilp); g_ril_append_print_buf(gril, "{"); /* Number of operators at the list */ num_strings = (unsigned int) parcel_r_int32(&rilp); if (num_strings % strings_per_opt) { ofono_error("%s: invalid QUERY_AVAIL_NETWORKS reply: " "num_strings (%d) MOD %d != 0", __func__, num_strings, strings_per_opt); goto error; } num_ops = num_strings / strings_per_opt; DBG("noperators = %d", num_ops); reply = g_try_new0(struct reply_avail_ops, 1); if (reply == NULL) { ofono_error("%s: can't allocate reply struct", __func__); goto error; } reply->num_ops = num_ops; for (i = 0; i < num_ops; i++) { operator = g_try_new0(struct reply_operator, 1); if (operator == NULL) { ofono_error("%s: can't allocate reply struct", __func__); goto error; } operator->lalpha = parcel_r_string(&rilp); operator->salpha = parcel_r_string(&rilp); operator->numeric = parcel_r_string(&rilp); operator->status = parcel_r_string(&rilp); /* * MTK: additional string with technology: 2G/3G are the only * valid values currently. */ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) { char *tech = parcel_r_string(&rilp); if (strcmp(tech, "3G") == 0) operator->tech = RADIO_TECH_UMTS; else operator->tech = RADIO_TECH_GSM; g_free(tech); } else { operator->tech = RADIO_TECH_GSM; } if (operator->lalpha == NULL && operator->salpha == NULL) { ofono_error("%s: operator (%s) doesn't specify names", operator->numeric, __func__); g_ril_reply_free_operator(operator); continue; } if (operator->numeric == NULL) { ofono_error("%s: operator (%s/%s) " "doesn't specify numeric", operator->lalpha, operator->salpha, __func__); g_ril_reply_free_operator(operator); continue; } if (operator->status == NULL) { ofono_error("%s: operator (%s/%s) " "doesn't specify status", operator->lalpha, operator->salpha, __func__); g_ril_reply_free_operator(operator); continue; } reply->list = g_slist_append(reply->list, operator); g_ril_append_print_buf(gril, "%s [lalpha=%s, salpha=%s, " " numeric=%s status=%s tech=%s]", print_buf, operator->lalpha, operator->salpha, operator->numeric, operator->status, ril_radio_tech_to_string(operator->tech)); } g_ril_append_print_buf(gril, "%s}", print_buf); g_ril_print_response(gril, message); return reply; error: if (reply) g_ril_reply_free_avail_ops(reply); return NULL; }
static void ril_sim_read_info(struct ofono_sim *sim, int fileid, const unsigned char *path, unsigned int path_len, ofono_sim_file_info_cb_t cb, void *data) { struct sim_data *sd = ofono_sim_get_data(sim); struct cb_data *cbd = cb_data_new(cb, data, sd); struct parcel rilp; char *hex_path; DBG("file %04x", fileid); hex_path = get_path(g_ril_vendor(sd->ril), sd->app_type, fileid, path, path_len); if (hex_path == NULL) { ofono_error("Couldn't build SIM read info request - NULL path"); goto error; } parcel_init(&rilp); parcel_w_int32(&rilp, CMD_GET_RESPONSE); parcel_w_int32(&rilp, fileid); parcel_w_string(&rilp, hex_path); parcel_w_int32(&rilp, 0); /* P1 */ parcel_w_int32(&rilp, 0); /* P2 */ /* * TODO: review parameters values used by Android. * The values of P1-P3 in this code were based on * values used by the atmodem driver impl. * * NOTE: * GET_RESPONSE_EF_SIZE_BYTES == 15; !255 */ parcel_w_int32(&rilp, 15); /* P3 - max length */ parcel_w_string(&rilp, NULL); /* data; only req'd for writes */ parcel_w_string(&rilp, NULL); /* pin2; only req'd for writes */ parcel_w_string(&rilp, sd->aid_str); /* AID (Application ID) */ /* * sessionId, specific to latest MTK modems (harmless for older ones). * It looks like this field selects one or another SIM application, but * we use only one at a time so using zero here seems safe. */ if (g_ril_vendor(sd->ril) == OFONO_RIL_VENDOR_MTK) parcel_w_int32(&rilp, 0); g_ril_append_print_buf(sd->ril, "(cmd=0x%.2X,efid=0x%.4X,path=%s," "0,0,15,(null),pin2=(null),aid=%s)", CMD_GET_RESPONSE, fileid, hex_path, sd->aid_str); g_free(hex_path); if (g_ril_send(sd->ril, RIL_REQUEST_SIM_IO, &rilp, ril_file_info_cb, cbd, g_free) > 0) return; error: g_free(cbd); CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, data); }
static gboolean set_path(GRil *ril, guint app_type, struct parcel *rilp, const int fileid, const guchar *path, const guint path_len) { unsigned char db_path[6] = { 0x00 }; unsigned char *comm_path = db_path; char *hex_path = NULL; int len = 0; if (path_len > 0 && path_len < 7) { memcpy(db_path, path, path_len); len = path_len; } else if (app_type == RIL_APPTYPE_USIM) { len = sim_ef_db_get_path_3g(fileid, db_path); } else if (app_type == RIL_APPTYPE_SIM) { len = sim_ef_db_get_path_2g(fileid, db_path); } else { ofono_error("Unsupported app_type: 0%x", app_type); return FALSE; } /* * db_path contains the ID of the MF, but MediaTek modems return an * error if we do not remove it. Other devices work the other way * around: they need the MF in the path. In fact MTK behaviour seem to * be the right one: to have the MF in the file is forbidden following * ETSI TS 102 221, section 8.4.2 (we are accessing the card in mode * "select by path from MF", see 3gpp 27.007, +CRSM). */ if (g_ril_vendor(ril) == OFONO_RIL_VENDOR_MTK && len >= (int) ROOTMF_SZ && memcmp(db_path, ROOTMF, ROOTMF_SZ) == 0) { comm_path = db_path + ROOTMF_SZ; len -= ROOTMF_SZ; } if (len > 0) { hex_path = encode_hex(comm_path, len, 0); parcel_w_string(rilp, hex_path); g_ril_append_print_buf(ril, "%spath=%s,", print_buf, hex_path); g_free(hex_path); } else { /* * The only known case of this is EFPHASE_FILED (0x6FAE). * The ef_db table ( see /src/simutil.c ) entry for * EFPHASE contains a value of 0x0000 for it's * 'parent3g' member. This causes a NULL path to * be returned. * (EF_PHASE does not exist for USIM) */ parcel_w_string(rilp, NULL); g_ril_append_print_buf(ril, "%spath=(null),", print_buf); } return TRUE; }