summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gen.c21
-rw-r--r--pwr.c1
-rw-r--r--samsung-ril.c22
-rw-r--r--samsung-ril.h45
-rw-r--r--sms.c577
5 files changed, 559 insertions, 107 deletions
diff --git a/gen.c b/gen.c
index 6140ec8..0a3d8d0 100644
--- a/gen.c
+++ b/gen.c
@@ -24,6 +24,10 @@
#include "samsung-ril.h"
#include "util.h"
+/**
+ * GEN global vars
+ */
+
struct ipc_gen_phone_res_expect ipc_gen_phone_res_expects[0x20];
int ipc_gen_phone_res_id = 0;
@@ -46,6 +50,15 @@ int ipc_gen_phone_res_id = 0;
* aseq = ril_request_reg_id(reqGetToken(info->aseq));
*/
+/**
+ * GEN expects functions
+ */
+
+void ipc_gen_phone_res_expects_init(void)
+{
+ memset(ipc_gen_phone_res_expects, 0, sizeof(struct ipc_gen_phone_res_expect) * 0x20);
+}
+
int ipc_gen_phone_res_id_new(void)
{
ipc_gen_phone_res_id++;
@@ -107,6 +120,14 @@ void ipc_gen_phone_res_expect_to_abort(unsigned char aseq, unsigned short comman
ipc_gen_phone_res_expects[id].to_abort = 1;
}
+/**
+ * GEN dequeue function
+ */
+
+/**
+ * In: IPC_GEN_PHONE_RES
+ * Check the ipc_gen_phone_res_expects queue and act accordingly
+ */
void ipc_gen_phone_res(struct ipc_message_info *info)
{
struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
diff --git a/pwr.c b/pwr.c
index 2c96fe9..ef26cdf 100644
--- a/pwr.c
+++ b/pwr.c
@@ -109,6 +109,7 @@ void ril_request_radio_power(RIL_Token t, void *data, size_t datalen)
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
/* We're not going to get any message to make sure we're in LPM so tell RILJ we're off anyway */
+ ril_globals_init();
ril_state_lpm();
RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
}
diff --git a/samsung-ril.c b/samsung-ril.c
index 4e63995..5e57dac 100644
--- a/samsung-ril.c
+++ b/samsung-ril.c
@@ -49,8 +49,7 @@
* - add MIC_MUTE from RILJ
*
* SMS-related:
- * - stabilize SMS
- * - SMS ret isn't NULL (tpid)
+ * - Add support for multiple-messages SMS
*
* Data-related:
* - find a reliable way to configure data iface
@@ -78,6 +77,11 @@ struct ril_state ril_state;
struct ril_request_token ril_requests_tokens[0x100];
int ril_request_id = 0;
+void ril_requests_tokens_init(void)
+{
+ memset(ril_requests_tokens, 0, sizeof(struct ril_request_token) * 0x100);
+}
+
int ril_request_id_new(void)
{
ril_request_id++;
@@ -463,9 +467,19 @@ const char *getVersion(void)
* RIL init function
*/
-void ril_state_lpm(void)
+void ril_globals_init(void)
{
memset(&ril_state, 0, sizeof(ril_state));
+ memset(&(ril_state.tokens), 0, sizeof(struct ril_tokens));
+
+ ril_requests_tokens_init();
+ ipc_gen_phone_res_expects_init();
+ ril_request_sms_init();
+ ipc_sms_tpid_queue_init();
+}
+
+void ril_state_lpm(void)
+{
ril_state.radio_state = RADIO_STATE_OFF;
ril_state.power_mode = POWER_MODE_LPM;
}
@@ -486,8 +500,8 @@ const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **a
ril_env = env;
+ ril_globals_init();
ril_state_lpm();
- memset(&(ril_state.tokens), 0, sizeof(struct ril_tokens));
ipc_fmt:
LOGD("Creating IPC FMT client");
diff --git a/samsung-ril.h b/samsung-ril.h
index c4e60a6..42b1305 100644
--- a/samsung-ril.h
+++ b/samsung-ril.h
@@ -114,7 +114,7 @@ struct ril_request_token {
int canceled;
};
-int ril_request_id_new(void);
+void ril_requests_tokens_init(void);
int ril_request_reg_id(RIL_Token token);
int ril_request_get_id(RIL_Token token);
RIL_Token ril_request_get_token(int id);
@@ -137,8 +137,6 @@ struct ril_tokens {
RIL_Token registration_state;
RIL_Token gprs_registration_state;
RIL_Token operator;
-
- RIL_Token send_sms;
};
void ril_tokens_check(void);
@@ -179,11 +177,9 @@ struct ril_state {
struct ipc_net_current_plmn plmndata;
struct ipc_gprs_pdp_context gprs_context;
-
- unsigned char msg_tpid_lock;
- char *msg_pdu;
};
+void ril_globals_init(void);
void ril_state_lpm(void);
int ril_modem_check(void);
@@ -205,6 +201,7 @@ struct ipc_gen_phone_res_expect {
int to_abort;
};
+void ipc_gen_phone_res_expects_init(void);
void ipc_gen_phone_res_expect_to_func(unsigned char aseq, unsigned short command,
void (*func)(struct ipc_message_info *info));
void ipc_gen_phone_res_expect_to_complete(unsigned char aseq, unsigned short command);
@@ -262,13 +259,43 @@ void ril_request_set_preffered_network_type(RIL_Token t, void *data, size_t data
void ipc_net_mode_sel(struct ipc_message_info *info);
/* SMS */
-void ipc_sms_incoming_msg(struct ipc_message_info *info);
-void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t datalen);
-void ipc_sms_deliver_report(struct ipc_message_info *info);
+struct ril_request_sms {
+ char *pdu;
+ unsigned char pdu_len;
+ char *smsc;
+ unsigned char smsc_len;
+
+ unsigned char aseq;
+};
+
+void ril_request_sms_init(void);
+void ril_request_sms_del(int id);
+void ril_request_sms_clear(int id);
+int ril_request_sms_add(unsigned char aseq,
+ char *pdu, unsigned char pdu_len,
+ char *smsc, unsigned char smsc_len);
+int ril_request_sms_get_id(unsigned char aseq);
+int ril_request_sms_get_next(void);
+int ril_request_sms_lock_acquire(void);
+void ril_request_sms_lock_release(void);
+
void ril_request_send_sms(RIL_Token t, void *data, size_t datalen);
void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t datalen);
+int ril_request_send_sms_next(void);
+void ril_request_send_sms_complete(RIL_Token t, char *pdu, char *smsc);
+void ipc_sms_send_msg_complete(struct ipc_message_info *info);
void ipc_sms_svc_center_addr(struct ipc_message_info *info);
void ipc_sms_send_msg(struct ipc_message_info *info);
+
+void ipc_sms_tpid_queue_init(void);
+void ipc_sms_tpid_queue_del(int id);
+int ipc_sms_tpid_queue_add(unsigned char sms_tpid);
+int ipc_sms_tpid_queue_get_next(void);
+
+void ipc_sms_incoming_msg(struct ipc_message_info *info);
+void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t datalen);
+void ipc_sms_deliver_report(struct ipc_message_info *info);
+
void ipc_sms_device_ready(struct ipc_message_info *info);
/* Call */
diff --git a/sms.c b/sms.c
index 4b07de0..46e6a79 100644
--- a/sms.c
+++ b/sms.c
@@ -26,6 +26,15 @@
#include "util.h"
/**
+ * SMS global vars
+ */
+
+struct ril_request_sms ril_request_sms[10];
+int ril_request_sms_lock = 0;
+
+unsigned char ipc_sms_tpid_queue[10];
+
+/**
* Format conversion utils
*/
@@ -43,99 +52,300 @@ unsigned short ril2ipc_sms_ack_error(int success, int failcause)
}
}
-RIL_Errno ipc2ril_sms_ack_error(unsigned short error)
+RIL_Errno ipc2ril_sms_ack_error(unsigned short error, int *error_code)
{
+ /* error_code is defined in See 3GPP 27.005, 3.2.5 for GSM/UMTS */
+
switch(error) {
case IPC_SMS_ACK_NO_ERROR:
+ *error_code = -1;
return RIL_E_SUCCESS;
default:
+ // unknown error
+ *error_code = 500;
return RIL_E_GENERIC_FAILURE;
}
}
-void ipc_sms_incoming_msg(struct ipc_message_info *info)
+/**
+ * RIL request SMS (queue) functions
+ */
+
+void ril_request_sms_init(void)
{
- struct ipc_sms_incoming_msg *msg = (struct ipc_sms_incoming_msg *) info->data;
- unsigned char *pdu = ((unsigned char *) info->data + sizeof(struct ipc_sms_incoming_msg));
+ memset(ril_request_sms, 0, sizeof(struct ril_request_sms) * 10);
+ ril_request_sms_lock = 0;
+}
- int resp_length = msg->length * 2 + 1;
- char *resp = (char *) malloc(resp_length);
+void ril_request_sms_del(int id)
+{
+ if(id < 0 || id > 9) {
+ LOGD("Invalid id (%d) for the SMS queue", id);
+ return;
+ }
- bin2hex(pdu, msg->length, resp);
- LOGD("PDU string is '%s'\n", resp);
+ ril_request_sms[id].aseq = 0;
+ ril_request_sms[id].pdu_len = 0;
+ ril_request_sms[id].smsc_len = 0;
- if(ril_state.msg_tpid_lock != 0) {
- LOGE("Another message is already waiting for ACK, aborting");
- //FIXME: it would be cleaner to enqueue it
- goto exit;
+ if(ril_request_sms[id].pdu != NULL)
+ free(ril_request_sms[id].pdu);
+ if(ril_request_sms[id].smsc != NULL)
+ free(ril_request_sms[id].smsc);
+}
+
+void ril_request_sms_clear(int id)
+{
+ if(id < 0 || id > 9) {
+ LOGD("Invalid id (%d) for the SMS queue", id);
+ return;
}
- ril_state.msg_tpid_lock = msg->msg_tpid;
+ ril_request_sms[id].aseq = 0;
+ ril_request_sms[id].pdu = NULL;
+ ril_request_sms[id].pdu_len = 0;
+ ril_request_sms[id].smsc = NULL;
+ ril_request_sms[id].smsc_len = 0;
+}
- if(msg->type == IPC_SMS_TYPE_POINT_TO_POINT) {
- RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS, resp, resp_length);
- } else if(msg->type == IPC_SMS_TYPE_STATUS_REPORT) {
- RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, resp, resp_length);
- } else {
- LOGE("%s: Unknown message type", __FUNCTION__);
+int ril_request_sms_new(void)
+{
+ int id = -1;
+ int i;
+
+ /* Find the highest place in the queue */
+ for(i=10 ; i > 0 ; i--) {
+ if(ril_request_sms[i-1].aseq && ril_request_sms[i-1].pdu) {
+ break;
+ }
+
+ id = i-1;
}
-exit:
- free(resp);
+ if(id < 0) {
+ LOGE("The SMS queue is full, removing the oldest req");
+
+ /* Free the request at index 0 (oldest) */
+ ril_request_sms_del(0);
+
+ /* Increase all the requests id to have the last one free */
+ for(i=1 ; i < 10 ; i++) {
+ LOGD("SMS queue: moving %d -> %d", i, i-1);
+ memcpy(&ril_request_sms[i-1], &ril_request_sms[i], sizeof(struct ril_request_sms));
+ }
+
+ /* We must not free the pointers here as we copied these at index 8 */
+
+ ril_request_sms_clear(9);
+
+ return 9;
+ }
+
+ return id;
+}
+
+int ril_request_sms_add(unsigned char aseq,
+ char *pdu, unsigned char pdu_len,
+ char *smsc, unsigned char smsc_len)
+{
+ int id = ril_request_sms_new();
+
+ LOGD("Storing new SMS request in the queue at index %d\n", id);
+
+ ril_request_sms[id].aseq = aseq;
+ ril_request_sms[id].smsc_len = smsc_len;
+ ril_request_sms[id].pdu_len = pdu_len;
+
+ if(pdu != NULL) {
+ ril_request_sms[id].pdu = malloc(pdu_len);
+ memcpy(ril_request_sms[id].pdu, pdu, pdu_len);
+ }
+
+ if(smsc != NULL) {
+ ril_request_sms[id].smsc = malloc(smsc_len);
+ memcpy(ril_request_sms[id].smsc, smsc, smsc_len);
+ }
+
+ return id;
+}
+
+int ril_request_sms_get_id(unsigned char aseq)
+{
+ int i;
+
+ for(i=0 ; i < 10 ; i++) {
+ if(ril_request_sms[i].aseq == aseq) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int ril_request_sms_get_next(void)
+{
+ int id = -1;
+ int i;
+
+ for(i=0 ; i < 10 ; i++) {
+ if(ril_request_sms[i].aseq && ril_request_sms[i].pdu) {
+ id = i;
+ }
+ }
+
+ if(id < 0)
+ LOGD("Nothing left on the queue!");
+ else
+ LOGD("Next queued request is at id #%d\n", id);
+
+ return id;
+}
+
+int ril_request_sms_lock_acquire(void)
+{
+ if(ril_request_sms_lock > 0) {
+ return 0;
+ } else
+ {
+ ril_request_sms_lock = 1;
+ return 1;
+ }
+}
+
+void ril_request_sms_lock_release(void)
+{
+ ril_request_sms_lock = 0;
}
/**
- * In: RIL_REQUEST_SMS_ACKNOWLEDGE
- * Acknowledge successful or failed receipt of SMS previously indicated
- * via RIL_UNSOL_RESPONSE_NEW_SMS
+ * Outgoing SMS functions
+ */
+
+/**
+ * In: RIL_REQUEST_SEND_SMS
+ * Send an SMS message.
*
- * Out: IPC_SMS_DELIVER_REPORT
- * Sends a SMS delivery report
+ * Out: IPC_SMS_SEND_MSG
*/
-void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t datalen)
+void ril_request_send_sms(RIL_Token t, void *data, size_t datalen)
{
- struct ipc_sms_deliv_report_msg report_msg;
- int success = ((int *)data)[0];
- int failcause = ((int *)data)[1];
+ const char **request = (char **) data;
+ char *pdu = request[1];
+ int pdu_len = pdu != NULL ? strlen(request[1]) : 0;
+ char *smsc = request[0];
+ int smsc_len = smsc != NULL ? strlen(request[0]) : 0;
+
+ if(!ril_request_sms_lock_acquire()) {
+ LOGD("The SMS lock is already taken, adding req to the SMS queue");
- if(ril_state.msg_tpid_lock == 0) {
- LOGE("No stored msg_tpid, aborting\n");
+ ril_request_sms_add(reqGetId(t), pdu, pdu_len, smsc, smsc_len);
return;
}
- report_msg.type = IPC_SMS_TYPE_STATUS_REPORT;
- report_msg.error = ril2ipc_sms_ack_error(success, failcause);
- report_msg.msg_tpid = ril_state.msg_tpid_lock;
- report_msg.unk = 0;
+ /* We first need to get SMS SVC before sending the message */
+ if(smsc == NULL) {
+ LOGD("We have no SMSC, let's ask one");
- ril_state.msg_tpid_lock = 0;
+ /* Enqueue the request */
+ ril_request_sms_add(reqGetId(t), pdu, pdu_len, NULL, 0);
- ipc_fmt_send(IPC_SMS_DELIVER_REPORT, IPC_TYPE_EXEC, (void *) &report_msg, sizeof(struct ipc_sms_deliv_report_msg), reqGetId(t));
+ ipc_fmt_send_get(IPC_SMS_SVC_CENTER_ADDR, reqGetId(t));
+
+ } else {
+ ril_request_send_sms_complete(t, pdu, smsc);
+ }
}
-void ipc_sms_deliver_report(struct ipc_message_info *info)
+/**
+ * In: RIL_REQUEST_SEND_SMS_EXPECT_MORE
+ * Send an SMS message. Identical to RIL_REQUEST_SEND_SMS,
+ * except that more messages are expected to be sent soon. If possible,
+ * keep SMS relay protocol link open (eg TS 27.005 AT+CMMS command)
+ *
+ * Out: IPC_SMS_SEND_MSG
+ */
+void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t datalen)
{
- //FIXME: check it's alright from data (or not, no need to check the ACK of our ACK)
+ /* No particular treatment here, we already have a queue */
+ ril_request_send_sms(t, data, datalen);
+}
- RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, NULL, 0);
+/**
+ * Send the next SMS in the queue
+ */
+int ril_request_send_sms_next(void)
+{
+ int id = ril_request_sms_get_next();
+
+ char *request[2] = { NULL };
+ unsigned char aseq;
+ char *pdu;
+ char *smsc;
+
+ /* When calling this function, you assume you're done with the previous sms req */
+ ril_request_sms_lock_release();
+
+ if(id < 0)
+ return -1;
+
+ LOGD("Sending queued SMS!");
+
+ aseq = ril_request_sms[id].aseq;
+ pdu = ril_request_sms[id].pdu;
+ smsc = ril_request_sms[id].smsc;
+
+ request[0] = smsc;
+ request[1] = pdu;
+
+ /* We need to clear here to prevent infinite loop, but we can't free mem yet */
+ ril_request_sms_clear(id);
+
+ ril_request_send_sms(reqGetToken(aseq), (void *) request, sizeof(request));
+
+ if(pdu != NULL)
+ free(pdu);
+
+ if(smsc != NULL)
+ free(smsc);
+
+ return id;
}
-void sms_send_msg(RIL_Token t, char *pdu, char *smsc_string)
+/**
+ * Complete (continue) the send_sms request (do the real sending)
+ */
+void ril_request_send_sms_complete(RIL_Token t, char *pdu, char *smsc)
{
- char *data;
- char *p;
struct ipc_sms_send_msg send_msg;
+
+ char *data;
char *decoded_pdu;
+ char *p;
+
+ if(pdu == NULL || smsc == NULL) {
+ LOGE("Provided PDU or SMSC is NULL! Aborting");
+
+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ /* Release the lock so we can accept new requests */
+ ril_request_sms_lock_release();
+ /* Now send the next message in the queue if any */
+ ril_request_send_sms_next();
+
+ return;
+ }
int pdu_str_len = strlen(pdu);
int pdu_len = pdu_str_len / 2;
- int smsc_len = smsc_string[0];
+ int smsc_len = smsc[0];
int send_msg_len = sizeof(struct ipc_sms_send_msg);
+
+ /* Final length of the message */
int length = pdu_len + smsc_len + send_msg_len;
LOGD("Sending SMS message!");
- LOGD("length is %x + %x + %x = 0x%x\n", pdu_len, smsc_len, send_msg_len, length);
+ LOGD("length is 0x%x + 0x%x + 0x%x = 0x%x\n", pdu_len, smsc_len, send_msg_len, length);
decoded_pdu = malloc(pdu_len);
hex2bin(pdu, pdu_str_len, decoded_pdu);
@@ -144,99 +354,278 @@ void sms_send_msg(RIL_Token t, char *pdu, char *smsc_string)
memset(&send_msg, 0, sizeof(struct ipc_sms_send_msg));
send_msg.type = IPC_SMS_TYPE_OUTGOING;
- send_msg.msg_type = IPC_SMS_MSG_SINGLE; //fixme: define based on PDU
- send_msg.length = (unsigned char) length;
+ send_msg.msg_type = IPC_SMS_MSG_SINGLE; //FIXME: decide based on PDU
+ send_msg.length = (unsigned char) length; //FIXME: in case of multiple msg, you need to send total size (pdu_size in logs)
send_msg.smsc_len = (unsigned char) smsc_len;
p = data;
memcpy(p, &send_msg, send_msg_len);
p += send_msg_len;
- memcpy(p, (char *) (smsc_string + 1), smsc_len);
+ memcpy(p, (char *) (smsc + 1), smsc_len);
p += smsc_len;
memcpy(p, decoded_pdu, pdu_len);
- ipc_fmt_send(IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, data, length, reqGetId(t));
+ ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_SMS_SEND_MSG, ipc_sms_send_msg_complete);
- /* Wait for ACK to return to RILJ */
- ril_state.tokens.send_sms = t;
+ ipc_fmt_send(IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, data, length, reqGetId(t));
free(decoded_pdu);
free(data);
}
-void ril_request_send_sms(RIL_Token t, void *data, size_t datalen)
+void ipc_sms_send_msg_complete(struct ipc_message_info *info)
{
- const char **request;
- request = (char **) data;
- int pdu_len = strlen(request[1]);
+ struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
- /* We first need to get SMS SVC before sending the message */
+ if(ipc_gen_phone_res_check(phone_res) < 0) {
+ LOGE("IPC_GEN_PHONE_RES indicates error, abort request to RILJ");
- if(request[0] == NULL) {
- LOGD("We have no SMSC, asking one before anything");
+ RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- if(ril_state.tokens.send_sms != 0 && ril_state.msg_pdu != NULL) {
- LOGE("Another message is being sent, aborting");
- //FIXME: it would be cleaner to enqueue it
- }
-
- ril_state.tokens.send_sms = t;
- ril_state.msg_pdu = malloc(pdu_len);
- memcpy(ril_state.msg_pdu, request[1], pdu_len);
-
- ipc_fmt_send_get(IPC_SMS_SVC_CENTER_ADDR, reqGetId(t));
-
- } else {
- sms_send_msg(t, request[1], request[0]);
+ /* Release the lock so we can accept new requests */
+ ril_request_sms_lock_release();
+ /* Now send the next message in the queue if any */
+ ril_request_send_sms_next();
}
}
+
/**
- * In: RIL_REQUEST_SEND_SMS_EXPECT_MORE
- * Send an SMS message. Identical to RIL_REQUEST_SEND_SMS,
- * except that more messages are expected to be sent soon. If possible,
- * keep SMS relay protocol link open (eg TS 27.005 AT+CMMS command)
+ * In: IPC_SMS_SVC_CENTER_ADDR
+ * SMSC: Service Center Address, needed to send an SMS
*
* Out: IPC_SMS_SEND_MSG
*/
-void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t datalen)
+void ipc_sms_svc_center_addr(struct ipc_message_info *info)
{
- /* FIXME: We seriously need a decent queue here */
+ int id = ril_request_sms_get_id(info->aseq);
-}
+ char *pdu;
+ unsigned char pdu_len;
-void ipc_sms_svc_center_addr(struct ipc_message_info *info)
-{
- RIL_Token t = reqGetToken(info->aseq);
+ if(id < 0) {
+ LOGE("The request wasn't queued, reporting generic error!");
- if(ril_state.tokens.send_sms == t && ril_state.msg_pdu != NULL) {
- sms_send_msg(t, ril_state.msg_pdu, info->data);
+ RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- free(ril_state.msg_pdu);
+ /* Release the lock so we can accept new requests */
+ ril_request_sms_lock_release();
+ /* Now send the next message in the queue if any */
+ ril_request_send_sms_next();
+
+ return;
}
+
+ LOGD("Completing the request");
+
+ pdu = ril_request_sms[id].pdu;
+ pdu_len = ril_request_sms[id].pdu_len;
+
+ /* We need to clear here to prevent infinite loop, but we can't free mem yet */
+ ril_request_sms_clear(id);
+
+ ril_request_send_sms_complete(reqGetToken(info->aseq), pdu, info->data);
+
+ /* Now it is safe to free mem */
+ if(pdu != NULL)
+ free(pdu);
}
+/**
+ * In: IPC_SMS_SEND_MSG
+ * This comes to ACK the latest sent SMS message
+ */
void ipc_sms_send_msg(struct ipc_message_info *info)
{
- struct ipc_sms_deliv_report_msg *report_msg = info->data;
+ struct ipc_sms_deliv_report_msg *report_msg = (struct ipc_sms_deliv_report_msg *) info->data;
+ RIL_SMS_Response response;
+
RIL_Errno ril_ack_err;
- RIL_Token t = reqGetToken(info->aseq);
- if(ril_state.tokens.send_sms != t) {
- LOGE("Wrong token to ACK");
+ LOGD("Got ACK for msg_tpid #%d\n", report_msg->msg_tpid);
+
+ response.messageRef = report_msg->msg_tpid;
+ response.ackPDU = NULL;
+ ril_ack_err = ipc2ril_sms_ack_error(report_msg->error, &(response.errorCode));
+
+ RIL_onRequestComplete(reqGetToken(info->aseq), ril_ack_err, &response, sizeof(response));
+
+ /* Release the lock so we can accept new requests */
+ ril_request_sms_lock_release();
+ /* Now send the next message in the queue if any */
+ ril_request_send_sms_next();
+}
+
+/**
+ * IPC incoming SMS queue functions
+ */
+
+void ipc_sms_tpid_queue_init(void)
+{
+ memset(ipc_sms_tpid_queue, 0, sizeof(unsigned char) * 10);
+}
+
+void ipc_sms_tpid_queue_del(int id)
+{
+ if(id < 0 || id > 9) {
+ LOGD("Invalid id (%d) for the SMS tpid queue", id);
+ return;
+ }
+
+ ipc_sms_tpid_queue[id] = 0;
+}
+
+int ipc_sms_tpid_queue_new(void)
+{
+ int id = -1;
+ int i;
+
+ /* Find the highest place in the queue */
+ for(i=10 ; i > 0 ; i--) {
+ if(ipc_sms_tpid_queue[i-1]) {
+ break;
+ }
+
+ id = i-1;
}
- LOGD("RECV ack for msg_tpid %d\n", report_msg->msg_tpid);
+ if(id < 0) {
+ LOGE("The SMS tpid queue is full, removing the oldest tpid");
- ril_ack_err = ipc2ril_sms_ack_error(report_msg->error);
+ ipc_sms_tpid_queue_del(0);
- ril_state.tokens.send_sms = 0;
+ for(i=1 ; i < 10 ; i++) {
+ LOGD("SMS tpid queue: moving %d -> %d", i, i-1);
+ ipc_sms_tpid_queue[i-1] = ipc_sms_tpid_queue[i];
+ }
- //messageRef = tpid, it's not NULL ↓
- RIL_onRequestComplete(t, ril_ack_err, NULL, 0);
+ ipc_sms_tpid_queue_del(9);
+ return 9;
+ }
+
+ return id;
}
+int ipc_sms_tpid_queue_add(unsigned char sms_tpid)
+{
+ int id = ipc_sms_tpid_queue_new();
+
+ LOGD("Storing new SMS tpid in the queue at index %d\n", id);
+
+ ipc_sms_tpid_queue[id] = sms_tpid;
+
+ return id;
+}
+
+int ipc_sms_tpid_queue_get_next(void)
+{
+ int id = -1;
+ int i;
+
+ for(i=0 ; i < 10 ; i++) {
+ if(ipc_sms_tpid_queue[i]) {
+ id = i;
+ }
+ }
+
+ if(id < 0)
+ LOGD("Nothing left on the queue!");
+ else
+ LOGD("Next queued tpid is at id #%d\n", id);
+
+ return id;
+}
+
+/**
+ * Incoming SMS functions
+ */
+
+/**
+ * In: IPC_SMS_INCOMING_MSG
+ * Message to notify an incoming message, with PDU
+ *
+ * Out: RIL_UNSOL_RESPONSE_NEW_SMS or RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT
+ * Notify RILJ about the incoming message
+ */
+
+void ipc_sms_incoming_msg(struct ipc_message_info *info)
+{
+ struct ipc_sms_incoming_msg *msg = (struct ipc_sms_incoming_msg *) info->data;
+ unsigned char *pdu = ((unsigned char *) info->data + sizeof(struct ipc_sms_incoming_msg));
+
+ int resp_length = msg->length * 2 + 1;
+ char *resp = (char *) malloc(resp_length);
+
+ bin2hex(pdu, msg->length, resp);
+
+ LOGD("PDU string is '%s'\n", resp);
+
+ ipc_sms_tpid_queue_add(msg->msg_tpid);
+
+ if(msg->type == IPC_SMS_TYPE_POINT_TO_POINT) {
+ RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS, resp, resp_length);
+ } else if(msg->type == IPC_SMS_TYPE_STATUS_REPORT) {
+ // FIXME: do we need to enqueue for this?
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, resp, resp_length);
+ } else {
+ LOGE("%s: Unknown message type", __FUNCTION__);
+ }
+
+exit:
+ free(resp);
+}
+
+/**
+ * In: RIL_REQUEST_SMS_ACKNOWLEDGE
+ * Acknowledge successful or failed receipt of SMS previously indicated
+ * via RIL_UNSOL_RESPONSE_NEW_SMS
+ *
+ * Out: IPC_SMS_DELIVER_REPORT
+ * Sends a SMS delivery report
+ */
+void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t datalen)
+{
+ struct ipc_sms_deliv_report_msg report_msg;
+ int success = ((int *)data)[0];
+ int failcause = ((int *)data)[1];
+ int id = ipc_sms_tpid_queue_get_next();
+
+ if(id < 0) {
+ LOGE("There is no SMS message to ACK!");
+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ return;
+ }
+
+ report_msg.type = IPC_SMS_TYPE_STATUS_REPORT;
+ report_msg.error = ril2ipc_sms_ack_error(success, failcause);
+ report_msg.msg_tpid = ipc_sms_tpid_queue[id];
+ report_msg.unk = 0;
+
+ ipc_gen_phone_res_expect_to_abort(reqGetId(t), IPC_SMS_DELIVER_REPORT);
+
+ ipc_fmt_send(IPC_SMS_DELIVER_REPORT, IPC_TYPE_EXEC, (void *) &report_msg, sizeof(struct ipc_sms_deliv_report_msg), reqGetId(t));
+
+ ipc_sms_tpid_queue_del(id);
+}
+
+/**
+ * In: IPC_SMS_DELIVER_REPORT
+ * Attest that the modem successfully sent our SMS recv ACK
+ */
+void ipc_sms_deliver_report(struct ipc_message_info *info)
+{
+ // TODO: check error code to eventually resend ACK
+
+ RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, NULL, 0);
+}
+
+/**
+ * Apparently non-SMS-messages-related function
+ */
+
void ipc_sms_device_ready(struct ipc_message_info *info)
{
if(ril_state.radio_state == RADIO_STATE_SIM_READY) {