diff options
-rw-r--r-- | ipc.c | 2 | ||||
-rw-r--r-- | samsung-ril.h | 6 | ||||
-rw-r--r-- | sms.c | 46 | ||||
-rw-r--r-- | ss.c | 2 | ||||
-rw-r--r-- | util.c | 151 | ||||
-rw-r--r-- | util.h | 4 |
6 files changed, 208 insertions, 3 deletions
@@ -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 */ @@ -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 */ @@ -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); @@ -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, ×tamp, 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; +} @@ -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, |