summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--samsung-ril.c11
-rw-r--r--samsung-ril.h8
-rw-r--r--ss.c210
-rw-r--r--util.h2
5 files changed, 232 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
index e088c67..89da396 100644
--- a/Android.mk
+++ b/Android.mk
@@ -31,6 +31,7 @@ LOCAL_SRC_FILES := \
disp.c \
misc.c \
sat.c \
+ ss.c \
sim.c \
net.c \
sms.c \
diff --git a/samsung-ril.c b/samsung-ril.c
index 7d08348..fc88514 100644
--- a/samsung-ril.c
+++ b/samsung-ril.c
@@ -36,6 +36,7 @@
*
* General:
* - USSD codes
+ * - SIM SMS I/O
* - ipc_disp_icon_info: trace on RILJ & emulate RIl_REQUEST_SIGNAL_STRENGTH
* - airplane mode: trace: sys nodes?
* - look at /sys nodes for data and airplane
@@ -203,6 +204,10 @@ void ipc_fmt_dispatch(struct ipc_message_info *info)
case IPC_SAT_ENVELOPE_CMD:
respondSatEnvelopeCmd(info);
break;
+ /* SS */
+ case IPC_SS_USSD:
+ ipc_ss_ussd(info);
+ break;
/* SIM */
case IPC_SEC_PIN_STATUS:
ipc_sec_pin_status(info);
@@ -352,6 +357,12 @@ void onRequest(int request, void *data, size_t datalen, RIL_Token t)
case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM:
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
break;
+ /* SS */
+ case RIL_REQUEST_SEND_USSD:
+ ril_request_send_ussd(t, data, datalen);
+ break;
+ case RIL_REQUEST_CANCEL_USSD:
+ ril_request_cancel_ussd(t, data, datalen);
/* SIM */
case RIL_REQUEST_GET_SIM_STATUS:
ril_request_sim_status(t);
diff --git a/samsung-ril.h b/samsung-ril.h
index 0226695..2294cc4 100644
--- a/samsung-ril.h
+++ b/samsung-ril.h
@@ -177,6 +177,8 @@ struct ril_state {
struct ipc_net_current_plmn plmndata;
struct ipc_gprs_pdp_context gprs_context;
+
+ unsigned char ussd_state;
};
void ril_globals_init(void);
@@ -233,6 +235,12 @@ void requestSatSendTerminalResponse(RIL_Token t, void *data, size_t datalen);
void requestSatSendEnvelopeCommand(RIL_Token t, void *data, size_t datalen);
void respondSatEnvelopeCmd(struct ipc_message_info *request);
+/* SS */
+
+void ril_request_send_ussd(RIL_Token t, void *data, size_t datalen);
+void ril_request_cancel_ussd(RIL_Token t, void *data, size_t datalen);
+void ipc_ss_ussd(struct ipc_message_info *info);
+
/* SIM */
void ipc_sec_pin_status(struct ipc_message_info *info);
void ril_request_sim_status(RIL_Token t);
diff --git a/ss.c b/ss.c
new file mode 100644
index 0000000..44a16cc
--- /dev/null
+++ b/ss.c
@@ -0,0 +1,210 @@
+/**
+ * This file is part of samsung-ril.
+ *
+ * Copyright (C) 2012 Paul Kocialkowski <contact@oaulk.fr>
+ *
+ * samsung-ril is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * samsung-ril is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with samsung-ril. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define LOG_TAG "RIL-SS"
+#include <utils/Log.h>
+
+#include "samsung-ril.h"
+#include "util.h"
+
+void ipc_ss_ussd_complete(struct ipc_message_info *info)
+{
+ struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
+ int rc;
+
+ rc = ipc_gen_phone_res_check(phone_res);
+ if(rc < 0) {
+ LOGE("There was an error, aborting USSD request");
+
+ RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ ril_state.ussd_state = 0;
+
+ return;
+ }
+
+ RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, NULL, 0);
+}
+
+void ril_request_send_ussd(RIL_Token t, void *data, size_t datalen)
+{
+ char *data_enc = NULL;
+ int data_enc_len = 0;
+
+ char *message =NULL;
+ struct ipc_ss_ussd *ussd = NULL;
+
+ int message_size = 0xc0;
+
+ switch(ril_state.ussd_state) {
+ case 0:
+ case IPC_SS_USSD_NO_ACTION_REQUIRE:
+ case IPC_SS_USSD_TERMINATED_BY_NET:
+ case IPC_SS_USSD_OTHER_CLIENT:
+ case IPC_SS_USSD_NOT_SUPPORT:
+ case IPC_SS_USSD_TIME_OUT:
+ LOGD("USSD Tx encoding is GSM7");
+
+ data_enc_len = ascii2gsm7(data, &data_enc, datalen);
+ // message_size = data_enc_len + sizeof(struct ipc_ss_ussd);
+
+ if(data_enc_len > message_size) {
+ LOGE("USSD message size is too long, aborting");
+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ free(data_enc);
+
+ return;
+ }
+
+ message = malloc(message_size);
+ memset(message, 0, message_size);
+
+ ussd = (struct ipc_ss_ussd *) message;
+ ussd->state = IPC_SS_USSD_NO_ACTION_REQUIRE;
+ ussd->dcs = 0x0f; // GSM7 in that case
+ ussd->length = data_enc_len;
+
+ memcpy((void *) (message + sizeof(struct ipc_ss_ussd)), data_enc, data_enc_len);
+
+ free(data_enc);
+
+ break;
+ case IPC_SS_USSD_ACTION_REQUIRE:
+ default:
+ LOGD("USSD Tx encoding is ASCII");
+
+ data_enc_len = asprintf(&data_enc, "%s", data);
+ // message_size = data_enc_len + sizeof(struct ipc_ss_ussd);
+
+ if(data_enc_len > message_size) {
+ LOGE("USSD message size is too long, aborting");
+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ free(data_enc);
+
+ return;
+ }
+
+ message = malloc(message_size);
+ memset(message, 0, message_size);
+
+ ussd = (struct ipc_ss_ussd *) message;
+ ussd->state = IPC_SS_USSD_ACTION_REQUIRE;
+ ussd->dcs = 0x0f; // ASCII in that case
+ ussd->length = data_enc_len;
+
+ memcpy((void *) (message + sizeof(struct ipc_ss_ussd)), data_enc, data_enc_len);
+
+ free(data_enc);
+
+ break;
+ }
+
+ if(message == NULL) {
+ LOGE("USSD message is empty, aborting");
+
+ RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return;
+ }
+
+ ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_SS_USSD,
+ ipc_ss_ussd_complete);
+
+ ipc_fmt_send(IPC_SS_USSD, IPC_TYPE_EXEC, (void *) message, message_size, reqGetId(t));
+}
+
+void ril_request_cancel_ussd(RIL_Token t, void *data, size_t datalen)
+{
+ struct ipc_ss_ussd ussd;
+
+ memset(&ussd, 0, sizeof(ussd));
+
+ ussd.state = IPC_SS_USSD_TERMINATED_BY_NET;
+ ril_state.ussd_state = IPC_SS_USSD_TERMINATED_BY_NET;
+
+ ipc_gen_phone_res_expect_to_complete(reqGetId(t), IPC_SS_USSD);
+
+ ipc_fmt_send(IPC_SS_USSD, IPC_TYPE_EXEC, (void *) &ussd, sizeof(ussd), reqGetId(t));
+}
+
+void ipc2ril_ussd_state(struct ipc_ss_ussd *ussd, char *message[2])
+{
+ switch(ussd->state) {
+ case IPC_SS_USSD_NO_ACTION_REQUIRE:
+ asprintf(&message[0], "%d", 0);
+ break;
+ case IPC_SS_USSD_ACTION_REQUIRE:
+ asprintf(&message[0], "%d", 1);
+ break;
+ case IPC_SS_USSD_TERMINATED_BY_NET:
+ asprintf(&message[0], "%d", 2);
+ break;
+ case IPC_SS_USSD_OTHER_CLIENT:
+ asprintf(&message[0], "%d", 3);
+ break;
+ case IPC_SS_USSD_NOT_SUPPORT:
+ asprintf(&message[0], "%d", 4);
+ break;
+ case IPC_SS_USSD_TIME_OUT:
+ asprintf(&message[0], "%d", 5);
+ break;
+ }
+}
+
+void ipc_ss_ussd(struct ipc_message_info *info)
+{
+ char *data_dec = NULL;
+ int data_dec_len = 0;
+
+ char *message[2];
+
+ struct ipc_ss_ussd *ussd = NULL;
+ unsigned char state;
+
+ memset(message, 0, sizeof(message) / sizeof(char *));
+
+ ussd = (struct ipc_ss_ussd *) info->data;
+
+ ipc2ril_ussd_state(ussd, message);
+
+ ril_state.ussd_state = ussd->state;
+
+ if(ussd->length > 0 && info->length > 0 && info->data != NULL) {
+ switch(ussd->dcs) {
+ case 0x0f:
+ LOGD("USSD Rx encoding is GSM7");
+
+ data_dec_len = gsm72ascii(info->data + sizeof(struct ipc_ss_ussd), &data_dec, info->length - sizeof(struct ipc_ss_ussd));
+ asprintf(&message[1], "%s", data_dec);
+ message[1][data_dec_len] = '\0';
+
+ break;
+ default:
+ LOGD("USSD Rx encoding is unknown, assuming ASCII");
+
+ data_dec_len = info->length - sizeof(struct ipc_ss_ussd);
+ asprintf(&message[1], "%s", info->data + sizeof(struct ipc_ss_ussd));
+ message[1][data_dec_len] = '\0';
+ break;
+ }
+ }
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_ON_USSD, message, sizeof(message));
+}
diff --git a/util.h b/util.h
index 34c4cd5..6eedbbc 100644
--- a/util.h
+++ b/util.h
@@ -23,6 +23,8 @@
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);
void hex_dump(void *data, int size);
#endif