void ril_request_setup_data_call(RIL_Token t, void *data, int length) { struct ril_gprs_connection *gprs_connection = NULL; struct ipc_client_gprs_capabilities gprs_capabilities; struct ipc_gprs_port_list port_list; struct ipc_client *ipc_client; char *username = NULL; char *password = NULL; char *apn = NULL; ipc_client = ((struct ipc_client_object *) ipc_fmt_client->object)->ipc_client; apn = ((char **) data)[2]; username = ((char **) data)[3]; password = ((char **) data)[4]; LOGD("Requesting data connection to APN '%s'\n", apn); gprs_connection = ril_gprs_connection_add(); if(!gprs_connection) { LOGE("Unable to create GPRS connection, aborting"); RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); return; } gprs_connection->token = t; // Create the structs with the apn ipc_gprs_define_pdp_context_setup(&(gprs_connection->define_context), gprs_connection->cid, 1, apn); // Create the structs with the username/password tuple ipc_gprs_pdp_context_setup(&(gprs_connection->context), gprs_connection->cid, 1, username, password); ipc_client_gprs_get_capabilities(ipc_client, &gprs_capabilities); // If the device has the capability, deal with port list if(gprs_capabilities.port_list) { ipc_gprs_port_list_setup(&port_list); ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_GPRS_PORT_LIST, ipc_gprs_port_list_complete); ipc_fmt_send(IPC_GPRS_PORT_LIST, IPC_TYPE_SET, (void *) &port_list, sizeof(struct ipc_gprs_port_list), reqGetId(t)); } else { ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_GPRS_DEFINE_PDP_CONTEXT, ipc_gprs_define_pdp_context_complete); ipc_fmt_send(IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET, (void *) &(gprs_connection->define_context), sizeof(struct ipc_gprs_define_pdp_context), reqGetId(t)); } }
int ipc_sec_pin_status(struct ipc_message *message) { struct ipc_sec_pin_status_response_data *data; struct ipc_sec_pin_status_request_data request_data; #if RIL_VERSION >= 6 RIL_CardStatus_v6 card_status; #else RIL_CardStatus card_status; #endif RIL_RadioState radio_state; int rc; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_pin_status_response_data)) return -1; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return 0; data = (struct ipc_sec_pin_status_response_data *) message->data; radio_state = ipc2ril_sec_pin_status_response(data, &card_status); if (radio_state == 0) return 0; if (card_status.applications[0].app_type == RIL_APPTYPE_SIM && card_status.applications[0].app_state == RIL_APPSTATE_PIN && ril_data->sim_pin != NULL) { ril_request_data_set_uniq(RIL_REQUEST_GET_SIM_STATUS, (void *) &card_status, sizeof(card_status)); rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, ril_data->sim_pin, NULL); if (rc < 0) { ril_request_data_free(RIL_REQUEST_GET_SIM_STATUS); return 0; } rc = ipc_gen_phone_res_expect_callback(message->aseq, IPC_SEC_PIN_STATUS, ipc_sec_pin_status_callback); if (rc < 0) { ril_request_data_free(RIL_REQUEST_GET_SIM_STATUS); return 0; } rc = ipc_fmt_send(message->aseq, IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) { ril_request_data_free(RIL_REQUEST_GET_SIM_STATUS); return 0; } return 0; } ril_radio_state_update(radio_state); if (message->type == IPC_TYPE_RESP && ipc_seq_valid(message->aseq)) { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &card_status, sizeof(card_status)); } else { ril_request_data_set_uniq(RIL_REQUEST_GET_SIM_STATUS, (void *) &card_status, sizeof(card_status)); ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0); } return 0; }
void srs_snd_set_call_clock_sync(struct srs_message *message) { unsigned char data = *((unsigned char *) message->data); LOGD("Clock sync data is 0x%x\n", data); ipc_fmt_send(IPC_SND_CLOCK_CTRL, IPC_TYPE_EXEC, &data, sizeof(data), reqIdNew()); }
int ril_request_answer(void *data, size_t size, RIL_Token token) { int rc; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_CALL_ANSWER); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_CALL_ANSWER, IPC_TYPE_EXEC, NULL, 0); if (rc < 0) goto error; ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0); rc = RIL_REQUEST_HANDLED; goto complete; error: ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; }
int ril_request_hangup(void *data, size_t size, RIL_Token token) { int hangup; int rc; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; hangup = 1; ril_request_data_set_uniq(RIL_REQUEST_HANGUP, &hangup, sizeof(hangup)); rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_CALL_RELEASE); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_CALL_RELEASE, IPC_TYPE_EXEC, NULL, 0); if (rc < 0) goto error; ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0); rc = RIL_REQUEST_HANDLED; goto complete; error: ril_request_data_free(RIL_REQUEST_HANGUP); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; }
void ril_request_stk_send_terminal_response(RIL_Token t, void *data, size_t length) { unsigned char buffer[264]; int size; if (data == NULL || length < sizeof(char *)) goto error; size = strlen(data) / 2; if (size > 255) { RIL_LOGE("%s: data exceeds maximum length", __func__); goto error; } memset(buffer, 0, sizeof(buffer)); buffer[0] = (unsigned char) size; hex2bin(data, strlen(data), &buffer[1]); ipc_fmt_send(IPC_SAT_PROACTIVE_CMD, IPC_TYPE_GET, buffer, sizeof(buffer), ril_request_get_id(t)); ril_request_complete(t, RIL_E_SUCCESS, buffer, sizeof(char *)); return; error: ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); }
void ril_request_delete_sms_on_sim(RIL_Token token, void *data, size_t size) { struct ipc_sms_del_msg_request_data sms_del_msg_request_data; int index = 0; if (data == NULL || size < sizeof(index)) goto error; if (ril_radio_state_complete(RADIO_STATE_OFF, token)) return; index = *((int *) data); if (index <= 0 || index > 0xffff) goto error; memset(&sms_del_msg_request_data, 0, sizeof(sms_del_msg_request_data)); sms_del_msg_request_data.unknown = 0x02; sms_del_msg_request_data.index = (short) index - 1; ipc_gen_phone_res_expect_to_abort(ril_request_get_id(token), IPC_SMS_DEL_MSG); ipc_fmt_send(IPC_SMS_DEL_MSG, IPC_TYPE_EXEC, (unsigned char *) &sms_del_msg_request_data, sizeof(sms_del_msg_request_data), ril_request_get_id(token)); return; error: ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); }
void ril_request_deactivate_data_call(RIL_Token t, void *data, int length) { struct ril_gprs_connection *gprs_connection; struct ipc_gprs_pdp_context_set context; char *cid = ((char **) data)[0]; int rc; gprs_connection = ril_gprs_connection_get_cid(atoi(cid)); if(!gprs_connection) { LOGE("Unable to find GPRS connection, aborting"); RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); return; } gprs_connection->token = t; ipc_gprs_pdp_context_setup(&context, gprs_connection->cid, 0, NULL, NULL); ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_GPRS_PDP_CONTEXT, ipc_gprs_pdp_context_disable_complete); ipc_fmt_send(IPC_GPRS_PDP_CONTEXT, IPC_TYPE_SET, (void *) &context, sizeof(struct ipc_gprs_pdp_context_set), reqGetId(t)); }
void srs_snd_set_call_audio_path(struct srs_message *message) { int audio_path = ((int *) message->data)[0]; unsigned char path = srs2ipc_audio_path(audio_path); LOGD("Audio path to: 0x%x\n", path); ipc_fmt_send(IPC_SND_AUDIO_PATH_CTRL, IPC_TYPE_SET, (void *) &path, sizeof(path), reqIdNew()); }
void ril_request_set_mute(RIL_Token t, void *data, size_t datalen) { unsigned char mute_data = ((int *)data)[0] > 0 ? 1 : 0; LOGD("Mute data is %d\n", mute_data); ipc_gen_phone_res_expect_to_complete(reqGetId(t), IPC_SND_MIC_MUTE_CTRL); ipc_fmt_send(IPC_SND_MIC_MUTE_CTRL, IPC_TYPE_SET, (void *) &mute_data, sizeof(mute_data), reqGetId(t)); }
void srs_snd_set_call_volume(struct srs_message *message) { struct srs_snd_call_volume *call_volume = (struct srs_snd_call_volume *) message->data; struct ipc_snd_spkr_volume_ctrl volume_ctrl; LOGD("Call volume for: 0x%x vol = 0x%x\n", call_volume->type, call_volume->volume); volume_ctrl.type = srs2ipc_call_type(call_volume->type); volume_ctrl.volume = call_volume->volume; ipc_fmt_send(IPC_SND_SPKR_VOLUME_CTRL, IPC_TYPE_SET, (void *) &volume_ctrl, sizeof(volume_ctrl), reqIdNew()); }
void ipc_sms_device_ready(struct ipc_message_info *info) { #if RIL_VERSION >= 7 if (ril_data.state.radio_state == RADIO_STATE_ON) { #else if (ril_data.state.radio_state == RADIO_STATE_SIM_READY) { #endif ipc_fmt_send(IPC_SMS_DEVICE_READY, IPC_TYPE_SET, NULL, 0, info->aseq); } ril_tokens_check(); }
int ril_request_dial(void *data, size_t size, RIL_Token token) { struct ipc_call_outgoing_data request_data; RIL_Dial *dial = NULL; unsigned char identity; unsigned char prefix; int rc; if (data == NULL || size < sizeof(RIL_Dial)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; dial = (RIL_Dial *) data; if (dial->address == NULL) goto error; identity = ril2ipc_call_identity(dial->clir); prefix = dial->address[0] == '+' ? IPC_CALL_PREFIX_INTL : IPC_CALL_PREFIX_NONE; rc = ipc_call_outgoing_setup(&request_data, IPC_CALL_TYPE_VOICE, identity, prefix, dial->address); if (rc < 0) goto error; free(dial->address); dial = NULL; rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_CALL_OUTGOING); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_CALL_OUTGOING, IPC_TYPE_EXEC, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (dial != NULL && dial->address != NULL) free(dial->address); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; }
void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t length) { struct ipc_sms_deliver_report_request report_msg; int success, fail_cause; if (data == NULL || length < 2 * sizeof(int)) goto error; if (ril_data.state.sms_incoming_msg_tpid == ril_data.state.ril_sms_tpid) { ril_data.state.ril_sms_tpid = 0; ril_request_complete(t, RIL_E_SUCCESS, NULL, 0); ipc_sms_incoming_msg_next(); return; } if (ril_radio_state_complete(RADIO_STATE_OFF, t)) return; success = ((int *) data)[0]; fail_cause = ((int *) data)[1]; if (ril_data.state.sms_incoming_msg_tpid == 0) { RIL_LOGE("There is no SMS message to ACK!"); goto error; } report_msg.type = IPC_SMS_TYPE_STATUS_REPORT; report_msg.error = ril2ipc_sms_ack_error(success, fail_cause); report_msg.msg_tpid = ril_data.state.sms_incoming_msg_tpid; report_msg.unk = 0; ipc_gen_phone_res_expect_to_abort(ril_request_get_id(t), IPC_SMS_DELIVER_REPORT); ipc_fmt_send(IPC_SMS_DELIVER_REPORT, IPC_TYPE_EXEC, (void *) &report_msg, sizeof(report_msg), ril_request_get_id(t)); ipc_sms_incoming_msg_next(); return; error: ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); ipc_sms_incoming_msg_next(); }
int ril_request_radio_power(void *data, size_t size, RIL_Token token) { struct ipc_pwr_phone_state_request_data request_data; struct ril_request *request; int power_state; int rc; if (data == NULL || size < sizeof(power_state)) goto error; request = ril_request_find_request_status(RIL_REQUEST_RADIO_POWER, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; power_state = *((int *)data); memset(&request_data, 0, sizeof(request_data)); if (power_state > 0) { RIL_LOGD("Requesting normal power state"); request_data.state = IPC_PWR_PHONE_STATE_REQUEST_NORMAL; } else { RIL_LOGD("Requesting low power mode power state"); request_data.state = IPC_PWR_PHONE_STATE_REQUEST_LPM; } rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_PWR_PHONE_STATE); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_PWR_PHONE_STATE, IPC_TYPE_EXEC, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; }
int ril_request_get_current_calls(void *data, size_t size, RIL_Token token) { int rc; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) { ril_request_complete(token, RIL_E_SUCCESS, NULL, 0); return RIL_REQUEST_COMPLETED; } rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_CALL_LIST, IPC_TYPE_GET, NULL, 0); if (rc < 0) { ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); return RIL_REQUEST_COMPLETED; } return RIL_REQUEST_HANDLED; }
int ril_request_dtmf_start_complete(unsigned char aseq, char tone) { struct ipc_call_cont_dtmf_data request_data; int rc; memset(&request_data, 0, sizeof(request_data)); request_data.status = IPC_CALL_DTMF_STATUS_START; request_data.tone = tone; rc = ipc_gen_phone_res_expect_complete(aseq, IPC_CALL_CONT_DTMF); if (rc < 0) return -1; rc = ipc_fmt_send(aseq, IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) return -1; return 0; }
void ipc_gprs_port_list_complete(struct ipc_message_info *info) { struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data; struct ril_gprs_connection *gprs_connection; int rc; int aseq; gprs_connection = ril_gprs_connection_get_token(reqGetToken(info->aseq)); if(!gprs_connection) { LOGE("Unable to find GPRS connection, aborting"); RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); return; } rc = ipc_gen_phone_res_check(phone_res); if(rc < 0) { LOGE("There was an error, aborting port list complete"); gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED; gprs_connection->token = (RIL_Token) 0x00; ril_state.gprs_last_failed_cid = gprs_connection->cid; RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); return; } // We need to get a clean new aseq here aseq = ril_request_reg_id(reqGetToken(info->aseq)); ipc_gen_phone_res_expect_to_func(aseq, IPC_GPRS_DEFINE_PDP_CONTEXT, ipc_gprs_define_pdp_context_complete); ipc_fmt_send(IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET, (void *) &(gprs_connection->define_context), sizeof(struct ipc_gprs_define_pdp_context), aseq); }
int ril_request_dtmf_complete(unsigned char aseq, char tone) { struct ipc_call_burst_dtmf_request_entry entry; void *request_data = NULL; size_t request_size = 0; int rc; memset(&entry, 0, sizeof(entry)); entry.status = IPC_CALL_DTMF_STATUS_START; entry.tone = tone; request_size = ipc_call_burst_dtmf_size_setup(&entry, 1); if (request_size == 0) goto error; request_data = ipc_call_burst_dtmf_setup(&entry, 1); if (request_data == NULL) goto error; rc = ipc_gen_phone_res_expect_abort(aseq, IPC_CALL_BURST_DTMF); if (rc < 0) goto error; rc = ipc_fmt_send(aseq, IPC_CALL_BURST_DTMF, IPC_TYPE_EXEC, request_data, request_size); if (rc < 0) goto error; rc = 0; goto complete; error: rc = -1; complete: if (request_data != NULL && request_size > 0) free(request_data); return rc; }
void ril_request_write_sms_to_sim(RIL_Token token, void *data, size_t size) { struct ipc_sms_save_msg_request_data *sms_save_msg_request_data; RIL_SMS_WriteArgs *args; void *buffer = NULL; size_t length; size_t data_length; size_t pdu_length = 0; size_t pdu_hex_length = 0; size_t smsc_length = 0; size_t smsc_hex_length = 0; unsigned char *p; if (data == NULL || size < sizeof(RIL_SMS_WriteArgs)) goto error; if (ril_radio_state_complete(RADIO_STATE_OFF, token)) return; args = (RIL_SMS_WriteArgs *) data; if (args->pdu != NULL) { pdu_length = strlen(args->pdu); pdu_hex_length = pdu_length % 2 == 0 ? pdu_length / 2 : (pdu_length ^ 1) / 2; } if (args->smsc != NULL) { smsc_length = strlen(args->smsc); smsc_hex_length = smsc_length % 2 == 0 ? smsc_length / 2 : (smsc_length ^ 1) / 2; } data_length = pdu_hex_length + smsc_hex_length; if (data_length == 0 || data_length > 0xff) goto error; length = sizeof(struct ipc_sms_save_msg_request_data) + data_length; buffer = malloc(length); sms_save_msg_request_data = (struct ipc_sms_save_msg_request_data *) buffer; memset(sms_save_msg_request_data, 0, sizeof(struct ipc_sms_save_msg_request_data)); sms_save_msg_request_data->unknown = 0x02; sms_save_msg_request_data->index = 12 - 1; sms_save_msg_request_data->status = ril2ipc_sms_save_msg_status(args->status); sms_save_msg_request_data->length = (unsigned char) (data_length & 0xff); p = (unsigned char *) buffer + sizeof(struct ipc_sms_save_msg_request_data); if (args->smsc != NULL && smsc_length > 0) { hex2bin(args->smsc, smsc_length, p); p += smsc_hex_length; } if (args->pdu != NULL && pdu_length > 0) { hex2bin(args->pdu, pdu_length, p); p += pdu_hex_length; } ipc_gen_phone_res_expect_to_abort(ril_request_get_id(token), IPC_SMS_SAVE_MSG); ipc_fmt_send(IPC_SMS_SAVE_MSG, IPC_TYPE_EXEC, buffer, length, ril_request_get_id(token)); goto complete; error: ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); complete: if (buffer != NULL) free(buffer); }
void ril_request_send_sms_complete(RIL_Token t, char *pdu, int pdu_length, unsigned char *smsc, int smsc_length) { struct ipc_sms_send_msg_request send_msg; unsigned char send_msg_type; unsigned char *pdu_hex; int pdu_hex_length; void *data; int length; unsigned char *p; if (pdu == NULL || pdu_length <= 0 || smsc == NULL || smsc_length <= 0) goto error; if ((pdu_length / 2 + smsc_length) > 0xfe) { RIL_LOGE("PDU or SMSC too large, aborting"); goto error; } pdu_hex_length = pdu_length % 2 == 0 ? pdu_length / 2 : (pdu_length ^ 1) / 2; // Length of the final message length = sizeof(send_msg) + pdu_hex_length + smsc_length; RIL_LOGD("Sending SMS message (length: 0x%x)!", length); pdu_hex = calloc(1, pdu_hex_length); hex2bin(pdu, pdu_length, pdu_hex); send_msg_type = IPC_SMS_MSG_SINGLE; /* PDU operations */ int pdu_tp_da_index = 2; unsigned char pdu_tp_da_len = pdu_hex[pdu_tp_da_index]; if (pdu_tp_da_len > 0xff / 2) { RIL_LOGE("PDU TP-DA Len failed (0x%x)\n", pdu_tp_da_len); goto pdu_end; } RIL_LOGD("PDU TP-DA Len is 0x%x\n", pdu_tp_da_len); int pdu_tp_udh_index = pdu_tp_da_index + pdu_tp_da_len; unsigned char pdu_tp_udh_len = pdu_hex[pdu_tp_udh_index]; if (pdu_tp_udh_len > 0xff / 2 || pdu_tp_udh_len < 5) { RIL_LOGE("PDU TP-UDH Len failed (0x%x)\n", pdu_tp_udh_len); goto pdu_end; } RIL_LOGD("PDU TP-UDH Len is 0x%x\n", pdu_tp_udh_len); int pdu_tp_udh_num_index = pdu_tp_udh_index + 4; unsigned char pdu_tp_udh_num = pdu_hex[pdu_tp_udh_num_index]; if (pdu_tp_udh_num > 0xf) { RIL_LOGE("PDU TP-UDH Num failed (0x%x)\n", pdu_tp_udh_num); goto pdu_end; } int pdu_tp_udh_seq_index = pdu_tp_udh_index + 5; unsigned char pdu_tp_udh_seq = pdu_hex[pdu_tp_udh_seq_index]; if (pdu_tp_udh_seq > 0xf || pdu_tp_udh_seq > pdu_tp_udh_num) { RIL_LOGE("PDU TP-UDH Seq failed (0x%x)\n", pdu_tp_udh_seq); goto pdu_end; } RIL_LOGD("We are sending message %d on %d\n", pdu_tp_udh_seq, pdu_tp_udh_num); if (pdu_tp_udh_num > 1) { RIL_LOGD("We are sending a multi-part message!"); send_msg_type = IPC_SMS_MSG_MULTIPLE; } pdu_end: // Alloc memory for the final message data = calloc(1, length); // Clear and fill the IPC structure part of the message memset(&send_msg, 0, sizeof(struct ipc_sms_send_msg_request)); send_msg.type = IPC_SMS_TYPE_OUTGOING; send_msg.msg_type = send_msg_type; send_msg.length = (unsigned char) (pdu_hex_length + smsc_length + 1); send_msg.smsc_len = smsc_length; // Copy the parts of the message p = data; memcpy(p, &send_msg, sizeof(send_msg)); p += sizeof(send_msg); memcpy(p, smsc, smsc_length); p += smsc_length; memcpy(p, pdu_hex, pdu_hex_length); ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SMS_SEND_MSG, ipc_sms_send_msg_complete); ipc_fmt_send(IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, data, length, ril_request_get_id(t)); free(pdu_hex); free(data); return; error: ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); // Send the next SMS in the list ril_request_send_sms_next(); }
int ril_request_get_sim_status(void *data, size_t size, RIL_Token token) { void *card_status_data; size_t card_status_size; #if RIL_VERSION >= 6 RIL_CardStatus_v6 *card_status; #else RIL_CardStatus *card_status; #endif struct ril_request *request; int rc; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_GET_SIM_STATUS, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; card_status_size = ril_request_data_size_get(RIL_REQUEST_GET_SIM_STATUS); card_status_data = ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS); #if RIL_VERSION >= 6 if (card_status_data != NULL && card_status_size >= sizeof(RIL_CardStatus_v6)) { card_status = (RIL_CardStatus_v6 *) ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS); #else if (card_status_data != NULL && card_status_size >= sizeof(RIL_CardStatus)) { card_status = (RIL_CardStatus *) ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS); #endif ril_request_complete(token, RIL_E_SUCCESS, card_status_data, card_status_size); free(card_status_data); return RIL_REQUEST_COMPLETED; } else { rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_GET, NULL, 0); if (rc < 0) { ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); return RIL_REQUEST_COMPLETED; } return RIL_REQUEST_HANDLED; } } int ipc_sec_phone_lock(struct ipc_message *message) { struct ipc_sec_phone_lock_response_data *data; int active; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_phone_lock_response_data)) return -1; if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq)) return 0; data = (struct ipc_sec_phone_lock_response_data *) message->data; active = !!data->active; ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &active, sizeof(active)); return 0; } int ril_request_query_facility_lock(void *data, size_t size, RIL_Token token) { struct ipc_sec_phone_lock_request_get_data request_data; char **values = NULL; int rc; if (data == NULL || size < 4 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; values = (char **) data; request_data.facility_type = ril2ipc_sec_facility_type(values[0]); if (request_data.facility_type == 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ipc_sec_callback(struct ipc_message *message) { struct ipc_sec_lock_infomation_request_data request_data; struct ipc_gen_phone_res_data *data; struct ril_request *request = NULL; void *request_complete_data; size_t request_complete_size; unsigned char facility_type; char **values; int retry_count; int rc; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data)) return -1; data = (struct ipc_gen_phone_res_data *) message->data; request = ril_request_find_token(ipc_fmt_request_token(message->aseq)); if (request == NULL) goto error; if (request->request == RIL_REQUEST_ENTER_SIM_PIN || request->request == RIL_REQUEST_CHANGE_SIM_PIN) { // Grab the count of remaining tries before completing the request ril_request_data_set_uniq(request->request, (void *) data, sizeof(struct ipc_gen_phone_res_data)); rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1); if (rc < 0) { ril_request_data_free(request->request); goto error; } rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data)); if (rc < 0) { ril_request_data_free(request->request); goto error; } } else if (request->request == RIL_REQUEST_ENTER_SIM_PIN2 || request->request == RIL_REQUEST_CHANGE_SIM_PIN2) { // Grab the count of remaining tries before completing the request ril_request_data_set_uniq(request->request, (void *) data, sizeof(struct ipc_gen_phone_res_data)); rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2); if (rc < 0) { ril_request_data_free(request->request); goto error; } rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data)); if (rc < 0) { ril_request_data_free(request->request); goto error; } } else if (request->request == RIL_REQUEST_SET_FACILITY_LOCK) { values = (char **) request->data; request_complete_size = ril_request_data_size_get(RIL_REQUEST_SET_FACILITY_LOCK); request_complete_data = ril_request_data_get(RIL_REQUEST_SET_FACILITY_LOCK); rc = ipc_gen_phone_res_check(data); if (request_complete_data != NULL && request_complete_size > 0 && rc >= 0) { rc = ipc_gen_phone_res_expect_callback(message->aseq, IPC_SEC_PHONE_LOCK, ipc_sec_callback); if (rc < 0) { strings_array_free(values, request->size); goto error; } rc = ipc_fmt_send(message->aseq, IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, request_complete_data, request_complete_size); if (rc < 0) { strings_array_free(values, request->size); goto error; } } else { // When FD facility PIN2 unlock failed, ask the count of remaining tries directly facility_type = ril2ipc_sec_facility_type(values[0]); strings_array_free(values, request->size); // Grab the count of remaining tries before completing the request ril_request_data_set_uniq(RIL_REQUEST_SET_FACILITY_LOCK, (void *) data, sizeof(struct ipc_gen_phone_res_data)); if (facility_type == IPC_SEC_FACILITY_TYPE_FD) { rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2); if (rc < 0) { ril_request_data_free(request->request); goto error; } } else { rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1); if (rc < 0) { ril_request_data_free(request->request); goto error; } } rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data)); if (rc < 0) { ril_request_data_free(request->request); goto error; } } } else if (request->request == RIL_REQUEST_SIM_IO) { request_complete_size = ril_request_data_size_get(RIL_REQUEST_SIM_IO); request_complete_data = ril_request_data_get(RIL_REQUEST_SIM_IO); rc = ipc_gen_phone_res_check(data); if (rc < 0) { ril_request_complete(request->token, RIL_E_SIM_PIN2, NULL, 0); goto complete; } if (request_complete_data != NULL && request_complete_size > 0) { rc = ipc_fmt_send(message->aseq, IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, request_complete_data, request_complete_size); if (rc < 0) goto error; } else { goto error; } } else { retry_count = -1; rc = ipc_gen_phone_res_check(data); if (rc < 0) { if ((data->code & 0xff) == 0x10) { RIL_LOGE("%s: Wrong password", __func__); ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count)); } else if ((data->code & 0xff) == 0x0c) { RIL_LOGE("%s: Wrong password and no attempts left", __func__); retry_count = 0; ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count)); } else { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, &retry_count, sizeof(retry_count)); } } else { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &retry_count, sizeof(retry_count)); } } if (request->request == RIL_REQUEST_ENTER_SIM_PUK || request->request == RIL_REQUEST_ENTER_SIM_PUK2) ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0); goto complete; error: if (request != NULL) ril_request_complete(request->token, RIL_E_GENERIC_FAILURE, NULL, 0); complete: return 0; } int ril_request_set_facility_lock(void *data, size_t size, RIL_Token token) { struct ipc_sec_phone_lock_request_set_data request_data; struct ipc_sec_pin_status_request_data pin_request_data; struct ril_request *request; unsigned char facility_type; unsigned char active; char **values = NULL; int rc; if (data == NULL || size < 4 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_SET_FACILITY_LOCK, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; facility_type = ril2ipc_sec_facility_type(values[0]); if (facility_type == 0) goto error; active = values[1][0] == '1'; rc = ipc_sec_phone_lock_request_set_setup(&request_data, facility_type, active, values[2]); if (rc < 0) goto error; if (facility_type == IPC_SEC_FACILITY_TYPE_FD) { // FD facility requires PIN2 unlock first rc = ipc_sec_pin_status_setup(&pin_request_data, IPC_SEC_PIN_TYPE_PIN2, values[2], NULL); if (rc < 0) goto error; ril_request_data_set_uniq(RIL_REQUEST_SET_FACILITY_LOCK, &request_data, sizeof(request_data)); rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) { ril_request_data_free(RIL_REQUEST_SET_FACILITY_LOCK); goto error; } rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &pin_request_data, sizeof(pin_request_data)); if (rc < 0) { ril_request_data_free(RIL_REQUEST_SET_FACILITY_LOCK); goto error; } rc = RIL_REQUEST_HANDLED; goto complete; } rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_enter_sim_pin(void *data, size_t size, RIL_Token token) { struct ipc_sec_pin_status_request_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 2 * sizeof(char *) || ril_data == NULL) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PIN, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; if (values[0] == NULL) goto error; if (ril_data->sim_pin != NULL) free(ril_data->sim_pin); ril_data->sim_pin = strdup(values[0]); rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, values[0], NULL); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_enter_sim_puk(void *data, size_t size, RIL_Token token) { struct ipc_sec_pin_status_request_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 2 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PUK, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, values[1], values[0]); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_enter_sim_pin2(void *data, size_t size, RIL_Token token) { struct ipc_sec_pin_status_request_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 2 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PIN2, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2, values[0], NULL); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_enter_sim_puk2(void *data, size_t size, RIL_Token token) { struct ipc_sec_pin_status_request_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 2 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PUK2, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2, values[1], values[0]); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_change_sim_pin(void *data, size_t size, RIL_Token token) { struct ipc_sec_change_locking_pw_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 3 * sizeof(char *)) goto error; request = ril_request_find_request_status(RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_change_locking_pw_setup(&request_data, IPC_SEC_FACILITY_TYPE_SC, values[0], values[1]); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_change_sim_pin2(void *data, size_t size, RIL_Token token) { struct ipc_sec_change_locking_pw_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 3 * sizeof(char *)) goto error; request = ril_request_find_request_status(RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_change_locking_pw_setup(&request_data, IPC_SEC_FACILITY_TYPE_FD, values[0], values[1]); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ipc_sec_rsim_access(struct ipc_message *message) { struct ipc_sec_rsim_access_response_header *header; struct ipc_sec_rsim_access_usim_response_header *usim_header; struct sim_file_response sim_file_response; struct ril_request *request; struct ril_client *client; struct ipc_fmt_data *ipc_fmt_data; RIL_SIM_IO_Response response; #if RIL_VERSION >= 6 RIL_SIM_IO_v6 *sim_io; #else RIL_SIM_IO *sim_io; #endif unsigned char *p; unsigned int offset; unsigned int i; void *data; size_t size; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_rsim_access_response_header)) return -1; client = ril_client_find_id(RIL_CLIENT_IPC_FMT); if (client == NULL || client->data == NULL) return 0; if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq)) return 0; ipc_fmt_data = (struct ipc_fmt_data *) client->data; header = (struct ipc_sec_rsim_access_response_header *) message->data; size = ipc_sec_rsim_access_size_extract(message->data, message->size); data = ipc_sec_rsim_access_extract(message->data, message->size); request = ril_request_find_token(ipc_fmt_request_token(message->aseq)); #if RIL_VERSION >= 6 if (request == NULL || request->data == NULL || request->size < sizeof(RIL_SIM_IO_v6)) #else if (request == NULL || request->data == NULL || request->size < sizeof(RIL_SIM_IO)) #endif return 0; #if RIL_VERSION >= 6 sim_io = (RIL_SIM_IO_v6 *) request->data; #else sim_io = (RIL_SIM_IO *) request->data; #endif memset(&response, 0, sizeof(response)); response.sw1 = header->sw1; response.sw2 = header->sw2; switch (sim_io->command) { case SIM_COMMAND_READ_BINARY: case SIM_COMMAND_READ_RECORD: if (header->length == 0) break; response.simResponse = data2string(data, header->length); break; case SIM_COMMAND_GET_RESPONSE: if (header->length == 0) break; if (ipc_fmt_data->sim_icc_type_data.type == 0x01) { response.simResponse = data2string(data, header->length); break; } if (header->length < sizeof(struct ipc_sec_rsim_access_usim_response_header)) break; usim_header = (struct ipc_sec_rsim_access_usim_response_header *) data; memset(&sim_file_response, 0, sizeof(sim_file_response)); offset = sizeof(struct ipc_sec_rsim_access_usim_response_header) + usim_header->offset; if (offset > header->length) break; offset = usim_header->offset - 2; p = (unsigned char *) usim_header + offset; sim_file_response.file_id[0] = p[0]; sim_file_response.file_id[1] = p[1]; offset = header->length - 2; p = (unsigned char *) usim_header; while (offset > 2) { if (p[offset] == 0x88) { offset -= 2; break; } offset--; } if (offset <= 2) break; p = (unsigned char *) usim_header + offset; sim_file_response.file_size[0] = p[0]; sim_file_response.file_size[1] = p[1]; // Fallback to EF sim_file_response.file_type = SIM_FILE_TYPE_EF; for (i = 0; i < sim_file_ids_count; i++) { if (sim_io->fileid == sim_file_ids[i].file_id) { sim_file_response.file_type = sim_file_ids[i].type; break; } } sim_file_response.access_condition[0] = 0x00; sim_file_response.access_condition[1] = 0xff; sim_file_response.access_condition[2] = 0xff; sim_file_response.file_status = 0x01; sim_file_response.file_length = 0x02; switch (usim_header->file_structure) { case IPC_SEC_RSIM_FILE_STRUCTURE_TRANSPARENT: sim_file_response.file_structure = SIM_FILE_STRUCTURE_TRANSPARENT; break; case IPC_SEC_RSIM_FILE_STRUCTURE_LINEAR_FIXED: default: sim_file_response.file_structure = SIM_FILE_STRUCTURE_LINEAR_FIXED; break; } sim_file_response.record_length = usim_header->length; response.simResponse = data2string((void *) &sim_file_response, sizeof(sim_file_response)); break; case SIM_COMMAND_UPDATE_BINARY: case SIM_COMMAND_UPDATE_RECORD: case SIM_COMMAND_SEEK: default: response.simResponse = NULL; break; } ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &response, sizeof(response)); if (response.simResponse != NULL) free(response.simResponse); return 0; } int ril_request_sim_io(void *data, size_t size, RIL_Token token) { struct ipc_sec_rsim_access_request_header request_header; struct ipc_sec_pin_status_request_data pin_request_data; struct ril_request *request; #if RIL_VERSION >= 6 RIL_SIM_IO_v6 *sim_io = NULL; #else RIL_SIM_IO *sim_io = NULL; #endif void *sim_io_data = NULL; size_t sim_io_size = 0; void *request_data = NULL; size_t request_size = 0; int pin_request = 0; int rc; #if RIL_VERSION >= 6 if (data == NULL || size < sizeof(RIL_SIM_IO_v6)) #else if (data == NULL || size < sizeof(RIL_SIM_IO)) #endif goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_SIM_IO, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; #if RIL_VERSION >= 6 sim_io = (RIL_SIM_IO_v6 *) data; #else sim_io = (RIL_SIM_IO *) data; #endif if (sim_io->data != NULL) { sim_io_size = string2data_size(sim_io->data); if (sim_io_size == 0) goto error; sim_io_data = string2data(sim_io->data); if (sim_io_data == NULL) goto error; } if (sim_io->pin2 != NULL) { // PIN2 unlock first pin_request = 1; rc = ipc_sec_pin_status_setup(&pin_request_data, IPC_SEC_PIN_TYPE_PIN2, sim_io->pin2, NULL); if (rc < 0) goto error; } if (sim_io->path != NULL) free(sim_io->path); if (sim_io->data != NULL) free(sim_io->data); if (sim_io->pin2 != NULL) free(sim_io->pin2); #if RIL_VERSION >= 6 if (sim_io->aidPtr != NULL) free(sim_io->aidPtr); #endif memset(&request_header, 0, sizeof(request_header)); request_header.command = sim_io->command; request_header.file_id = sim_io->fileid; request_header.p1 = sim_io->p1; request_header.p2 = sim_io->p2; request_header.p3 = sim_io->p3; sim_io = NULL; request_size = ipc_sec_rsim_access_size_setup(&request_header, sim_io_data, sim_io_size); if (request_size == 0) goto error; request_data = ipc_sec_rsim_access_setup(&request_header, sim_io_data, sim_io_size); if (request_data == NULL) goto error; if (pin_request) { // PIN2 unlock first ril_request_data_set_uniq(RIL_REQUEST_SIM_IO, request_data, request_size); rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) { ril_request_data_free(RIL_REQUEST_SIM_IO); goto error; } rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &pin_request_data, sizeof(pin_request_data)); if (rc < 0) { ril_request_data_free(RIL_REQUEST_SIM_IO); goto error; } rc = RIL_REQUEST_HANDLED; goto complete; } rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, request_data, request_size); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (sim_io != NULL) { if (sim_io->path != NULL) free(sim_io->path); if (sim_io->data != NULL) free(sim_io->data); if (sim_io->pin2 != NULL) free(sim_io->pin2); #if RIL_VERSION >= 6 if (sim_io->aidPtr != NULL) free(sim_io->aidPtr); #endif } ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: if (sim_io_data != NULL && sim_io_size > 0) free(sim_io_data); if (request_data != NULL && request_size > 0) free(request_data); return rc; } int ipc_sec_sim_icc_type(struct ipc_message *message) { struct ipc_sec_sim_icc_type_data *data; struct ril_client *client; struct ipc_fmt_data *ipc_fmt_data; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_sim_icc_type_data)) return -1; client = ril_client_find_id(RIL_CLIENT_IPC_FMT); if (client == NULL || client->data == NULL) return 0; ipc_fmt_data = (struct ipc_fmt_data *) client->data; data = (struct ipc_sec_sim_icc_type_data *) message->data; if (ipc_fmt_data->sim_icc_type_data.type != data->type) ipc_fmt_data->sim_icc_type_data.type = data->type; return 0; } int ipc_sec_lock_infomation(struct ipc_message *message) { struct ipc_sec_lock_infomation_response_data *data; struct ipc_gen_phone_res_data *gen_phone_res; int requests[] = { RIL_REQUEST_ENTER_SIM_PIN, RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_ENTER_SIM_PIN2, RIL_REQUEST_CHANGE_SIM_PIN2, RIL_REQUEST_SET_FACILITY_LOCK }; void *gen_phone_res_data = NULL; size_t gen_phone_res_size = 0; int retry_count; unsigned int count; unsigned int i; int rc; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_lock_infomation_response_data)) return -1; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return 0; if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq)) return 0; data = (struct ipc_sec_lock_infomation_response_data *) message->data; if (data->type != IPC_SEC_PIN_TYPE_PIN1 && data->type != IPC_SEC_PIN_TYPE_PIN2) return 0; count = sizeof(requests) / sizeof(int); for (i = 0; i < count; i++) { gen_phone_res_size = ril_request_data_size_get(requests[i]); if (gen_phone_res_size < sizeof(struct ipc_gen_phone_res_data)) continue; gen_phone_res_data = ril_request_data_get(requests[i]); if (gen_phone_res_data == NULL) continue; break; } if (gen_phone_res_data == NULL || gen_phone_res_size < sizeof(struct ipc_gen_phone_res_data)) return 0; gen_phone_res = (struct ipc_gen_phone_res_data *) gen_phone_res_data; retry_count = data->retry_count; rc = ipc_gen_phone_res_check(gen_phone_res); if (rc < 0) { if ((gen_phone_res->code & 0xff) == 0x10) { RIL_LOGE("%s: Wrong password and %d attempts left", __func__, retry_count); ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count)); } else if ((gen_phone_res->code & 0xff) == 0x0c) { RIL_LOGE("%s: Wrong password and no attempts left", __func__); retry_count = 0; ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count)); } else { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, &retry_count, sizeof(retry_count)); } } else { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &retry_count, sizeof(retry_count)); } free(gen_phone_res_data); return 0; }