summaryrefslogtreecommitdiffstats
path: root/samsung-ril.c
diff options
context:
space:
mode:
Diffstat (limited to 'samsung-ril.c')
-rw-r--r--samsung-ril.c1812
1 files changed, 1254 insertions, 558 deletions
diff --git a/samsung-ril.c b/samsung-ril.c
index 245685e..43784a7 100644
--- a/samsung-ril.c
+++ b/samsung-ril.c
@@ -2,7 +2,7 @@
* This file is part of Samsung-RIL.
*
* Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
- * Copyright (C) 2011-2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2011-2014 Paul Kocialkowski <contact@paulk.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
@@ -18,805 +18,1501 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
+#include <ctype.h>
+
#define LOG_TAG "RIL"
-#include "samsung-ril.h"
-#include "util.h"
+#include <utils/Log.h>
+#include <telephony/ril.h>
+
+#include <samsung-ril.h>
+#include <utils.h>
/*
* RIL data
*/
-struct ril_data ril_data;
+struct ril_data *ril_data = NULL;
/*
- * RIL requests
+ * RIL clients
*/
-int ril_request_id_get(void)
-{
- ril_data.request_id++;
- ril_data.request_id %= 0xff;
+struct ril_client *ril_clients[] = {
+ &ipc_fmt_client,
+ &ipc_rfs_client,
+ &srs_client,
+};
- return ril_data.request_id;
-}
+unsigned int ril_clients_count = sizeof(ril_clients) /
+ sizeof(struct ril_client *);
+
+struct ipc_dispatch_handler ipc_fmt_dispatch_handlers[] = {
+ /* Power */
+ {
+ .command = IPC_PWR_PHONE_PWR_UP,
+ .handler = ipc_pwr_phone_pwr_up,
+ },
+ {
+ .command = IPC_PWR_PHONE_RESET,
+ .handler = ipc_pwr_phone_reset,
+ },
+ {
+ .command = IPC_PWR_PHONE_STATE,
+ .handler = ipc_pwr_phone_state,
+ },
+ /* Call */
+ {
+ .command = IPC_CALL_INCOMING,
+ .handler = ipc_call_incoming,
+ },
+ {
+ .command = IPC_CALL_STATUS,
+ .handler = ipc_call_status,
+ },
+ {
+ .command = IPC_CALL_LIST,
+ .handler = ipc_call_list,
+ },
+ {
+ .command = IPC_CALL_BURST_DTMF,
+ .handler = ipc_call_burst_dtmf,
+ },
+ /* SMS */
+ {
+ .command = IPC_SMS_SEND_MSG,
+ .handler = ipc_sms_send_msg,
+ },
+ {
+ .command = IPC_SMS_INCOMING_MSG,
+ .handler = ipc_sms_incoming_msg,
+ },
+ {
+ .command = IPC_SMS_SAVE_MSG,
+ .handler = ipc_sms_save_msg,
+ },
+ {
+ .command = IPC_SMS_DEL_MSG,
+ .handler = ipc_sms_del_msg,
+ },
+ {
+ .command = IPC_SMS_DELIVER_REPORT,
+ .handler = ipc_sms_deliver_report,
+ },
+ {
+ .command = IPC_SMS_SVC_CENTER_ADDR,
+ .handler = ipc_sms_svc_center_addr,
+ },
+ /* SIM */
+ {
+ .command = IPC_SEC_PIN_STATUS,
+ .handler = ipc_sec_pin_status,
+ },
+ {
+ .command = IPC_SEC_PHONE_LOCK,
+ .handler = ipc_sec_phone_lock,
+ },
+ {
+ .command = IPC_SEC_RSIM_ACCESS,
+ .handler = ipc_sec_rsim_access,
+ },
+ {
+ .command = IPC_SEC_SIM_ICC_TYPE,
+ .handler = ipc_sec_sim_icc_type,
+ },
+ {
+ .command = IPC_SEC_LOCK_INFOMATION,
+ .handler = ipc_sec_lock_infomation,
+ },
+ /* Network */
+ {
+ .command = IPC_DISP_ICON_INFO,
+ .handler = ipc_disp_icon_info,
+ },
+ {
+ .command = IPC_DISP_RSSI_INFO,
+ .handler = ipc_disp_rssi_info,
+ },
+ {
+ .command = IPC_NET_PLMN_SEL,
+ .handler = ipc_net_plmn_sel,
+ },
+ {
+ .command = IPC_NET_SERVING_NETWORK,
+ .handler = ipc_net_serving_network,
+ },
+ {
+ .command = IPC_NET_PLMN_LIST,
+ .handler = ipc_net_plmn_list,
+ },
+ {
+ .command = IPC_NET_REGIST,
+ .handler = ipc_net_regist,
+ },
+ {
+ .command = IPC_NET_MODE_SEL,
+ .handler = ipc_net_mode_sel,
+ },
+ /* Misc */
+ {
+ .command = IPC_MISC_ME_VERSION,
+ .handler = ipc_misc_me_version,
+ },
+ {
+ .command = IPC_MISC_ME_IMSI,
+ .handler = ipc_misc_me_imsi,
+ },
+ {
+ .command = IPC_MISC_ME_SN,
+ .handler = ipc_misc_me_sn,
+ },
+ {
+ .command = IPC_MISC_TIME_INFO,
+ .handler = ipc_misc_time_info,
+ },
+ /* OEM */
+ {
+ .command = IPC_SVC_DISPLAY_SCREEN,
+ .handler = ipc_svc_display_screen,
+ },
+ /* Data */
+ {
+ .command = IPC_GPRS_PS,
+ .handler = ipc_gprs_ps,
+ },
+ {
+ .command = IPC_GPRS_PDP_CONTEXT,
+ .handler = ipc_gprs_pdp_context,
+ },
+ {
+ .command = IPC_GPRS_IP_CONFIGURATION,
+ .handler = ipc_gprs_ip_configuration,
+ },
+ {
+ .command = IPC_GPRS_HSDPA_STATUS,
+ .handler = ipc_gprs_hsdpa_status,
+ },
+ {
+ .command = IPC_GPRS_CALL_STATUS,
+ .handler = ipc_gprs_call_status,
+ },
+ /* GEN */
+ {
+ .command = IPC_GEN_PHONE_RES,
+ .handler = ipc_gen_phone_res,
+ },
+};
+
+unsigned int ipc_fmt_dispatch_handlers_count = sizeof(ipc_fmt_dispatch_handlers) /
+ sizeof(struct ipc_dispatch_handler);
+
+struct ipc_dispatch_handler ipc_rfs_dispatch_handlers[] = {
+ {
+ .command = IPC_RFS_NV_READ_ITEM,
+ .handler = ipc_rfs_nv_read_item,
+ },
+ {
+ .command = IPC_RFS_NV_WRITE_ITEM,
+ .handler = ipc_rfs_nv_write_item,
+ },
+};
+
+unsigned int ipc_rfs_dispatch_handlers_count = sizeof(ipc_rfs_dispatch_handlers) /
+ sizeof(struct ipc_dispatch_handler);
+
+struct srs_dispatch_handler srs_dispatch_handlers[] = {
+ {
+ .command = SRS_CONTROL_PING,
+ .handler = srs_control_ping,
+ },
+ {
+ .command = SRS_SND_SET_CALL_VOLUME,
+ .handler = srs_snd_set_call_volume,
+ },
+ {
+ .command = SRS_SND_SET_CALL_AUDIO_PATH,
+ .handler = srs_snd_set_call_audio_path,
+ },
+ {
+ .command = SRS_SND_SET_CALL_CLOCK_SYNC,
+ .handler = srs_snd_set_call_clock_sync,
+ },
+};
+
+unsigned int srs_dispatch_handlers_count = sizeof(srs_dispatch_handlers) /
+ sizeof(struct srs_dispatch_handler);
+
+/*
+ * RIL request
+ */
+
+struct ril_request_handler ril_request_handlers[] = {
+ /* Power */
+ {
+ .request = RIL_REQUEST_RADIO_POWER,
+ .handler = ril_request_radio_power,
+ },
+ /* Call */
+ {
+ .request = RIL_REQUEST_DIAL,
+ .handler = ril_request_dial,
+ },
+ {
+ .request = RIL_REQUEST_HANGUP,
+ .handler = ril_request_hangup,
+ },
+ {
+ .request = RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND,
+ .handler = ril_request_hangup,
+ },
+ {
+ .request = RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
+ .handler = ril_request_hangup,
+ },
+ {
+ .request = RIL_REQUEST_ANSWER,
+ .handler = ril_request_answer,
+ },
+ {
+ .request = RIL_REQUEST_LAST_CALL_FAIL_CAUSE,
+ .handler = ril_request_last_call_fail_cause,
+ },
+ {
+ .request = RIL_REQUEST_GET_CURRENT_CALLS,
+ .handler = ril_request_get_current_calls,
+ },
+ {
+ .request = RIL_REQUEST_DTMF,
+ .handler = ril_request_dtmf,
+ },
+ {
+ .request = RIL_REQUEST_DTMF_START,
+ .handler = ril_request_dtmf_start,
+ },
+ {
+ .request = RIL_REQUEST_DTMF_STOP,
+ .handler = ril_request_dtmf_stop,
+ },
+ /* SMS */
+ {
+ .request = RIL_REQUEST_SEND_SMS,
+ .handler = ril_request_send_sms,
+ },
+ {
+ .request = RIL_REQUEST_SEND_SMS_EXPECT_MORE,
+ .handler = ril_request_send_sms,
+ },
+ {
+ .request = RIL_REQUEST_WRITE_SMS_TO_SIM,
+ .handler = ril_request_write_sms_to_sim,
+ },
+ {
+ .request = RIL_REQUEST_DELETE_SMS_ON_SIM,
+ .handler = ril_request_delete_sms_on_sim,
+ },
+ {
+ .request = RIL_REQUEST_SMS_ACKNOWLEDGE,
+ .handler = ril_request_sms_acknowledge,
+ },
+ /* SIM */
+ {
+ .request = RIL_REQUEST_GET_SIM_STATUS,
+ .handler = ril_request_get_sim_status,
+ },
+ {
+ .request = RIL_REQUEST_QUERY_FACILITY_LOCK,
+ .handler = ril_request_query_facility_lock,
+ },
+ {
+ .request = RIL_REQUEST_SET_FACILITY_LOCK,
+ .handler = ril_request_set_facility_lock,
+ },
+ {
+ .request = RIL_REQUEST_ENTER_SIM_PIN,
+ .handler = ril_request_enter_sim_pin,
+ },
+ {
+ .request = RIL_REQUEST_ENTER_SIM_PUK,
+ .handler = ril_request_enter_sim_puk,
+ },
+ {
+ .request = RIL_REQUEST_ENTER_SIM_PIN2,
+ .handler = ril_request_enter_sim_pin2,
+ },
+ {
+ .request = RIL_REQUEST_ENTER_SIM_PUK2,
+ .handler = ril_request_enter_sim_puk2,
+ },
+ {
+ .request = RIL_REQUEST_CHANGE_SIM_PIN,
+ .handler = ril_request_change_sim_pin,
+ },
+ {
+ .request = RIL_REQUEST_CHANGE_SIM_PIN2,
+ .handler = ril_request_change_sim_pin2,
+ },
+ {
+ .request = RIL_REQUEST_SIM_IO,
+ .handler = ril_request_sim_io,
+ },
+ /* Network */
+ {
+ .request = RIL_REQUEST_SIGNAL_STRENGTH,
+ .handler = ril_request_signal_strength,
+ },
+ {
+ .request = RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE,
+ .handler = ril_request_query_network_selection_mode,
+ },
+ {
+ .request = RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC,
+ .handler = ril_request_set_network_selection_automatic,
+ },
+ {
+ .request = RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
+ .handler = ril_request_set_network_selection_manual,
+ },
+ {
+ .request = RIL_REQUEST_OPERATOR,
+ .handler = ril_request_operator,
+ },
+ {
+ .request = RIL_REQUEST_QUERY_AVAILABLE_NETWORKS,
+ .handler = ril_request_query_available_networks,
+ },
+ {
+#if RIL_VERSION >= 6
+ .request = RIL_REQUEST_VOICE_REGISTRATION_STATE,
+ .handler = ril_request_voice_registration_state,
+#else
+ .request = RIL_REQUEST_REGISTRATION_STATE,
+ .handler = ril_request_registration_state,
+#endif
+ },
+ {
+#if RIL_VERSION >= 6
+ .request = RIL_REQUEST_DATA_REGISTRATION_STATE,
+ .handler = ril_request_data_registration_state,
+#else
+ .request = RIL_REQUEST_GPRS_REGISTRATION_STATE,
+ .handler = ril_request_gprs_registration_state,
+#endif
+ },
+ {
+ .request = RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
+ .handler = ril_request_get_preferred_network_type,
+ },
+ {
+ .request = RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
+ .handler = ril_request_set_preferred_network_type,
+ },
+ /* Sound */
+ {
+ .request = RIL_REQUEST_SET_MUTE,
+ .handler = ril_request_set_mute,
+ },
+ /* Misc */
+ {
+ .request = RIL_REQUEST_BASEBAND_VERSION,
+ .handler = ril_request_baseband_version,
+ },
+ {
+ .request = RIL_REQUEST_GET_IMSI,
+ .handler = ril_request_get_imsi,
+ },
+ {
+ .request = RIL_REQUEST_GET_IMEI,
+ .handler = ril_request_get_imei,
+ },
+ {
+ .request = RIL_REQUEST_GET_IMEISV,
+ .handler = ril_request_get_imeisv,
+ },
+ {
+ .request = RIL_REQUEST_SCREEN_STATE,
+ .handler = ril_request_screen_state,
+ },
+ /* OEM */
+ {
+ .request = RIL_REQUEST_OEM_HOOK_RAW,
+ .handler = ril_request_oem_hook_raw,
+ },
+ /* Data */
+ {
+ .request = RIL_REQUEST_SETUP_DATA_CALL,
+ .handler = ril_request_setup_data_call,
+ },
+ {
+ .request = RIL_REQUEST_DEACTIVATE_DATA_CALL,
+ .handler = ril_request_deactivate_data_call,
+ },
+ {
+ .request = RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE,
+ .handler = ril_request_last_data_call_fail_cause,
+ },
+ {
+ .request = RIL_REQUEST_DATA_CALL_LIST,
+ .handler = ril_request_data_call_list,
+ },
+};
-int ril_request_id_set(int id)
+unsigned int ril_request_handlers_count = sizeof(ril_request_handlers) /
+ sizeof(struct ril_request_handler);
+
+int ril_request_stats_log(void)
{
- id %= 0xff;
+ struct ril_request *request;
+ struct list_head *list;
+ unsigned int pending = 0;
+ unsigned int handled = 0;
+ unsigned int unhandled = 0;
+ unsigned int count = 0;
+
+ if (ril_data == NULL)
+ return -1;
+
+ RIL_REQUEST_LOCK();
+
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ request = (struct ril_request *) list->data;
+
+ switch (request->status) {
+ case RIL_REQUEST_PENDING:
+ pending++;
+ break;
+ case RIL_REQUEST_HANDLED:
+ handled++;
+ break;
+ case RIL_REQUEST_UNHANDLED:
+ unhandled++;
+ break;
+ }
+
+ count++;
+
+list_continue:
+ list = list->next;
+ }
+
+ RIL_LOGD("%d RIL request%s in the queue (%d pending, %d handled, %d unhandled)", count, count > 1 ? "s" : "", pending, handled, unhandled);
+
+ count = 0;
- while (ril_data.request_id < id) {
- ril_data.request_id++;
- ril_data.request_id %= 0xff;
+ list = ril_data->requests_data;
+ while (list != NULL) {
+ count++;
+
+ list = list->next;
}
- return ril_data.request_id;
+ if (count > 0)
+ RIL_LOGD("%d RIL request%s data in the queue", count, count > 1 ? "s" : "");
+
+ RIL_REQUEST_UNLOCK();
+
+ return 0;
}
-int ril_request_register(RIL_Token t, int id)
+int ril_request_register(int request, void *data, size_t size, RIL_Token token)
{
- struct ril_request_info *request;
+ struct ril_request *ril_request;
struct list_head *list_end;
struct list_head *list;
+ unsigned int i;
- request = calloc(1, sizeof(struct ril_request_info));
- if (request == NULL)
+ if (ril_data == NULL)
return -1;
- request->token = t;
- request->id = id;
- request->canceled = 0;
+ RIL_REQUEST_LOCK();
+
+ ril_request = (struct ril_request *) calloc(1, sizeof(struct ril_request));
+ ril_request->request = request;
+ ril_request->data = NULL;
+ ril_request->size = size;
+ ril_request->token = token;
+ ril_request->status = RIL_REQUEST_PENDING;
- list_end = ril_data.requests;
+ if (size > 0) {
+ ril_request->data = calloc(1, size);
+ memcpy(ril_request->data, data, size);
+ }
+
+ list_end = ril_data->requests;
while (list_end != NULL && list_end->next != NULL)
list_end = list_end->next;
- list = list_head_alloc((void *) request, list_end, NULL);
+ list = list_head_alloc(list_end, NULL, (void *) ril_request);
+
+ if (ril_data->requests == NULL)
+ ril_data->requests = list;
+
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
- if (ril_data.requests == NULL)
- ril_data.requests = list;
+ ril_client_request_register(ril_clients[i], request, token);
+ }
+
+ RIL_REQUEST_UNLOCK();
return 0;
}
-void ril_request_unregister(struct ril_request_info *request)
+int ril_request_unregister(struct ril_request *request)
{
struct list_head *list;
+ unsigned int i;
- if (request == NULL)
- return;
+ if (request == NULL || ril_data == NULL)
+ return -1;
+
+ RIL_REQUEST_LOCK();
+
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
+
+ ril_client_request_unregister(ril_clients[i], request->request, request->token);
+ }
- list = ril_data.requests;
+ list = ril_data->requests;
while (list != NULL) {
if (list->data == (void *) request) {
- memset(request, 0, sizeof(struct ril_request_info));
+ if (request->data != NULL && request->size > 0)
+ free(request->data);
+
+ memset(request, 0, sizeof(struct ril_request));
free(request);
- if (list == ril_data.requests)
- ril_data.requests = list->next;
+ if (list == ril_data->requests)
+ ril_data->requests = list->next;
list_head_free(list);
break;
}
+
list_continue:
list = list->next;
}
+
+ RIL_REQUEST_UNLOCK();
+
+ return 0;
}
-struct ril_request_info *ril_request_info_find_id(int id)
+int ril_request_flush(void)
{
- struct ril_request_info *request;
+ struct ril_request *request;
struct list_head *list;
+ struct list_head *list_next;
+
+ if (ril_data == NULL)
+ return -1;
+
+ RIL_REQUEST_LOCK();
- list = ril_data.requests;
+ list = ril_data->requests;
while (list != NULL) {
- request = (struct ril_request_info *) list->data;
- if (request == NULL)
+ if (list->data != NULL) {
+ request = (struct ril_request *) list->data;
+
+ if (request->data != NULL && request->size > 0)
+ free(request->data);
+
+ memset(request, 0, sizeof(struct ril_request));
+ free(request);
+ }
+
+ if (list == ril_data->requests)
+ ril_data->requests = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
+ }
+
+ RIL_REQUEST_UNLOCK();
+
+ return 0;
+}
+
+struct ril_request *ril_request_find(void)
+{
+ struct ril_request *request;
+ struct list_head *list;
+
+ if (ril_data == NULL)
+ return NULL;
+
+ RIL_REQUEST_LOCK();
+
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
goto list_continue;
- if (request->id == id)
- return request;
+ request = (struct ril_request *) list->data;
+
+ RIL_REQUEST_UNLOCK();
+ return request;
list_continue:
list = list->next;
}
+ RIL_REQUEST_UNLOCK();
+
return NULL;
}
-struct ril_request_info *ril_request_info_find_token(RIL_Token t)
+struct ril_request *ril_request_find_request_status(int request, int status)
{
- struct ril_request_info *request;
+ struct ril_request *ril_request;
struct list_head *list;
- list = ril_data.requests;
+ if (ril_data == NULL)
+ return NULL;
+
+ RIL_REQUEST_LOCK();
+
+ list = ril_data->requests;
while (list != NULL) {
- request = (struct ril_request_info *) list->data;
- if (request == NULL)
+ if (list->data == NULL)
goto list_continue;
- if (request->token == t)
- return request;
+ ril_request = (struct ril_request *) list->data;
+
+ if (ril_request->request == request && ril_request->status == status) {
+ RIL_REQUEST_UNLOCK();
+ return ril_request;
+ }
list_continue:
list = list->next;
}
+ RIL_REQUEST_UNLOCK();
+
return NULL;
}
-int ril_request_set_canceled(RIL_Token t, int canceled)
+struct ril_request *ril_request_find_request(int request)
{
- struct ril_request_info *request;
+ struct ril_request *ril_request;
+ struct list_head *list;
- request = ril_request_info_find_token(t);
- if (request == NULL)
- return -1;
+ if (ril_data == NULL)
+ return NULL;
- request->canceled = canceled ? 1 : 0;
+ RIL_REQUEST_LOCK();
- return 0;
-}
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
-int ril_request_get_canceled(RIL_Token t)
-{
- struct ril_request_info *request;
+ ril_request = (struct ril_request *) list->data;
- request = ril_request_info_find_token(t);
- if (request == NULL)
- return -1;
+ if (ril_request->request == request) {
+ RIL_REQUEST_UNLOCK();
+ return ril_request;
+ }
+
+list_continue:
+ list = list->next;
+ }
+
+ RIL_REQUEST_UNLOCK();
- return request->canceled;
+ return NULL;
}
-RIL_Token ril_request_get_token(int id)
+struct ril_request *ril_request_find_token(RIL_Token token)
{
- struct ril_request_info *request;
+ struct ril_request *request;
+ struct list_head *list;
- request = ril_request_info_find_id(id);
- if (request == NULL)
- return RIL_TOKEN_NULL;
+ if (ril_data == NULL)
+ return NULL;
+
+ RIL_REQUEST_LOCK();
+
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ request = (struct ril_request *) list->data;
+
+ if (request->token == token) {
+ RIL_REQUEST_UNLOCK();
+ return request;
+ }
+
+list_continue:
+ list = list->next;
+ }
- return request->token;
+ RIL_REQUEST_UNLOCK();
+
+ return NULL;
}
-int ril_request_get_id(RIL_Token t)
+struct ril_request *ril_request_find_status(int status)
{
- struct ril_request_info *request;
- int id, rc;
+ struct ril_request *request;
+ struct list_head *list;
- request = ril_request_info_find_token(t);
- if (request != NULL)
- return request->id;
+ if (ril_data == NULL)
+ return NULL;
- id = ril_request_id_get();
+ RIL_REQUEST_LOCK();
- // Unregister a previous request with the same id
- request = ril_request_info_find_id(id);
- if (request != NULL)
- ril_request_unregister(request);
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
- rc = ril_request_register(t, id);
- if (rc < 0)
- return -1;
+ request = (struct ril_request *) list->data;
+
+ if (request->status == status) {
+ RIL_REQUEST_UNLOCK();
+ return request;
+ }
- return id;
+list_continue:
+ list = list->next;
+ }
+
+ RIL_REQUEST_UNLOCK();
+
+ return NULL;
}
-void ril_request_complete(RIL_Token t, RIL_Errno e, void *data, size_t length)
+int ril_request_complete(RIL_Token token, RIL_Errno error, void *data,
+ size_t size)
{
- struct ril_request_info *request;
- int canceled = 0;
+ struct ril_request *request;
+
+ if (ril_data == NULL || ril_data->env == NULL || ril_data->env->OnRequestComplete == NULL)
+ return -1;
- request = ril_request_info_find_token(t);
+ if (token == NULL)
+ return 0;
+
+ request = ril_request_find_token(token);
if (request == NULL)
goto complete;
- canceled = ril_request_get_canceled(t);
ril_request_unregister(request);
- if (canceled)
- return;
+ ril_request_stats_log();
complete:
- ril_data.env->OnRequestComplete(t, e, data, length);
+ ril_data->env->OnRequestComplete(token, error, data, size);
+
+ RIL_REQUEST_LOOP_UNLOCK();
+
+ return 0;
}
-void ril_request_unsolicited(int request, void *data, size_t length)
+int ril_request_unsolicited(int request, void *data, size_t size)
{
- ril_data.env->OnUnsolicitedResponse(request, data, length);
+ if (ril_data == NULL || ril_data->env == NULL || ril_data->env->OnUnsolicitedResponse == NULL)
+ return -1;
+
+ ril_data->env->OnUnsolicitedResponse(request, data, size);
+
+ return 0;
}
-void ril_request_timed_callback(RIL_TimedCallback callback, void *data, const struct timeval *time)
+int ril_request_timed_callback(RIL_TimedCallback callback, void *data,
+ const struct timeval *time)
{
- ril_data.env->RequestTimedCallback(callback, data, time);
-}
+ if (ril_data == NULL || ril_data->env == NULL || ril_data->env->RequestTimedCallback == NULL)
+ return -1;
-/*
- * RIL radio state
- */
+ ril_data->env->RequestTimedCallback(callback, data, time);
-int ril_radio_state_complete(RIL_RadioState radio_state, RIL_Token token)
-{
- RIL_Errno error = RIL_E_SUCCESS;
+ return 0;
+}
- // This goes from best case of failure to worst case of failure
- switch (radio_state) {
- case RADIO_STATE_SIM_NOT_READY:
- if (ril_data.state.radio_state == RADIO_STATE_SIM_NOT_READY)
- error = RIL_E_GENERIC_FAILURE;
- case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
- if (ril_data.state.radio_state == RADIO_STATE_SIM_LOCKED_OR_ABSENT)
- error = RIL_E_GENERIC_FAILURE;
- case RADIO_STATE_OFF:
- if (ril_data.state.radio_state == RADIO_STATE_OFF)
- error = RIL_E_RADIO_NOT_AVAILABLE;
- case RADIO_STATE_UNAVAILABLE:
- default:
- if (ril_data.state.radio_state == RADIO_STATE_UNAVAILABLE)
- error = RIL_E_RADIO_NOT_AVAILABLE;
- break;
- }
+int ril_request_dispatch(struct ril_request *request)
+{
+ unsigned int i;
+ int status;
+ int rc;
- if (error != RIL_E_SUCCESS) {
- if (token != RIL_TOKEN_NULL)
- ril_request_complete(token, error, NULL, 0);
+ if (request == NULL || ril_data == NULL)
+ return -1;
- return 1;
+ for (i = 0; i < ril_request_handlers_count; i++) {
+ if (ril_request_handlers[i].handler == NULL)
+ continue;
+
+ if (ril_request_handlers[i].request == request->request) {
+ status = ril_request_handlers[i].handler(request->data, request->size, request->token);
+ switch (status) {
+ case RIL_REQUEST_PENDING:
+ case RIL_REQUEST_HANDLED:
+ case RIL_REQUEST_UNHANDLED:
+ request->status = status;
+ break;
+ case RIL_REQUEST_COMPLETED:
+ break;
+ default:
+ RIL_LOGE("Handling RIL request %d failed", request->request);
+ return -1;
+ }
+
+ return 0;
+ }
}
+ RIL_LOGD("Unhandled RIL request: %d", request->request);
+ ril_request_complete(request->token, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+
return 0;
}
-void ril_radio_state_update(RIL_RadioState radio_state)
+void *ril_request_loop(void *data)
{
- RIL_LOGD("Setting radio state to %d", radio_state);
- ril_data.state.radio_state = radio_state;
+ struct ril_request *request;
+ int rc;
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
+ if (ril_data == NULL)
+ return NULL;
+
+ while (1) {
+ RIL_REQUEST_LOOP_LOCK();
+
+ RIL_LOCK();
+
+ rc = ril_radio_state_check(RADIO_STATE_OFF);
+ if (rc < 0) {
+ RIL_UNLOCK();
+ continue;
+ }
- ril_tokens_check();
+ do {
+ request = ril_request_find_status(RIL_REQUEST_UNHANDLED);
+ if (request == NULL)
+ break;
+
+ request->status = RIL_REQUEST_PENDING;
+ } while (request != NULL);
+
+ do {
+ request = ril_request_find_status(RIL_REQUEST_PENDING);
+ if (request == NULL)
+ break;
+
+ rc = ril_request_dispatch(request);
+ if (rc < 0)
+ ril_request_unregister(request);
+ } while (request != NULL);
+
+ RIL_UNLOCK();
+ }
+
+ return NULL;
}
/*
- * RIL tokens
+ * RIL request data
*/
-void ril_tokens_check(void)
+int ril_request_data_register(int request, void *data, size_t size)
{
- RIL_Token t;
+ struct ril_request_data *request_data;
+ struct list_head *list_end;
+ struct list_head *list;
+ unsigned int i;
+
+ if (data == NULL || ril_data == NULL)
+ return -1;
+
+ request_data = (struct ril_request_data *) calloc(1, sizeof(struct ril_request_data));
+ request_data->request = request;
+ request_data->data = data;
+ request_data->size = size;
+
+ list_end = ril_data->requests_data;
+ while (list_end != NULL && list_end->next != NULL)
+ list_end = list_end->next;
+
+ list = list_head_alloc(list_end, NULL, (void *) request_data);
+
+ if (ril_data->requests_data == NULL)
+ ril_data->requests_data = list;
- if (ril_data.tokens.baseband_version != 0) {
- if (ril_data.state.radio_state != RADIO_STATE_OFF) {
- t = ril_data.tokens.baseband_version;
- ril_data.tokens.baseband_version = 0;
- ril_request_baseband_version(t);
+ return 0;
+}
+
+int ril_request_data_unregister(struct ril_request_data *request_data)
+{
+ struct list_head *list;
+ unsigned int i;
+
+ if (request_data == NULL || ril_data == NULL)
+ return -1;
+
+ list = ril_data->requests_data;
+ while (list != NULL) {
+ if (list->data == (void *) request_data) {
+ memset(request_data, 0, sizeof(struct ril_request_data));
+ free(request_data);
+
+ if (list == ril_data->requests_data)
+ ril_data->requests_data = list->next;
+
+ list_head_free(list);
+
+ break;
}
+
+list_continue:
+ list = list->next;
}
- if (ril_data.tokens.get_imei != 0 && ril_data.tokens.get_imeisv != 0) {
- if (ril_data.state.radio_state != RADIO_STATE_OFF) {
- t = ril_data.tokens.get_imei;
- ril_data.tokens.get_imei = 0;
- ril_request_get_imei(t);
+ return 0;
+}
+
+int ril_request_data_flush(void)
+{
+ struct ril_request_data *request_data;
+ struct list_head *list;
+ struct list_head *list_next;
+
+ if (ril_data == NULL)
+ return -1;
+
+ list = ril_data->requests_data;
+ while (list != NULL) {
+ if (list->data != NULL) {
+ request_data = (struct ril_request_data *) list->data;
+
+ if (request_data->data != NULL && request_data->size > 0)
+ free(request_data->data);
+
+ memset(request_data, 0, sizeof(struct ril_request_data));
+ free(request_data);
}
+
+ if (list == ril_data->requests_data)
+ ril_data->requests_data = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
}
+
+ return 0;
+}
+
+struct ril_request_data *ril_request_data_find_request(int request)
+{
+ struct ril_request_data *request_data;
+ struct list_head *list;
+
+ if (ril_data == NULL)
+ return NULL;
+
+ list = ril_data->requests_data;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ request_data = (struct ril_request_data *) list->data;
+
+ if (request_data->request == request)
+ return request_data;
+
+list_continue:
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+int ril_request_data_free(int request)
+{
+ struct ril_request_data *request_data;
+
+ do {
+ request_data = ril_request_data_find_request(request);
+ if (request_data == NULL)
+ break;
+
+ if (request_data->data != NULL && request_data->size > 0)
+ free(request_data->data);
+
+ ril_request_data_unregister(request_data);
+ } while (request_data != NULL);
+
+ return 0;
+}
+
+int ril_request_data_set(int request, void *data, size_t size)
+{
+ void *buffer;
+ int rc;
+
+ if (data == NULL || size == 0)
+ return -1;
+
+ buffer = calloc(1, size);
+ memcpy(buffer, data, size);
+
+ rc = ril_request_data_register(request, buffer, size);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int ril_request_data_set_uniq(int request, void *data, size_t size)
+{
+ int rc;
+
+ ril_request_data_free(request);
+
+ rc = ril_request_data_set(request, data, size);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+size_t ril_request_data_size_get(int request)
+{
+ struct ril_request_data *request_data;
+
+ request_data = ril_request_data_find_request(request);
+ if (request_data == NULL)
+ return 0;
+
+ return request_data->size;
+}
+
+void *ril_request_data_get(int request)
+{
+ struct ril_request_data *request_data;
+ void *buffer;
+
+ request_data = ril_request_data_find_request(request);
+ if (request_data == NULL)
+ return NULL;
+
+ buffer = request_data->data;
+
+ ril_request_data_unregister(request_data);
+
+ return buffer;
}
/*
- * Clients dispatch functions
+ * RIL radio state
*/
-void ipc_fmt_dispatch(struct ipc_message_info *info)
+int ril_radio_state_update(RIL_RadioState radio_state)
{
- if (info == NULL)
- return;
+ struct ril_request *request;
+ unsigned int i;
+ int rc;
- RIL_LOCK();
+ if (ril_data == NULL)
+ return -1;
- ril_request_id_set(info->aseq);
+ if (ril_data->radio_state == radio_state)
+ return 0;
- switch (IPC_COMMAND(info)) {
- /* GEN */
- case IPC_GEN_PHONE_RES:
- ipc_gen_phone_res(info);
- break;
- /* PWR */
- case IPC_PWR_PHONE_PWR_UP:
- ipc_pwr_phone_pwr_up();
- break;
- case IPC_PWR_PHONE_RESET:
- ipc_pwr_phone_reset();
- break;
- case IPC_PWR_PHONE_STATE:
- ipc_pwr_phone_state(info);
- break;
- /* DISP */
- case IPC_DISP_ICON_INFO:
- ipc_disp_icon_info(info);
- break;
- case IPC_DISP_RSSI_INFO:
- ipc_disp_rssi_info(info);
- break;
- /* MISC */
- case IPC_MISC_ME_SN:
- ipc_misc_me_sn(info);
- break;
- case IPC_MISC_ME_VERSION:
- ipc_misc_me_version(info);
- break;
- case IPC_MISC_ME_IMSI:
- ipc_misc_me_imsi(info);
- break;
- case IPC_MISC_TIME_INFO:
- ipc_misc_time_info(info);
- break;
- /* SAT */
-#ifndef DISABLE_STK
- case IPC_SAT_PROACTIVE_CMD:
- ipc_sat_proactive_cmd(info);
- break;
- case IPC_SAT_ENVELOPE_CMD:
- ipc_sat_envelope_cmd(info);
- break;
-#endif
- /* SS */
- case IPC_SS_USSD:
- ipc_ss_ussd(info);
- break;
- /* SEC */
- case IPC_SEC_SIM_STATUS:
- ipc_sec_sim_status(info);
- break;
- case IPC_SEC_SIM_ICC_TYPE:
- ipc_sec_sim_icc_type(info);
- break;
- case IPC_SEC_LOCK_INFO:
- ipc_sec_lock_info(info);
- break;
- case IPC_SEC_RSIM_ACCESS:
- ipc_sec_rsim_access(info);
- break;
- case IPC_SEC_PHONE_LOCK:
- ipc_sec_phone_lock(info);
- break;
- /* NET */
- case IPC_NET_CURRENT_PLMN:
- ipc_net_current_plmn(info);
- break;
- case IPC_NET_REGIST:
- ipc_net_regist(info);
- break;
- case IPC_NET_PLMN_LIST:
- ipc_net_plmn_list(info);
- break;
- case IPC_NET_PLMN_SEL:
- ipc_net_plmn_sel(info);
- break;
- case IPC_NET_MODE_SEL:
- ipc_net_mode_sel(info);
- break;
- /* SMS */
- case IPC_SMS_INCOMING_MSG:
- ipc_sms_incoming_msg(info);
- break;
- case IPC_SMS_DELIVER_REPORT:
- ipc_sms_deliver_report(info);
- break;
- case IPC_SMS_SVC_CENTER_ADDR:
- ipc_sms_svc_center_addr(info);
- break;
- case IPC_SMS_SEND_MSG:
- ipc_sms_send_msg(info);
- break;
- case IPC_SMS_DEVICE_READY:
- ipc_sms_device_ready(info);
- break;
- case IPC_SMS_SAVE_MSG:
- ipc_sms_save_msg(info);
- break;
- case IPC_SMS_DEL_MSG:
- ipc_sms_del_msg(info);
- break;
- /* SVC */
- case IPC_SVC_DISPLAY_SCREEN:
- ipc_svc_display_screen(info);
- break;
- /* CALL */
- case IPC_CALL_INCOMING:
- ipc_call_incoming(info);
- break;
- case IPC_CALL_LIST:
- ipc_call_list(info);
- break;
- case IPC_CALL_STATUS:
- ipc_call_status(info);
- break;
- case IPC_CALL_BURST_DTMF:
- ipc_call_burst_dtmf(info);
- break;
- /* GPRS */
- case IPC_GPRS_IP_CONFIGURATION:
- ipc_gprs_ip_configuration(info);
- break;
- case IPC_GPRS_CALL_STATUS:
- ipc_gprs_call_status(info);
- break;
- case IPC_GPRS_PDP_CONTEXT:
- ipc_gprs_pdp_context(info);
+ RIL_LOGD("Updating RIL radio state to %d", radio_state);
+
+ ril_data->radio_state = radio_state;
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
+
+ switch (ril_data->radio_state) {
+ case RADIO_STATE_UNAVAILABLE:
+ do {
+ request = ril_request_find();
+ if (request == NULL)
+ break;
+
+ ril_request_complete(request->token, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+
+ ril_request_unregister(request);
+ } while (request != NULL);
+
+ ril_request_flush();
+ ril_request_data_flush();
+
+ ril_request_stats_log();
+
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
+
+ ril_client_flush(ril_clients[i]);
+ }
+ case RADIO_STATE_OFF:
+ ril_data_connection_flush();
+
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
+ ril_request_unsolicited(RIL_UNSOL_DATA_CALL_LIST_CHANGED, NULL, 0);
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
break;
default:
- RIL_LOGE("%s: Unhandled request: %s (%04x)", __func__, ipc_command_to_str(IPC_COMMAND(info)), IPC_COMMAND(info));
+ RIL_REQUEST_LOOP_UNLOCK();
break;
}
- RIL_UNLOCK();
+ return 0;
}
-void ipc_rfs_dispatch(struct ipc_message_info *info)
+int ril_radio_state_check(RIL_RadioState radio_state)
{
- if (info == NULL)
- return;
+ RIL_RadioState radio_states[] = {
+ RADIO_STATE_UNAVAILABLE,
+ RADIO_STATE_OFF,
+ RADIO_STATE_ON,
+ RADIO_STATE_NV_NOT_READY,
+ RADIO_STATE_NV_READY,
+ RADIO_STATE_SIM_NOT_READY,
+ RADIO_STATE_SIM_LOCKED_OR_ABSENT,
+ RADIO_STATE_SIM_READY,
+ };
+ unsigned int index;
+ unsigned int count;
+ unsigned int i;
+
+ if (ril_data == NULL)
+ return -1;
- RIL_LOCK();
+ count = sizeof(radio_states) / sizeof(RIL_RadioState);
- switch (IPC_COMMAND(info)) {
- case IPC_RFS_NV_READ_ITEM:
- ipc_rfs_nv_read_item(info);
- break;
- case IPC_RFS_NV_WRITE_ITEM:
- ipc_rfs_nv_write_item(info);
+ for (i = 0; i < count; i++)
+ if (radio_states[i] == radio_state)
break;
- default:
- RIL_LOGE("%s: Unhandled request: %s (%04x)", __func__, ipc_command_to_str(IPC_COMMAND(info)), IPC_COMMAND(info));
+
+ index = i;
+
+ for (i = 0; i < count; i++)
+ if (radio_states[i] == ril_data->radio_state)
break;
- }
- RIL_UNLOCK();
+ if (i < index)
+ return -1;
+
+ return 0;
}
-void srs_dispatch(struct srs_message *message)
+/*
+ * RIL data
+ */
+
+int ril_data_create(void)
{
- if (message == NULL)
- return;
+ ril_data = (struct ril_data *) calloc(1, sizeof(struct ril_data));
- RIL_LOCK();
+ pthread_mutex_init(&ril_data->mutex, NULL);
+ pthread_mutex_init(&ril_data->request_mutex, NULL);
+ pthread_mutex_init(&ril_data->request_loop_mutex, NULL);
- switch (message->command) {
- case SRS_CONTROL_PING:
- srs_control_ping(message);
- break;
- case SRS_SND_SET_CALL_CLOCK_SYNC:
- srs_snd_set_call_clock_sync(message);
- break;
- case SRS_SND_SET_CALL_VOLUME:
- srs_snd_set_call_volume(message);
- break;
- case SRS_SND_SET_CALL_AUDIO_PATH:
- srs_snd_set_call_audio_path(message);
- break;
- default:
- RIL_LOGE("%s: Unhandled request: (%04x)", __func__, message->command);
- break;
- }
+ RIL_REQUEST_LOOP_LOCK();
- RIL_UNLOCK();
+ ril_data->radio_state = RADIO_STATE_UNAVAILABLE;
+
+ return 0;
+}
+
+int ril_data_destroy(void)
+{
+ if (ril_data == NULL)
+ return -1;
+
+ pthread_mutex_destroy(&ril_data->mutex);
+ pthread_mutex_destroy(&ril_data->request_mutex);
+ pthread_mutex_destroy(&ril_data->request_loop_mutex);
+
+ free(ril_data);
+ ril_data = NULL;
+
+ return 0;
}
/*
* RIL interface
*/
-void ril_on_request(int request, void *data, size_t length, RIL_Token t)
+void ril_on_request(int request, void *data, size_t size, RIL_Token token)
{
+ struct ril_request *ril_request;
+ void *buffer = NULL;
+ unsigned int strings_count = 0;
+ unsigned int i;
+ char *c;
+
RIL_LOCK();
+ ril_request = ril_request_find_token(token);
+ if (ril_request != NULL)
+ ril_request_unregister(ril_request);
+
switch (request) {
- /* PWR */
- case RIL_REQUEST_RADIO_POWER:
- ril_request_radio_power(t, data, length);
- break;
- case RIL_REQUEST_BASEBAND_VERSION:
- ril_request_baseband_version(t);
- break;
- /* DISP */
- case RIL_REQUEST_SIGNAL_STRENGTH:
- ril_request_signal_strength(t);
- break;
- /* MISC */
- case RIL_REQUEST_GET_IMEI:
- ril_request_get_imei(t);
- break;
- case RIL_REQUEST_GET_IMEISV:
- ril_request_get_imeisv(t);
- break;
- case RIL_REQUEST_GET_IMSI:
- ril_request_get_imsi(t);
- break;
- /* SAT */
-#ifndef DISABLE_STK
- case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING:
- ril_request_report_stk_service_is_running(t);
- break;
- case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
- ril_request_stk_send_terminal_response(t, data, length);
- break;
- case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND:
- ril_request_stk_send_envelope_command(t, data, length);
- break;
- case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM:
- ril_request_complete(t, RIL_E_SUCCESS, NULL, 0);
- break;
-#endif
- /* SS */
- case RIL_REQUEST_SEND_USSD:
- ril_request_send_ussd(t, data, length);
- break;
- case RIL_REQUEST_CANCEL_USSD:
- ril_request_cancel_ussd(t, data, length);
- break;
- /* SEC */
- case RIL_REQUEST_GET_SIM_STATUS:
- ril_request_get_sim_status(t);
- break;
- case RIL_REQUEST_SIM_IO:
- ril_request_sim_io(t, data, length);
- break;
- case RIL_REQUEST_ENTER_SIM_PIN:
- ril_request_enter_sim_pin(t, data, length);
- break;
- case RIL_REQUEST_CHANGE_SIM_PIN:
- ril_request_change_sim_pin(t, data, length);
+ case RIL_REQUEST_DIAL:
+ if (data == NULL || size < sizeof(RIL_Dial))
+ break;
+
+ buffer = calloc(1, size);
+
+ memcpy(buffer, data, size);
+
+ if (((RIL_Dial *) data)->address != NULL)
+ ((RIL_Dial *) buffer)->address = strdup(((RIL_Dial *) data)->address);
+
+ data = buffer;
break;
- case RIL_REQUEST_ENTER_SIM_PUK:
- ril_request_enter_sim_puk(t, data, length);
+ case RIL_REQUEST_WRITE_SMS_TO_SIM:
+ if (data == NULL || size < sizeof(RIL_SMS_WriteArgs))
+ break;
+
+
+ buffer = calloc(1, size);
+
+ memcpy(buffer, data, size);
+
+ if (((RIL_SMS_WriteArgs *) data)->pdu != NULL)
+ ((RIL_SMS_WriteArgs *) buffer)->pdu = strdup(((RIL_SMS_WriteArgs *) data)->pdu);
+
+ if (((RIL_SMS_WriteArgs *) data)->smsc != NULL)
+ ((RIL_SMS_WriteArgs *) buffer)->smsc = strdup(((RIL_SMS_WriteArgs *) data)->smsc);
+
+ data = buffer;
break;
+ case RIL_REQUEST_SEND_SMS:
+ case RIL_REQUEST_SEND_SMS_EXPECT_MORE:
case RIL_REQUEST_QUERY_FACILITY_LOCK:
- ril_request_query_facility_lock(t, data, length);
- break;
case RIL_REQUEST_SET_FACILITY_LOCK:
- ril_request_set_facility_lock(t, data, length);
- break;
- /* SVC */
- case RIL_REQUEST_OEM_HOOK_RAW:
- ril_request_oem_hook_raw(t, data, length);
- break;
- /* NET */
- case RIL_REQUEST_OPERATOR:
- ril_request_operator(t);
+ case RIL_REQUEST_ENTER_SIM_PIN:
+ case RIL_REQUEST_ENTER_SIM_PUK:
+ case RIL_REQUEST_ENTER_SIM_PIN2:
+ case RIL_REQUEST_ENTER_SIM_PUK2:
+ case RIL_REQUEST_CHANGE_SIM_PIN:
+ case RIL_REQUEST_CHANGE_SIM_PIN2:
+ strings_count = size / sizeof(char *);
break;
+ case RIL_REQUEST_SIM_IO:
#if RIL_VERSION >= 6
- case RIL_REQUEST_VOICE_REGISTRATION_STATE:
- ril_request_voice_registration_state(t);
- break;
- case RIL_REQUEST_DATA_REGISTRATION_STATE:
- ril_request_data_registration_state(t);
- break;
+ if (data == NULL || size < sizeof(RIL_SIM_IO_v6))
#else
- case RIL_REQUEST_REGISTRATION_STATE:
- ril_request_registration_state(t);
- break;
- case RIL_REQUEST_GPRS_REGISTRATION_STATE:
- ril_request_gprs_registration_state(t);
- break;
+ if (data == NULL || size < sizeof(RIL_SIM_IO))
#endif
- case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS:
- ril_request_query_available_networks(t);
- break;
- case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
- ril_request_get_preferred_network_type(t);
- break;
- case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
- ril_request_set_preferred_network_type(t, data, length);
- break;
- case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
- ril_request_query_network_selection_mode(t);
- break;
- case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
- ril_request_set_network_selection_automatic(t);
- break;
- case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL:
- ril_request_set_network_selection_manual(t, data, length);
- break;
- /* SMS */
- case RIL_REQUEST_SEND_SMS:
- ril_request_send_sms(t, data, length);
- break;
- case RIL_REQUEST_SEND_SMS_EXPECT_MORE:
- ril_request_send_sms_expect_more(t, data, length);
- break;
- case RIL_REQUEST_SMS_ACKNOWLEDGE:
- ril_request_sms_acknowledge(t, data, length);
- break;
- case RIL_REQUEST_WRITE_SMS_TO_SIM:
- ril_request_write_sms_to_sim(t, data, length);
- break;
- case RIL_REQUEST_DELETE_SMS_ON_SIM:
- ril_request_delete_sms_on_sim(t, data, length);
- break;
- /* CALL */
- case RIL_REQUEST_DIAL:
- ril_request_dial(t, data, length);
- break;
- case RIL_REQUEST_GET_CURRENT_CALLS:
- ril_request_get_current_calls(t);
- break;
- case RIL_REQUEST_HANGUP:
- case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
- case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
- ril_request_hangup(t);
- break;
- case RIL_REQUEST_ANSWER:
- ril_request_answer(t);
- break;
- case RIL_REQUEST_LAST_CALL_FAIL_CAUSE:
- ril_request_last_call_fail_cause(t);
- break;
- case RIL_REQUEST_DTMF:
- ril_request_dtmf(t, data, length);
- break;
- case RIL_REQUEST_DTMF_START:
- ril_request_dtmf_start(t, data, length);
- break;
- case RIL_REQUEST_DTMF_STOP:
- ril_request_dtmf_stop(t);
+ break;
+
+ buffer = calloc(1, size);
+
+ memcpy(buffer, data, size);
+
+#if RIL_VERSION >= 6
+ if (((RIL_SIM_IO_v6 *) data)->path != NULL)
+ ((RIL_SIM_IO_v6 *) buffer)->path = strdup(((RIL_SIM_IO_v6 *) data)->path);
+
+ if (((RIL_SIM_IO_v6 *) data)->data != NULL)
+ ((RIL_SIM_IO_v6 *) buffer)->data = strdup(((RIL_SIM_IO_v6 *) data)->data);
+
+ if (((RIL_SIM_IO_v6 *) data)->pin2 != NULL)
+ ((RIL_SIM_IO_v6 *) buffer)->pin2 = strdup(((RIL_SIM_IO_v6 *) data)->pin2);
+
+ if (((RIL_SIM_IO_v6 *) data)->aidPtr != NULL)
+ ((RIL_SIM_IO_v6 *) buffer)->aidPtr = strdup(((RIL_SIM_IO_v6 *) data)->aidPtr);
+#else
+ if (((RIL_SIM_IO *) data)->path != NULL)
+ ((RIL_SIM_IO *) buffer)->path = strdup(((RIL_SIM_IO *) data)->path);
+
+ if (((RIL_SIM_IO *) data)->data != NULL)
+ ((RIL_SIM_IO *) buffer)->data = strdup(((RIL_SIM_IO *) data)->data);
+
+ if (((RIL_SIM_IO *) data)->pin2 != NULL)
+ ((RIL_SIM_IO *) buffer)->pin2 = strdup(((RIL_SIM_IO *) data)->pin2);
+#endif
+
+ data = buffer;
break;
- /* GPRS */
case RIL_REQUEST_SETUP_DATA_CALL:
- ril_request_setup_data_call(t, data, length);
- break;
case RIL_REQUEST_DEACTIVATE_DATA_CALL:
- ril_request_deactivate_data_call(t, data, length);
- break;
- case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE:
- ril_request_last_data_call_fail_cause(t);
- break;
- case RIL_REQUEST_DATA_CALL_LIST:
- ril_request_data_call_list(t);
- break;
- /* SND */
- case RIL_REQUEST_SET_MUTE:
- ril_request_set_mute(t, data, length);
- break;
- /* OTHER */
- case RIL_REQUEST_SCREEN_STATE:
- /* This doesn't affect anything */
- ril_request_complete(t, RIL_E_SUCCESS, NULL, 0);
+ strings_count = size / sizeof(char *);
break;
default:
- RIL_LOGE("%s: Unhandled request: %d", __func__, request);
- ril_request_complete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+ if (data == NULL || size != sizeof(char *))
+ break;
+
+ c = (char *) data;
+
+ for (i = 0; isprint(c[i]); i++);
+
+ if (i > 0 && c[i] == '\0') {
+ size = i + 1;
+ RIL_LOGD("Detected string with a size of %d byte%s", size, size > 0 ? "s" : "");
+ }
+
break;
}
+ if (strings_count > 0 && data != NULL && size >= strings_count * sizeof(char *)) {
+ buffer = calloc(1, size);
+
+ for (i = 0; i < strings_count; i++) {
+ if (((char **) data)[i] != NULL) {
+ c = strdup(((char **) data)[i]);
+ ((char **) buffer)[i] = c;
+ }
+ }
+
+ data = buffer;
+ }
+
+ ril_request_register(request, data, size, token);
+
+ if (buffer != NULL)
+ free(buffer);
+
+ ril_request_stats_log();
+
RIL_UNLOCK();
+
+ RIL_REQUEST_LOOP_UNLOCK();
}
+
RIL_RadioState ril_on_state_request(void)
{
- return ril_data.state.radio_state;
-}
+ if (ril_data == NULL)
+ return RADIO_STATE_UNAVAILABLE;
-int ril_on_supports(int request)
-{
- return 1;
+ return ril_data->radio_state;
}
-void ril_on_cancel(RIL_Token t)
+int ril_supports(int request)
{
- ril_request_set_canceled(t, 1);
+ unsigned int i;
+
+ for (i = 0; i < ril_request_handlers_count; i++) {
+ if (ril_request_handlers[i].handler == NULL)
+ continue;
+
+ if (ril_request_handlers[i].request == request)
+ return 1;
+ }
+
+ return 0;
}
-const char *ril_get_version(void)
+void ril_on_cancel(RIL_Token token)
{
- return RIL_VERSION_STRING;
-}
+ struct ril_request *request;
-/*
- * RIL init
- */
+ RIL_LOCK();
-void ril_data_init(void)
-{
- memset(&ril_data, 0, sizeof(ril_data));
+ request = ril_request_find_token(token);
+ if (request == NULL) {
+ RIL_UNLOCK();
+ return;
+ }
- pthread_mutex_init(&ril_data.mutex, NULL);
+ ril_request_unregister(request);
- ril_data.state.radio_state = RADIO_STATE_UNAVAILABLE;
+ ril_request_stats_log();
+
+ RIL_UNLOCK();
}
-/*
- * RIL interface
- */
+const char *ril_get_version(void)
+{
+ return RIL_VERSION_STRING;
+}
-static const RIL_RadioFunctions ril_ops = {
- RIL_VERSION >= 6 ? 6 : RIL_VERSION,
+RIL_RadioFunctions ril_radio_functions = {
+ RIL_VERSION,
ril_on_request,
ril_on_state_request,
- ril_on_supports,
+ ril_supports,
ril_on_cancel,
ril_get_version
};
-const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
+const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
+ char **argv)
{
- struct ril_client *ipc_fmt_client;
- struct ril_client *ipc_rfs_client;
- struct ril_client *srs_client;
+ RIL_RadioFunctions *radio_functions;
+ pthread_attr_t attr;
+ unsigned int i;
int rc;
if (env == NULL)
return NULL;
- ril_data_init();
- ril_data.env = (struct RIL_Env *) env;
-
- RIL_LOCK();
-
- RIL_LOGD("Creating IPC FMT client");
-
- ipc_fmt_client = ril_client_new(&ipc_fmt_client_funcs);
- rc = ril_client_create(ipc_fmt_client);
-
+ rc = ril_data_create();
if (rc < 0) {
- RIL_LOGE("IPC FMT client creation failed.");
- goto ipc_rfs;
- }
-
- rc = ril_client_thread_start(ipc_fmt_client);
-
- if (rc < 0) {
- RIL_LOGE("IPC FMT thread creation failed.");
- goto ipc_rfs;
+ RIL_LOGE("Creating RIL data failed");
+ return NULL;
}
- ril_data.ipc_fmt_client = ipc_fmt_client;
- RIL_LOGD("IPC FMT client ready");
-
-ipc_rfs:
- RIL_LOGD("Creating IPC RFS client");
-
- ipc_rfs_client = ril_client_new(&ipc_rfs_client_funcs);
- rc = ril_client_create(ipc_rfs_client);
+ RIL_LOCK();
- if (rc < 0) {
- RIL_LOGE("IPC RFS client creation failed.");
- goto srs;
- }
+ ril_data->env = env;
- rc = ril_client_thread_start(ipc_rfs_client);
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
- if (rc < 0) {
- RIL_LOGE("IPC RFS thread creation failed.");
- goto srs;
+ rc = ril_client_create(ril_clients[i]);
+ if (rc < 0)
+ goto error;
}
- ril_data.ipc_rfs_client = ipc_rfs_client;
- RIL_LOGD("IPC RFS client ready");
-
-srs:
- RIL_LOGD("Creating SRS client");
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
- srs_client = ril_client_new(&srs_client_funcs);
- rc = ril_client_create(srs_client);
+ rc = ril_client_open(ril_clients[i]);
+ if (rc < 0)
+ goto error;
- if (rc < 0) {
- RIL_LOGE("SRS client creation failed.");
- goto end;
+ rc = ril_client_loop(ril_clients[i]);
+ if (rc < 0)
+ goto error;
}
- rc = ril_client_thread_start(srs_client);
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (rc < 0) {
- RIL_LOGE("SRS thread creation failed.");
- goto end;
+ rc = pthread_create(&ril_data->request_thread, &attr, ril_request_loop, NULL);
+ if (rc != 0) {
+ RIL_LOGE("Starting request loop failed");
+ goto error;
}
- ril_data.srs_client = srs_client;
- RIL_LOGD("SRS client ready");
+ radio_functions = &ril_radio_functions;
+ goto complete;
-end:
+error:
+ radio_functions = NULL;
+
+complete:
RIL_UNLOCK();
- return &ril_ops;
+ return radio_functions;
}