39da23728b70b88c9306de1758a8be401d778270
[samsung-ril.git] / sms.c
1 /**
2  * This file is part of samsung-ril.
3  *
4  * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
5  * Copyright (C) 2011 Paul Kocialkowski <contact@oaulk.fr>
6  *
7  * samsung-ril is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * samsung-ril is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21
22 #define LOG_TAG "RIL-SMS"
23 #include <utils/Log.h>
24
25 #include "samsung-ril.h"
26 #include "util.h"
27
28 /**
29  * SMS global vars
30  */
31
32 struct ril_request_sms ril_request_sms[10];
33 int ril_request_sms_lock = 0;
34
35 /**
36  * Format conversion utils
37  */
38
39 unsigned short ril2ipc_sms_ack_error(int success, int failcause)
40 {
41         if(success) {
42                 return IPC_SMS_ACK_NO_ERROR;
43         } else {
44                 switch(failcause) {
45                         case 0xD3:
46                                 return IPC_SMS_ACK_PDA_FULL_ERROR;
47                         default:
48                                 return IPC_SMS_ACK_UNSPEC_ERROR;
49                 }
50         }
51 }
52
53 RIL_Errno ipc2ril_sms_ack_error(unsigned short error, int *error_code)
54 {
55         /* error_code is defined in See 3GPP 27.005, 3.2.5 for GSM/UMTS */
56
57         switch(error) {
58                 case IPC_SMS_ACK_NO_ERROR:
59                         *error_code = -1;
60                         return RIL_E_SUCCESS;
61                 default:
62                         // unknown error
63                         *error_code = 500;
64                         return RIL_E_GENERIC_FAILURE;
65         }
66 }
67
68 /**
69  * RIL request SMS (queue) functions
70  */
71
72 void ril_request_sms_init(void)
73 {
74         memset(ril_request_sms, 0, sizeof(struct ril_request_sms) * 10);
75         ril_request_sms_lock = 0;
76 }
77
78 void ril_request_sms_del(int id)
79 {
80         if(id < 0 || id > 9) {
81                 LOGD("Invalid id (%d) for the SMS queue", id);
82                 return;
83         }
84
85         ril_request_sms[id].aseq = 0;
86         ril_request_sms[id].pdu_len = 0;
87         ril_request_sms[id].smsc_len = 0;
88
89         if(ril_request_sms[id].pdu != NULL)
90                 free(ril_request_sms[id].pdu);
91         if(ril_request_sms[id].smsc != NULL)
92                 free(ril_request_sms[id].smsc);
93 }
94
95 void ril_request_sms_clear(int id)
96 {
97         if(id < 0 || id > 9) {
98                 LOGD("Invalid id (%d) for the SMS queue", id);
99                 return;
100         }
101
102         ril_request_sms[id].aseq = 0;
103         ril_request_sms[id].pdu = NULL;
104         ril_request_sms[id].pdu_len = 0;
105         ril_request_sms[id].smsc = NULL;
106         ril_request_sms[id].smsc_len = 0;
107 }
108
109 int ril_request_sms_new(void)
110 {
111         int id = -1;
112         int i;
113
114         /* Find the highest place in the queue */
115         for(i=10 ; i > 0 ; i--) {
116                 if(ril_request_sms[i-1].aseq && ril_request_sms[i-1].pdu) {
117                         break;
118                 }
119
120                 id = i-1;
121         }
122
123         if(id < 0) {
124                 LOGE("The SMS queue is full, removing the oldest req");
125
126                 /* Free the request at index 0 (oldest) */
127                 ril_request_sms_del(0);
128
129                 /* Increase all the requests id to have the last one free */
130                 for(i=1 ; i < 10 ; i++) {
131                         LOGD("SMS queue: moving %d -> %d", i, i-1);
132                         memcpy(&ril_request_sms[i-1], &ril_request_sms[i], sizeof(struct ril_request_sms));
133                 }
134
135                 /* We must not free the pointers here as we copied these at index 8 */
136
137                 ril_request_sms_clear(9);
138
139                 return 9;
140         }
141
142         return id;
143 }
144
145 int ril_request_sms_add(unsigned char aseq,
146                         char *pdu, int pdu_len, 
147                         char *smsc, int smsc_len)
148 {
149         int id = ril_request_sms_new();
150
151         LOGD("Storing new SMS request in the queue at index %d\n", id);
152
153         ril_request_sms[id].aseq = aseq;
154         ril_request_sms[id].smsc_len = smsc_len;
155         ril_request_sms[id].pdu_len = pdu_len;
156
157         if(pdu != NULL) {
158                 ril_request_sms[id].pdu = malloc(pdu_len);
159                 memcpy(ril_request_sms[id].pdu, pdu, pdu_len);
160         }
161
162         if(smsc != NULL) {
163                 ril_request_sms[id].smsc = malloc(smsc_len);
164                 memcpy(ril_request_sms[id].smsc, smsc, smsc_len);
165         }
166
167         return id;
168 }
169
170 int ril_request_sms_get_id(unsigned char aseq)
171 {
172         int i;
173
174         for(i=0 ; i < 10 ; i++) {
175                 if(ril_request_sms[i].aseq == aseq) {
176                         return i;
177                 }
178         }
179
180         return -1;
181 }
182
183 int ril_request_sms_get_next(void)
184 {
185         int id = -1;
186         int i;
187
188         for(i=0 ; i < 10 ; i++) {
189                 if(ril_request_sms[i].aseq && ril_request_sms[i].pdu) {
190                         id = i;
191                 }
192         }
193
194         if(id < 0)
195                 LOGD("Nothing left on the queue!");
196         else
197                 LOGD("Next queued request is at id #%d\n", id);
198
199         return id;
200 }
201
202 int ril_request_sms_lock_acquire(void)
203 {
204         if(ril_request_sms_lock > 0) {
205                 return 0;
206         } else
207         {
208                 ril_request_sms_lock = 1;
209                 return 1;
210         }
211 }
212
213 void ril_request_sms_lock_release(void)
214 {
215         ril_request_sms_lock = 0;
216 }
217
218 /**
219  * Outgoing SMS functions
220  */
221
222 /**
223  * In: RIL_REQUEST_SEND_SMS
224  *   Send an SMS message.
225  *
226  * Out: IPC_SMS_SEND_MSG
227  */
228 void ril_request_send_sms(RIL_Token t, void *data, size_t datalen)
229 {
230         char **request = (char **) data;
231         char *pdu = request[1];
232         int pdu_len = pdu != NULL ? strlen(pdu) : 0;
233         char *smsc = request[0];
234         int smsc_len = smsc != NULL ? strlen(smsc) : 0;
235
236         if(!ril_request_sms_lock_acquire()) {
237                 LOGD("The SMS lock is already taken, adding req to the SMS queue");
238
239                 ril_request_sms_add(ril_request_get_id(t), pdu, pdu_len, smsc, smsc_len);
240                 return;
241         }
242
243         /* We first need to get SMS SVC before sending the message */
244         if(smsc == NULL) {
245                 LOGD("We have no SMSC, let's ask one");
246
247                 /* Enqueue the request */
248                 ril_request_sms_add(ril_request_get_id(t), pdu, pdu_len, NULL, 0);
249
250                 ipc_fmt_send_get(IPC_SMS_SVC_CENTER_ADDR, ril_request_get_id(t));
251
252         } else {
253                 ril_request_send_sms_complete(t, pdu, smsc);
254         }
255 }
256
257 /**
258  * In: RIL_REQUEST_SEND_SMS_EXPECT_MORE
259  *   Send an SMS message. Identical to RIL_REQUEST_SEND_SMS,
260  *   except that more messages are expected to be sent soon. If possible,
261  *   keep SMS relay protocol link open (eg TS 27.005 AT+CMMS command)
262  *
263  * Out: IPC_SMS_SEND_MSG
264  */
265 void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t datalen)
266 {
267         /* No particular treatment here, we already have a queue */
268         ril_request_send_sms(t, data, datalen);
269 }
270
271 /**
272  * Send the next SMS in the queue
273  */
274 int ril_request_send_sms_next(void)
275 {
276         int id = ril_request_sms_get_next();
277
278         char *request[2] = { NULL };
279         unsigned char aseq;
280         char *pdu;
281         char *smsc;
282
283         /* When calling this function, you assume you're done with the previous sms req */
284         ril_request_sms_lock_release();
285
286         if(id < 0) 
287                 return -1;
288
289         LOGD("Sending queued SMS!");
290
291         aseq = ril_request_sms[id].aseq;
292         pdu = ril_request_sms[id].pdu;
293         smsc = ril_request_sms[id].smsc;
294
295         request[0] = smsc;
296         request[1] = pdu;
297
298         /* We need to clear here to prevent infinite loop, but we can't free mem yet */
299         ril_request_sms_clear(id);
300
301         ril_request_send_sms(ril_request_get_token(aseq), (void *) request, sizeof(request));
302
303         if(pdu != NULL)
304                 free(pdu);
305
306         if(smsc != NULL)
307                 free(smsc);
308
309         return id;
310 }
311
312 /**
313  * Complete (continue) the send_sms request (do the real sending)
314  */
315 void ril_request_send_sms_complete(RIL_Token t, char *pdu, char *smsc)
316 {
317         struct ipc_sms_send_msg_request send_msg;
318         unsigned char send_msg_type = IPC_SMS_MSG_SINGLE;
319         int send_msg_len;
320
321         char *data;
322         int data_len;
323
324         char *pdu_dec;
325         unsigned char pdu_dec_len;
326
327         int pdu_len;
328         unsigned char smsc_len;
329
330         char *p;
331
332         if(pdu == NULL || smsc == NULL) {
333                 LOGE("Provided PDU or SMSC is NULL! Aborting");
334
335                 ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
336
337                 /* Release the lock so we can accept new requests */
338                 ril_request_sms_lock_release();
339                 /* Now send the next message in the queue if any */
340                 ril_request_send_sms_next();
341
342                 return;
343         }
344
345         /* Setting various len vars */
346         pdu_len = strlen(pdu);
347
348         if(pdu_len / 2 > 0xff) {
349                 LOGE("PDU is too large, aborting");
350
351                 ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
352
353                 /* Release the lock so we can accept new requests */
354                 ril_request_sms_lock_release();
355                 /* Now send the next message in the queue if any */
356                 ril_request_send_sms_next();
357
358                 return;
359         }
360
361         pdu_dec_len = pdu_len / 2;
362         smsc_len = smsc[0];
363         send_msg_len = sizeof(struct ipc_sms_send_msg_request);
364
365         /* Length of the final message */
366         data_len = pdu_dec_len + smsc_len + send_msg_len;
367
368         LOGD("Sending SMS message!");
369
370         LOGD("data_len is 0x%x + 0x%x + 0x%x = 0x%x\n", pdu_dec_len, smsc_len, send_msg_len, data_len);
371
372         pdu_dec = malloc(pdu_dec_len);
373         hex2bin(pdu, pdu_len, (unsigned char*)pdu_dec);
374
375         /* PDU operations */
376         int pdu_tp_da_index = 2;
377         unsigned char pdu_tp_da_len = pdu_dec[pdu_tp_da_index];
378
379         if(pdu_tp_da_len > 0xff / 2) {
380                 LOGE("PDU TP-DA Len failed (0x%x)\n", pdu_tp_da_len);
381                 goto pdu_end;
382         }
383
384         LOGD("PDU TP-DA Len is 0x%x\n", pdu_tp_da_len);
385
386         int pdu_tp_udh_index = pdu_tp_da_index + pdu_tp_da_len;
387         unsigned char pdu_tp_udh_len = pdu_dec[pdu_tp_udh_index];
388
389         if(pdu_tp_udh_len > 0xff / 2 || pdu_tp_udh_len < 5) {
390                 LOGE("PDU TP-UDH Len failed (0x%x)\n", pdu_tp_udh_len);
391                 goto pdu_end;
392         }
393
394         LOGD("PDU TP-UDH Len is 0x%x\n", pdu_tp_udh_len);
395
396         int pdu_tp_udh_num_index = pdu_tp_udh_index + 4;
397         unsigned char pdu_tp_udh_num = pdu_dec[pdu_tp_udh_num_index];
398
399         if(pdu_tp_udh_num > 0xf) {
400                 LOGE("PDU TP-UDH Num failed (0x%x)\n", pdu_tp_udh_num);
401                 goto pdu_end;
402         }
403
404         int pdu_tp_udh_seq_index = pdu_tp_udh_index + 5;
405         unsigned char pdu_tp_udh_seq = pdu_dec[pdu_tp_udh_seq_index];
406
407         if(pdu_tp_udh_seq > 0xf || pdu_tp_udh_seq > pdu_tp_udh_num) {
408                 LOGE("PDU TP-UDH Seq failed (0x%x)\n", pdu_tp_udh_seq);
409                 goto pdu_end;
410         }
411
412         LOGD("We are sending message %d on %d\n", pdu_tp_udh_seq, pdu_tp_udh_num);
413
414         if(pdu_tp_udh_num > 1) {
415                 LOGD("We are sending a multi-part message!");
416                 send_msg_type = IPC_SMS_MSG_MULTIPLE;
417         }
418
419 pdu_end:
420         /* Alloc and clean memory for the final message */
421         data = malloc(data_len);
422         memset(&send_msg, 0, sizeof(struct ipc_sms_send_msg_request));
423
424         /* Fill the IPC structure part of the message */
425         send_msg.type = IPC_SMS_TYPE_OUTGOING;
426         send_msg.msg_type = send_msg_type;
427         send_msg.length = (unsigned char) (pdu_dec_len + smsc_len + 1);
428         send_msg.smsc_len = smsc_len;
429
430         /* Copy the other parts of the message */
431         p = data;
432         memcpy(p, &send_msg, send_msg_len);
433         p +=  send_msg_len;
434         memcpy(p, (char *) (smsc + 1), smsc_len); // First SMSC bytes is length
435         p += smsc_len;
436         memcpy(p, pdu_dec, pdu_dec_len);
437
438         ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SMS_SEND_MSG, ipc_sms_send_msg_complete);
439
440         ipc_fmt_send(IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, (void *) data, data_len, ril_request_get_id(t));
441
442         free(pdu_dec);
443         free(data);
444 }
445
446 void ipc_sms_send_msg_complete(struct ipc_message_info *info)
447 {
448         struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
449
450         if(ipc_gen_phone_res_check(phone_res) < 0) {
451                 LOGE("IPC_GEN_PHONE_RES indicates error, abort request to RILJ");
452
453                 ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
454
455                 /* Release the lock so we can accept new requests */
456                 ril_request_sms_lock_release();
457                 /* Now send the next message in the queue if any */
458                 ril_request_send_sms_next();
459         }
460 }
461
462 /**
463  * In: IPC_SMS_SVC_CENTER_ADDR
464  *   SMSC: Service Center Address, needed to send an SMS
465  *
466  * Out: IPC_SMS_SEND_MSG
467  */
468 void ipc_sms_svc_center_addr(struct ipc_message_info *info)
469 {
470         int id = ril_request_sms_get_id(info->aseq);
471
472         char *pdu;
473         int pdu_len;
474
475         if(id < 0) {
476                 LOGE("The request wasn't queued, reporting generic error!");
477
478                 ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
479
480                 /* Release the lock so we can accept new requests */
481                 ril_request_sms_lock_release();
482                 /* Now send the next message in the queue if any */
483                 ril_request_send_sms_next();
484
485                 return;
486         }
487
488         LOGD("Completing the request");
489
490         pdu = ril_request_sms[id].pdu;
491         pdu_len = ril_request_sms[id].pdu_len;
492
493         /* We need to clear here to prevent infinite loop, but we can't free mem yet */
494         ril_request_sms_clear(id);
495
496         ril_request_send_sms_complete(ril_request_get_token(info->aseq), pdu, (char *) info->data);
497
498         /* Now it is safe to free mem */
499         if(pdu != NULL)
500                 free(pdu);
501 }
502
503 /**
504  * In: IPC_SMS_SEND_MSG
505  *   This comes to ACK the latest sent SMS message
506  */
507 void ipc_sms_send_msg(struct ipc_message_info *info)
508 {
509         struct ipc_sms_send_msg_response *report_msg = (struct ipc_sms_send_msg_response *) info->data;
510         RIL_SMS_Response response;
511
512         RIL_Errno ril_ack_err;
513
514         LOGD("Got ACK for msg_tpid #%d\n", report_msg->msg_tpid);
515
516         response.messageRef = report_msg->msg_tpid;
517         response.ackPDU = NULL;
518         ril_ack_err = ipc2ril_sms_ack_error(report_msg->error, &(response.errorCode));
519
520         ril_request_complete(ril_request_get_token(info->aseq), ril_ack_err, &response, sizeof(response));
521
522         /* Release the lock so we can accept new requests */
523         ril_request_sms_lock_release();
524         /* Now send the next message in the queue if any */
525         ril_request_send_sms_next();
526 }
527
528 /**
529  * Incoming SMS functions
530  */
531
532 int ipc_sms_incoming_msg_register(char *pdu, int length, unsigned char type, unsigned char tpid)
533 {
534         struct ipc_sms_incoming_msg_info *incoming_msg;
535         struct list_head *list_end;
536         struct list_head *list;
537
538         incoming_msg = calloc(1, sizeof(struct ipc_sms_incoming_msg_info));
539         if(incoming_msg == NULL)
540                 return -1;
541
542         incoming_msg->pdu = pdu;
543         incoming_msg->length = length;
544         incoming_msg->type = type;
545         incoming_msg->tpid = tpid;
546
547         list_end = ril_data.incoming_sms;
548         while(list_end != NULL && list_end->next != NULL)
549                 list_end = list_end->next;
550
551         list = list_head_alloc((void *) incoming_msg, list_end, NULL);
552
553         if(ril_data.incoming_sms == NULL)
554                 ril_data.incoming_sms = list;
555
556         return 0;
557 }
558
559 void ipc_sms_incoming_msg_unregister(struct ipc_sms_incoming_msg_info *incoming_msg)
560 {
561         struct list_head *list;
562
563         if(incoming_msg == NULL)
564                 return;
565
566         list = ril_data.incoming_sms;
567         while(list != NULL) {
568                 if(list->data == (void *) incoming_msg) {
569                         memset(incoming_msg, 0, sizeof(struct ipc_sms_incoming_msg_info));
570                         free(incoming_msg);
571
572                         if(list == ril_data.incoming_sms)
573                                 ril_data.incoming_sms = list->next;
574
575                         list_head_free(list);
576
577                         break;
578                 }
579 list_continue:
580                 list = list->next;
581         }
582 }
583
584 struct ipc_sms_incoming_msg_info *ipc_sms_incoming_msg_info_find(void)
585 {
586         struct ipc_sms_incoming_msg_info *incoming_msg;
587         struct list_head *list;
588
589         list = ril_data.incoming_sms;
590         while(list != NULL) {
591                 incoming_msg = (struct ipc_sms_incoming_msg_info *) list->data;
592                 if(incoming_msg == NULL)
593                         goto list_continue;
594
595                 return incoming_msg;
596
597 list_continue:
598                 list = list->next;
599         }
600
601         return NULL;
602 }
603
604 /**
605  * In: IPC_SMS_INCOMING_MSG
606  *   Message to notify an incoming message, with PDU
607  *
608  * Out: RIL_UNSOL_RESPONSE_NEW_SMS or RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT
609  *   Notify RILJ about the incoming message
610  */
611
612 void ipc_sms_incoming_msg_complete(char *pdu, int length, unsigned char type, unsigned char tpid)
613 {
614         if(pdu == NULL || length <= 0)
615                 return;
616
617         ril_data.state.sms_incoming_msg_tpid = tpid;
618
619         if(type == IPC_SMS_TYPE_POINT_TO_POINT) {
620                 ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS, pdu, length);
621         } else if(type == IPC_SMS_TYPE_STATUS_REPORT) {
622                 ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, pdu, length);
623         } else {
624                 LOGE("Unhandled message type: %x", type);
625         }
626
627         free(pdu);
628 }
629
630 void ipc_sms_incoming_msg(struct ipc_message_info *info)
631 {
632         struct ipc_sms_incoming_msg *msg;
633         unsigned char *pdu_hex;
634         char *pdu;
635         int length;
636         int rc;
637
638         if(info == NULL || info->data == NULL || info->length < sizeof(struct ipc_sms_incoming_msg))
639                 return;
640
641         msg = (struct ipc_sms_incoming_msg *) info->data;
642         pdu_hex = ((unsigned char *) info->data + sizeof(struct ipc_sms_incoming_msg));
643
644         length = msg->length * 2 + 1;
645         pdu = (char *) calloc(1, length);
646
647         bin2hex(pdu_hex, msg->length, pdu);
648
649         if(ril_data.state.sms_incoming_msg_tpid != 0) {
650                 LOGD("Another message is waiting ACK, queuing");
651                 rc = ipc_sms_incoming_msg_register(pdu, length, msg->type, msg->msg_tpid);
652                 if(rc < 0)
653                         LOGE("Unable to register incoming msg");
654
655                 return;
656         }
657
658         ipc_sms_incoming_msg_complete(pdu, length, msg->type, msg->msg_tpid);
659 }
660
661 /**
662  * In: RIL_REQUEST_SMS_ACKNOWLEDGE
663  *   Acknowledge successful or failed receipt of SMS previously indicated
664  *   via RIL_UNSOL_RESPONSE_NEW_SMS
665  *
666  * Out: IPC_SMS_DELIVER_REPORT
667  *   Sends a SMS delivery report
668  */
669 void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t length)
670 {
671         struct ipc_sms_incoming_msg_info *incoming_msg;
672         struct ipc_sms_deliver_report_request report_msg;
673         int success, fail_cause;
674
675         if(data == NULL || length < 2 * sizeof(int))
676                 return;
677
678         success = ((int *) data)[0];
679         fail_cause = ((int *) data)[1];
680
681         if(ril_data.state.sms_incoming_msg_tpid == 0) {
682                 LOGE("There is no SMS message to ACK!");
683                 ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
684
685                 return;
686         }
687
688         report_msg.type = IPC_SMS_TYPE_STATUS_REPORT;
689         report_msg.error = ril2ipc_sms_ack_error(success, fail_cause);
690         report_msg.msg_tpid = ril_data.state.sms_incoming_msg_tpid;
691         report_msg.unk = 0;
692
693         ipc_gen_phone_res_expect_to_abort(ril_request_get_id(t), IPC_SMS_DELIVER_REPORT);
694
695         ipc_fmt_send(IPC_SMS_DELIVER_REPORT, IPC_TYPE_EXEC, (void *) &report_msg, sizeof(report_msg), ril_request_get_id(t));
696
697         ril_data.state.sms_incoming_msg_tpid = 0;
698
699         incoming_msg = ipc_sms_incoming_msg_info_find();
700         if(incoming_msg == NULL)
701                 return;
702
703         ipc_sms_incoming_msg_complete(incoming_msg->pdu, incoming_msg->length, incoming_msg->type, incoming_msg->tpid);
704         ipc_sms_incoming_msg_unregister(incoming_msg);
705 }
706
707 /**
708  * In: IPC_SMS_DELIVER_REPORT
709  *   Attest that the modem successfully sent our SMS recv ACK 
710  */
711 void ipc_sms_deliver_report(struct ipc_message_info *info)
712 {
713         struct ipc_sms_deliver_report_response *report_msg;
714         RIL_Errno e;
715         int error_code;
716
717         if(info == NULL || info->data == NULL || info->length < sizeof(struct ipc_sms_deliver_report_response))
718                 return;
719
720         report_msg = (struct ipc_sms_deliver_report_response *) info->data;
721         e = ipc2ril_sms_ack_error(report_msg->error, &error_code);
722
723         ril_request_complete(ril_request_get_token(info->aseq), e, NULL, 0);
724 }
725
726 /**
727  * Apparently non-SMS-messages-related function
728  */
729
730 void ipc_sms_device_ready(struct ipc_message_info *info)
731 {
732 #if RIL_VERSION >= 7
733         if(ril_data.state.radio_state == RADIO_STATE_ON) {
734 #else
735         if(ril_data.state.radio_state == RADIO_STATE_SIM_READY) {
736 #endif
737                 ipc_fmt_send(IPC_SMS_DEVICE_READY, IPC_TYPE_SET, NULL, 0, info->aseq);
738         }
739
740         ril_tokens_check();
741 }