diff options
Diffstat (limited to 'sms.c')
-rw-r--r-- | sms.c | 1041 |
1 files changed, 373 insertions, 668 deletions
@@ -2,7 +2,7 @@ * This file is part of Samsung-RIL. * * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com> - * Copyright (C) 2011-2013 Paul Kocialkowski <contact@paulk.fr> + * Copyright (C) 2011-2014 Paul Kocialkowski <contact@paulk.fr> * * Samsung-RIL is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,18 +18,20 @@ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>. */ -#define LOG_TAG "RIL-SMS" +#include <stdlib.h> + +#define LOG_TAG "RIL" #include <utils/Log.h> -#include "samsung-ril.h" -#include "util.h" +#include <samsung-ril.h> +#include <utils.h> -unsigned short ril2ipc_sms_ack_error(int success, int failcause) +unsigned short ril2ipc_sms_ack(int success, int fail_cause) { if (success) { return IPC_SMS_ACK_NO_ERROR; } else { - switch (failcause) { + switch (fail_cause) { case 0xD3: return IPC_SMS_ACK_PDA_FULL_ERROR; default: @@ -38,25 +40,29 @@ unsigned short ril2ipc_sms_ack_error(int success, int failcause) } } -RIL_Errno ipc2ril_sms_ack_error(unsigned short error, int *error_code) +RIL_Errno ipc2ril_sms_ack_error(unsigned short ack) { - // error_code is defined in See 3GPP 27.005, 3.2.5 for GSM/UMTS - - if (error_code == NULL) - return RIL_E_GENERIC_FAILURE; - - switch (error) { + switch (ack) { case IPC_SMS_ACK_NO_ERROR: - *error_code = -1; return RIL_E_SUCCESS; default: - // unknown error - *error_code = 500; return RIL_E_GENERIC_FAILURE; } } -unsigned char ril2ipc_sms_save_msg_status(int status) +int ipc2ril_sms_ack_error_code(unsigned short ack) +{ + // Error code is defined in 3GPP 27.005, 3.2.5 for GSM/UMTS + + switch (ack) { + case IPC_SMS_ACK_NO_ERROR: + return -1; + default: + return 500; + } +} + +unsigned char ril2ipc_sms_status(int status) { switch (status) { case 0: @@ -68,851 +74,550 @@ unsigned char ril2ipc_sms_save_msg_status(int status) case 3: return IPC_SMS_STATUS_STO_SENT; default: - return IPC_SMS_STATUS_REC_READ; + return 0; } } -/* - * Outgoing SMS functions - */ - -int ril_request_send_sms_register(char *pdu, int pdu_length, unsigned char *smsc, int smsc_length, RIL_Token t) +int ipc_sms_send_msg(struct ipc_message *message) { - struct ril_request_send_sms_info *send_sms; - struct list_head *list_end; - struct list_head *list; + struct ipc_sms_send_msg_response_data *data; + RIL_SMS_Response response; - send_sms = calloc(1, sizeof(struct ril_request_send_sms_info)); - if (send_sms == NULL) + if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_send_msg_response_data)) return -1; - send_sms->pdu = pdu; - send_sms->pdu_length = pdu_length; - send_sms->smsc = smsc; - send_sms->smsc_length = smsc_length; - send_sms->token = t; + if (!ipc_seq_valid(message->aseq)) + return 0; - list_end = ril_data.outgoing_sms; - while (list_end != NULL && list_end->next != NULL) - list_end = list_end->next; + data = (struct ipc_sms_send_msg_response_data *) message->data; - list = list_head_alloc((void *) send_sms, list_end, NULL); + memset(&response, 0, sizeof(response)); + response.messageRef = data->id; + response.ackPDU = NULL; - if (ril_data.outgoing_sms == NULL) - ril_data.outgoing_sms = list; + ril_request_complete(ipc_fmt_request_token(message->aseq), ipc2ril_sms_ack_error(data->ack), &response, sizeof(response)); return 0; } -void ril_request_send_sms_unregister(struct ril_request_send_sms_info *send_sms) -{ - struct list_head *list; - - if (send_sms == NULL) - return; - - list = ril_data.outgoing_sms; - while (list != NULL) { - if (list->data == (void *) send_sms) { - memset(send_sms, 0, sizeof(struct ril_request_send_sms_info)); - free(send_sms); - - if (list == ril_data.outgoing_sms) - ril_data.outgoing_sms = list->next; - - list_head_free(list); - - break; - } -list_continue: - list = list->next; - } -} - -struct ril_request_send_sms_info *ril_request_send_sms_info_find(void) -{ - struct ril_request_send_sms_info *send_sms; - struct list_head *list; - - list = ril_data.outgoing_sms; - while (list != NULL) { - send_sms = (struct ril_request_send_sms_info *) list->data; - if (send_sms == NULL) - goto list_continue; - - return send_sms; - -list_continue: - list = list->next; - } - - return NULL; -} - -struct ril_request_send_sms_info *ril_request_send_sms_info_find_token(RIL_Token t) -{ - struct ril_request_send_sms_info *send_sms; - struct list_head *list; - - list = ril_data.outgoing_sms; - while (list != NULL) { - send_sms = (struct ril_request_send_sms_info *) list->data; - if (send_sms == NULL) - goto list_continue; - - if (send_sms->token == t) - return send_sms; - -list_continue: - list = list->next; - } - - return NULL; -} - -void ril_request_send_sms_info_clear(struct ril_request_send_sms_info *send_sms) -{ - if (send_sms == NULL) - return; - - if (send_sms->pdu != NULL) - free(send_sms->pdu); - - if (send_sms->smsc != NULL) - free(send_sms->smsc); -} - -void ril_request_send_sms_next(void) -{ - struct ril_request_send_sms_info *send_sms; - RIL_Token t; - char *pdu; - int pdu_length; - unsigned char *smsc; - int smsc_length; - int rc; - - ril_data.tokens.outgoing_sms = RIL_TOKEN_NULL; - - send_sms = ril_request_send_sms_info_find(); - if (send_sms == NULL) - return; - - t = send_sms->token; - pdu = send_sms->pdu; - pdu_length = send_sms->pdu_length; - smsc = send_sms->smsc; - smsc_length = send_sms->smsc_length; - - ril_request_send_sms_unregister(send_sms); - - if (pdu == NULL) { - RIL_LOGE("SMS send request has no valid PDU"); - if (smsc != NULL) - free(smsc); - return; - } - - ril_data.tokens.outgoing_sms = t; - if (smsc == NULL) { - // We first need to get SMS SVC before sending the message - RIL_LOGD("We have no SMSC, let's ask one"); - - rc = ril_request_send_sms_register(pdu, pdu_length, NULL, 0, t); - if (rc < 0) { - RIL_LOGE("Unable to add the request to the list"); - - ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - if (pdu != NULL) - free(pdu); - // Send the next SMS in the list - ril_request_send_sms_next(); - } - - ipc_fmt_send_get(IPC_SMS_SVC_CENTER_ADDR, ril_request_get_id(t)); - } else { - ril_request_send_sms_complete(t, pdu, pdu_length, smsc, smsc_length); - if (pdu != NULL) - free(pdu); - if (smsc != NULL) - free(smsc); - } -} - -void ril_request_send_sms_complete(RIL_Token t, char *pdu, int pdu_length, unsigned char *smsc, int smsc_length) +int ril_request_send_sms_complete(unsigned char seq, const void *smsc, + size_t smsc_size, const void *pdu, size_t pdu_size) { - 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; - + struct ipc_sms_send_msg_request_header request_header; + unsigned int count; + unsigned int index; + void *data = NULL; + size_t size = 0; unsigned char *p; + int rc; - 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; + if (smsc == NULL || smsc_size == 0 || pdu == NULL || pdu_size == 0) + return -1; - // Length of the final message - length = sizeof(send_msg) + pdu_hex_length + smsc_length; + if (!ipc_seq_valid(seq)) + return -1; - RIL_LOGD("Sending SMS message (length: 0x%x)!", length); + memset(&request_header, 0, sizeof(request_header)); + request_header.type = IPC_SMS_TYPE_OUTGOING; + request_header.msg_type = IPC_SMS_MSG_TYPE_SINGLE; - pdu_hex = calloc(1, pdu_hex_length); - hex2bin(pdu, pdu_length, pdu_hex); - send_msg_type = IPC_SMS_MSG_SINGLE; + p = (unsigned char *) pdu; - /* PDU operations */ - int pdu_tp_da_index = 2; - unsigned char pdu_tp_da_len = pdu_hex[pdu_tp_da_index]; + // PDU TP-DA length + p += 2; - if (pdu_tp_da_len > 0xff / 2) { - RIL_LOGE("PDU TP-DA Len failed (0x%x)\n", pdu_tp_da_len); - goto pdu_end; + if (*p > (255 / 2)) { + RIL_LOGE("PDU TP-DA length failed (0x%x)", *p); + goto setup; } - RIL_LOGD("PDU TP-DA Len is 0x%x\n", pdu_tp_da_len); + // PDU TP-UDH length + p += *p; - 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; + if (*p > (255 / 2) || *p < 5) { + RIL_LOGE("PDU TP-UDH length failed (0x%x)", *p); + goto setup; } - 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]; + // PDU TO-UDH count + p += 4; + count = (unsigned int) *p; - if (pdu_tp_udh_num > 0xf) { - RIL_LOGE("PDU TP-UDH Num failed (0x%x)\n", pdu_tp_udh_num); - goto pdu_end; + if (count > 0x0f) { + RIL_LOGE("PDU TP-UDH count failed (%d)", count); + goto setup; } - int pdu_tp_udh_seq_index = pdu_tp_udh_index + 5; - unsigned char pdu_tp_udh_seq = pdu_hex[pdu_tp_udh_seq_index]; + // PDU TO-UDH index + p += 1; + index = (unsigned int) *p; - 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; + if (index > count) { + RIL_LOGE("PDU TP-UDH index failed (%d)", index); + goto setup; } - 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; + if (count > 1) { + request_header.msg_type = IPC_SMS_MSG_TYPE_MULTIPLE; + RIL_LOGD("Sending multi-part message %d/%d\n", index, count); } -pdu_end: - // Alloc memory for the final message - data = calloc(1, length); +setup: + size = ipc_sms_send_msg_size_setup(&request_header, smsc, smsc_size, pdu, pdu_size); + if (size == 0) + goto error; - // 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; + data = ipc_sms_send_msg_setup(&request_header, smsc, smsc_size, pdu, pdu_size); + if (data == NULL) + goto error; - // 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); + rc = ipc_gen_phone_res_expect_abort(seq, IPC_SMS_SEND_MSG); + if (rc < 0) + goto error; - ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SMS_SEND_MSG, ipc_sms_send_msg_complete); + rc = ipc_fmt_send(seq, IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, data, size); + if (rc < 0) + goto error; - ipc_fmt_send(IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, data, length, ril_request_get_id(t)); + rc = 0; + goto complete; - free(pdu_hex); - free(data); +error: + rc = -1; - return; +complete: + if (data != NULL && size > 0) + free(data); -error: - ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - // Send the next SMS in the list - ril_request_send_sms_next(); + return rc; } -void ril_request_send_sms(RIL_Token t, void *data, size_t length) +int ril_request_send_sms(void *data, size_t size, RIL_Token token) { - char *pdu = NULL; - int pdu_length; - unsigned char *smsc = NULL; - int smsc_length; + struct ril_request *request; + char **values = NULL; + void *smsc = NULL; + size_t smsc_size = 0; + void *pdu = NULL; + size_t pdu_size = 0; + unsigned int i; int rc; - if (data == NULL || length < (int) (2 * sizeof(char *))) + if (data == NULL || size < 2 * sizeof(char *)) goto error; - if (ril_radio_state_complete(RADIO_STATE_OFF, t)) - return; + rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); + if (rc < 0) + return RIL_REQUEST_UNHANDLED; - pdu = ((char **) data)[1]; - smsc = ((unsigned char **) data)[0]; - pdu_length = 0; - smsc_length = 0; + request = ril_request_find_request_status(RIL_REQUEST_SEND_SMS, RIL_REQUEST_HANDLED); + if (request != NULL) + return RIL_REQUEST_UNHANDLED; - if (pdu != NULL) { - pdu_length = strlen(pdu) + 1; - pdu = strdup(pdu); - } - if (smsc != NULL) { - smsc_length = strlen((char *) smsc); - smsc = (unsigned char *) strdup((char *) smsc); - } + values = (char **) data; + if (values[1] == NULL) + goto error; - if (ril_data.tokens.outgoing_sms != RIL_TOKEN_NULL) { - RIL_LOGD("Another outgoing SMS is being processed, adding to the list"); + pdu_size = string2data_size(values[1]); + if (pdu_size == 0) + goto error; - rc = ril_request_send_sms_register(pdu, pdu_length, smsc, smsc_length, t); - if (rc < 0) { - RIL_LOGE("Unable to add the request to the list"); + pdu = string2data(values[1]); + if (pdu == NULL) + goto error; + + if (values[0] != NULL) { + smsc_size = string2data_size(values[0]); + if (smsc_size == 0) goto error; - } - return; + smsc = string2data(values[0]); + if (smsc == NULL) + goto error; } - ril_data.tokens.outgoing_sms = t; - if (smsc == NULL) { - // We first need to get SMS SVC before sending the message - RIL_LOGD("We have no SMSC, let's ask one"); + strings_array_free(values, size); + values = NULL; - rc = ril_request_send_sms_register(pdu, pdu_length, NULL, 0, t); + if (smsc != NULL && smsc_size > 0) { + rc = ril_request_send_sms_complete(ipc_fmt_request_seq(token), pdu, pdu_size, (void *) ((unsigned char *) smsc + sizeof(unsigned char)), ((unsigned char *) smsc)[0]); + if (rc < 0) + goto error; + } else { + ril_request_data_set_uniq(RIL_REQUEST_SEND_SMS, pdu, pdu_size); + + rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SMS_SVC_CENTER_ADDR, IPC_TYPE_GET, NULL, 0); if (rc < 0) { - RIL_LOGE("Unable to add the request to the list"); + ril_request_data_free(RIL_REQUEST_SEND_SMS); goto error; } - - ipc_fmt_send_get(IPC_SMS_SVC_CENTER_ADDR, ril_request_get_id(t)); - } else { - ril_request_send_sms_complete(t, pdu, pdu_length, smsc, smsc_length); - if (pdu != NULL) - free(pdu); - if (smsc != NULL) - free(smsc); } - return; + rc = RIL_REQUEST_HANDLED; + goto complete; error: - ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); - - if (pdu != NULL) - free(pdu); - if (smsc != NULL) - free(smsc); - // Send the next SMS in the list - ril_request_send_sms_next(); -} - -void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t length) -{ - // No particular treatment here, we already have a queue - ril_request_send_sms(t, data, length); -} + if (values != NULL) + strings_array_free(values, size); -void ipc_sms_svc_center_addr(struct ipc_message_info *info) -{ - struct ril_request_send_sms_info *send_sms; - RIL_Token t; - char *pdu; - int pdu_length; - unsigned char *smsc; - int smsc_length; - int rc; - - if (info->data == NULL || info->length < sizeof(unsigned char)) - goto error; + ril_request_complete(token, RIL_E_SMS_SEND_FAIL_RETRY, NULL, 0); - send_sms = ril_request_send_sms_info_find_token(ril_request_get_token(info->aseq)); - if (send_sms == NULL || send_sms->pdu == NULL || send_sms->pdu_length <= 0) { - RIL_LOGE("The request wasn't queued, reporting generic error!"); + rc = RIL_REQUEST_COMPLETED; - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); - ril_request_send_sms_info_clear(send_sms); - ril_request_send_sms_unregister(send_sms); - // Send the next SMS in the list - ril_request_send_sms_next(); - - return; - } - - t = send_sms->token; - pdu = send_sms->pdu; - pdu_length = send_sms->pdu_length; - smsc = (unsigned char *) info->data + sizeof(unsigned char); - smsc_length = (int) ((unsigned char *) info->data)[0]; +complete: + if (smsc != NULL && smsc_size > 0) + free(smsc); - RIL_LOGD("Got SMSC, completing the request"); - ril_request_send_sms_unregister(send_sms); - ril_request_send_sms_complete(t, pdu, pdu_length, smsc, smsc_length); - if (pdu != NULL) + if (pdu != NULL && pdu_size > 0) free(pdu); - return; - -error: - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); -} - -void ipc_sms_send_msg_complete(struct ipc_message_info *info) -{ - struct ril_request_send_sms_info *send_sms; - struct ipc_gen_phone_res *phone_res; - - phone_res = (struct ipc_gen_phone_res *) info->data; - if (ipc_gen_phone_res_check(phone_res) < 0) { - RIL_LOGE("IPC_GEN_PHONE_RES indicates error, abort request to RILJ"); - - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); - // Send the next SMS in the list - ril_request_send_sms_next(); - } + return rc; } -void ipc_sms_send_msg(struct ipc_message_info *info) +int ipc_sms_incoming_msg(struct ipc_message *message) { - struct ipc_sms_send_msg_response *report_msg; - RIL_SMS_Response response; - RIL_Errno e; + struct ipc_sms_incoming_msg_header *header; + void *pdu; + size_t pdu_size; + char *pdu_string; - if (info->data == NULL || info->length < sizeof(struct ipc_sms_send_msg_response)) - goto error; + if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_incoming_msg_header)) + return -1; - report_msg = (struct ipc_sms_send_msg_response *) info->data; + header = (struct ipc_sms_incoming_msg_header *) message->data; - RIL_LOGD("Got ACK for msg_tpid #%d\n", report_msg->msg_tpid); + pdu_size = ipc_sms_incoming_msg_pdu_size_extract(message->data, message->size); + if (pdu_size == 0) + return 0; - memset(&response, 0, sizeof(response)); - response.messageRef = report_msg->msg_tpid; - response.ackPDU = NULL; + pdu = ipc_sms_incoming_msg_pdu_extract(message->data, message->size); + if (pdu == NULL) + return 0; - e = ipc2ril_sms_ack_error(report_msg->error, &response.errorCode); + pdu_string = data2string(pdu, pdu_size); + if (pdu_string == NULL) + return 0; - ril_request_complete(ril_request_get_token(info->aseq), e, (void *) &response, sizeof(response)); + ril_request_data_set_uniq(RIL_REQUEST_SMS_ACKNOWLEDGE, &header->id, sizeof(header->id)); - // Send the next SMS in the list - ril_request_send_sms_next(); + if (header->type == IPC_SMS_TYPE_STATUS_REPORT) + ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, (void *) pdu_string, sizeof(pdu_string)); + else + ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS, (void *) pdu_string, sizeof(pdu_string)); - return; + free(pdu_string); -error: - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); + return 0; } -/* - * Incoming SMS functions - */ - -int ipc_sms_incoming_msg_register(char *pdu, int length, unsigned char type, unsigned char tpid) +int ipc_sms_save_msg(struct ipc_message *message) { - struct ipc_sms_incoming_msg_info *incoming_msg; - struct list_head *list_end; - struct list_head *list; + struct ipc_sms_save_msg_response_data *data; - incoming_msg = calloc(1, sizeof(struct ipc_sms_incoming_msg_info)); - if (incoming_msg == NULL) + if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_save_msg_response_data)) return -1; - incoming_msg->pdu = pdu; - incoming_msg->length = length; - incoming_msg->type = type; - incoming_msg->tpid = tpid; - - list_end = ril_data.incoming_sms; - while (list_end != NULL && list_end->next != NULL) - list_end = list_end->next; + if (!ipc_seq_valid(message->aseq)) + return 0; - list = list_head_alloc((void *) incoming_msg, list_end, NULL); + data = (struct ipc_sms_save_msg_response_data *) message->data; - if (ril_data.incoming_sms == NULL) - ril_data.incoming_sms = list; + if (data->error) + ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); + else + ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0); return 0; } -void ipc_sms_incoming_msg_unregister(struct ipc_sms_incoming_msg_info *incoming_msg) +int ril_request_write_sms_to_sim(void *data, size_t size, RIL_Token token) { - struct list_head *list; - - if (incoming_msg == NULL) - return; + struct ipc_sms_save_msg_request_header request_header; + RIL_SMS_WriteArgs *args = NULL; + void *smsc = NULL; + size_t smsc_size = 0; + void *pdu = NULL; + size_t pdu_size = 0; + void *request_data = NULL; + size_t request_size = 0; + int rc; - list = ril_data.incoming_sms; - while (list != NULL) { - if (list->data == (void *) incoming_msg) { - memset(incoming_msg, 0, sizeof(struct ipc_sms_incoming_msg_info)); - free(incoming_msg); + if (data == NULL || size < sizeof(RIL_SMS_WriteArgs)) + goto error; - if (list == ril_data.incoming_sms) - ril_data.incoming_sms = list->next; + rc = ril_radio_state_check(RADIO_STATE_SIM_READY); + if (rc < 0) + return RIL_REQUEST_UNHANDLED; - list_head_free(list); + args = (RIL_SMS_WriteArgs *) data; + if (args->pdu == NULL) { + if (args->smsc != NULL) + free(args->smsc); - break; - } -list_continue: - list = list->next; + goto error; } -} -struct ipc_sms_incoming_msg_info *ipc_sms_incoming_msg_info_find(void) -{ - struct ipc_sms_incoming_msg_info *incoming_msg; - struct list_head *list; + memset(&request_header, 0, sizeof(request_header)); + request_header.status = ril2ipc_sms_status(args->status); - list = ril_data.incoming_sms; - while (list != NULL) { - incoming_msg = (struct ipc_sms_incoming_msg_info *) list->data; - if (incoming_msg == NULL) - goto list_continue; + pdu_size = string2data_size(args->pdu); + if (pdu_size == 0) { + free(args->pdu); - return incoming_msg; + if (args->smsc != NULL) + free(args->smsc); -list_continue: - list = list->next; + goto error; } - return NULL; -} - -void ipc_sms_incoming_msg_next(void) -{ - struct ipc_sms_incoming_msg_info *incoming_msg; + pdu = string2data(args->pdu); + if (pdu == NULL) { + free(args->pdu); - ril_data.state.sms_incoming_msg_tpid = 0; + if (args->smsc != NULL) + free(args->smsc); - incoming_msg = ipc_sms_incoming_msg_info_find(); - if (incoming_msg == NULL) - return; + goto error; + } - ipc_sms_incoming_msg_complete(incoming_msg->pdu, incoming_msg->length, incoming_msg->type, incoming_msg->tpid); - ipc_sms_incoming_msg_unregister(incoming_msg); -} + free(args->pdu); -void ipc_sms_incoming_msg_complete(char *pdu, int length, unsigned char type, unsigned char tpid) -{ - if (pdu == NULL || length <= 0) - return; + if (args->smsc == NULL) + goto setup; - ril_data.state.sms_incoming_msg_tpid = tpid; + smsc_size = string2data_size(args->smsc); + if (smsc_size == 0) { + free(args->smsc); - if (type == IPC_SMS_TYPE_POINT_TO_POINT) { - ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS, pdu, length); - } else if (type == IPC_SMS_TYPE_STATUS_REPORT) { - ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, pdu, length); - } else { - RIL_LOGE("Unhandled message type: %x", type); + goto error; } - free(pdu); -} - -void ipc_sms_incoming_msg(struct ipc_message_info *info) -{ - struct ipc_sms_incoming_msg *msg; - unsigned char *pdu_hex; - char *pdu; - int length; - int rc; + smsc = string2data(args->smsc); + if (smsc == NULL) { + free(args->smsc); - if (info->data == NULL || info->length < sizeof(struct ipc_sms_incoming_msg)) goto error; - - msg = (struct ipc_sms_incoming_msg *) info->data; - pdu_hex = ((unsigned char *) info->data + sizeof(struct ipc_sms_incoming_msg)); - - length = msg->length * 2 + 1; - pdu = (char *) calloc(1, length); - - bin2hex(pdu_hex, msg->length, pdu); - - if (ril_data.state.sms_incoming_msg_tpid != 0) { - RIL_LOGD("Another message is waiting ACK, queuing"); - rc = ipc_sms_incoming_msg_register(pdu, length, msg->type, msg->msg_tpid); - if (rc < 0) - RIL_LOGE("Unable to register incoming msg"); - - return; } - ipc_sms_incoming_msg_complete(pdu, length, msg->type, msg->msg_tpid); - - return; - -error: - if (info != NULL) - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); -} - -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; + free(args->smsc); - if (data == NULL || length < 2 * sizeof(int)) +setup: + request_size = ipc_sms_save_msg_size_setup(&request_header, smsc, smsc_size, pdu, pdu_size); + if (request_size == 0) 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; + request_data = ipc_sms_save_msg_setup(&request_header, smsc, smsc_size, pdu, pdu_size); + if (request_data == NULL) + goto error; - success = ((int *) data)[0]; - fail_cause = ((int *) data)[1]; + rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_SMS_SAVE_MSG); + if (rc < 0) + goto error; - if (ril_data.state.sms_incoming_msg_tpid == 0) { - RIL_LOGE("There is no SMS message to ACK!"); + rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SMS_SAVE_MSG, IPC_TYPE_EXEC, request_data, request_size); + if (rc < 0) 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; + rc = RIL_REQUEST_HANDLED; + goto complete; - ipc_gen_phone_res_expect_to_abort(ril_request_get_id(t), IPC_SMS_DELIVER_REPORT); +error: + ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); - ipc_fmt_send(IPC_SMS_DELIVER_REPORT, IPC_TYPE_EXEC, (void *) &report_msg, sizeof(report_msg), ril_request_get_id(t)); + rc = RIL_REQUEST_COMPLETED; - ipc_sms_incoming_msg_next(); +complete: + if (smsc != NULL && smsc_size > 0) + free(smsc); - return; + if (pdu != NULL && pdu_size > 0) + free(pdu); -error: - ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); + if (request_data != NULL && request_size > 0) + free(request_data); - ipc_sms_incoming_msg_next(); + return rc; } -void ipc_sms_deliver_report(struct ipc_message_info *info) +int ipc_sms_del_msg(struct ipc_message *message) { - struct ipc_sms_deliver_report_response *report_msg; - RIL_Errno e; - int error_code; + struct ipc_sms_del_msg_response_data *data; - if (info->data == NULL || info->length < sizeof(struct ipc_sms_deliver_report_response)) - goto error; + if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_del_msg_response_data)) + return -1; - report_msg = (struct ipc_sms_deliver_report_response *) info->data; - e = ipc2ril_sms_ack_error(report_msg->error, &error_code); + if (!ipc_seq_valid(message->aseq)) + return 0; - ril_request_complete(ril_request_get_token(info->aseq), e, NULL, 0); + data = (struct ipc_sms_del_msg_response_data *) message->data; - return; + if (data->error) + ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); + else + ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0); -error: - if (info != NULL) - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); + return 0; } -void ril_request_write_sms_to_sim(RIL_Token token, void *data, size_t size) +int ril_request_delete_sms_on_sim(void *data, size_t size, RIL_Token token) { - 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; + struct ipc_sms_del_msg_request_data request_data; + int index; + int rc; - if (data == NULL || size < sizeof(RIL_SMS_WriteArgs)) + if (data == NULL || size < sizeof(int)) 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) + index = *((int *) data); + if (index == 0) 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; - } + rc = ipc_sms_del_msg_setup(&request_data, (unsigned short) (index - 1)); + if (rc < 0) + goto error; - ipc_gen_phone_res_expect_to_abort(ril_request_get_id(token), IPC_SMS_SAVE_MSG); + rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_SMS_DEL_MSG); + if (rc < 0) + goto error; - ipc_fmt_send(IPC_SMS_SAVE_MSG, IPC_TYPE_EXEC, buffer, length, ril_request_get_id(token)); + rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SMS_DEL_MSG, 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: - if (buffer != NULL) - free(buffer); + return rc; } -void ipc_sms_save_msg(struct ipc_message_info *info) +int ipc_sms_deliver_report(struct ipc_message *message) { - struct ipc_sms_save_msg_response_data *sms_save_msg_response_data; + struct ipc_sms_deliver_report_response_data *data; + RIL_Errno error; - if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_sms_save_msg_response_data)) - return; + if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_deliver_report_response_data)) + return -1; - sms_save_msg_response_data = (struct ipc_sms_save_msg_response_data *) info->data; + if (!ipc_seq_valid(message->aseq)) + return 0; - if (sms_save_msg_response_data->error) - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); - else - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0); + data = (struct ipc_sms_deliver_report_response_data *) message->data; + + error = ipc2ril_sms_ack_error(data->ack); + + ril_request_complete(ipc_fmt_request_token(message->aseq), error, NULL, 0); + + return 0; } -void ril_request_delete_sms_on_sim(RIL_Token token, void *data, size_t size) +int ril_request_sms_acknowledge(void *data, size_t size, RIL_Token token) { - struct ipc_sms_del_msg_request_data sms_del_msg_request_data; - int index = 0; + struct ipc_sms_deliver_report_request_data report_data; + void *id_data; + size_t id_size; + unsigned char id; + int *values; + int rc; - if (data == NULL || size < sizeof(index)) + if (data == NULL || size < 2 * sizeof(int)) goto error; - if (ril_radio_state_complete(RADIO_STATE_OFF, token)) - return; + rc = ril_radio_state_check(RADIO_STATE_SIM_READY); + if (rc < 0) + return RIL_REQUEST_UNHANDLED; - index = *((int *) data); + values = (int *) data; - if (index <= 0 || index > 0xffff) + id_size = ril_request_data_size_get(RIL_REQUEST_SMS_ACKNOWLEDGE); + id_data = ril_request_data_get(RIL_REQUEST_SMS_ACKNOWLEDGE); + + if (id_data == NULL || id_size == 0) { + RIL_LOGE("%s: No SMS left to acknowledge", __func__); 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; + id = *((unsigned char *) id_data); - ipc_gen_phone_res_expect_to_abort(ril_request_get_id(token), IPC_SMS_DEL_MSG); + free(id_data); - 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)); + memset(&report_data, 0, sizeof(report_data)); + report_data.type = IPC_SMS_TYPE_STATUS_REPORT; + report_data.ack = ril2ipc_sms_ack(values[0], values[1]); + report_data.id = id; - return; + rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_SMS_DELIVER_REPORT); + if (rc < 0) + goto error; -error: - ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); -} + rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SMS_DELIVER_REPORT, IPC_TYPE_EXEC, (void *) &report_data, sizeof(report_data)); + if (rc < 0) + goto error; -void ipc_sms_del_msg(struct ipc_message_info *info) -{ - struct ipc_sms_del_msg_response_data *sms_del_msg_response_data; + rc = RIL_REQUEST_HANDLED; + goto complete; - if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_sms_del_msg_response_data)) - return; +error: + ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); - sms_del_msg_response_data = (struct ipc_sms_del_msg_response_data *) info->data; + rc = RIL_REQUEST_COMPLETED; - if (sms_del_msg_response_data->error) - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); - else - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0); +complete: + return rc; } -/* - * RIL SMS - */ - -int ril_sms_send(char *number, char *message) +int ipc_sms_svc_center_addr(struct ipc_message *message) { - char *pdu; - size_t length; + struct ipc_sms_svc_center_addr_header *header; + void *smsc = NULL; + size_t smsc_size = 0; + void *pdu = NULL; + size_t pdu_size = 0; int rc; - pdu = pdu_create(number, message); - if (pdu == NULL) + if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_svc_center_addr_header)) return -1; - length = strlen(pdu); - if (length == 0) - return -1; + if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq)) + return 0; - ril_data.state.ril_sms_tpid = RIL_SMS_TPID; + header = (struct ipc_sms_svc_center_addr_header *) message->data; + if (header->length == 0 || header->length > (message->size - sizeof(struct ipc_sms_svc_center_addr_header))) + goto error; - if (ril_data.state.sms_incoming_msg_tpid != 0) { - RIL_LOGD("Another message is waiting ACK, queuing"); - rc = ipc_sms_incoming_msg_register(pdu, length, IPC_SMS_TYPE_POINT_TO_POINT, ril_data.state.ril_sms_tpid); - if (rc < 0) { - RIL_LOGE("Unable to register incoming msg"); - return -1; - } + pdu_size = ril_request_data_size_get(RIL_REQUEST_SEND_SMS); + if (pdu_size == 0) + goto error; - return 0; - } + pdu = ril_request_data_get(RIL_REQUEST_SEND_SMS); + if (pdu == NULL) + goto error; - ipc_sms_incoming_msg_complete(pdu, length, IPC_SMS_TYPE_POINT_TO_POINT, ril_data.state.ril_sms_tpid); + smsc_size = ipc_sms_svc_center_addr_smsc_size_extract(message->data, message->size); + if (smsc_size == 0) + goto error; - return 0; -} + smsc = ipc_sms_svc_center_addr_smsc_extract(message->data, message->size); + if (smsc == NULL) + goto error; -/* - * Apparently non-SMS-messages-related function - */ + rc = ril_request_send_sms_complete(message->aseq, smsc, smsc_size, pdu, pdu_size); + if (rc < 0) + goto error; -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); - } + goto complete; - ril_tokens_check(); +error: + ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SMS_SEND_FAIL_RETRY, NULL, 0); + +complete: + if (pdu != NULL) + free(pdu); + + return 0; } |