Send internal SMS to alert the user when an important crash just happened
authorPaul Kocialkowski <contact@paulk.fr>
Sun, 29 Sep 2013 12:51:10 +0000 (14:51 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Sun, 29 Sep 2013 12:51:10 +0000 (14:51 +0200)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
ipc.c
samsung-ril.h
sms.c
ss.c
util.c
util.h

diff --git a/ipc.c b/ipc.c
index c7d3513..c427295 100644 (file)
--- a/ipc.c
+++ b/ipc.c
@@ -89,6 +89,7 @@ int ipc_fmt_read_loop(struct ril_client *client)
 
 error:
        ril_radio_state_update(RADIO_STATE_UNAVAILABLE);
+       ril_sms_send(RIL_SMS_NUMBER, "Samsung-RIL: The modem just crashed, please reboot your device if you can't get service back.");
 
        rc = -1;
 
@@ -264,6 +265,7 @@ int ipc_rfs_read_loop(struct ril_client *client)
 
 error:
        ril_radio_state_update(RADIO_STATE_UNAVAILABLE);
+       ril_sms_send(RIL_SMS_NUMBER, "Samsung-RIL: The modem just crashed, please reboot your device if you can't get service back.");
 
        rc = -1;
 
index d9b4055..6fdc686 100644 (file)
@@ -59,6 +59,9 @@
 #define RIL_TOKEN_DATA_WAITING (RIL_Token) 0xff
 #define RIL_TOKEN_NULL         (RIL_Token) 0x00
 
+#define RIL_SMS_TPID           0xff
+#define RIL_SMS_NUMBER         "0123456789"
+
 #define RIL_CLIENT_MAX_TRIES   7
 
 /*
@@ -186,6 +189,7 @@ struct ril_state {
        unsigned char ussd_state;
 
        unsigned char sms_incoming_msg_tpid;
+       unsigned char ril_sms_tpid;
 };
 
 /*
@@ -428,6 +432,8 @@ void ipc_sms_save_msg(struct ipc_message_info *info);
 void ril_request_delete_sms_on_sim(RIL_Token token, void *data, size_t size);
 void ipc_sms_del_msg(struct ipc_message_info *info);
 
+int ril_sms_send(char *number, char *message);
+
 void ipc_sms_device_ready(struct ipc_message_info *info);
 
 /* Call */
diff --git a/sms.c b/sms.c
index 0b30f6e..0a1f310 100644 (file)
--- a/sms.c
+++ b/sms.c
@@ -671,6 +671,16 @@ void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t length)
        if (data == NULL || length < 2 * sizeof(int))
                goto error;
 
+       if (ril_data.state.sms_incoming_msg_tpid == ril_data.state.ril_sms_tpid) {
+               ril_data.state.ril_sms_tpid = 0;
+
+               ril_request_complete(t, RIL_E_SUCCESS, NULL, 0);
+
+               ipc_sms_incoming_msg_next();
+
+               return;
+       }
+
        if (ril_radio_state_complete(RADIO_STATE_OFF, t))
                return;
 
@@ -855,6 +865,42 @@ void ipc_sms_del_msg(struct ipc_message_info *info)
 }
 
 /*
+ * RIL SMS
+ */
+
+int ril_sms_send(char *number, char *message)
+{
+       char *pdu;
+       size_t length;
+       int rc;
+
+       pdu = pdu_create(number, message);
+       if (pdu == NULL)
+               return -1;
+
+       length = strlen(pdu);
+       if (length == 0)
+               return -1;
+
+       ril_data.state.ril_sms_tpid = RIL_SMS_TPID;
+
+       if (ril_data.state.sms_incoming_msg_tpid != 0) {
+               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) {
+                       LOGE("Unable to register incoming msg");
+                       return -1;
+               }
+
+               return 0;
+       }
+
+       ipc_sms_incoming_msg_complete(pdu, length, IPC_SMS_TYPE_POINT_TO_POINT, ril_data.state.ril_sms_tpid);
+
+       return 0;
+}
+
+/*
  * Apparently non-SMS-messages-related function
  */
 
diff --git a/ss.c b/ss.c
index d05fa2f..d28221c 100644 (file)
--- a/ss.c
+++ b/ss.c
@@ -68,7 +68,7 @@ void ril_request_send_ussd(RIL_Token t, void *data, size_t length)
                case IPC_SS_USSD_TIME_OUT:
                        LOGD("USSD Tx encoding is GSM7");
 
