SMS: Use lists stored in ril_data instead of global table
authorPaul Kocialkowski <contact@paulk.fr>
Sun, 4 Nov 2012 18:35:33 +0000 (19:35 +0100)
committerPaul Kocialkowski <contact@paulk.fr>
Sun, 4 Nov 2012 18:35:33 +0000 (19:35 +0100)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
pwr.c
samsung-ril.c
samsung-ril.h
sms.c

diff --git a/pwr.c b/pwr.c
index 92f25dd..b672f08 100644 (file)
--- a/pwr.c
+++ b/pwr.c
@@ -108,7 +108,6 @@ void ril_request_radio_power(RIL_Token t, void *data, size_t datalen)
                ril_request_complete(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_data.state.radio_state = RADIO_STATE_OFF;
                ril_data.state.power_state = IPC_PWR_PHONE_STATE_LPM;
 
index 94f935a..3b25f2f 100644 (file)
@@ -645,11 +645,6 @@ void ril_data_init(void)
        pthread_mutex_init(&ril_data.mutex, NULL);
 }
 
-void ril_globals_init(void)
-{
-       ril_request_sms_init();
-}
-
 /**
  * RIL interface
  */
index af7313f..f7ab23f 100644 (file)
@@ -121,6 +121,8 @@ struct ril_tokens {
        RIL_Token registration_state;
        RIL_Token gprs_registration_state;
        RIL_Token operator;
+
+       RIL_Token outgoing_sms;
 };
 
 void ril_tokens_check(void);
@@ -302,39 +304,33 @@ struct ipc_sms_incoming_msg_info {
        unsigned char tpid;
 };
 
-struct ril_request_sms {
+struct ril_request_send_sms_info {
        char *pdu;
-       int pdu_len;
-       char *smsc;
-       int smsc_len;
+       int pdu_length;
+       unsigned char *smsc;
+       int smsc_length;
 
-       unsigned char aseq;
+       RIL_Token token;
 };
 
-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, int pdu_len, 
-                       char *smsc, int 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);
+
+int ril_request_send_sms_register(char *pdu, int pdu_length, unsigned char *smsc, int smsc_length, RIL_Token t);
+void ril_request_send_sms_unregister(struct ril_request_send_sms_info *send_sms);
+struct ril_request_send_sms_info *ril_request_send_sms_info_find(void);
+struct ril_request_send_sms_info *ril_request_send_sms_info_find_token(RIL_Token t);
+
+void ril_request_send_sms_next(void);
+void ril_request_send_sms_complete(RIL_Token t, char *pdu, int pdu_length, unsigned char *smsc, int smsc_length);
+void ril_request_send_sms(RIL_Token t, void *data, size_t length);
+void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t length);
 void ipc_sms_svc_center_addr(struct ipc_message_info *info);
+void ipc_sms_send_msg_complete(struct ipc_message_info *info);
 void ipc_sms_send_msg(struct ipc_message_info *info);
 
 int ipc_sms_incoming_msg_register(char *pdu, int length, unsigned char type, unsigned char tpid);
 void ipc_sms_incoming_msg_unregister(struct ipc_sms_incoming_msg_info *incoming_msg);
 struct ipc_sms_incoming_msg_info *ipc_sms_incoming_msg_info_find(void);
 
-void ipc_sms_incoming_msg_next(void);
 void ipc_sms_incoming_msg_complete(char *pdu, int length, unsigned char type, unsigned char tpid);
 void ipc_sms_incoming_msg(struct ipc_message_info *info);
 void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t length);
diff --git a/sms.c b/sms.c
index 43e3c28..2f62ae8 100644 (file)
--- a/sms.c
+++ b/sms.c
 #include "util.h"
 
 /**
- * SMS global vars
- */
-
-struct ril_request_sms ril_request_sms[10];
-int ril_request_sms_lock = 0;
-
-/**
  * Format conversion utils
  */
 
@@ -66,315 +59,225 @@ RIL_Errno ipc2ril_sms_ack_error(unsigned short error, int *error_code)
 }
 
 /**
- * RIL request SMS (queue) functions
+ * Outgoing SMS functions
  */
 
-void ril_request_sms_init(void)
+int ril_request_send_sms_register(char *pdu, int pdu_length, unsigned char *smsc, int smsc_length, RIL_Token t)
 {
-       memset(ril_request_sms, 0, sizeof(struct ril_request_sms) * 10);
-       ril_request_sms_lock = 0;
-}
+       struct ril_request_send_sms_info *send_sms;
+       struct list_head *list_end;
+       struct list_head *list;
 
