summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2013-09-29 14:51:10 +0200
committerPaul Kocialkowski <contact@paulk.fr>2013-09-29 14:51:10 +0200
commitd69f5490530cf7fc78b1cbf52827471039d8a6cb (patch)
tree9dc75b0e570e347ec514b9efb8fd07100a1b9b0d
parent0bad2567392b7d98912f59353bf09937b89eff2f (diff)
downloadhardware_replicant_libsamsung-ril-d69f5490530cf7fc78b1cbf52827471039d8a6cb.tar.gz
hardware_replicant_libsamsung-ril-d69f5490530cf7fc78b1cbf52827471039d8a6cb.tar.bz2
hardware_replicant_libsamsung-ril-d69f5490530cf7fc78b1cbf52827471039d8a6cb.zip
Send internal SMS to alert the user when an important crash just happened
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
-rw-r--r--ipc.c2
-rw-r--r--samsung-ril.h6
-rw-r--r--sms.c46
-rw-r--r--ss.c2
-rw-r--r--util.c151
-rw-r--r--util.h4
6 files changed, 208 insertions, 3 deletions
diff --git a/ipc.c b/ipc.c
index c7d3513..c427295 100644
--- 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;
diff --git a/samsung-ril.h b/samsung-ril.h
index d9b4055..6fdc686 100644
--- a/samsung-ril.h
+++ b/samsung-ril.h
@@ -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
--- 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
--- 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
--- 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
--- 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,