-                       data_enc_len = ascii2gsm7(data, (unsigned char**)&data_enc, length);
+                       data_enc_len = ascii2gsm7_ussd(data, (unsigned char**)&data_enc, length);
                        if (data_enc_len > message_size) {
                                LOGE("USSD message size is too long, aborting");
                                ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
diff --git a/util.c b/util.c
index cd57284..e0943c1 100644 (file)
--- a/util.c
+++ b/util.c
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <time.h>
 
 #define LOG_TAG "RIL-UTIL"
 #include <utils/Log.h>
@@ -165,7 +166,7 @@ int gsm72ascii(unsigned char *data, char **data_dec, int length)
 /*
  * Converts ASCII (7 bits) data to GSM7 (8 bits)
  */
-int ascii2gsm7(char *data, unsigned char **data_enc, int length)
+int ascii2gsm7_ussd(char *data, unsigned char **data_enc, int length)
 {
        int d_off, d_pos, a_off, a_pos = 0;
        int i;
@@ -212,6 +213,50 @@ int ascii2gsm7(char *data, unsigned char **data_enc, int length)
        return enc_length;
 }
 
+size_t ascii2gsm7(char *ascii, unsigned char *gsm7)
+{
+       int ascii_length;
+       int gsm7_length;
+       int offset;
+
+       unsigned char *p;
+       int i;
+
+       if (ascii == NULL)
+               return -1;
+
+       ascii_length = strlen(ascii);
+
+       gsm7_length = ((ascii_length * 7) - (ascii_length * 7) % 8) / 8;
+       gsm7_length = (ascii_length * 7) % 8 > 0 ? gsm7_length + 1 : gsm7_length;
+
+       if (gsm7 == NULL)
+               return gsm7_length;
+
+       memset(gsm7, 0, gsm7_length);
+
+       offset = 0;
+       p = gsm7;
+
+       for (i = 0; i < ascii_length; i++) {
+               *p |= ((ascii[i] & 0x7f) >> offset) & 0xff;
+
+               if (offset) {
+                       p--;
+                       *p |= ((ascii[i] & ((1 << (offset + 1)) - 1)) << (8 - offset)) & 0xff;
+                       p++;
+               }
+
+               if (offset < 7)
+                       p++;
+
+               offset++;
+               offset %= 8;
+       }
+
+       return gsm7_length;
+}
+
 void hex_dump(void *data, int size)
 {
        /* dumps size bytes of *data to stdout. Looks like:
@@ -335,3 +380,107 @@ SmsCodingScheme sms_get_coding_scheme(int dataCoding)
        return SMS_CODING_SCHEME_UNKNOWN;
 }
 
+char *pdu_create(char *number, char *message)
+{
+       unsigned char pdu_first[] = { 0x00, 0x04 };
+       unsigned char pdu_toa[] = { 0x91 };
+       unsigned char pdu_tp[] = { 0x00, 0x00 };
+       unsigned char timestamp[7] = { 0 };
+       time_t t;
+       struct tm *tm;
+
+       unsigned char number_length;
+       unsigned char message_length;
+
+       unsigned char *buffer = NULL;
+       char *pdu = NULL;
+       size_t length = 0;
+
+       unsigned char *p;
+       unsigned char a;
+       char c;
+       int i;
+
+       if (number == NULL || message == NULL || strlen(message) > 0xff)
+               return NULL;
+
+       number_length = strlen(number) & 0xff;
+       if (number_length % 2 != 0)
+               number_length++;
+       number_length /= 2;
+
+       message_length = ascii2gsm7(message, NULL) & 0xff;
+
+       length = sizeof(pdu_first) + sizeof(number_length) + sizeof(pdu_toa) + number_length + sizeof(pdu_tp) + sizeof(timestamp) + sizeof(message_length) + message_length;
+       buffer = calloc(1, length);
+
+       p = (unsigned char *) buffer;
+
+       memcpy(p, &pdu_first, sizeof(pdu_first));
+       p += sizeof(pdu_first);
+
+       number_length = strlen(number) & 0xff;
+
+       memcpy(p, &number_length, sizeof(number_length));
+       p += sizeof(number_length);
+       memcpy(p, &pdu_toa, sizeof(pdu_toa));
+       p += sizeof(pdu_toa);
+
+       i = 0;
+       while (i < number_length) {
+               c = number[i++];
+
+               if (isdigit(c))
+                       *p = (c - '0') & 0x0f;
+
+               if (i < number_length) {
+                       c = number[i++];
+                       if (isdigit(c))
+                               *p |= ((c - '0') & 0x0f) << 4;
+               } else {
+                       *p |= 0xf << 4;
+               }
+
+               p++;
+       }
+
+       memcpy(p, &pdu_tp, sizeof(pdu_tp));
+       p += sizeof(pdu_tp);
+
+       t = time(NULL);
+       tm = localtime(&t);
+
+       a = (tm->tm_year - 100);
+       timestamp[0] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
+       a = (tm->tm_mon + 1);
+       timestamp[1] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
+       a = tm->tm_mday;
+       timestamp[2] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
+       a = tm->tm_hour;
+       timestamp[3] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
+       a = tm->tm_min;
+       timestamp[4] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
+       a = tm->tm_sec;
+       timestamp[5] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
+       a = (unsigned char) (-timezone / 900);
+       timestamp[6] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
+
+       memcpy(p, &timestamp, sizeof(timestamp));
+       p += sizeof(timestamp);
+
+       message_length = strlen(message) & 0xff;
+
+       memcpy(p, &message_length, sizeof(message_length));
+       p += sizeof(message_length);
+
+       ascii2gsm7(message, p);
+       p += message_length;
+
+       pdu = (char *) calloc(1, length * 2 + 1);
+
+       bin2hex(buffer, length, pdu);
+
+       free(buffer);
+
+       return pdu;
+}
diff --git a/util.h b/util.h
index 67ca939..b962e46 100644 (file)
--- a/util.h
+++ b/util.h
@@ -33,9 +33,11 @@ void list_head_free(struct list_head *list);
 void bin2hex(const unsigned char *data, int length, char *buf);
 void hex2bin(const char *data, int length, unsigned char *buf);
 int gsm72ascii(unsigned char *data, char **data_dec, int length);
-int ascii2gsm7(char *data, unsigned char **data_enc, int length);
+int ascii2gsm7_ussd(char *data, unsigned char **data_enc, int length);
+size_t ascii2gsm7(char *ascii, unsigned char *gsm7);
 void hex_dump(void *data, int size);
 int utf8_write(char *utf8, int offset, int v);
+char *pdu_create(char *number, char *message);
 
 typedef enum {
        SMS_CODING_SCHEME_UNKNOWN = 0,