-void ril_request_sms_del(int id)
-{
-       if(id < 0 || id > 9) {
-               LOGD("Invalid id (%d) for the SMS queue", id);
-               return;
-       }
+       send_sms = calloc(1, sizeof(struct ril_request_send_sms_info));
+       if(send_sms == NULL)
+               return -1;
 
-       ril_request_sms[id].aseq = 0;
-       ril_request_sms[id].pdu_len = 0;
-       ril_request_sms[id].smsc_len = 0;
+       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(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);
-}
+       list_end = ril_data.outgoing_sms;
+       while(list_end != NULL && list_end->next != NULL)
+               list_end = list_end->next;
 
-void ril_request_sms_clear(int id)
-{
-       if(id < 0 || id > 9) {
-               LOGD("Invalid id (%d) for the SMS queue", id);
-               return;
-       }
+       list = list_head_alloc((void *) send_sms, list_end, NULL);
+
+       if(ril_data.outgoing_sms == NULL)
+               ril_data.outgoing_sms = list;
 
-       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;
+       return 0;
 }
 
-int ril_request_sms_new(void)
+void ril_request_send_sms_unregister(struct ril_request_send_sms_info *send_sms)
 {
-       int id = -1;
-       int i;
+       struct list_head *list;
 
-       /* 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;
-               }
+       if(send_sms == NULL)
+               return;
 
-               id = i-1;
-       }
+       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(id < 0) {
-               LOGE("The SMS queue is full, removing the oldest req");
+                       if(list == ril_data.outgoing_sms)
+                               ril_data.outgoing_sms = list->next;
 
-               /* Free the request at index 0 (oldest) */
-               ril_request_sms_del(0);
+                       list_head_free(list);
 
-               /* 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));
+                       break;
                }
-
-               /* We must not free the pointers here as we copied these at index 8 */
-
-               ril_request_sms_clear(9);
-
-               return 9;
+list_continue:
+               list = list->next;
        }
-
-       return id;
 }
 
-int ril_request_sms_add(unsigned char aseq,
-                       char *pdu, int pdu_len, 
-                       char *smsc, int smsc_len)
+struct ril_request_send_sms_info *ril_request_send_sms_info_find(void)
 {
-       int id = ril_request_sms_new();
+       struct ril_request_send_sms_info *send_sms;
+       struct list_head *list;
 
-       LOGD("Storing new SMS request in the queue at index %d\n", id);
+       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;
 
-       ril_request_sms[id].aseq = aseq;
-       ril_request_sms[id].smsc_len = smsc_len;
-       ril_request_sms[id].pdu_len = pdu_len;
+               return send_sms;
 
-       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);
+list_continue:
+               list = list->next;
        }
 
-       return id;
+       return NULL;
 }
 
-int ril_request_sms_get_id(unsigned char aseq)
+struct ril_request_send_sms_info *ril_request_send_sms_info_find_token(RIL_Token t)
 {
-       int i;
+       struct ril_request_send_sms_info *send_sms;
+       struct list_head *list;
 
-       for(i=0 ; i < 10 ; i++) {
-               if(ril_request_sms[i].aseq == aseq) {
-                       return i;
-               }
+       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 -1;
+       return NULL;
 }
 
-int ril_request_sms_get_next(void)
+void ril_request_send_sms_info_clear(struct ril_request_send_sms_info *send_sms)
 {
-       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(send_sms == NULL)
+               return;
 
-       if(id < 0)
-               LOGD("Nothing left on the queue!");
-       else
-               LOGD("Next queued request is at id #%d\n", id);
+       if(send_sms->pdu != NULL)
+               free(send_sms->pdu);
 
-       return id;
+       if(send_sms->smsc != NULL)
+               free(send_sms->smsc);
 }
 
-int ril_request_sms_lock_acquire(void)
+void ril_request_send_sms_next(void)
 {
-       if(ril_request_sms_lock > 0) {
-               return 0;
-       } else
-       {
-               ril_request_sms_lock = 1;
-               return 1;
-       }
-}
+       struct ril_request_send_sms_info *send_sms;
+       RIL_Token t;
+       char *pdu;
+       int pdu_length;
+       unsigned char *smsc;
+       int smsc_length;
+       int rc;
 
-void ril_request_sms_lock_release(void)
-{
-       ril_request_sms_lock = 0;
-}
+       ril_data.tokens.outgoing_sms = (RIL_Token) 0x00;
 
-/**
- * Outgoing SMS functions
- */
+       send_sms = ril_request_send_sms_info_find();
+       if(send_sms == NULL)
+               return;
 
-/**
- * In: RIL_REQUEST_SEND_SMS
- *   Send an SMS message.
- *
- * Out: IPC_SMS_SEND_MSG
- */
-void ril_request_send_sms(RIL_Token t, void *data, size_t datalen)
-{
-       char **request = (char **) data;
-       char *pdu = request[1];
-       int pdu_len = pdu != NULL ? strlen(pdu) : 0;
-       char *smsc = request[0];
-       int smsc_len = smsc != NULL ? strlen(smsc) : 0;
+       t = send_sms->token;
+       pdu = send_sms->pdu;
+       pdu_length = send_sms->pdu_length;
+       smsc = send_sms->smsc;
+       smsc_length = send_sms->smsc_length;
 
-       if(!ril_request_sms_lock_acquire()) {
-               LOGD("The SMS lock is already taken, adding req to the SMS queue");
+       ril_request_send_sms_unregister(send_sms);
 
-               ril_request_sms_add(ril_request_get_id(t), pdu, pdu_len, smsc, smsc_len);
+       if(pdu == NULL) {
+               LOGE("SMS send request has no valid PDU");
+               if(smsc != NULL)
+                       free(smsc);
                return;
        }
 
-       /* We first need to get SMS SVC before sending the message */
+       ril_data.tokens.outgoing_sms = t;
        if(smsc == NULL) {
+               // We first need to get SMS SVC before sending the message
                LOGD("We have no SMSC, let's ask one");
 
-               /* Enqueue the request */
-               ril_request_sms_add(ril_request_get_id(t), pdu, pdu_len, NULL, 0);
+               rc = ril_request_send_sms_register(pdu, pdu_length, NULL, 0, t);
+               if(rc < 0) {
+                       LOGE("Unable to add the request to the list");
 
-               ipc_fmt_send_get(IPC_SMS_SVC_CENTER_ADDR, ril_request_get_id(t));
+                       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, smsc);
+               ril_request_send_sms_complete(t, pdu, pdu_length, smsc, smsc_length);
+               if(pdu != NULL)
+                       free(pdu);
+               if(smsc != NULL)
+                       free(smsc);
        }
 }
 
 /**
- * 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: RIL_REQUEST_SEND_SMS
+ *   Send an SMS message.
  *
  * Out: IPC_SMS_SEND_MSG
  */
-void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t datalen)
-{
-       /* No particular treatment here, we already have a queue */
-       ril_request_send_sms(t, data, datalen);
-}
-
-/**
- * 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(ril_request_get_token(aseq), (void *) request, sizeof(request));
-
-       if(pdu != NULL)
-               free(pdu);
-
-       if(smsc != NULL)
-               free(smsc);
-
-       return id;
-}
-
-/**
- * Complete (continue) the send_sms request (do the real sending)
- */
-void ril_request_send_sms_complete(RIL_Token t, char *pdu, char *smsc)
+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 = IPC_SMS_MSG_SINGLE;
-       int send_msg_len;
+       unsigned char send_msg_type;
 
-       char *data;
-       int data_len;
-
-       char *pdu_dec;
-       unsigned char pdu_dec_len;
+       unsigned char *pdu_hex;
+       int pdu_hex_length;
 
-       int pdu_len;
-       unsigned char smsc_len;
+       void *data;
+       int length;
 
-       char *p;
+       unsigned char *p;
 
-       if(pdu == NULL || smsc == NULL) {
-               LOGE("Provided PDU or SMSC is NULL! Aborting");
+       if(pdu == NULL || pdu_length <= 0 || smsc == NULL || smsc_length <= 0) {
+               LOGE("Provided PDU or SMSC is invalid! Aborting");
 
                ril_request_complete(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 */
+               // Send the next SMS in the list
                ril_request_send_sms_next();
 
                return;
        }
-
-       /* Setting various len vars */
-       pdu_len = strlen(pdu);
-
-       if(pdu_len / 2 > 0xff) {
-               LOGE("PDU is too large, aborting");
+       if((pdu_length / 2 + smsc_length) > 0xfe) {
+               LOGE("PDU or SMSC too large, aborting");
 
                ril_request_complete(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 */
+               // Send the next SMS in the list
                ril_request_send_sms_next();
 
                return;
        }
 
-       pdu_dec_len = pdu_len / 2;
-       smsc_len = smsc[0];
-       send_msg_len = sizeof(struct ipc_sms_send_msg_request);
-
-       /* Length of the final message */
-       data_len = pdu_dec_len + smsc_len + send_msg_len;
+       pdu_hex_length = pdu_length % 2 == 0 ? pdu_length / 2 :
+               (pdu_length ^ 1) / 2;
 
-       LOGD("Sending SMS message!");
+       // Length of the final message
+       length = sizeof(send_msg) + pdu_hex_length + smsc_length;
 
-       LOGD("data_len is 0x%x + 0x%x + 0x%x = 0x%x\n", pdu_dec_len, smsc_len, send_msg_len, data_len);
+       LOGD("Sending SMS message (length: 0x%x)!", length);
 
-       pdu_dec = malloc(pdu_dec_len);
-       hex2bin(pdu, pdu_len, (unsigned char*)pdu_dec);
+       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_dec[pdu_tp_da_index];
+       unsigned char pdu_tp_da_len = pdu_hex[pdu_tp_da_index];
 
        if(pdu_tp_da_len > 0xff / 2) {
                LOGE("PDU TP-DA Len failed (0x%x)\n", pdu_tp_da_len);
@@ -384,7 +287,7 @@ void ril_request_send_sms_complete(RIL_Token t, char *pdu, char *smsc)
        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_dec[pdu_tp_udh_index];
+       unsigned char pdu_tp_udh_len = pdu_hex[pdu_tp_udh_index];
 
        if(pdu_tp_udh_len > 0xff / 2 || pdu_tp_udh_len < 5) {
                LOGE("PDU TP-UDH Len failed (0x%x)\n", pdu_tp_udh_len);
@@ -394,7 +297,7 @@ void ril_request_send_sms_complete(RIL_Token t, char *pdu, char *smsc)
        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_dec[pdu_tp_udh_num_index];
+       unsigned char pdu_tp_udh_num = pdu_hex[pdu_tp_udh_num_index];
 
        if(pdu_tp_udh_num > 0xf) {
                LOGE("PDU TP-UDH Num failed (0x%x)\n", pdu_tp_udh_num);
@@ -402,7 +305,7 @@ void ril_request_send_sms_complete(RIL_Token t, char *pdu, char *smsc)
        }
 
        int pdu_tp_udh_seq_index = pdu_tp_udh_index + 5;
-       unsigned char pdu_tp_udh_seq = pdu_dec[pdu_tp_udh_seq_index];
+       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) {
                LOGE("PDU TP-UDH Seq failed (0x%x)\n", pdu_tp_udh_seq);
@@ -417,49 +320,117 @@ void ril_request_send_sms_complete(RIL_Token t, char *pdu, char *smsc)
        }
 
 pdu_end:
-       /* Alloc and clean memory for the final message */
-       data = malloc(data_len);
-       memset(&send_msg, 0, sizeof(struct ipc_sms_send_msg_request));
+       // Alloc memory for the final message
+       data = calloc(1, length);
 
-       /* Fill the IPC structure part of the message */
+       // 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_dec_len + smsc_len + 1);
-       send_msg.smsc_len = smsc_len;
+       send_msg.length = (unsigned char) (pdu_hex_length + smsc_length + 1);
+       send_msg.smsc_len = smsc_length;
 
-       /* Copy the other parts of the message */
+       // Copy the parts of the message
        p = data;
-       memcpy(p, &send_msg, send_msg_len);
-       p +=  send_msg_len;
-       memcpy(p, (char *) (smsc + 1), smsc_len); // First SMSC bytes is length
-       p += smsc_len;
-       memcpy(p, pdu_dec, pdu_dec_len);
+       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, (void *) data, data_len, ril_request_get_id(t));
+       ipc_fmt_send(IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, data, length, ril_request_get_id(t));
 
-       free(pdu_dec);
+       free(pdu_hex);
        free(data);
 }
 
-void ipc_sms_send_msg_complete(struct ipc_message_info *info)
+void ril_request_send_sms(RIL_Token t, void *data, size_t length)
 {
-       struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
+       char *pdu;
+       int pdu_length;
+       unsigned char *smsc;
+       int smsc_length;
+       int rc;
 
-       if(ipc_gen_phone_res_check(phone_res) < 0) {
-               LOGE("IPC_GEN_PHONE_RES indicates error, abort request to RILJ");
+       if(data == NULL || length < 2 * sizeof(char *))
+               return;
 
-               ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+       pdu = ((char **) data)[1];
+       smsc = ((unsigned char **) data)[0];
+       pdu_length = 0;
+       smsc_length = 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();
+       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);
+       }
+
+       if(ril_data.tokens.outgoing_sms != (RIL_Token) 0x00) {
+               LOGD("Another outgoing SMS is being processed, adding to the list");
+
+               rc = ril_request_send_sms_register(pdu, pdu_length, smsc, smsc_length, t);
+               if(rc < 0) {
+                       LOGE("Unable to add the request to the list");
+
+                       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();
+               }
+
+               return;
+       }
+
+       ril_data.tokens.outgoing_sms = t;
+       if(smsc == NULL) {
+               // We first need to get SMS SVC before sending the message
+               LOGD("We have no SMSC, let's ask one");
+
+               rc = ril_request_send_sms_register(pdu, pdu_length, NULL, 0, t);
+               if(rc < 0) {
+                       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);
        }
 }
 
 /**
+ * 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 length)
+{
+       /* No particular treatment here, we already have a queue */
+       ril_request_send_sms(t, data, length);
+}
+
+/**
  * In: IPC_SMS_SVC_CENTER_ADDR
  *   SMSC: Service Center Address, needed to send an SMS
  *
@@ -467,37 +438,59 @@ void ipc_sms_send_msg_complete(struct ipc_message_info *info)
  */
 void ipc_sms_svc_center_addr(struct ipc_message_info *info)
 {
-       int id = ril_request_sms_get_id(info->aseq);
-
+       struct ril_request_send_sms_info *send_sms;
+       RIL_Token t;
        char *pdu;
-       int pdu_len;
+       int pdu_length;
+       unsigned char *smsc;
+       int smsc_length;
+       int rc;
 
-       if(id < 0) {
+       if(info == NULL || info->data == NULL)
+               return;
+
+       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) {
                LOGE("The request wasn't queued, reporting generic error!");
 
                ril_request_complete(ril_request_get_token(info->aseq), 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_info_clear(send_sms);
+               ril_request_send_sms_unregister(send_sms);
+               // Send the next SMS in the list
                ril_request_send_sms_next();
 
                return;
        }
 
-       LOGD("Completing the request");
+       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];
 
-       pdu = ril_request_sms[id].pdu;
-       pdu_len = ril_request_sms[id].pdu_len;
+       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)
+               free(pdu);
+}
 
-       /* We need to clear here to prevent infinite loop, but we can't free mem yet */
-       ril_request_sms_clear(id);
+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;
 
-       ril_request_send_sms_complete(ril_request_get_token(info->aseq), pdu, (char *) info->data);
+       if(info->data == NULL || info->length < sizeof(struct ipc_gen_phone_res))
+               return;
 
-       /* Now it is safe to free mem */
-       if(pdu != NULL)
-               free(pdu);
+       phone_res = (struct ipc_gen_phone_res *) info->data;
+       if(ipc_gen_phone_res_check(phone_res) < 0) {
+               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();
+       }
 }
 
 /**
@@ -506,22 +499,26 @@ void ipc_sms_svc_center_addr(struct ipc_message_info *info)
  */
 void ipc_sms_send_msg(struct ipc_message_info *info)
 {
-       struct ipc_sms_send_msg_response *report_msg = (struct ipc_sms_send_msg_response *) info->data;
+       struct ipc_sms_send_msg_response *report_msg;
        RIL_SMS_Response response;
+       RIL_Errno e;
 
-       RIL_Errno ril_ack_err;
+       if(info == NULL || info->data == NULL || info->length < sizeof(struct ipc_sms_send_msg_response))
+               return;
+
+       report_msg = (struct ipc_sms_send_msg_response *) info->data;
 
        LOGD("Got ACK for msg_tpid #%d\n", report_msg->msg_tpid);
 
+       memset(&response, 0, sizeof(response));
        response.messageRef = report_msg->msg_tpid;
        response.ackPDU = NULL;
-       ril_ack_err = ipc2ril_sms_ack_error(report_msg->error, &(response.errorCode));
 
-       ril_request_complete(ril_request_get_token(info->aseq), ril_ack_err, &response, sizeof(response));
+       e = ipc2ril_sms_ack_error(report_msg->error, &response.errorCode);
+
+       ril_request_complete(ril_request_get_token(info->aseq), e, (void *) &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 */
+       // Send the next SMS in the list
        ril_request_send_sms_next();
 }
 
@@ -601,14 +598,6 @@ list_continue:
        return NULL;
 }
 
-/**
- * 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_next(void)
 {
        struct ipc_sms_incoming_msg_info *incoming_msg;
@@ -623,6 +612,13 @@ void ipc_sms_incoming_msg_next(void)
        ipc_sms_incoming_msg_unregister(incoming_msg);
 }
 
+/**
+ * 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_complete(char *pdu, int length, unsigned char type, unsigned char tpid)
 {
        if(pdu == NULL || length <= 0)