--- /dev/null
+Jongman Park <jman.park@samsung.com>
+Ja-young Gu <jygu@samsung.com>
+Kyeongchul Kim <kyeongchul.kim@samsung.com>
+DongHoo Park <donghoo.park@samsung.>
+Youngman Park <youngman.park@samsung.com>
+Inho Oh <inho48.oh@samsung.com>
+Hayoon Ko <hayoon.ko@samsung.com>
+Junhwan An <jh48.an@samsung.com>
+Kyoungyoup Park <gynaru.park@samsung.com>
+Jinyup Kim <kjy9411@samsung.com>
### Global setting ###
SET(PREFIX ${CMAKE_INSTALL_PREFIX})
SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${prefix}/lib")
SET(INCLUDEDIR "\${prefix}/include")
# Set required packages
INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED glib-2.0 tcore libtzplatform-config tel-headers vconf)
+pkg_check_modules(pkgs REQUIRED glib-2.0 tcore dlog)
FOREACH(flag ${pkgs_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/)
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wdeclaration-after-statement -Wmissing-declarations -Wredundant-decls -Wcast-align")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -O2 -Werror -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wdeclaration-after-statement -Wmissing-declarations -Wredundant-decls -Wcast-align -Wall -Wno-array-bounds -Wno-empty-body -Wno-ignored-qualifiers -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-but-set-parameter -Wno-unused-but-set-variable")
ADD_DEFINITIONS("-DFEATURE_TLOG_DEBUG")
ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"ATMODEM\"")
MESSAGE(${CMAKE_EXE_LINKER_FLAGS})
SET(SRCS
- src/desc_atmodem.c
- src/atmodem_modem.c
- src/atmodem_common.c
- src/atmodem_network.c
- src/atmodem_sim.c
- src/atmodem_call.c
- src/atmodem_ps.c
- src/atmodem_sms.c
- src/atmodem_ss.c
+ src/desc_at.c
+ src/s_modem.c
+ src/s_common.c
+ src/s_network.c
+ src/s_sim.c
+ src/s_call.c
+ src/s_ps.c
+ src/s_sms.c
+ src/s_ss.c
)
# install
INSTALL(TARGETS atmodem-plugin
- LIBRARY DESTINATION ${LIB_INSTALL_DIR}/telephony/plugins/modems)
+ LIBRARY DESTINATION lib/telephony/plugins/modems)
INSTALL(FILES ${CMAKE_SOURCE_DIR}/res/wiki_mcc_mnc_oper_list.sql DESTINATION /tmp RENAME mcc_mnc_oper_list.sql)
INSTALL(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION /usr/share/license RENAME tel-plugin-atmodem)
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __ATMODEM_COMMON_H__
-#define __ATMODEM_COMMON_H__
-
-#define ATMODEM_SWAP_BYTES_16(x) \
-{ \
- unsigned short int data = *(unsigned short int *)&(x); \
- data = ((data & 0xff00) >> 8) | \
- ((data & 0x00ff) << 8); \
- *(unsigned short int *)&(x) = data; \
-}
-
-typedef struct {
- TcoreObjectResponseCallback cb;
- void *cb_data;
- char data[]; /* Additional data */
-} AtmodemRespCbData;
-
-#define ATMODEM_GET_DATA_FROM_RESP_CB_DATA(ptr) (gpointer)ptr->data
-#define ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, request) \
-do {\
- if (ret != TEL_RETURN_SUCCESS) { \
- err("Failed to process request - [%s]", request); \
- atmodem_destroy_resp_cb_data(resp_cb_data); \
- } \
-} while(0)
-
-AtmodemRespCbData *atmodem_create_resp_cb_data(TcoreObjectResponseCallback cb,
- void *cb_data, void *data, guint data_len);
-void atmodem_destroy_resp_cb_data(AtmodemRespCbData *resp_cb_data);
-
-void on_send_atmodem_request(TcorePending *p,
- TelReturn send_status, void *user_data);
-
-#endif /* __ATMODEM_COMMON_H__ */
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __ATMODEM_MODEM_H__
-#define __ATMODEM_MODEM_H__
-
-gboolean atmodem_modem_init(TcorePlugin *p, CoreObject *co);
-void atmodem_modem_exit(TcorePlugin *p, CoreObject *co);
-
-gboolean atmodem_modem_power_on_modem(TcorePlugin *plugin);
-
-#endif /* __ATMODEM_MODEM_H__ */
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __ATMODEM_NETWORK_H__
-#define __ATMODEM_NETWORK_H__
-
-gboolean atmodem_network_init(TcorePlugin *p, CoreObject *co);
-void atmodem_network_exit(TcorePlugin *p, CoreObject *co);
-
-#endif /* __ATMODEM_NETWORK_H__ */
/*
* tel-plugin-atmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef __ATMODEM_SS_H__
-#define __ATMODEM_SS_H__
+#ifndef __S_CALL_H__
+#define __S_CALL_H__
+
+gboolean s_call_init(TcorePlugin *p, TcoreHal *h);
+void s_call_exit(TcorePlugin *p);
-gboolean atmodem_ss_init(TcorePlugin *p, CoreObject *co);
-void atmodem_ss_exit(TcorePlugin *p, CoreObject *co);
+#endif
-#endif /* __ATMODEM_SS_H__ */
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __S_COMMON_H__
+#define __S_COMMON_H__
+
+#include <tcore.h>
+#include <glib.h>
+#include <user_request.h>
+
+#define EVENT_SYS_NOTI_MODEM_POWER "system_power"
+#define EVENT_MODEM_POWER "modem_power"
+#define EVENT_MODEM_PHONE_STATE "modem_phone_state"
+
+#define EVENT_CALL_STATUS "call_status"
+#define EVENT_CALL_INCOMING "call_incoming"
+#define EVENT_CALL_WAITING "call_waiting"
+
+#define EVENT_SS_INFO "ss_info"
+#define EVENT_SS_USSD "ss_ussd"
+
+#define EVENT_PS_CALL_STATUS "ps_call_status"
+#define EVENT_PS_DATA_COUNTER "ps_data_counter"
+#define EVENT_PS_IPCONFIGURATION "ps_ipconfiguration"
+#define EVENT_PS_PIN_CTRL "ps_pin_control"
+#define EVENT_PS_HSDPA_STATUS "ps_hsdpa_status"
+#define EVENT_PS_ATTACH_DETACH "ps_attach_detach"
+#define EVENT_PS_EXTERNAL_CALL "ps_external_call"
+
+#define EVENT_SAP_STATUS "sap_status"
+#define EVENT_SAP_DISCONNECT "sap_disconnect"
+
+#define EVENT_SIM_PIN_STATUS "sim_pin_status"
+
+#define EVENT_SAT_ENVELOPE_RESP "sat_envelope_response"
+#define EVENT_SAT_REFRESH_STATUS "sat_refresh_status"
+#define EVENT_SAT_PROACTIVE_COMMAND "sat_proactive_command"
+#define EVENT_SAT_CONTROL_RESULT "sat_control_result"
+
+
+#define EVENT_CALL_STATUS "call_status"
+#define EVENT_CALL_INCOMING "call_incoming"
+
+#define EVENT_NETWORK_REGISTRATION "network_regist"
+#define EVENT_NETWORK_ICON_INFO "network_icon_info"
+#define EVENT_NETWORK_TIME_INFO "network_time_info"
+#define EVENT_NETWORK_IDENTITY "network_identity"
+
+#define EVENT_SMS_INCOM_MSG "sms_incom_msg"
+#define EVENT_SMS_SEND_ACK "sms_send_ack"
+#define EVENT_SMS_MEMORY_STATUS "sms_memory_status"
+#define EVENT_SMS_CB_INCOM_MSG "sms_cb_incom_msg"
+#define EVENT_SMS_DELETE_MSG_CNF "sms_delete_msg_cnf"
+#define EVENT_SMS_WRITE_MSG_CNF "sms_write_msg_cnf"
+#define EVENT_SMS_DELIVERY_RPT_CNF "sms_deliver_rpt_cnf"
+#define EVENT_SMS_DEVICE_READY "sms_device_ready"
+
+#define EVENT_PHONEBOOK_STATUS "phonebook_status"
+#define EVENT_PHONEBOOK_FIRST_INDEX "phonebook_first_index"
+
+enum direction_e {
+ RX,
+ TX
+};
+
+struct global_data {
+ unsigned int msg_auto_id_current;
+ unsigned int msg_auto_id_start;
+ unsigned int msg_auto_id_end;
+};
+
+struct work_queue_data {
+ unsigned int id;
+ UserRequest *ur;
+};
+
+#define UTIL_ID(hdr) ((hdr).main_cmd << 8 | (hdr).sub_cmd)
+#define UTIL_IDP(hdr) ((hdr)->main_cmd << 8 | (hdr)->sub_cmd)
+
+/* If condition fails it retuns 'ret_val' without asserting program */
+#define CHECK_AND_RETURN_VALUE(cond, ret_val) \
+ do { \
+ if(!(cond)) { \
+ err("*** Condition (%s) Fails ***", #cond); \
+ return ret_val; \
+ } \
+ } while (0)
+
+#define CHECK_AND_RETURN(cond) \
+ do { \
+ if(!(cond)) { \
+ err("*** Condition (%s) Fails ***", #cond); \
+ return ; \
+ } \
+ } while (0)
+
+void hook_hex_dump(enum direction_e d, int size, const void *data);
+unsigned int util_assign_message_sequence_id(TcorePlugin *p);
+gboolean util_add_waiting_job(GQueue *queue, unsigned int id, UserRequest *ur);
+UserRequest* util_pop_waiting_job(GQueue *queue, unsigned int id);
+void util_hex_dump(char *pad, int size, const void *data);
+unsigned char util_hexCharToInt(char c);
+char* util_hexStringToBytes(char * s);
+gboolean util_byte_to_hex(const char *byte_pdu, char *hex_pdu, int num_bytes);
+
+void on_send_at_request(TcorePending *p,
+ TReturn send_status, void *user_data);
+
+#endif
/*
* tel-plugin-atmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef __ATMODEM_CALL_H__
-#define __ATMODEM_CALL_H__
+#ifndef __S_MODEM_H__
+#define __S_MODEM_H__
+
+gboolean s_modem_init(TcorePlugin *p, TcoreHal *h);
+void s_modem_exit(TcorePlugin *p);
-gboolean atmodem_call_init(TcorePlugin *p, CoreObject *co);
-void atmodem_call_exit(TcorePlugin *p, CoreObject *co);
+gboolean s_modem_send_poweron(TcorePlugin *p);
-#endif /* __ATMODEM_CALL_H__ */
+#endif
/*
* tel-plugin-atmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef __ATMODEM_SIM_H__
-#define __ATMODEM_SIM_H__
+#ifndef __S_NETWORK_H__
+#define __S_NETWORK_H__
-gboolean atmodem_sim_init(TcorePlugin *p, CoreObject *co);
-void atmodem_sim_exit(TcorePlugin *p, CoreObject *co);
+gboolean s_network_init(TcorePlugin *p, TcoreHal *h);
+void s_network_exit(TcorePlugin *p);
-#endif /* __ATMODEM_SIM_H__ */
+#endif
/*
* tel-plugin-atmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef __ATMODEM_PS_H__
-#define __ATMODEM_PS_H__
+#ifndef __S_PS_H__
+#define __S_PS_H__
-gboolean atmodem_ps_init(TcorePlugin *p, CoreObject *co);
-void atmodem_ps_exit(TcorePlugin *p, CoreObject *co);
+gboolean s_ps_init(TcorePlugin *p, TcoreHal *h);
+void s_ps_exit(TcorePlugin *p);
-#endif /* __ATMODEM_PS_H__ */
+#endif
/*
* tel-plugin-atmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef __ATMODEM_SMS_H__
-#define __ATMODEM_SMS_H__
+#ifndef __S_SIM_H__
+#define __S_SIM_H__
-gboolean atmodem_sms_init(TcorePlugin *p, CoreObject *co);
-void atmodem_sms_exit(TcorePlugin *p, CoreObject *co);
+gboolean s_sim_init(TcorePlugin *p, TcoreHal *h);
+void s_sim_exit(TcorePlugin *p);
-#endif /* __ATMODEM_SMS_H__ */
+#endif
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __S_SMS_H__
+#define __S_SMS_H__
+
+gboolean s_sms_init(TcorePlugin *p, TcoreHal *h);
+void s_sms_exit(TcorePlugin *p);
+
+#endif
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __S_SS_H__
+#define __S_SS_H__
+
+gboolean s_ss_init(TcorePlugin *p, TcoreHal *h);
+void s_ss_exit(TcorePlugin *p);
+
+#endif
-%define major 3
-%define minor 0
-%define patchlevel 1
+%define major 0
+%define minor 1
+%define patchlevel 57
-Name: tel-plugin-atmodem
-Summary: Telephony AT Modem library
-Version: %{major}.%{minor}.%{patchlevel}
-Release: 1
-Group: System/Libraries
-License: Apache-2.0
-Source0: tel-plugin-atmodem-%{version}.tar.gz
-Source1001: tel-plugin-atmodem.manifest
-Requires(post): /sbin/ldconfig
-Requires(postun): /sbin/ldconfig
-BuildRequires: cmake
-BuildRequires: pkgconfig(glib-2.0)
-BuildRequires: pkgconfig(tcore)
-BuildRequires: pkgconfig(libtzplatform-config)
-BuildRequires: pkgconfig(tel-headers)
-BuildRequires: pkgconfig(vconf)
+Name: tel-plugin-atmodem
+Version: %{major}.%{minor}.%{patchlevel}
+Release: 1
+License: Apache-2.0
+Summary: Telephony AT Modem library
+Group: System/Libraries
+Source0: tel-plugin-atmodem-%{version}.tar.gz
+BuildRequires: cmake
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(tcore)
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
%description
Telephony AT Modem library
%prep
%setup -q
-cp %{SOURCE1001} .
%build
-%cmake .
-make %{?jobs:-j%jobs}
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?_smp_mflags}
%post
/sbin/ldconfig
-mkdir -p %{TZ_SYS_DB}
+mkdir -p /opt/dbspace
-if [ ! -f %{TZ_SYS_DB}/.mcc_mnc_oper_list.db ]
+if [ ! -f /opt/dbspace/.mcc_mnc_oper_list.db ]
then
- sqlite3 %{TZ_SYS_DB}/.mcc_mnc_oper_list.db < /tmp/mcc_mnc_oper_list.sql
+ sqlite3 /opt/dbspace/.mcc_mnc_oper_list.db < /tmp/mcc_mnc_oper_list.sql
fi
rm -f /tmp/mcc_mnc_oper_list.sql
-if [ -f %{TZ_SYS_DB}/.mcc_mnc_oper_list.db ]
+if [ -f /opt/dbspace/.mcc_mnc_oper_list.db ]
then
-chmod 600 %{TZ_SYS_DB}/.mcc_mnc_oper_list.db
+chmod 600 /opt/dbspace/.mcc_mnc_oper_list.db
fi
-if [ -f %{TZ_SYS_DB}/.mcc_mnc_oper_list.db-journal ]
+if [ -f /opt/dbspace/.mcc_mnc_oper_list.db-journal ]
then
-chmod 644 %{TZ_SYS_DB}/.mcc_mnc_oper_list.db-journal
+chmod 644 /opt/dbspace/.mcc_mnc_oper_list.db-journal
fi
%postun -p /sbin/ldconfig
%install
-rm -rf %{buildroot}
%make_install
mkdir -p %{buildroot}/usr/share/license
cp LICENSE %{buildroot}/usr/share/license/%{name}
%files
-%manifest %{name}.manifest
+%manifest tel-plugin-atmodem.manifest
%defattr(-,root,root,-)
#%doc COPYING
%{_libdir}/telephony/plugins/modems/atmodem-plugin*
/*
* tel-plugin-atmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Ja-young Gu <jygu@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-#include <server.h>
-#include <plugin.h>
-#include <core_object.h>
-#include <hal.h>
-#include <queue.h>
-#include <storage.h>
-#include <at.h>
-
-#include <co_call.h>
-
-#include "atmodem_call.h"
-#include "atmodem_common.h"
-
-/* Call Status */
-typedef enum {
- ATMODEM_CALL_STATUS_ACTIVE,
- ATMODEM_CALL_STATUS_HELD,
- ATMODEM_CALL_STATUS_DIALING,
- ATMODEM_CALL_STATUS_ALERT,
- ATMODEM_CALL_STATUS_INCOMING,
- ATMODEM_CALL_STATUS_WAITING,
- ATMODEM_CALL_STATUS_CONNECTING,
- ATMODEM_CALL_STATUS_DISCONNECTED,
- ATMODEM_CALL_STATUS_IDLE
-} AtmodemCallStatus;
-
-static void on_response_atmodem_call_default(TcorePending *p,
- guint data_len, const void *data, void *user_data);
-
-static TelReturn __atmodem_call_get_call_list(CoreObject *co, gboolean flag);
-
-static TelCallType __atmodem_call_type(gint type)
-{
- dbg("Entry");
-
- switch (type) {
- case 0:
- return TEL_CALL_TYPE_VOICE;
- case 1:
- return TEL_CALL_TYPE_VIDEO;
- default:
- err("invalid call type, returing default call type as voice");
- return TEL_CALL_TYPE_VOICE;
- }
-}
-
-static TelCallState __atmodem_call_state(AtmodemCallStatus state)
-{
- dbg("Entry");
-
- switch (state) {
- case ATMODEM_CALL_STATUS_ACTIVE:
- return TEL_CALL_STATE_ACTIVE;
-
- case ATMODEM_CALL_STATUS_HELD:
- return TEL_CALL_STATE_HELD;
-
- case ATMODEM_CALL_STATUS_DIALING:
- return TEL_CALL_STATE_DIALING;
-
- case ATMODEM_CALL_STATUS_ALERT:
- return TEL_CALL_STATE_ALERT;
-
- case ATMODEM_CALL_STATUS_INCOMING:
- case ATMODEM_CALL_STATUS_WAITING:
- return TEL_CALL_STATE_INCOMING;
-
- default:
- return TEL_CALL_STATE_IDLE;
- }
-}
-
-static void __atmodem_call_branch_by_status(CoreObject *co,
- CallObject *call_obj, TelCallState call_state)
-{
- guint call_id;
- TelCallType call_type;
- TelCallState state;
- TcoreNotification command = TCORE_NOTIFICATION_UNKNOWN;
-
- if (tcore_call_object_get_state(call_obj, &state) == FALSE) {
- err("Unable to get Call status");
- return;
- }
-
- dbg("Call State - Present : [%d] New: [%d]", state, call_state);
- if (call_state == state) {
- dbg("No change in Call State...");
- return;
- }
-
- if (tcore_call_object_get_call_type(call_obj, &call_type) == FALSE) {
- err("Unable to get Call type");
- return;
- }
-
- if (tcore_call_object_get_id(call_obj, &call_id) == FALSE) {
- err("Unable to get Call id");
- return;
- }
-
- /* Update Call state */
- tcore_call_object_set_state(call_obj, call_state);
-
- if (call_type == TEL_CALL_TYPE_VOICE) { /* Voice call notification */
- switch (call_state) {
- case TEL_CALL_STATE_ACTIVE:
- command = TCORE_NOTIFICATION_CALL_STATUS_ACTIVE;
- break;
-
- case TEL_CALL_STATE_HELD:
- command = TCORE_NOTIFICATION_CALL_STATUS_HELD;
- break;
-
- case TEL_CALL_STATE_DIALING:
- command = TCORE_NOTIFICATION_CALL_STATUS_DIALING;
- break;
-
- case TEL_CALL_STATE_ALERT:
- command = TCORE_NOTIFICATION_CALL_STATUS_ALERT;
- break;
-
- case TEL_CALL_STATE_INCOMING:
- case TEL_CALL_STATE_WAITING:
- command = TCORE_NOTIFICATION_CALL_STATUS_INCOMING;
- break;
-
- case TEL_CALL_STATE_IDLE: {
- TelCallStatusIdleNoti idle;
-
- idle.call_id = call_id;
- /* TODO - get proper call end cause. */
- idle.cause = TEL_CALL_END_CAUSE_NONE;
-
- /* Send notification */
- tcore_object_send_notification(co,
- TCORE_NOTIFICATION_CALL_STATUS_IDLE,
- sizeof(TelCallStatusIdleNoti), &idle);
-
- /* Free Call object */
- tcore_call_object_free(co, call_obj);
-
- return;
- }
- }
- } else {
- err("Unknown Call type: [%d]", call_type);
- return;
- }
-
- /* Send notification */
- tcore_object_send_notification(co,
- command, sizeof(call_id), &call_id);
-}
-
-static void __atmodem_handle_call_get_call_list(CoreObject *co,
- gboolean flag, void *data)
-{
- gint call_id;
- gint direction;
- gint mode;
- gint state;
- gint mpty;
- gint ton;
- GSList *tokens = NULL;
- gchar *resp = NULL;
- gchar *line;
- gchar *num = NULL;
- gint num_type;
- gchar number[TEL_CALL_CALLING_NUMBER_LEN_MAX + 1] = {0, };
- GSList *lines = data;
- CallObject *call_obj = NULL;
-
- while (lines != NULL) {
- line = (gchar *)lines->data;
- /* point to next node */
- lines = lines->next;
-
- /* free previous tokens*/
- tcore_at_tok_free(tokens);
-
- tokens = tcore_at_tok_new(line);
- resp = g_slist_nth_data(tokens, 0);
- if (NULL == resp) {
- err("Invalid call_id");
- continue;
- }
-
- call_id = atoi(resp);
- resp = g_slist_nth_data(tokens, 1);
- if (NULL == resp) {
- err("Invalid direction");
- continue;
- }
-
- direction = (atoi(resp) == 0) ? 1 : 0;
- resp = g_slist_nth_data(tokens, 2);
- if (NULL == resp) {
- err("Invalid state");
- continue;
- }
-
- state = __atmodem_call_state(atoi(resp));
- resp = g_slist_nth_data(tokens, 3);
- if (NULL == resp) {
- err("Invalid mode");
- continue;
- }
- mode = __atmodem_call_type(atoi(resp));
-
- resp = g_slist_nth_data(tokens, 4);
- if (NULL == resp) {
- err("Invalid mpty");
- continue;
- }
- mpty = atoi(resp);
-
- resp = g_slist_nth_data(tokens, 5);
- if (NULL == resp) {
- err("Number is NULL");
- } else {
- /* Strike off double quotes */
- num = tcore_at_tok_extract(resp);
- dbg("Number: [%s]", num);
-
- resp = g_slist_nth_data(tokens, 6);
- if (!resp) {
- err("Invalid Number type");
- } else {
- num_type = atoi(resp);
-
- /* Check if number is International or National */
- ton = ((num_type) >> 4) & 0x07;
- if (ton == 1 && num[0] != '+') {
- /* International number */
- number[0] = '+';
- memcpy(&number[1], num, strlen(num));
- } else {
- memcpy(number, num, strlen(num));
- }
- }
- g_free(num);
- }
-
- dbg("Call ID: [%d] Direction: [%s] Call Type: [%d] " \
- "Multi-party: [%s] Number: [%s] Type-of-Number: [%d] State: [%d]", \
- call_id, (direction ? "Outgoing" : "Incoming"),
- mode, (mpty ? "YES" : "NO"), number, ton, state);
-
- call_obj = tcore_call_object_find_by_id(co, call_id);
- if (NULL == call_obj) {
- call_obj = tcore_call_object_new(co, call_id);
- if (NULL == call_obj) {
- err("Unable to create call object");
- continue;
- }
- }
-
- /* Set Call parameters */
- tcore_call_object_set_type(call_obj, mode);
- tcore_call_object_set_direction(call_obj, direction);
- tcore_call_object_set_multiparty_state(call_obj, mpty);
- if (number[0] != '\0')
- tcore_call_object_set_cli_info(call_obj,
- TEL_CALL_CLI_VALIDITY_VALID, number);
- else
- tcore_call_object_set_cli_info(call_obj,
- TEL_CALL_CLI_VALIDITY_NOT_AVAILABLE, number);
- tcore_call_object_set_active_line(call_obj, TEL_CALL_ACTIVE_LINE1);
- if (flag == TRUE)
- __atmodem_call_branch_by_status(co, call_obj, state);
- else
- tcore_call_object_set_state(call_obj, state);
- }
-}
-
-/* Incoming Call notification */
-static void __on_notification_atmodem_call_incoming(CoreObject *co,
- guint call_id, const void *data)
-{
- GSList *list = NULL;
- GSList *tokens = NULL;
- gchar *resp = NULL;
- gchar *line;
- gboolean direction = TRUE;
- gint mode;
- gpointer state;
- gint call_state;
- gint mpty;
- gint ton;
- gchar *num = NULL;
- gchar number[TEL_CALL_CALLING_NUMBER_LEN_MAX + 1] = {0, };
- GSList *lines = (GSList *)data;
- CallObject *call_obj = NULL;
-
- dbg("Entry");
-
- /* Check call with 'Incoming' status already exist */
- list = tcore_call_object_find_by_status(co, TEL_CALL_STATE_INCOMING);
- if (list != NULL) {
- err("Incoming Call already exist... Skip!!!");
- return;
- }
-
- call_obj = tcore_call_object_find_by_id(co, call_id);
- if (call_obj != NULL) {
- err("co with same id already exist. skip");
- return;
- }
-
- /* Create Call object */
- call_obj = tcore_call_object_new(co, (guint)call_id);
- if (NULL == call_obj) {
- err(" Unable to create call object");
- return;
- }
-
- lines = (GSList *)data;
- if (lines == NULL) {
- err("Invalid response received");
- return;
- }
-
- line = (gchar *)lines->data;
-
- /* Tokenize */
- tokens = tcore_at_tok_new(line);
-
- state = g_slist_nth_data(tokens, 2);
- if (NULL == state) {
- err("State is missing");
- goto out;
- }
- call_state = __atmodem_call_state(atoi(state));
-
- resp = g_slist_nth_data(tokens, 3);
- if (NULL == resp) {
- err("Invalid mode");
- goto out;
- }
- mode = __atmodem_call_type(atoi(resp));
-
- resp = g_slist_nth_data(tokens, 4);
- if (NULL == resp) {
- err("Invalid mpty");
- goto out;
- }
- mpty = atoi(resp);
-
- resp = g_slist_nth_data(tokens, 5);
- if (NULL == resp) {
- err("Number is NULL");
- } else {
- /* Strike off double quotes */
- num = tcore_at_tok_extract(resp);
- dbg("Number: [%s]", num);
-
- memcpy(number, num, strlen(num));
- number[strlen(num)] = '\0';
- g_free(num);
- }
-
- dbg("Call ID: [%d] Direction: [%s] Call Type: [%d] " \
- "Multi-party: [%s] Number: [%s] Type-of-Number: [%d] State: [%d]", \
- call_id, (direction ? "Outgoing" : "Incoming"),
- mode, (mpty ? "YES" : "NO"), number, ton, call_state); /* Set Call parameters */
-
- /* Update Call Object */
- tcore_call_object_set_type(call_obj, mode);
- tcore_call_object_set_direction(call_obj, direction);
- tcore_call_object_set_multiparty_state(call_obj, mpty);
- if (number[0] != '\0')
- tcore_call_object_set_cli_info(call_obj,
- TEL_CALL_CLI_VALIDITY_VALID, number);
- else
- tcore_call_object_set_cli_info(call_obj,
- TEL_CALL_CLI_VALIDITY_NOT_AVAILABLE, number);
- tcore_call_object_set_active_line(call_obj, TEL_CALL_ACTIVE_LINE1);
-
- /* Send notification */
- __atmodem_call_branch_by_status(co, call_obj, call_state);
-
-out:
- /* Free tokens */
- tcore_at_tok_free(tokens);
-}
-
-static void __on_notification_atmodem_call_status(CoreObject *co,
- guint call_id, AtmodemCallStatus call_state)
-{
- CallObject *call_obj = NULL;
- TelCallState state;
-
- state = __atmodem_call_state(call_state);
- dbg("Call state [%d]", state);
-
- switch (state) {
- case TEL_CALL_STATE_ACTIVE:
- case TEL_CALL_STATE_HELD:
- case TEL_CALL_STATE_ALERT:
- case TEL_CALL_STATE_IDLE: {
- call_obj = tcore_call_object_find_by_id(co, call_id);
- if (call_obj == NULL) {
- err("Unable to find Call Object - Call ID: [%d]", call_id);
- return;
- }
-
- /* Send notification to application */
- __atmodem_call_branch_by_status(co, call_obj, state);
- }
- break;
-
- case TEL_CALL_STATE_DIALING: {
- call_obj = tcore_call_object_find_by_id(co, call_id);
- if (!call_obj) {
- call_obj = tcore_call_object_new(co, call_id);
- if (!call_obj) {
- err("Unable to create Call Object");
- return;
- }
- }
-
- /*
- * Make request to get current Call list.
- * Update CallObject with <number>
- * and send notification to application
- */
- __atmodem_call_get_call_list(co, TRUE);
- }
- break;
-
- default:
- err("Unhandled Call Status: [%d]", state);
- break;
- }
-}
-
-/* Internal response operation */
-static void __on_response_atmodem_call_get_call_list(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- GSList *lines = NULL;
- TelCallResult result = TEL_CALL_RESULT_FAILURE; //TODO - CME error mapping required
- gboolean *flag = ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- gint count;
- dbg("Entry");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success) {
- result = TEL_CALL_RESULT_SUCCESS;
- if (NULL == at_resp->lines) {
- err("invalid response received");
- return;
- }
-
- lines = (GSList *)at_resp->lines;
- count = g_slist_length(lines);
- dbg("Total records : %d", g_slist_length(lines));
- if (0 == count) {
- err("Call count is zero");
- return;
- }
-
- dbg("RESPONSE OK");
-
- /* Process +CLCC notification parameter */
- __atmodem_handle_call_get_call_list(co, *flag, lines);
-
- } else {
- err("RESPONSE NOK");
- }
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-/*internal request operation */
-static TelReturn __atmodem_send_call_request(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data,
- gchar *at_cmd, gchar *func_name)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, func_name, strlen(func_name) + 1);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_call_default, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, func_name);
-
- /* Free resources */
- g_free(at_cmd);
- return ret;
-}
-
- /*
- * Operation - Get current call list.
- *
- * Request -
- * AT-Command: AT+CLCC
- *
- * Response -
- * Success:
- *[+CLCC: <id1>, <dir>, <stat>, <mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>]]]
- *[<CR><LF> +CLCC: <id2>,<dir>,<stat>,<mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>]]][\85]]]
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn __atmodem_call_get_call_list(CoreObject *co, gboolean flag)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret =TEL_RETURN_FAILURE;
- dbg("Entry");
-
- if (NULL == co) {
- err("Core Object is NULL");
- return ret;
- }
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(NULL, NULL, &flag, sizeof(gboolean));
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+CLCC","+CLCC",
- TCORE_AT_COMMAND_TYPE_MULTILINE,
- NULL,
- __on_response_atmodem_call_get_call_list, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get current call list");
-
- return ret;
-}
-
-/* Notification */
-/*
-* Operation - call status notification from network.
-* notification message format:
-* %SCLCC: <call_id><direction><status><type><mpty>
-* where
-* <call_id>
-* indicates the call identification.
-* <direction>
-* indicates call direction (MO or MT)
-* <status>
-* 0 active
-* 1 hold
-* 2 dialling (MO call)
-* 3 alerting (MO call; ringing for the remote party)
-* 4 ringing (MT call)
-* 5 waiting (MT call)
-* 6 connecting (MO call)
-* 7 disconneted
-* <type>
-* call type
-* <mpty>
-* multiparty call
-*
-*/
-static gboolean on_notification_atmodem_call_status(CoreObject *co,
- const void *data, void *user_data)
-{
- GSList *tokens = NULL;
- GSList *lines = NULL;
- const gchar *line = NULL;
- gchar *state = NULL, *call_handle = NULL;
- AtmodemCallStatus status;
- guint call_id;
-
- dbg("Entry");
-
- lines = (GSList *)data;
- if (lines == NULL) {
- err("Invalid response received");
- return TRUE;
- }
-
- line = (gchar *)lines->data;
-
- /* Tokenize */
- tokens = tcore_at_tok_new(line);
- call_handle = g_slist_nth_data(tokens, 0);
- if (NULL == call_handle) {
- err("call_id missing");
- goto out;
- }
- call_id = atoi(call_handle);
-
- state = g_slist_nth_data(tokens, 2);
- if (NULL == state) {
- err("State is missing");
- goto out;
- }
- status = atoi(state);
-
- dbg("Call ID: [%d] Call Status: [%d]", call_id, status);
-
- switch (status) {
- case ATMODEM_CALL_STATUS_INCOMING:
- case ATMODEM_CALL_STATUS_WAITING:
- dbg("Incoming/Waiting Call...");
- __on_notification_atmodem_call_incoming(co, call_id, data);
- break;
-
- default:
- __on_notification_atmodem_call_status(co, call_id, status);
- break;
- }
-
-out:
- /* Free tokens */
- tcore_at_tok_free(tokens);
- return TRUE;
-}
-
-/*
- * Operation - SS network initiated notification.
- *
- * notification message format:
- * +CSSU: <code2>[<index> [,<number>,<type>]]
- * <code2>
- * (it is manufacturer specific, which of these codes are supported):
- * 0 this is a forwarded call (MT call setup)
- * 1 this is a CUG call (<index> present) (MT call setup)
- * 2 call has been put on hold (during a voice call)
- * 3 call has been retrieved (during a voice call)
- * 4 multiparty call entered (during a voice call)
- * 5 Call has been released - not a SS notification (during a voice call)
- * 6 forward check SS message received (can be received whenever)
- * 7 call is being connected (alerting) with the remote party in alerting state
- * in explicit call transfer operation
- * (during a voice call)
- * 8 call has been connected with the other remote party in explicit call transfer
- * operation (during a voice call or MT call setup)
- * 9 this is a deflected call (MT call setup)
- * 10 additional incoming call forwarded
- * <index>
- * refer Closed user group +CCUG
- * <number>
- * string type phone of format specified by <type>
- * <type>
- * type of address octet in integer format.
- */
-static gboolean on_notification_atmodem_call_ss_cssu_info(CoreObject *co,
- const void *event_data, void *user_data)
-{
- GSList *tokens = NULL;
- TcoreNotification command = TCORE_NOTIFICATION_UNKNOWN;
- gchar *resp = NULL;
- gchar *cmd = 0;
- gint index = 0;
- gint code2 = -1;
- gchar number[TEL_CALL_CALLING_NUMBER_LEN_MAX + 1] = {'\0',};
-
- dbg("Entry");
-
- if (1 != g_slist_length((GSList *) event_data)) {
- err("unsolicited msg but multiple line");
- return TRUE;
- }
-
- cmd = (gchar *) ((GSList *) event_data)->data;
- dbg("ss notification message[%s]", cmd);
-
- tokens = tcore_at_tok_new(cmd);
-
- /* parse <code2> */
- resp = g_slist_nth_data(tokens, 0);
- if (NULL == resp) {
- err("Code2 is missing from %CSSU indiaction");
- tcore_at_tok_free(tokens);
- return TRUE;
- }
- code2 = atoi(resp);
-
- /* parse [ <index>, <number>] */
- if ((resp = g_slist_nth_data(tokens, 1)))
- index = atoi(resp);
-
- if ((resp = g_slist_nth_data(tokens, 2))) {
- resp = tcore_at_tok_extract((const gchar *)resp);
- memcpy(number, resp, strlen(resp));
- number[strlen(resp)] = '\0';;
- g_free(resp);
- }
- dbg("+CSSU: <code2>: %d <index>: %d <number>: %s ", code2, index, number);
-
- /* <code2> - other values will be ignored */
- switch (code2) {
- case 0:
- command = TCORE_NOTIFICATION_CALL_INFO_MT_FORWARDED;
- break;
-
- case 2:
- command = TCORE_NOTIFICATION_CALL_INFO_HELD;
- break;
-
- case 3:
- command = TCORE_NOTIFICATION_CALL_INFO_ACTIVE;
- break;
-
- case 4:
- command = TCORE_NOTIFICATION_CALL_INFO_JOINED;
- break;
-
- case 7:
- case 8:
- command = TCORE_NOTIFICATION_CALL_INFO_TRANSFERED;
- break;
-
- case 9:
- command = TCORE_NOTIFICATION_CALL_INFO_MT_DEFLECTED;
- break;
-
- default:
- dbg("Unsupported +CSSU notification: [%d]", code2);
- break;
- }
-
- if (command != TCORE_NOTIFICATION_UNKNOWN)
- tcore_object_send_notification(co, command, 0, NULL);
-
- tcore_at_tok_free(tokens);
- return TRUE;
-}
-
-/* Response */
-static void on_response_atmodem_call_default(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelCallResult result;
- dbg("Entry");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success) {
- result = TEL_CALL_RESULT_SUCCESS;
- } else {
- err("ERROR: [%s]", at_resp->final_response);
- result = TEL_CALL_RESULT_FAILURE;
- /*
- * TODO -
- * need to map CME error and final response
- * error to TelCallResult
- */
- }
- dbg("%s: [%s]", ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data),
- (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
- /* Request */
- /*
- * Operation - dial
- *
- * Request -
- * AT-Command: ATD <num> [I] [G] [;]
- * <num> - dialed number
- * [I][i] - CLI presentation(supression or invocation)
- * [G] - control the CUG supplementary service information for this call.
- *
- * Response -
- * Success:
- * OK or CONNECT
- * Failure:
- * "ERROR"
- * "NO ANSWER"
- * "NO CARRIER"
- * "BUSY"
- * "NO DIALTONE"
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_dial(CoreObject *co, const TelCallDial *dial_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
- const gchar *clir;
- gchar *num;
- dbg("Entry");
-
- if (dial_info->call_type == TEL_CALL_TYPE_VIDEO) {
- err("Video call is not supported in atmodem");
- return TEL_RETURN_OPERATION_NOT_SUPPORTED;
- }
-
- if (!strncmp(dial_info->number, "*31#", 4)) {
- dbg("clir suppression");
- clir = "i";
- num = (gchar *)&(dial_info->number[4]);
- } else if (!strncmp(dial_info->number, "#31#", 4)) {
- dbg("clir invocation");
- clir = "I";
- num = (gchar *)&(dial_info->number[4]);
- } else {
- dbg("set clir state to default");
- clir = "";
- num = (gchar *)dial_info->number;
- }
-
- /* AT-Command */
- at_cmd = g_strdup_printf("ATD%s%s;", num, clir);
- dbg(" at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_answer");
-}
-
-/*
- * Operation - Answer/Reject/Replace/hold(current call) & accept incoming call.
- *
- * Request -
- *
- * 1. AT-Command: ATA
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- *
- * 2. AT-Command: AT+CHLD=[<n>]
- * <n>
- * 0 - (deafult)release all held calls or set User Determined User Busy for a waiting/incoming
- * call; if both exists then only the waiting call will be rejected.
- * 1 - release all active calls and accepts the other (held or waiting)
- * Note: In the scenario: An active call, a waiting call and held call, when the active call is
- * terminated, we will make the Waiting call as active.
- * 2 - place all active calls (if exist) on hold and accepts the other call (held or waiting/in-coming).
- * If only one call exists which is active, place it on hold and if only held call exists make it active call.
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- * For more informatiion refer 3GPP TS 27.007.
- */
-static TelReturn atmodem_call_answer(CoreObject *co, TelCallAnswerType ans_type,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
- dbg("Entry");
-
- if (ans_type == TEL_CALL_ANSWER_ACCEPT) {
- /* AT-Command */
- at_cmd = g_strdup_printf("%s", "ATA");
- }else if (ans_type == TEL_CALL_ANSWER_REJECT) {
- /* AT-Command */
- at_cmd = g_strdup_printf("%s", "AT+CHLD=0");
- } else if (ans_type == TEL_CALL_ANSWER_REPLACE) {
- /* AT-Command */
- at_cmd = g_strdup_printf("%s", "AT+CHLD=1");
- } else if (ans_type == TEL_CALL_ANSWER_HOLD_AND_ACCEPT) {
- /* AT-Command */
- at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
- }else {
- err("Unsupported call answer type");
- return TEL_RETURN_FAILURE;
- }
-
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_answer");
-}
-
-/*
- * Operation - release all calls/release specific call/release all active call/release all held calls.
- *
- * Request -
- * 1. AT-Command: AT+CHLD=[<n>]
- * <n>
- * 0 - (defualt)release all held calls or set User Determined User Busy for a waiting/incoming.
- * call; if both exists then only the waiting call will be rejected.
- * 1 - release all active calls and accepts the other (held or waiting).
- * 1x - release a specific call (x specific call number as indicated by call id).
- * 8 - release all calls.
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_end(CoreObject *co, const TelCallEnd *end_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
- dbg("Entry");
-
- if (end_info->end_type == TEL_CALL_END_ALL) {
- /* AT-Command */
- at_cmd = g_strdup_printf("%s", "AT+CHLD=8");
- }else if (end_info->end_type == TEL_CALL_END) {
- /* AT-Command */
- at_cmd = g_strdup_printf("%s%d", "AT+CHLD=1",end_info->call_id);
- } else if (end_info->end_type == TEL_CALL_END_ACTIVE_ALL) {
- /* AT-Command */
- at_cmd = g_strdup_printf("%s", "AT+CHLD=1");
- } else if (end_info->end_type == TEL_CALL_END_HOLD_ALL) {
- /* AT-Command */
- at_cmd = g_strdup_printf("%s", "AT+CHLD=0");
- }else {
- err("Unsupported call end type");
- return TEL_RETURN_FAILURE;
- }
-
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_end");
-}
-
-/*
- * Operation - call hold.
- *
- * Request -
- * 1. AT-Command: AT+CHLD=[<n>]
- * Where
- * <n>
- * 2 - place all active calls (if exist) on hold and accepts the other call (held or waiting/incoming).
- * If only one call exists which is active, place it on hold and if only held call exists
- * make it active call
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_hold(CoreObject *co, TcoreObjectResponseCallback cb,
- void *cb_data)
-
-{
- gchar *at_cmd;
- dbg("Entry");
-
- at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_hold");
-}
-
-/*
- * Operation - call active.
- *
- * Request -
- * 1. AT-Command: AT+CHLD=[<n>]
- * Where
- * <n>
- * 2 - place all active calls (if exist) on hold and accepts the other call (held or waiting/incoming).
- * If only one call exists which is active, place it on hold and if only held call exists
- * make it active call
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_active(CoreObject *co, TcoreObjectResponseCallback cb,
- void *cb_data)
-{
- gchar *at_cmd;
- dbg("Entry");
-
- at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_active");
-}
-
-/*
- * Operation - call swap.
- *
- * Request -
- * 1. AT-Command: AT+CHLD=[<n>]
- * Where
- * <n>
- * 2 - place all active calls (if exist) on hold and accepts the other call (held or waiting/incoming).
- * If only one call exists which is active, place it on hold and if only held call exists
- * make it active call
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_swap(CoreObject *co, TcoreObjectResponseCallback cb,
- void *cb_data)
-{
- gchar *at_cmd;
- dbg("Entry");
-
- at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_swap");
-}
-
-/*
- * Operation - call join.
- *
- * Request -
- * 1. AT-Command: AT+CHLD=[<n>]
- * Where
- * <n>
- * 3 - adds a held call to the conversation
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_join(CoreObject *co, TcoreObjectResponseCallback cb,
- void *cb_data)
-{
- gchar *at_cmd;
- dbg("Entry");
-
- at_cmd = g_strdup_printf("%s", "AT+CHLD=3");
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_join");
-}
-
-/*
- * Operation - call split.
- *
- * Request -
- * 1. AT-Command: AT+CHLD=[<n>]
- * Where
- * <n>
- * 2x - place all active calls on hold except call x with which communication is supported
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_split(CoreObject *co, guint call_id,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
- dbg("Entry");
-
- at_cmd = g_strdup_printf("%s%d", "AT+CHLD=2", call_id);
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_split");
-}
-
-/*
- * Operation - call transfer.
- *
- * Request -
- * 1. AT-Command: AT+CHLD=[<n>]
- * Where
- * <n>
- * 4 connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer)
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_transfer(CoreObject *co, TcoreObjectResponseCallback cb,
- void *cb_data)
-{
- gchar *at_cmd;
- dbg("Entry");
-
- at_cmd = g_strdup_printf("%s", "AT+CHLD=4");
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_transfer");
-}
-
-/*
- * Operation - call transfer.
- *
- * Request -
- * 1. AT-Command: AT+CTFR= <number>[,<type>]
- * Where
- * number>
- * string type phone number
- * <type>
- * type of address octet in integer format. It is optional parameter.
- *
- * Response -
- * Success:
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_call_deflect(CoreObject *co, const gchar *deflect_to,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
- dbg("Entry");
-
- at_cmd = g_strdup_printf("AT+CTFR=%s", deflect_to);
- dbg("at command : %s", at_cmd);
-
- return __atmodem_send_call_request(co, cb, cb_data, at_cmd, "atmodem_call_deflect");
-}
-
-/* Call Operations */
-static TcoreCallOps atmodem_call_ops = {
- .dial = atmodem_call_dial,
- .answer = atmodem_call_answer,
- .end = atmodem_call_end,
- .send_dtmf = NULL,
- .hold = atmodem_call_hold,
- .active = atmodem_call_active,
- .swap = atmodem_call_swap,
- .join = atmodem_call_join,
- .split = atmodem_call_split,
- .transfer = atmodem_call_transfer,
- .deflect = atmodem_call_deflect,
- .set_active_line = NULL,
- .get_active_line = NULL,
- .set_volume_info = NULL,
- .get_volume_info = NULL,
- .set_sound_path = NULL,
- .set_mute = NULL,
- .get_mute_status = NULL,
- .set_sound_recording = NULL,
- .set_sound_equalization = NULL,
-};
-
-gboolean atmodem_call_init(TcorePlugin *p, CoreObject *co)
-{
- dbg("Entry");
-
- /* Set operations */
- tcore_call_set_ops(co, &atmodem_call_ops);
-
- /* Add Callbacks */
- tcore_object_add_callback(co,
- "%SCLCC:",
- on_notification_atmodem_call_status, NULL);
- tcore_object_add_callback(co,
- "+CSSU:",
- on_notification_atmodem_call_ss_cssu_info, NULL);
-
- return TRUE;
-}
-
-void atmodem_call_exit(TcorePlugin *p, CoreObject *co)
-{
- dbg("Exit");
-}
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <glib.h>
-
-#include <log.h>
-#include <tcore.h>
-
-#include "atmodem_common.h"
-
-void on_send_atmodem_request(TcorePending *p,
- TelReturn send_status, void *user_data)
-{
- dbg("Send - [%s]",
- (send_status == TEL_RETURN_SUCCESS ? "OK" : "NOK"));
-}
-
-AtmodemRespCbData *atmodem_create_resp_cb_data(TcoreObjectResponseCallback cb,
- void *cb_data, void *data, guint data_len)
-{
- AtmodemRespCbData *resp_cb_data;
-
- resp_cb_data = tcore_malloc0(sizeof(AtmodemRespCbData) + data_len);
- resp_cb_data->cb = cb;
- resp_cb_data->cb_data = cb_data;
- if ((data != NULL) && (data_len > 0))
- memcpy(resp_cb_data->data, data, data_len);
-
- return resp_cb_data;
-}
-
-void atmodem_destroy_resp_cb_data(AtmodemRespCbData *resp_cb_data)
-{
- if (resp_cb_data)
- tcore_free(resp_cb_data);
-}
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-#include <server.h>
-#include <plugin.h>
-#include <core_object.h>
-#include <hal.h>
-#include <queue.h>
-#include <storage.h>
-#include <at.h>
-
-#include <co_modem.h>
-
-#include "atmodem_modem.h"
-#include "atmodem_common.h"
-
-typedef enum {
- ATMODEM_CP_STATE_OFFLINE,
- ATMODEM_CP_STATE_CRASH_RESET,
- ATMODEM_CP_STATE_CRASH_EXIT,
- ATMODEM_CP_STATE_BOOTING,
- ATMODEM_CP_STATE_ONLINE,
- ATMODEM_CP_STATE_NV_REBUILDING,
- ATMODEM_CP_STATE_LOADER_DONE,
-} AtmodemCpState;
-
-/* Notifications */
-#if 0 /* To be supported later */
-static gboolean on_event_atmodem_cp_power(CoreObject *co, const void *event_info, void *user_data)
-{
- GSList *lines = (GSList *)event_info;
- const gchar *line;
-
- dbg("Modem Power notification - SIM status: [\%SCSIM]");
-
- if (g_slist_length(lines) != 1) {
- err("\%SCSIM unsolicited message expected to be "
- "Single line but received multiple lines");
- return TRUE;
- }
-
- line = (const gchar *)lines->data;
- if (line != NULL) {
- GSList *tokens;
- AtmodemCpState cp_state;
- TelModemPowerStatus power_status;
-
- tokens = tcore_at_tok_new(line);
-
- /* <CP state> */
- cp_state = atoi(g_slist_nth_data(tokens, 0));
- dbg("CP state: [0x%x]", cp_state);
- switch (cp_state) {
- case ATMODEM_CP_STATE_OFFLINE:
- power_status = TEL_MODEM_POWER_OFF;
- break;
-
- case ATMODEM_CP_STATE_CRASH_RESET:
- power_status = TEL_MODEM_POWER_ERROR;
- break;
-
- default:
- dbg("Unhandled State : [0x%x]", cp_state);
- goto out;
- }
-
- /* Set Power */
- tcore_modem_set_powered(co, FALSE);
-
- /* Send notification */
- tcore_object_send_notification(co,
- TCORE_NOTIFICATION_MODEM_POWER,
- sizeof(TelModemPowerStatus), &power_status);
-
-out:
- tcore_at_tok_free(tokens);
- }
-
- return TRUE;
-}
-#endif /* To be supported later */
-
-static gboolean on_event_atmodem_phone_state(CoreObject *co, const void *event_info, void *user_data)
-{
- GSList *lines = (GSList *)event_info;
- const gchar *line;
-
- dbg("Modem Power notification - SIM status: [\%SCFUN]");
-
- if (g_slist_length(lines) != 1) {
- err("\%SCFUN unsolicited message expected to be "
- "Single line but received multiple lines");
- return TRUE;
- }
-
- line = (const gchar *)lines->data;
- if (line != NULL) {
- GSList *tokens;
- guint state;
-
- tokens = tcore_at_tok_new(line);
-
- /* <CP state> */
- state = atoi(g_slist_nth_data(tokens, 0));
- dbg("Flight mdoe State: [%s]", (state ? "OFF" : "ON"));
-
- /* Set Flight mode */
- tcore_modem_set_flight_mode_state(co, !state);
-
- tcore_at_tok_free(tokens);
-
- /*
- * TODO:
- * Handle Notification as response to Request
- */
- }
-
- return TRUE;
-}
-
-/* System function responses */
-static void on_response_modem_set_flight_mode_internal(TcorePlugin *plugin,
- gint result, const void *response, void *user_data)
-{
- CoreObject *co;
- gboolean flight_mode;
- dbg("Enter");
-
- co = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
- tcore_check_return_assert(co != NULL);
-
- tcore_check_return(result == TEL_MODEM_RESULT_SUCCESS);
-
- /* Get Flight mode state */
- (void)tcore_modem_get_flight_mode_state(co, &flight_mode);
-
- dbg("Setting Modem Fiight mode (internal) - [%s] - [SUCCESS]",
- (flight_mode ? "ON": "OFF"));
-
- /*
- * Send notification
- *
- * This is an internal request to set Flight mode, which is sent during
- * boot-up based on AP-side configuration (VCONF).
- *
- * Need to notify TAPI through Notiifcation -
- * TCORE_NOTIFICATION_MODEM_FLIGHT_MODE
- */
- (void)tcore_object_send_notification(co,
- TCORE_NOTIFICATION_MODEM_FLIGHT_MODE,
- sizeof(gboolean), &flight_mode);
-}
-
-/* System functions */
-gboolean atmodem_modem_power_on_modem(TcorePlugin *plugin)
-{
- CoreObject *co;
- TcoreStorage *strg;
- gboolean flight_mode;
- TelModemPowerStatus power_status;
-
- co = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
- tcore_check_return_value_assert(co != NULL, FALSE);
-
- /* Set Modem Power State to 'ON' */
- tcore_modem_set_powered(co, TRUE);
-
- /*
- * Set Flight mode (as per AP settings -VCONF)
- */
- /* Get Flight mode from VCONFKEY */
- strg = tcore_server_find_storage(tcore_plugin_ref_server(plugin), "vconf");
- tcore_check_return_value_assert(strg != NULL, FALSE);
-
- flight_mode = tcore_storage_get_bool(strg, STORAGE_KEY_FLIGHT_MODE);
-
- /*
- * Set Flight mode request is dispatched to Core Object (Modem)
- * to ensure that 'Request Hooks' get executed.
- */
- (void)tcore_object_dispatch_request(co, TRUE,
- TCORE_COMMAND_MODEM_SET_FLIGHTMODE,
- &flight_mode, sizeof(gboolean),
- on_response_modem_set_flight_mode_internal, NULL);
-
- /*
- * Send notification
- *
- * Need to notify Modem is Powered UP through Notiifcation -
- * TCORE_NOTIFICATION_MODEM_POWER
- */
- power_status = TEL_MODEM_POWER_ON;
- (void)tcore_object_send_notification(co,
- TCORE_NOTIFICATION_MODEM_POWER,
- sizeof(TelModemPowerStatus), &power_status);
- dbg("Modem Powered ON");
-
- return FALSE;
-}
-
-/* Modem Responses */
-static void on_response_atmodem_modem_set_flight_mode(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- gboolean *enable;
-
- TelModemResult result = TEL_MODEM_RESULT_FAILURE;
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success)
- result = TEL_MODEM_RESULT_SUCCESS;
-
- enable = (gboolean *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- dbg("Setting Modem Flight mode - [%s] - [%s]",
- (*enable ? "ON": "OFF"),
- (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Update Core Object */
- (void)tcore_modem_set_flight_mode_state(co, *enable);
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-
- /*
- * In case Flight mode is set to OFF, we need to trigger
- * Network Registration.
- *
- * This is taken care by Network module which hooks on
- * Set Flight mode Request of Modem module.
- */
-}
-
-static void on_response_atmodem_modem_get_version(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelModemVersion version = {{0}, {0}, {0}, {0}};
-
- TelModemResult result = TEL_MODEM_RESULT_FAILURE;
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp) {
- if (at_resp->lines) {
- const gchar *line;
- GSList *tokens = NULL;
-
- line = (const gchar *)at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) > 0) {
- if (at_resp->success) {
- gchar *sw_ver = NULL, *hw_ver = NULL;
- gchar *calib_date = NULL, *p_code = NULL;
-
- sw_ver = g_slist_nth_data(tokens, 0);
- hw_ver = g_slist_nth_data(tokens, 1);
- calib_date = g_slist_nth_data(tokens, 2);
- p_code = g_slist_nth_data(tokens, 3);
-
- g_strlcpy(version.software_version,
- sw_ver,
- TEL_MODEM_VERSION_LENGTH_MAX + 1);
- g_strlcpy(version.hardware_version,
- hw_ver,
- TEL_MODEM_VERSION_LENGTH_MAX + 1);
- g_strlcpy(version.calibration_date,
- calib_date,
- TEL_MODEM_VERSION_LENGTH_MAX + 1);
- g_strlcpy(version.product_code,
- p_code,
- TEL_MODEM_VERSION_LENGTH_MAX + 1);
-
- dbg("Version - Software: [%s] Hardware: [%s] "
- "Calibration date: [%s] Product "
- "Code: [%s]", sw_ver, hw_ver,
- calib_date, p_code);
-
- result = TEL_MODEM_RESULT_SUCCESS;
- } else {
- err("RESPONSE - [NOK]");
- err("[%s]", g_slist_nth_data(tokens, 0));
- }
- } else {
- err("Invalid response message");
- result = TEL_MODEM_RESULT_UNKNOWN_FAILURE;
- }
- tcore_at_tok_free(tokens);
- }
- }
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &version, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_modem_get_imei(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- gchar imei[TEL_MODEM_IMEI_LENGTH_MAX +1] = {0};
-
- TelModemResult result = TEL_MODEM_RESULT_FAILURE;
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp) {
- if (at_resp->lines) {
- const gchar *line;
- GSList *tokens = NULL;
-
- line = (const gchar *)at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) == 1) {
- if (at_resp->success) {
- dbg("RESPONSE - [OK]");
- g_strlcpy(imei,
- (const gchar *)g_slist_nth_data(tokens, 0),
- TEL_MODEM_IMEI_LENGTH_MAX+1);
- dbg("IMEI: [%s]", imei);
-
- result = TEL_MODEM_RESULT_SUCCESS;
- } else {
- err("RESPONSE - [NOK]");
- err("[%s]", g_slist_nth_data(tokens, 0));
- }
- } else {
- err("Invalid response message");
- result = TEL_MODEM_RESULT_UNKNOWN_FAILURE;
- }
- tcore_at_tok_free(tokens);
- }
- }
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, imei, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-/* Modem Operations */
-/*
- * Operation - set_flight_mode
- *
- * Request -
- * AT-Command: AT+CFUN=<fun>
- * where,
- * <fun>
- * 0 ENABLE Flight Mode
- * 1 DISABLE Flight Mode
- * Response -
- * Success: (No Result)
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_modem_set_flight_mode(CoreObject *co, gboolean enable,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
- guint power_mode;
-
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
-
- if (enable) {
- dbg("Flight mode - [ON]");
- power_mode = 0;
- } else {
- dbg("Flight mode - [OFF]");
- power_mode = 1;
- }
-
- /* AT-Command */
- at_cmd = g_strdup_printf("AT+CFUN=%d", power_mode);
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &enable, sizeof(gboolean));
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_modem_set_flight_mode, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Flight mode");
-
- /* Free resources */
- g_free(at_cmd);
-
- return ret;
-}
-
-/*
- * Operation - get_flight_mode
- *
- * Request -
- * AT-Command: None
- * Fetch information from Core Object
- *
- * Response - flight_mode (gboolean)
- */
-static TelReturn atmodem_modem_get_flight_mode(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gboolean flight_mode;
-
- /* Fetch Flight mode from Core Object */
- (void)tcore_modem_get_flight_mode_state(co, &flight_mode);
- dbg("Modem Flight mode - [%s]", (flight_mode ? "ON": "OFF"));
-
- /* Invoke response callback */
- if (cb)
- cb(co, (gint)TEL_MODEM_RESULT_SUCCESS, &flight_mode, cb_data);
-
- return TEL_RETURN_SUCCESS;
-}
-
-/*
- * Operation - get_version
- *
- * Request -
- * AT-Command: AT+CGMR
- *
- * Response - version (TelModemVersion)
- * Success: (Single line) -
- * <sw_ver>, <hw_ver>, <calib_date>, <p_code>
- * OK
- * Note:
- * Success Response is different from standard 3GPP AT-Command (+CGMR)
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_modem_get_version(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+CGMR", NULL,
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_modem_get_version, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Version");
-
- return ret;
-}
-
-/*
- * Operation - get_imei
- *
- * Request -
- * AT-Command: AT+CGSN
- *
- * Response - imei (gchar array of length 20+'\0' bytes)
- * Success: (Single line)
- * <IMEI>
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_modem_get_imei(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+CGSN", NULL,
- TCORE_AT_COMMAND_TYPE_NUMERIC,
- NULL,
- on_response_atmodem_modem_get_imei, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get IMEI");
-
- return ret;
-}
-
-/* Modem Operations */
-static TcoreModemOps atmodem_modem_ops = {
- .set_power_status = NULL,
- .set_flight_mode = atmodem_modem_set_flight_mode,
- .get_flight_mode = atmodem_modem_get_flight_mode,
- .get_version = atmodem_modem_get_version,
- .get_imei = atmodem_modem_get_imei
-};
-
-gboolean atmodem_modem_init(TcorePlugin *p, CoreObject *co)
-{
- dbg("Enter");
-
- /* Set operations */
- tcore_modem_set_ops(co, &atmodem_modem_ops);
-
- /* Add Callbacks */
-#if 0 /* To be supported later */
- tcore_object_add_callback(co, "\%SCSIM:",
- on_event_atmodem_cp_power, NULL);
-#endif /* To be supported later */
- tcore_object_add_callback(co, "\%SCFUN:",
- on_event_atmodem_phone_state, NULL);
-
- dbg("Exit");
- return TRUE;
-}
-
-void atmodem_modem_exit(TcorePlugin *p, CoreObject *co)
-{
- dbg("Exit");
-}
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-#include <server.h>
-#include <plugin.h>
-#include <core_object.h>
-#include <hal.h>
-#include <queue.h>
-#include <storage.h>
-#include <at.h>
-
-#include <co_network.h>
-
-#include "atmodem_network.h"
-#include "atmodem_common.h"
-
-#define ATMODEM_NETWORK_BASE_16 16
-
-typedef enum {
- ATMDOEM_NETWORK_ACT_GSM, /* GSM */
- ATMDOEM_NETWORK_ACT_GSM_COMPACT, /* GSM Compact */
- ATMDOEM_NETWORK_ACT_UTRAN, /* UTRAN */
- ATMDOEM_NETWORK_ACT_GSM_EGPRS, /* GSM w/EGPRS */
- ATMDOEM_NETWORK_ACT_UTRAN_HSDPA, /* UTRAN w/HSDPA */
- ATMDOEM_NETWORK_ACT_UTRAN_HSUPA, /* UTRAN w/HSUPA */
- ATMDOEM_NETWORK_ACT_UTRAN_HSDPA_HSUPA, /* UTRAN w/HSDPA and HSUPA */
- ATMDOEM_NETWORK_ACT_E_UTRAN, /* E-UTRAN */
-} AtmodemNetworkAct;
-
-static TelNetworkAct __atmodem_network_map_act(AtmodemNetworkAct act)
-{
- /*
- * <ACT>
- * 0 GSM
- * 1 GSM Compact
- * 2 UTRAN
- * 3 GSM w/EGPRS
- * 4 UTRAN w/HSDPA
- * 5 UTRAN w/HSUPA
- * 6 UTRAN w/HSDPA and HSUPA - HSPA
- */
- switch (act) {
- case ATMDOEM_NETWORK_ACT_GSM:
- case ATMDOEM_NETWORK_ACT_GSM_COMPACT:
- return TEL_NETWORK_ACT_GSM;
-
- case ATMDOEM_NETWORK_ACT_UTRAN:
- return TEL_NETWORK_ACT_UMTS;
-
- case ATMDOEM_NETWORK_ACT_GSM_EGPRS:
- return TEL_NETWORK_ACT_EGPRS;
-
- case ATMDOEM_NETWORK_ACT_UTRAN_HSDPA:
- return TEL_NETWORK_ACT_HSDPA;
-
- case ATMDOEM_NETWORK_ACT_UTRAN_HSUPA:
- return TEL_NETWORK_ACT_HSUPA;
-
- case ATMDOEM_NETWORK_ACT_UTRAN_HSDPA_HSUPA:
- return TEL_NETWORK_ACT_HSPA;
-
- default:
- return TEL_NETWORK_ACT_UNKNOWN;
- }
-}
-
-static TelNetworkRegStatus __atmodem_network_map_stat(guint stat)
-{
- /*
- * <stat>
- * 0 Not registered, ME is not currently searching a
- * new operator to register to
- * 1 Registered, home network
- * 2 Not registered, but ME is currently searching a
- * new operator to register
- * 3 Registration denied
- * 4 Unknown
- * 5 Registered, in roaming
- */
- switch (stat) {
- case 0:
- return TEL_NETWORK_REG_STATUS_UNREGISTERED;
-
- case 1:
- return TEL_NETWORK_REG_STATUS_REGISTERED;
-
- case 2:
- return TEL_NETWORK_REG_STATUS_SEARCHING;
-
- case 3:
- return TEL_NETWORK_REG_STATUS_DENIED;
-
- case 4:
- return TEL_NETWORK_REG_STATUS_UNKNOWN;
-
- case 5:
- return TEL_NETWORK_REG_STATUS_ROAMING;
-
- default:
- return TEL_NETWORK_REG_STATUS_UNKNOWN;
- }
-}
-
-static void __on_response_atmodem_network_registration(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- dbg("Entry");
-
- if (at_resp && at_resp->success) {
- dbg("Network Registration - [OK]");
- } else {
- err("Network Registration - [NOK]");
- }
-}
-
-static void __atmodem_network_register_to_network(CoreObject *co)
-{
- TelReturn ret;
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+COPS=0", NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- __on_response_atmodem_network_registration, NULL,
- on_send_atmodem_request, NULL);
- dbg("Sending Network Registration request: [%s]",
- (ret == TEL_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
-}
-
-static void __on_response_atmodem_network_fetch_nw_name_internal(CoreObject *co,
- gint result, const void *response, void *user_data)
-{
- TelNetworkIdentityInfo *identity = (TelNetworkIdentityInfo *)response;
-
- /* Send notification if result is SUCCESS */
- if (result == TEL_NETWORK_RESULT_SUCCESS)
- tcore_plugin_send_notification(tcore_object_ref_plugin(co),
- TCORE_NOTIFICATION_NETWORK_IDENTITY,
- sizeof(TelNetworkIdentityInfo), &identity);
-}
-
-static TcoreHookReturn __on_response_atmodem_hook_set_flight_mode(CoreObject *co,
- gint result, TcoreCommand command, const void *response, const void *user_data)
-{
-
- tcore_check_return_value(result == TEL_MODEM_RESULT_SUCCESS,
- TCORE_HOOK_RETURN_CONTINUE);
-
- dbg("Flight mode 'disabled', register to Network");
-
- /*
- * TODO - Check for selection_mode
- * Need to check if it is Manual or Automatic and based on
- * that need to initiate Network Registratin accordingly.
- */
- __atmodem_network_register_to_network(co);
-
- return TCORE_HOOK_RETURN_CONTINUE;
-}
-
-static void __on_response_atmodem_network_fetch_nw_name(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelNetworkIdentityInfo identity = {0, };
-
- TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE;
-
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success) {
- if (at_resp->lines) {
- const gchar *line;
- GSList *tokens = NULL;
- gchar *token_str;
- guint i, nol;
-
- /* Validate that only 3 lines of response is received */
- nol = g_slist_length(at_resp->lines);
- if (nol > 3) {
- err("Invalid response message");
- return;
- }
-
- /* Process the Multi-line response */
- for (i = 0; i < nol; i++) {
- line = g_slist_nth_data(at_resp->lines, i);
-
- /*
- * Tokenize
- *
- * +COPS: <mode>[,<format>,<oper>[,< AcT>]]
- */
- tokens = tcore_at_tok_new(line);
-
- if ((token_str = tcore_at_tok_nth(tokens, 0))) {
- guint mode = atoi(token_str);
- dbg("<mode> : [%d]", mode);
- }
-
- if ((token_str = tcore_at_tok_nth(tokens, 0))) {
- guint format = atoi(token_str);
- dbg("<format> : [%d]", format);
-
- switch (format) {
- case 0: /* Long Network Name */
- if ((token_str = tcore_at_tok_nth(tokens, 1))) {
- if (strlen(token_str) > 0) {
- identity.long_name = tcore_at_tok_extract((const char *)token_str);
-
- /* Update Long name */
- tcore_network_set_long_name(co, identity.long_name);
- }
- }
- break;
-
- case 1: /* Short Network Name */
- if ((token_str = tcore_at_tok_nth(tokens, 1))) {
- if (strlen(token_str) > 0) {
- identity.short_name = tcore_at_tok_extract((const char *)token_str);
-
- /* Update Short name */
- tcore_network_set_short_name(co, identity.short_name);
- }
- }
- break;
-
- case 2: /* PLMN (mcc, mnc) */
- if ((token_str = tcore_at_tok_nth(tokens, 1))) {
- if (strlen(token_str) > 0) {
- identity.plmn = tcore_at_tok_extract((const char *)token_str);
-
- /* Update PLMN */
- tcore_network_set_plmn( co, identity.plmn);
- }
- }
- break;
-
- default:
- break;
- }
- }
-
- /* Free resource */
- tcore_at_tok_free(tokens);
- }
-
- /* Send Notification - Network identity */
- dbg("Network name - Long name: [%s] Short name: [%s] "
- "PLMN: [%s]", identity.long_name,
- identity.short_name, identity.plmn);
-
- result = TEL_NETWORK_RESULT_SUCCESS;
- }
- }
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &identity, resp_cb_data->cb_data);
-
- /* Free resource */
- tcore_free(identity.long_name);
- tcore_free(identity.short_name);
- tcore_free(identity.plmn);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-/*
- * Operation - fetch_nw_name
- *
- * Request -
- * AT-Command: AT+COPS=[<mode>[,<format>[,<oper>[,< AcT>]]]]
- *
- * <mode> may be
- * 1 Manual. Other parameters like format and operator need to be passed
- * 2 Deregister from network
- * 3 It sets <format> value. In this case <format> becomes a mandatory input
- * 4 Manual / Automatic. In this case if manual selection fails then automatic mode
- * is entered
- *
- * <format> may be
- * 0 format presentations are set to long alphanumeric. If Network name not
- * available it displays combination of Mcc and MNC in string format.
- * 1 format presentation is set to short alphanumeric.
- * 2 format presentations set to numeric.
- *
- * <oper> may be
- * string type given in format <format>
- *
- * Response - Network name
- * Success: (Multiple Single line)
- * +COPS: <mode>[,<format>,<oper>[,< AcT>]]
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn __atmodem_network_fetch_nw_name(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret;
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,0+COPS?;", "+COPS",
- TCORE_AT_COMMAND_TYPE_MULTILINE,
- NULL,
- __on_response_atmodem_network_fetch_nw_name, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Fetch Network name");
-
- return ret;
-}
-
-/* Hook functions */
-static TcoreHookReturn on_hook_atmodem_set_flight_mode(CoreObject *co,
- TcoreCommand command, const void *request, const void *user_data,
- TcoreObjectResponseCallback cb, const void *cb_data)
-{
- gboolean *flight_mode = (gboolean *)request;
-
- /*
- * Hook Set Flight mode request.
- *
- * Disable Flight mode - Hook response (if success Register to Network)
- * Enable Flight mode - return
- */
- if(*flight_mode != TRUE) {
- /* Add response hook */
- tcore_object_add_response_hook(co, command, request,
- __on_response_atmodem_hook_set_flight_mode, NULL);
-
- return TCORE_HOOK_RETURN_CONTINUE;
- }
-
- dbg("Flight mode - [Enabled]");
- return TCORE_HOOK_RETURN_CONTINUE;
-}
-
-static TcoreHookReturn on_hook_atmodem_sim_status(TcorePlugin *plugin,
- TcoreNotification command, guint data_len, void *data, void *user_data)
-{
- const TelSimCardStatus *sim_status = (TelSimCardStatus *)data;
-
- tcore_check_return_value(sim_status != NULL,
- TCORE_HOOK_RETURN_CONTINUE);
-
- /*
- * Hook SIM initialization Notification
- *
- * SIM INIT complete - Attach to network (Register to network)
- * SIM INIT not complete - return
- */
- if (*sim_status == TEL_SIM_STATUS_SIM_INIT_COMPLETED) {
- CoreObject *co = (CoreObject *)user_data;
- dbg("SIM Initialized!!! Attach to Network");
-
- tcore_check_return_value_assert(co != NULL,
- TCORE_HOOK_RETURN_CONTINUE);
-
- /*
- * TODO - Check for selection_mode
- * Need to check if it is Manual or Automatic and based on
- * that need to initiate Network Registratin accordingly.
- */
- __atmodem_network_register_to_network(co);
-
- return TCORE_HOOK_RETURN_CONTINUE;
- }
-
- dbg("SIM not yet initialized - SIM Status: [%d]", *sim_status);
- return TCORE_HOOK_RETURN_CONTINUE;
-}
-
-/* Notification callbacks */
-/*
- * Notification: +CREG: <stat>[,<lac>,<ci>[,<AcT>]]
- *
- * Possible values of <stat> can be
- * 0 Not registered, ME is not currently searching
- * a new operator to register to
- * 1 Registered, home network
- * 2 Not registered, but ME is currently searching
- * a new operator to register
- * 3 Registration denied
- * 4 Unknown
- * 5 Registered, in roaming
- *
- * <lac>
- * string type; two byte location area code in
- * hexadecimal format (e.g. 00C3)
- *
- * <ci>
- * string type; four byte cell ID in hexadecimal
- * format (e.g. 0000A13F)
- *
- * <ACT>
- * 0 GSM
- * 2 UTRAN
- * 3 GSM w/EGPRS
- * 4 UTRAN w/HSDPA
- * 5 UTRAN w/HSUPA
- * 6 UTRAN w/HSDPA and HSUPA
- */
-static gboolean on_notification_atmodem_cs_network_info(CoreObject *co,
- const void *event_info, void *user_data)
-{
- GSList *lines = NULL;
- gchar *line = NULL;
-
- dbg("Network notification - CS network info: [+CREG]");
-
- lines = (GSList *)event_info;
- if (g_slist_length(lines) != 1) {
- err("+CREG unsolicited message expected to be Single line "
- "but received multiple lines");
- return TRUE;
- }
-
- line = (gchar *) (lines->data);
- if (line != NULL) {
- TelNetworkRegStatusInfo registration_status = {0, };
- TelNetworkCellInfo cell_info = {0, };
- GSList *tokens = NULL;
- gchar *token_str;
- guint stat = 0, act = 0, lac = 0, ci = 0;
- gboolean roam_state = FALSE;
-
- /*
- * Tokenize
- *
- * +CREG: <stat>[,<lac>,<ci>[,<AcT>]]
- */
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) < 1) {
- err("Invalid notification message");
- goto out;
- }
-
- /* <stat> */
- if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
- err("No <stat> in +CREG");
- goto out;
- }
- stat = __atmodem_network_map_stat(atoi(token_str));
- (void)tcore_network_set_cs_reg_status(co, stat);
-
- /* <lac> */
- if ((token_str = g_slist_nth_data(tokens, 1))) {
- token_str = tcore_at_tok_extract((const gchar *)token_str);
-
- lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
-
- /* Update Location Area Code (lac) information */
- (void)tcore_network_set_lac(co, lac);
-
- tcore_free(token_str);
- } else {
- dbg("No <lac> in +CREG");
- (void)tcore_network_get_lac(co, &lac);
- }
-
- /* <ci> */
- if ((token_str = g_slist_nth_data(tokens, 2))) {
- token_str = tcore_at_tok_extract((const gchar *)token_str);
-
- ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
-
- /* Update Cell ID (ci) information */
- (void)tcore_network_set_cell_id(co, ci);
-
- tcore_free(token_str);
- } else {
- dbg("No <ci> in +CREG");
- (void)tcore_network_get_cell_id(co, &ci);
- }
-
- /* <AcT> */
- if ((token_str = g_slist_nth_data(tokens, 3))) {
- act = __atmodem_network_map_act(atoi(token_str));
- (void)tcore_network_set_access_technology(co, act);
- } else {
- dbg("No <AcT> in +CREG");
- (void)tcore_network_get_access_technology(co, &act);
- }
- dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d", stat, lac, ci, act);
-
- /* Send Notification - Network (CS) Registration status */
- registration_status.cs_status = stat;
- registration_status.act = act;
- (void)tcore_network_get_ps_reg_status(co, ®istration_status.ps_status);
-
- tcore_object_send_notification(co,
- TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS,
- sizeof(TelNetworkRegStatusInfo), ®istration_status);
-
- switch (stat) {
- case TEL_NETWORK_REG_STATUS_ROAMING:
- roam_state = TRUE; // no break
- case TEL_NETWORK_REG_STATUS_REGISTERED:
- /* Fetch Network name - Internal request */
- (void)__atmodem_network_fetch_nw_name(co,
- __on_response_atmodem_network_fetch_nw_name_internal, NULL);
- break;
- default:
- break;
- }
-
- /* Set Roaming state */
- tcore_network_set_roam_state(co, roam_state);
-
- /* Send Notification - Cell info */
- cell_info.lac = (gint)lac;
- cell_info.cell_id = (gint)ci;
- (void)tcore_network_get_rac(co, &cell_info.rac);
-
- tcore_plugin_send_notification(tcore_object_ref_plugin(co),
- TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO,
- sizeof(TelNetworkCellInfo), &cell_info);
-
-out:
- /* Free resource */
- tcore_at_tok_free(tokens);
- }
-
- return TRUE;
-}
-
-/*
- * Notification: +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]]
- *
- * Possible values of <stat> can be
- * 0 Not registered, ME is not currently searching a
- * new operator to register to
- * 1 Registered, home network
- * 2 Not registered, but ME is currently searching a
- * new operator to register
- * 3 Registration denied
- * 4 Unknown
- * 5 Registered, in roaming
- *
- * <lac>
- * string type; two byte location area code in
- * hexadecimal format (e.g. 00C3)
- *
- * <ci>
- * string type; four byte cell ID in hexadecimal
- * format (e.g. 0000A13F)
- *
- * <ACT>
- * 0 GSM
- * 2 UTRAN
- * 3 GSM w/EGPRS
- * 4 UTRAN w/HSDPA
- * 5 UTRAN w/HSUPA
- * 6 UTRAN w/HSDPA and HSUPA
- *
- * <rac>:
- * string type; one byte routing area code in hexadecimal format
- */
-static gboolean on_notification_atmodem_ps_network_info(CoreObject *co,
- const void *event_info, void *user_data)
-{
- GSList *lines = NULL;
- gchar *line = NULL;
-
- dbg("Network notification - PS network info: [+CGREG]");
-
- lines = (GSList *)event_info;
- if (g_slist_length(lines) != 1) {
- err("+CGREG unsolicited message expected to be Single line "
- "but received multiple lines");
- return TRUE;
- }
-
- line = (gchar *) (lines->data);
- if (line != NULL) {
- TelNetworkRegStatusInfo registration_status = {0, };
- TelNetworkCellInfo cell_info = {0, };
- GSList *tokens = NULL;
- gchar *token_str;
- guint stat = 0, act = 0, lac = 0, ci = 0, rac = 0;
- gboolean roam_state = FALSE;
-
- /*
- * Tokenize
- *
- * +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]]
- */
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) < 1) {
- err("Invalid notification message");
- goto out;
- }
-
- /* <stat> */
- if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
- err("No <stat> in +CGREG");
- goto out;
- }
- stat = __atmodem_network_map_stat(atoi(token_str));
- (void)tcore_network_set_ps_reg_status(co, stat);
-
- /* <lac> */
- if ((token_str = g_slist_nth_data(tokens, 1))) {
- token_str = tcore_at_tok_extract((const gchar *)token_str);
-
- lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
-
- /* Update Location Area Code (lac) information */
- (void)tcore_network_set_lac(co, lac);
-
- tcore_free(token_str);
- } else {
- dbg("No <lac> in +CGREG");
- (void)tcore_network_get_lac(co, &lac);
- }
-
- /* <ci> */
- if ((token_str = g_slist_nth_data(tokens, 2))) {
- token_str = tcore_at_tok_extract((const gchar *)token_str);
-
- ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
-
- /* Update Cell ID (ci) information */
- (void)tcore_network_set_cell_id(co, ci);
-
- tcore_free(token_str);
- } else {
- dbg("No <ci> in +CGREG");
- (void)tcore_network_get_cell_id(co, &ci);
- }
-
- /* <AcT> */
- if ((token_str = g_slist_nth_data(tokens, 3))) {
- act = __atmodem_network_map_act(atoi(token_str));
- (void)tcore_network_set_access_technology(co, act);
- } else {
- dbg("No <AcT> in +CGREG");
- (void)tcore_network_get_access_technology(co, &act);
- }
-
- /* <rac> */
- if ((token_str = g_slist_nth_data(tokens, 4))) {
- token_str = tcore_at_tok_extract((const gchar *)token_str);
-
- rac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
-
- /* Update Routing Area Code (rac) information */
- (void)tcore_network_set_rac(co, rac);
-
- tcore_free(token_str);
- } else {
- err("No <ci> in +CGREG");
- (void)tcore_network_get_rac(co, &rac);
- }
- dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d <rac>: 0x%x", stat, lac, ci, act, rac);
-
- /* Send Notification - Network (PS) Registration status */
- registration_status.ps_status = stat;
- registration_status.act = act;
- (void)tcore_network_get_cs_reg_status(co, ®istration_status.cs_status);
-
- tcore_object_send_notification(co,
- TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS,
- sizeof(TelNetworkRegStatusInfo), ®istration_status);
-
-
- /* Set Roaming state */
- if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING)
- roam_state = TRUE;
-
- tcore_network_set_roam_state(co, roam_state);
-
- /* Send Notification - Cell info */
- cell_info.lac = lac;
- cell_info.cell_id = ci;
- cell_info.rac = rac;
- tcore_plugin_send_notification(tcore_object_ref_plugin(co),
- TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO,
- sizeof(TelNetworkCellInfo), &cell_info);
-
-out:
- /* Free resource */
- tcore_at_tok_free(tokens);
- }
-
- return TRUE;
-}
-
-static gboolean on_notification_atmodem_network_rssi(CoreObject *co,
- const void *event_info, void *user_data)
-{
- GSList *lines;
- const gchar *line = NULL;
-
- dbg("Network notification - Icon (rssi) info: [+CIEV]");
-
- lines = (GSList *)event_info;
- if (g_slist_length(lines) != 1) {
- err("+CIEV unsolicited message expected to be "
- "Single line but received multiple lines");
- return TRUE;
- }
-
- line = (const gchar *)lines->data;
- if (line != NULL) {
- GSList *tokens;
- guint descriptor;
- guint value;
-
- tokens = tcore_at_tok_new(line);
-
- /* <desc> */
- descriptor = atoi(g_slist_nth_data(tokens, 0));
- dbg("Descriptor: [%s]", (descriptor == 10 ? "RSSI"
- : (descriptor == 15 ? "Battery" : "Unknown")));
-
- /* <value> */
- value = atoi(g_slist_nth_data(tokens, 1));
-
- switch (descriptor) {
- case 10:
- dbg("RSSI Level: [%d]", value);
-
- /* Send Notification - Network Rssi */
- tcore_object_send_notification(co,
- TCORE_NOTIFICATION_NETWORK_RSSI,
- sizeof(guint), &value);
- break;
- case 15:
- dbg("Battery Level: [%d]", value);
- break;
- default:
- warn("Unknown descriptor: [%d]", descriptor);
- break;
- }
-
- /* Free resource */
- tcore_at_tok_free(tokens);
- }
-
- return TRUE;
-}
-
-/* Network Responses */
-static void on_response_atmodem_network_search(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; //TODO - CME Error mapping required.
- TelNetworkPlmnList plmn_list = {0,};
- guint num_network_avail;
- guint count;
- GSList *tokens = NULL;
-
- dbg("Enter");
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success) {
- const gchar *line;
- GSList *net_token = NULL;
- gchar *resp;
- gint act;
-
- if (!at_resp->lines) {
- err("invalid response received");
- goto END;
- }
-
- line = (char *) at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- num_network_avail = g_slist_length(tokens);
- if (num_network_avail < 1) {
- err("invalid message");
- goto END;
- }
-
- plmn_list.network_list = tcore_malloc0(sizeof(TelNetworkInfo) * num_network_avail);
- dbg("RESPONSE OK");
- plmn_list.count = 0;
- for (count = 0; count < num_network_avail; count++) {
-
- net_token = tcore_at_tok_new(g_slist_nth_data(tokens, count));
- if (NULL == net_token)
- continue;
-
- resp = tcore_at_tok_nth(net_token, 0);
- if (resp != NULL) {
- plmn_list.network_list[count].plmn_status = atoi(resp);
- dbg("status[%d]", plmn_list.network_list[count].plmn_status);
- }
-
- if ((resp = tcore_at_tok_nth(net_token, 1))) {
- /* Long Alpha name */
- dbg("long alpha name[%s]", resp);
- plmn_list.network_list[count].network_identity.long_name =
- tcore_at_tok_extract(resp);
- }
-
- if ((resp = tcore_at_tok_nth(net_token, 2))) {
- /* Short Alpha name */
- dbg("Short Alpha name[%s]", resp);
- plmn_list.network_list[count].network_identity.short_name =
- tcore_at_tok_extract(resp);
- }
-
- /* PLMN ID */
- if ((resp = tcore_at_tok_nth(net_token, 3))) {
- dbg("PLMN ID[%s]", resp);
- plmn_list.network_list[count].network_identity.plmn =
- tcore_at_tok_extract(resp);
- }
-
- /* Parse Access Technology */
- if ((resp = tcore_at_tok_nth(tokens, 4))) {
- act = atoi(resp);
- if (0 == act)
- plmn_list.network_list[count].act = TEL_NETWORK_ACT_GSM;
- else if (2 == act)
- plmn_list.network_list[count].act = TEL_NETWORK_ACT_UMTS;
- }
-
- dbg("Operator [%d] :: status = %d, long_name = %s, short_name = %s plmn = %s, AcT=%d",
- plmn_list.network_list[count].plmn_status,
- plmn_list.network_list[count].network_identity.long_name,
- plmn_list.network_list[count].network_identity.short_name,
- plmn_list.network_list[count].network_identity.plmn,
- plmn_list.network_list[count].act);
-
- plmn_list.count ++;
- tcore_at_tok_free(net_token);
- }
- result = TEL_NETWORK_RESULT_SUCCESS;
- } else {
- err("RESPONSE NOK");
- if (at_resp->lines)
- err("CME Error[%s]",(char *)at_resp->lines->data);
- }
-
-END:
- dbg("Network search : [%s]",
- (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Invoke callback */
- if(resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &plmn_list, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
- /* Free resources*/
- for (count = 0; count < num_network_avail; count++) {
- g_free(plmn_list.network_list[count].network_identity.long_name);
- g_free(plmn_list.network_list[count].network_identity.short_name);
- g_free(plmn_list.network_list[count].network_identity.plmn);
- }
-
- tcore_free(plmn_list.network_list);
- tcore_at_tok_free(tokens);
-}
-
-static void on_response_atmodem_network_get_selection_mode(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelNetworkSelectionMode selection_mode = -1;
- GSList *tokens = NULL;
-
- TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; //TODO - CME Error mapping required.
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success) {
- const gchar *line;
- gint mode;
-
- if (!at_resp->lines) {
- err("invalid response received");
- goto END;
- }
-
- line = (char *) at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) < 1) {
- msg("invalid message");
- goto END;
- }
- dbg("RESPONSE OK");
-
- mode = atoi(tcore_at_tok_nth(tokens, 0));
- if(mode == 0)
- selection_mode = TEL_NETWORK_SELECTION_MODE_AUTOMATIC;
- else if (mode == 1)
- selection_mode = TEL_NETWORK_SELECTION_MODE_MANUAL;
-
- dbg("selection mode[%d]", selection_mode);
- result = TEL_NETWORK_RESULT_SUCCESS;
-
- } else {
- err("RESPONSE NOK");
- }
-
-END:
- dbg("Get selection mode : [%s]",
- (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &selection_mode, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-
- /* Free resource*/
- tcore_at_tok_free(tokens);
-}
-
-static void on_response_atmodem_network_default(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; //TODO - CME Error mapping required.
-
- dbg("Enter");
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success) {
- dbg("RESPONSE OK");
- result = TEL_NETWORK_RESULT_SUCCESS;
- } else {
- err("RESPONSE NOK");
- if (at_resp->lines)
- err("CME Error[%s]",(char *)at_resp->lines->data);
- }
-
- /* Invoke callback */
- if(resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-/* Network Operations */
-/*
- * Operation - fetch_nw_name
- *
- * Request -
- * AT-Command: AT+COPS=[<mode>[,<format>[,<oper>[,< AcT>]]]]
- *
- * <mode> may be
- * 1 Manual. Other parameters like format and operator need to be passed
- * 2 Deregister from network
- * 3 It sets <format> value. In this case <format> becomes a mandatory input
- * 4 Manual / Automatic. In this case if manual selection fails then automatic mode
- * is entered
- *
- * <format> may be
- * 0 format presentations are set to long alphanumeric. If Network name not
- * available it displays combination of Mcc and MNC in string format.
- * 1 format presentation is set to short alphanumeric.
- * 2 format presentations set to numeric.
- *
- * <oper> may be
- * string type given in format <format>
- *
- * Response - Network name
- * Success: (Multiple Single line)
- * +COPS: <mode>[,<format>,<oper>[,< AcT>]]
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_network_get_identity_info(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- return __atmodem_network_fetch_nw_name(co, cb, cb_data);
-}
-
-/*
- * Operation - network search
- * Request -
- * AT-Command: AT+COPS=?
- *
- * Response -
- * Success: (Single line)
- * +COPS: [list of supported (<stat>,long alphanumeric <oper>
- * ,short alphanumeric <oper>,numeric <oper>[,< AcT>]
- * [,,(list of supported <mode>s),(list of supported <format>s)]
-
- * <format>
- * describes the format in which operator name is to be displayed. Different values of <format> can be:
- * 0 <oper> format presentations are set to long alphanumeric. If Network name not available it displays
- * combination of Mcc and MNC in string format.
- * 1 <oper> format presentation is set to short alphanumeric.
- * 2 <oper> format presentations set to numeric.
- * <oper>:
- * string type given in format <format>; this field may be up to 16 character long for long alphanumeric format, up
- * to 8 characters for short alphanumeric format and 5 Characters long for numeric format (MCC/MNC codes)
- * <stat>:
- * describes the status of the network. It is one of the response parameter for test command.
- * 0 Unknown Networks
- * 1 Network Available
- * 2 Current
- * 3 Forbidden Network
- * <AcT>
- * indicates the radio access technology and values can be:
- * 0 GSM
- * 2 UMTS
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-
-static TelReturn atmodem_network_search(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+COPS=?", "+COPS",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_network_search, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Network Search");
-
- return ret;
-}
-
-/*
- * Operation - automatic network selection
- * Request -
- * AT-Command: AT+COPS= [<mode> [, <format> [, <oper>> [, <AcT>]]]]
- * where
- * <mode>
- * is used to select, whether the selection is done automatically by the ME or is forced by this command to
- * operator <oper> given in the format <format>.
- * The values of <mode> can be:
- * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
- * 1 Manual. Other parameters like format and operator need to be passed
- * 2 Deregister from network
- * 3 It sets <format> value. In this case <format> becomes a mandatory input
- * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered
- *
- * Response -
- * Success:(No result)
- * OK or
- * +CME ERROR: <err>
- */
-static TelReturn atmodem_network_select_automatic(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
- dbg("entry");
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+COPS=0", NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_network_default, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Automatic network selection");
-
- return ret;
-}
-
-/*
- * Operation - manual network selection
- * Request -
- * AT-Command: AT+COPS= [<mode> [, <format> [, <oper>> [, <AcT>]]]]
- * where
- * <mode>
- * is used to select, whether the selection is done automatically by the ME or is forced by this command to
- * operator <oper> given in the format <format>.
- * The values of <mode> can be:
- * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
- * 1 Manual. Other parameters like format and operator need to be passed
- * 2 Deregister from network
- * 3 It sets <format> value. In this case <format> becomes a mandatory input
- * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered.
- * <oper>
- * string type given in format <format>; this field may be up to 16 character long for long alphanumeric format, up
- * to 8 characters for short alphanumeric format and 5 Characters long for numeric format (MCC/MNC codes)
- * <AcT>
- * indicates the radio access technology and values can be:
- * 0 GSM
- * 2 UMTS
- *
- * Response -
- * Success:(No result)
- * OK or
- * +CME ERROR: <err>
- */
-static TelReturn atmodem_network_select_manual(CoreObject *co,
- const TelNetworkSelectManualInfo *sel_manual,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
- gchar *at_cmd;
- gint act;
- dbg("entry");
-
- switch(sel_manual->act) {
- case TEL_NETWORK_ACT_GSM:
- case TEL_NETWORK_ACT_GPRS:
- case TEL_NETWORK_ACT_EGPRS:
- act = 0;
- break;
- case TEL_NETWORK_ACT_UMTS:
- case TEL_NETWORK_ACT_GSM_AND_UMTS:
- case TEL_NETWORK_ACT_HSDPA:
- case TEL_NETWORK_ACT_HSPA:
- act = 2;
- break;
- default:
- err("unsupported AcT");
- return ret;
- }
-
- /* AT-Command */
- at_cmd = g_strdup_printf("AT+COPS=1,2,\"%s\",%d", sel_manual->plmn, act);
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_network_default, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Manual network selection");
-
- /* Free resources*/
- g_free(at_cmd);
- return ret;
-}
-
-/*
- * Operation - get network selection mode
- * Request -
- * AT-Command: AT+COPS?
- *
- * Response -
- * Success: (Single line)
- * +COPS: <mode>[,<format>,<oper>[,< AcT>]]
- * <mode>
- * is used to select, whether the selection is done automatically by the ME or is forced by this command to
- * operator <oper> given in the format <format>.
- * The values of <mode> can be:
- * 0 Automatic, in this case other fields are ignored and registration is done automatically by ME
- * 1 Manual. Other parameters like format and operator need to be passed
- * 2 Deregister from network
- * 3 It sets <format> value. In this case <format> becomes a mandatory input
- * 4 Manual / Automatic. In this case if manual selection fails then automatic mode is entered
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_network_get_selection_mode(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+COPS?", "+COPS",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_network_get_selection_mode, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get selection mode");
-
- return ret;
-}
-
-/* Network Operations */
-static TcoreNetworkOps atmodem_network_ops = {
- .get_identity_info = atmodem_network_get_identity_info,
- .search = atmodem_network_search,
- .cancel_search = NULL,
- .select_automatic = atmodem_network_select_automatic,
- .select_manual = atmodem_network_select_manual,
- .get_selection_mode = atmodem_network_get_selection_mode,
- .set_preferred_plmn = NULL,
- .get_preferred_plmn = NULL,
- .set_mode = NULL,
- .get_mode = NULL,
- .get_neighboring_cell_info = NULL
-};
-
-gboolean atmodem_network_init(TcorePlugin *p, CoreObject *co)
-{
- dbg("Enter");
-
- /* Set operations */
- tcore_network_set_ops(co, &atmodem_network_ops);
-
- /* Add Callbacks */
- tcore_object_add_callback(co,
- "+CREG:",
- on_notification_atmodem_cs_network_info, NULL);
- tcore_object_add_callback(co,
- "+CGREG:",
- on_notification_atmodem_ps_network_info, NULL);
- tcore_object_add_callback(co,
- "+CIEV:",
- on_notification_atmodem_network_rssi, NULL);
-
- /*
- * Add Hooks - Request and Notification
- */
- tcore_plugin_add_request_hook(p,
- TCORE_COMMAND_MODEM_SET_FLIGHTMODE,
- on_hook_atmodem_set_flight_mode, NULL);
- tcore_plugin_add_notification_hook(p,
- TCORE_NOTIFICATION_SIM_STATUS,
- on_hook_atmodem_sim_status, co);
-
- //_insert_mcc_mnc_oper_list(cp, co_network);
-
- dbg("Exit");
- return TRUE;
-}
-
-void atmodem_network_exit(TcorePlugin *p, CoreObject *co)
-{
- dbg("Exit");
-}
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-#include <server.h>
-#include <plugin.h>
-#include <core_object.h>
-#include <hal.h>
-#include <queue.h>
-#include <storage.h>
-#include <at.h>
-
-#include <co_ps.h>
-#include <co_context.h>
-
-#include "atmodem_ps.h"
-#include "atmodem_common.h"
-
-typedef struct {
- TcorePsCallState ps_call_status;
-} PrivateInfo;
-
-static void __notify_context_status_changed(CoreObject *co_ps, guint context_id,
- TcorePsCallState status)
-{
- PrivateInfo *private_info = tcore_object_ref_user_data(co_ps);
- TcorePsCallStatusInfo data_resp = {0,};
- tcore_check_return_assert(private_info != NULL);
-
- dbg("Entry");
-
- private_info->ps_call_status = status;
- data_resp.context_id = context_id;
- data_resp.state = status;
- dbg("Sending PS Call Status Notification - Context ID: [%d] Context State: [%d]",
- data_resp.context_id, data_resp.state);
-
- /* Send PS CALL Status Notification */
- (void)tcore_object_send_notification(co_ps,
- TCORE_NOTIFICATION_PS_CALL_STATUS,
- sizeof(TcorePsCallStatusInfo),
- &data_resp);
-
- dbg("Exit");
-}
-
-static void __atmodem_ps_setup_pdp(CoreObject *co_ps, gint result, const gchar *netif_name,
- void *user_data)
-{
- CoreObject *ps_context = user_data;
- guint context_id;
-
- tcore_check_return_assert(ps_context != NULL);
-
- dbg("Enter");
-
- if (result < 0) {
- /* Deactivate PDP context */
- (void)tcore_object_dispatch_request(co_ps, TRUE,
- TCORE_COMMAND_PS_DEACTIVATE_CONTEXT,
- NULL, 0,
- NULL, NULL);
-
- return;
- }
-
- dbg("devname = [%s]", netif_name);
-
- tcore_context_set_ipv4_devname(ps_context, netif_name);
-
- (void)tcore_context_get_id(ps_context, &context_id);
- dbg("Context ID : %d", context_id);
-
- __notify_context_status_changed(co_ps, context_id, TCORE_PS_CALL_STATE_CONNECTED);
-
- dbg("Exit");
-}
-
-static void __on_response_atmodem_get_ipconfiguration(TcorePending *p, guint data_len, const void *data, void *user_data)
-{
- CoreObject *co_ps = tcore_pending_ref_core_object(p);
- CoreObject *ps_context = user_data;
- const TcoreAtResponse *at_resp = data;
- TcoreHal *hal = tcore_object_get_hal(co_ps);
- PrivateInfo *private_info = tcore_object_ref_user_data(co_ps);
- guint context_id;
- TcorePsCallState curr_call_status;
- GSList *p_cur = NULL;
-
- (void)tcore_context_get_id(ps_context, &context_id);
-
- if (at_resp && at_resp->success) {
- for (p_cur = at_resp->lines; p_cur != NULL; p_cur = p_cur->next) {
- const gchar *line;
- GSList *tokens = NULL;
-
- line = (const char *) p_cur->data;
- tokens = tcore_at_tok_new(line);
-
- if (g_slist_length(tokens) >= 2) {
- gchar *pdp_type = NULL, *apn = NULL;
- gchar *ip = NULL, *pdp_address = NULL, *p_cid = NULL;
-
- p_cid = g_slist_nth_data(tokens, 0);
- dbg("cid: %d", p_cid);
-
- /* Send IP Configuration noti only on the requested CID. */
- if (atoi(p_cid) && (context_id == (unsigned int)atoi(p_cid))) {
- pdp_type = g_slist_nth_data(tokens, 1);
- dbg("PDP type: %s", pdp_type);
-
- if (pdp_type != NULL) {
- apn = g_slist_nth_data(tokens, 2);
- dbg("APN: %s", apn);
- }
- if (apn != NULL) {
- ip = g_slist_nth_data(tokens, 3);
- pdp_address = tcore_at_tok_extract(ip);
- dbg("IP address: %s", ip);
- }
-
- (void)tcore_context_set_ipv4_addr(ps_context, (const char*)pdp_address);
- tcore_free(pdp_address);
-
- dbg("Adding default DNS pri: 8.8.8.8 sec: 8.8.4.4");
-
- tcore_context_set_ipv4_dns(ps_context, "8.8.8.8", "8.8.4.4");
-
- /* Mount network interface */
- if (tcore_hal_setup_netif(hal, co_ps, __atmodem_ps_setup_pdp, ps_context, context_id, TRUE)
- != TEL_RETURN_SUCCESS) {
- err("Setup network interface failed");
- return;
- }
- } else {
- err("No matched response with CID: %d", atoi(p_cid));
- }
- }
- }
- }else {
- err("Response NOK");
-
- (void)tcore_context_get_id(ps_context, &context_id);
-
- curr_call_status = private_info->ps_call_status;
-
- __notify_context_status_changed(co_ps, context_id, curr_call_status);
- }
-}
-
-static void __atmodem_get_ipconfiguration(CoreObject *co_ps, CoreObject *ps_context)
-{
- TelReturn ret;
-
- dbg("Enter");
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co_ps,
- "AT+CGDCONT?", NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- __on_response_atmodem_get_ipconfiguration,
- ps_context,
- on_send_atmodem_request, NULL);
- if (ret != TEL_RETURN_SUCCESS){
- err("Failed to prepare and send AT request");
- /* Deactivate PDP context */
- (void)tcore_object_dispatch_request(co_ps, TRUE,
- TCORE_COMMAND_PS_DEACTIVATE_CONTEXT,
- NULL, 0,
- NULL, NULL);
- }
-
- dbg("Exit");
-}
-
-static void __on_response_atmodem_attach_ps(TcorePending *p, guint data_len,
- const void *data, void *user_data)
-{
- CoreObject *co_ps = tcore_pending_ref_core_object(p);
- CoreObject *ps_context = user_data;
- const TcoreAtResponse *at_resp = data;
- PrivateInfo *private_info = tcore_object_ref_user_data(co_ps);
- guint context_id;
- TcorePsCallState curr_call_status;
-
- tcore_check_return_assert(at_resp != NULL);
- tcore_check_return_assert(ps_context != NULL);
-
- if (at_resp && at_resp->success) {
- __atmodem_get_ipconfiguration(co_ps, ps_context);
- return;
- }
-
- err("Response NOK");
-
- (void)tcore_context_get_id(ps_context, &context_id);
-
- curr_call_status = private_info->ps_call_status;
-
- __notify_context_status_changed(co_ps, context_id, curr_call_status);
-
- dbg("Exit");
-}
-
-static void __atmodem_attach_ps(CoreObject *co_ps, CoreObject *ps_context)
-{
- TelReturn ret;
-
- dbg("Enter");
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co_ps,
- "ATD*99***1#", NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- __on_response_atmodem_attach_ps,
- ps_context,
- on_send_atmodem_request, NULL);
- if (ret != TEL_RETURN_SUCCESS){
- err("Failed to prepare and send AT request");
- /* Deactivate PDP context */
- (void)tcore_object_dispatch_request(co_ps, TRUE,
- TCORE_COMMAND_PS_DEACTIVATE_CONTEXT,
- NULL, 0,
- NULL, NULL);
- }
-
- dbg("Exit");
-}
-
-static void on_response_atmodem_ps_activate_context(TcorePending *p, guint data_len,
- const void *data,
- void *user_data)
-{
- CoreObject *co_ps = tcore_pending_ref_core_object(p);
- const TcoreAtResponse *at_resp = data;
- CoreObject *ps_context = user_data;
- PrivateInfo *private_info = tcore_object_ref_user_data(co_ps);
- tcore_check_return_assert(private_info != NULL);
-
- dbg("Enter");
-
- tcore_check_return_assert(at_resp != NULL);
- tcore_check_return_assert(ps_context != NULL);
-
- if (at_resp && at_resp->success) {
- dbg("Response OK");
- __atmodem_attach_ps(co_ps, ps_context);
- } else {
- guint context_id;
- TcorePsCallState curr_call_status;
-
- (void)tcore_context_get_id(ps_context, &context_id);
-
- err("Response NOK");
- curr_call_status = private_info->ps_call_status;
- __notify_context_status_changed(co_ps, context_id, curr_call_status);
- }
-
- dbg("Exit");
-}
-
-static void on_response_atmodem_ps_deactivate_context(TcorePending *p, guint data_len,
- const void *data,
- void *user_data)
-{
- CoreObject *co_ps = tcore_pending_ref_core_object(p);
- TcoreHal *hal = tcore_object_get_hal(co_ps);
- const TcoreAtResponse *at_resp = data;
- CoreObject *ps_context = user_data;
- guint context_id;
-
- dbg("Enter");
-
- tcore_check_return_assert(at_resp != NULL);
- tcore_check_return_assert(ps_context != NULL);
-
- (void)tcore_context_get_id(ps_context, &context_id);
- dbg("Context ID : %d", context_id);
-
- /*
- * AT+CGACT = 0 is returning NO CARRIER or an error. Just test if the
- * response contains NO CARRIER else decode CME error.
- */
- if (at_resp && at_resp->success) {
- const gchar *line;
-
- line = (const gchar *)at_resp->lines->data;
- if (g_strcmp0(line, "NO CARRIER") != 0) {
- err("%s", line);
- err("Context %d has not been deactivated", context_id);
-
- goto out;
- }
- }
-
- __notify_context_status_changed(co_ps, context_id, TCORE_PS_CALL_STATE_NOT_CONNECTED);
-
- if (tcore_hal_setup_netif(hal, co_ps, NULL, NULL, context_id, FALSE) != TEL_RETURN_SUCCESS)
- err("Failed to disable network interface");
-
-out:
- dbg("Exit");
-}
-
-static void on_response_atmodem_ps_define_context(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *ps_context = (CoreObject *) user_data;
- CoreObject *co_ps = tcore_pending_ref_core_object(p);
- PrivateInfo *private_info = tcore_object_ref_user_data(co_ps);
- guint context_id;
- TcorePsCallState curr_call_status;
-
- dbg("entry");
-
- tcore_check_return_assert(at_resp != NULL);
- tcore_check_return_assert(ps_context != NULL);
- tcore_check_return_assert(private_info != NULL);
-
- if (at_resp && at_resp->success) {
- dbg("Response OK");
- curr_call_status = TCORE_PS_CALL_STATE_CTX_DEFINED;
- tcore_context_set_state(co_ps, curr_call_status);
- }else {
- err("ERROR[%s]",at_resp->final_response);
- curr_call_status =private_info->ps_call_status;
- }
- (void)tcore_context_get_id(ps_context, &context_id);
- __notify_context_status_changed(co_ps, context_id, curr_call_status);
-}
-
-/*
- * Operation - PDP Context Activate
- *
- * Request -
- * AT-Command: AT+CGACT= [<state> [, <cid> [, <cid> [,...]]]]
- *
- * where,
- * <state>
- * indicates the state of PDP context activation
- *
- * 1 activated
- *
- * <cid>
- * It is a numeric parameter which specifies a particular PDP context definition
- *
- * Response -
- * Success: (No Result)
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-
-static TelReturn atmodem_ps_activate_context(CoreObject *co_ps, CoreObject *ps_context,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- TelReturn ret;
- guint context_id;
- PrivateInfo *private_info = tcore_object_ref_user_data(co_ps);
- tcore_check_return_value_assert(private_info != NULL, TEL_RETURN_INVALID_PARAMETER);
-
- dbg("Entry");
-
- (void)tcore_context_get_id(ps_context, &context_id);
- dbg("Context ID : %d", context_id);
-
- at_cmd = g_strdup_printf("AT+CGACT=1,%d", context_id);
- dbg(" at command : %s", at_cmd);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co_ps,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_ps_activate_context,
- ps_context,
- on_send_atmodem_request, NULL);
- if (ret != TEL_RETURN_SUCCESS){
- TcorePsCallState curr_call_status;
-
- curr_call_status = private_info->ps_call_status;
- err("AT request failed. Send notification for call status [%d]", curr_call_status);
- __notify_context_status_changed(co_ps, context_id, curr_call_status);
- }
- tcore_free(at_cmd);
- dbg("Exit");
-
- return ret;
-}
-
-/*
- * Operation - PDP Context Deactivate
- *
- * Request -
- * AT-Command: AT+CGACT= [<state> [, <cid> [, <cid> [,...]]]]
- *
- * where,
- * <state>
- * indicates the state of PDP context activation
- *
- * 0 deactivated
- *
- * <cid>
- * It is a numeric parameter which specifies a particular PDP context definition
- *
- * Response -
- * Success: (No Result)
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_ps_deactivate_context(CoreObject *co_ps, CoreObject *ps_context,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- TelReturn ret;
- guint context_id;
- PrivateInfo *private_info = tcore_object_ref_user_data(co_ps);
- tcore_check_return_value_assert(private_info != NULL, TEL_RETURN_INVALID_PARAMETER);
-
- dbg("Entry");
-
- (void)tcore_context_get_id(ps_context, &context_id);
- dbg("Context ID : %d", context_id);
-
- at_cmd = g_strdup_printf("AT+CGACT=0,%d", context_id);
- dbg(" at command : %s", at_cmd);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co_ps,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_ps_deactivate_context,
- ps_context,
- on_send_atmodem_request, NULL);
- if (ret != TEL_RETURN_SUCCESS){
- TcorePsCallState curr_call_status;
-
- curr_call_status = private_info->ps_call_status;
- err("AT request failed. Send notification for call status [%d]", curr_call_status);
- __notify_context_status_changed(co_ps, context_id, curr_call_status);
- }
- tcore_free(at_cmd);
- dbg("Exit");
-
- return ret;
-}
-
-/*
- * Operation - Define PDP Context
- *
- * Request -
- * AT-Command: AT+CGDCONT= [<cid> [, <PDP_type> [, <APN> [, <PDP_addr> [,
- * <d_comp> [, <h_comp> [, <pd1> [... [, pdN]]]]]]]]]
- * where,
- * <cid>
- * It is a numeric parameter, which specifies a particular PDP context definition
- *
- * <PDP_type>
- * "IP" Internet Protocol (IETF STD 5)
- * "IPV6" Internet Protocol, version 6 (IETF RFC 2460)
- * "IPV4V6" Virtual <PDP_type>introduced to handle dual IP stack UE capability (see 3GPP
- * TS 24.301[83])
- *
- * <APN>
- * Access Point Name
- *
- * <PDP_address>
- * It is the string parameter that identifies the MT in the address space applicable to the PDP
- * The allocated address may be read using the command +CGPADDR command
- *
- * <d_comp>
- * A numeric parameter that controls PDP data compression
- * 0 off
- * 1 on
- * 2 V.42 bis
- *
- * <h_comp>
- * A numeric parameter that controls PDP header compression
- * 0 off
- * 1 on
- * 2 RFC1144
- * 3 RFC2507
- * 4 RFC3095
- *
- * <pd1>...<pdN>
- * zero to N string parameters whose meanings are specific to the <PDP_type>
- *
- * Response -
- * Success: (No Result)
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_ps_define_context(CoreObject *co_ps, CoreObject *ps_context,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- guint context_id = 0;
- gchar *at_cmd = NULL;
- gchar *apn = NULL;
- gchar *pdp_type_str = NULL;
- TcoreContextType pdp_type;
- TcoreContextDComp d_comp;
- TcoreContextHComp h_comp;
- TelReturn ret = TEL_RETURN_FAILURE;
- TcorePsCallState curr_call_status;
- PrivateInfo *private_info = tcore_object_ref_user_data(co_ps);
- tcore_check_return_value_assert(private_info != NULL, TEL_RETURN_INVALID_PARAMETER);
-
- dbg("Entry");
-
- (void)tcore_context_get_id(ps_context, &context_id);
- (void)tcore_context_get_type(ps_context, &pdp_type);
-
- switch (pdp_type) {
- case TCORE_CONTEXT_TYPE_X25:
- dbg("CONTEXT_TYPE_X25");
- pdp_type_str = g_strdup("X.25");
- break;
-
- case TCORE_CONTEXT_TYPE_IP:
- dbg("CONTEXT_TYPE_IP");
- pdp_type_str = g_strdup("IP");
- break;
-
- case TCORE_CONTEXT_TYPE_PPP:
- dbg("CONTEXT_TYPE_PPP");
- pdp_type_str = g_strdup("PPP");
- break;
-
- case TCORE_CONTEXT_TYPE_IPV6:
- dbg("CONTEXT_TYPE_IPV6");
- pdp_type_str = g_strdup("IPV6");
- break;
-
- default:
- /*PDP Type not supported*/
- dbg("Unsupported PDP type: %d", pdp_type);
- goto error;
- }
-
- (void)tcore_context_get_data_compression(ps_context, &d_comp);
- (void)tcore_context_get_header_compression(ps_context, &h_comp);
- (void) tcore_context_get_apn(ps_context, &apn);
-
- dbg("Define context for CID: %d", context_id);
- /* AT-Command */
- at_cmd = g_strdup_printf("AT+CGDCONT=%d,\"%s\",\"%s\",,%d,%d", context_id, pdp_type_str, apn, d_comp, h_comp);
- dbg(" at command : %s", at_cmd);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co_ps,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_ps_define_context,
- ps_context,
- on_send_atmodem_request, NULL);
-
- tcore_free(pdp_type_str);
- tcore_free(at_cmd);
- tcore_free(apn);
-
- if (ret == TEL_RETURN_SUCCESS)
- goto out;
-
-error:
- err("Failed to prepare and send AT request");
-
- curr_call_status = private_info->ps_call_status;
- __notify_context_status_changed(co_ps, context_id, curr_call_status);
-
-out:
- dbg("Exit");
- return ret;
-}
-
-/* PS Operations */
-static TcorePsOps atmodem_ps_ops = {
- .define_context = atmodem_ps_define_context,
- .activate_context = atmodem_ps_activate_context,
- .deactivate_context = atmodem_ps_deactivate_context
-};
-
-
-gboolean atmodem_ps_init(TcorePlugin *p, CoreObject *co)
-{
- PrivateInfo *private_info;
-
- dbg("Entry");
-
- /* Set PrivateInfo */
- private_info = tcore_malloc0(sizeof(PrivateInfo));
- tcore_object_link_user_data(co, private_info);
-
- /* Set operations */
- tcore_ps_set_ops(co, &atmodem_ps_ops);
-
- dbg("Exit");
- return TRUE;
-}
-
-void atmodem_ps_exit(TcorePlugin *p, CoreObject *co)
-{
- PrivateInfo *private_info;
-
- private_info = tcore_object_ref_user_data(co);
- tcore_check_return_assert(private_info != NULL);
-
- tcore_free(private_info);
-
- dbg("Exit");
-}
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-#include <server.h>
-#include <plugin.h>
-#include <core_object.h>
-#include <hal.h>
-#include <queue.h>
-#include <storage.h>
-#include <at.h>
-#include <vconf.h>
-
-#include <co_sim.h>
-#include <co_sms.h>
-
-#include "atmodem_sim.h"
-#include "atmodem_common.h"
-
-#define ENABLE_FLAG 1
-#define DISABLE_FLAG 2
-
-#define ATMODEM_SIM_ACCESS_READ_BINARY 176
-#define ATMODEM_SIM_ACCESS_READ_RECORD 178
-#define ATMODEM_SIM_ACCESS_GET_RESPONSE 192
-#define ATMODEM_SIM_ACCESS_UPDATE_BINARY 214
-#define ATMODEM_SIM_ACCESS_UPDATE_RECORD 220
-
-typedef enum {
- ATMODEM_SIM_FILE_TYPE_DEDICATED = 0x00, /**< Dedicated */
- ATMODEM_SIM_FILE_TYPE_TRANSPARENT = 0x01, /**< Transparent -binary type*/
- ATMODEM_SIM_FILE_TYPE_LINEAR_FIXED = 0x02, /**< Linear fixed - record type*/
- ATMODEM_SIM_FILE_TYPE_CYCLIC = 0x04, /**< Cyclic - record type*/
- ATMODEM_SIM_FILE_TYPE_INVALID_TYPE = 0xFF /**< Invalid type */
-} AtmodemSimFileType;
-
-typedef enum {
- ATMODEM_SIM_CURR_SEC_OP_PIN1_VERIFY,
- ATMODEM_SIM_CURR_SEC_OP_PIN2_VERIFY,
- ATMODEM_SIM_CURR_SEC_OP_PUK1_VERIFY,
- ATMODEM_SIM_CURR_SEC_OP_PUK2_VERIFY,
- ATMODEM_SIM_CURR_SEC_OP_SIM_VERIFY,
- ATMODEM_SIM_CURR_SEC_OP_ADM_VERIFY,
- ATMODEM_SIM_CURR_SEC_OP_PIN1_CHANGE,
- ATMODEM_SIM_CURR_SEC_OP_PIN2_CHANGE,
- ATMODEM_SIM_CURR_SEC_OP_PIN1_ENABLE,
- ATMODEM_SIM_CURR_SEC_OP_PIN1_DISABLE,
- ATMODEM_SIM_CURR_SEC_OP_PIN2_ENABLE,
- ATMODEM_SIM_CURR_SEC_OP_PIN2_DISABLE, // 10
- ATMODEM_SIM_CURR_SEC_OP_SIM_ENABLE,
- ATMODEM_SIM_CURR_SEC_OP_SIM_DISABLE,
- ATMODEM_SIM_CURR_SEC_OP_NET_ENABLE,
- ATMODEM_SIM_CURR_SEC_OP_NET_DISABLE,
- ATMODEM_SIM_CURR_SEC_OP_NS_ENABLE,
- ATMODEM_SIM_CURR_SEC_OP_NS_DISABLE,
- ATMODEM_SIM_CURR_SEC_OP_SP_ENABLE,
- ATMODEM_SIM_CURR_SEC_OP_SP_DISABLE,
- ATMODEM_SIM_CURR_SEC_OP_CP_ENABLE,
- ATMODEM_SIM_CURR_SEC_OP_CP_DISABLE, // 20
- ATMODEM_SIM_CURR_SEC_OP_FDN_ENABLE,
- ATMODEM_SIM_CURR_SEC_OP_FDN_DISABLE,
- ATMODEM_SIM_CURR_SEC_OP_PIN1_STATUS,
- ATMODEM_SIM_CURR_SEC_OP_PIN2_STATUS,
- ATMODEM_SIM_CURR_SEC_OP_FDN_STATUS,
- ATMODEM_SIM_CURR_SEC_OP_NET_STATUS,
- ATMODEM_SIM_CURR_SEC_OP_NS_STATUS,
- ATMODEM_SIM_CURR_SEC_OP_SP_STATUS,
- ATMODEM_SIM_CURR_SEC_OP_CP_STATUS,
- ATMODEM_SIM_CURR_SEC_OP_SIM_STATUS,
- ATMODEM_SIM_CURR_SEC_OP_SIM_UNKNOWN = 0xff
-} AtmodemSimCurrSecOp;
-
-typedef enum {
- SEC_LOCK_TYPE_NONE =0,
- SEC_LOCK_TYPE_READY, /* ME is not locked */
- SEC_LOCK_TYPE_PS, /* PH-SIM, Lock Phone to SIM/UICC card(MT asks password when other than current SIM/UICC card inserted; MT may remember certain amount of
- previously used cards thus not requiring password when they are inserted ) */
- SEC_LOCK_TYPE_PF, /* PH-FSIM, Lock Phone to the very First inserted SIM/UICC card ( MT asks password when other than the first SIM/UICC card is inserted ) */
- SEC_LOCK_TYPE_SC, /*Lock SIM/UICC card ( SIM asks password in ME power-up and when this command is issued ) */
- SEC_LOCK_TYPE_FD, /* SIM card or active application in the UICC(GSM or USIM) fixed dialing memory feature */
- SEC_LOCK_TYPE_PN, /* Network Personalization */
- SEC_LOCK_TYPE_PU, /* Network subset Personalization */
- SEC_LOCK_TYPE_PP, /* Service Provider Personalization */
- SEC_LOCK_TYPE_PC, /* Corporate Personalization */
- SEC_LOCK_TYPE_SC2, /* Lock PIN2 ( ... ) */
- SEC_LOCK_TYPE_PUK2, /* Lock PUK2 (... ) */
- SEC_LOCK_TYPE_ACL, /* ACL */
-
- SEC_LOCK_TYPE_NO_SIM, /* SIM is not inserted */
- SEC_LOCK_TYPE_UNAVAIL, /* SIM is inserted but can not communicate with SIM ( SIM interface error ) */
- SEC_SIM_INIT_COMPLETED, /* SIM Initialize Completed */
- SEC_PB_INIT_COMPLETED, /* Phonebook Initialize Completed*/
- SEC_SIM_INIT_CRASH, /* SIM Crash request from SMC lab*/
-
- SEC_LOCK_TYPE_MAX
-} AtmodemSimSecLockType;
-
-typedef enum {
- SEC_LOCK_KEY_NONE,
- SEC_LOCK_KEY_UNLOCKED, /* Not necessary */
- SEC_LOCK_KEY_PIN, /* PIN required as a password */
- SEC_LOCK_KEY_PUK, /* 0PUK required as a password */
- SEC_LOCK_KEY_PIN2, /* PIN2 required as a password */
- SEC_LOCK_KEY_PUK2, /* PUK2 required as a password */
- SEC_LOCK_KEY_PERM_BLOCKED, /* PIN Permanent Blocked */
- SEC_LOCK_KEY_PIN2_DISABLE, /* PIN2 Lock Disabled*/
- SEC_LOCK_KEY_MAX
-} AtmodemSimSecLockKey;
-
-typedef struct {
- guint smsp_count; /**< SMSP record count */
- guint smsp_rec_len; /**< SMSP record length */
-} AtmodemSimPrivateInfo;
-
-typedef struct {
- gboolean b_valid; /**< Valid or not */
- guint rec_length; /**< Length of one record in file */
- guint rec_count; /**< Number of records in file */
- guint data_size; /**< File size */
- guint current_index; /**< Current index to read */
- AtmodemSimFileType file_type; /**< File type and structure */
- AtmodemSimCurrSecOp sec_op; /**< Current index to read */
- TelSimMailboxList mbi_list; /**< Mailbox List */
- TelSimMailBoxNumber mb_list[TEL_SIM_MSP_CNT_MAX*5]; /**< Mailbox number */
- TelSimFileId file_id; /**< Current file id */
- TelSimResult file_result; /**< File access result */
- TelSimFileResult files; /**< File read data */
- TcoreCommand req_command; /**< Request command Id */
- TelSimImsiInfo imsi; /**< Stored locally as of now,
- Need to store in secure storage*/
-} AtmodemSimMetaInfo;
-
-/* Request Function Declaration */
-static TelReturn atmodem_sim_get_imsi (CoreObject *co_sim, TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_get_ecc (CoreObject *co_sim, TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_get_spdi (CoreObject *co_sim, TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_get_spn (CoreObject *co_sim, TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_get_language (CoreObject *co_sim, TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_get_cfis (CoreObject *co_sim, TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_verify_pins(CoreObject *co, const TelSimSecPinPw *request,
- TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_verify_puks(CoreObject *co, const TelSimSecPukPw *request,
- TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_change_pins(CoreObject *co, const TelSimSecChangePinPw *request,
- TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_disable_facility(CoreObject *co, const TelSimFacilityPw *request,
- TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_enable_facility(CoreObject *co, const TelSimFacilityPw *request,
- TcoreObjectResponseCallback cb, void *cb_data);
-static TelReturn atmodem_sim_get_facility(CoreObject *co, TelSimLockType lock_type,
- TcoreObjectResponseCallback cb, void *cb_data);
-
-/* Utility Function Declaration */
-static TelSimResult __atmodem_sim_decode_status_word(unsigned short status_word1, unsigned short status_word2);
-static void __atmodem_sim_update_sim_status(CoreObject *co, TelSimCardStatus sim_status);
-static void __atmodem_sim_get_sim_type(CoreObject *co, TcoreObjectResponseCallback cb, void *cb_data);
-static void __atmodem_sim_next_from_get_file_data(CoreObject *co,
- AtmodemRespCbData *resp_cb_data, TelSimResult sim_result, gboolean decode_ret);
-static void __atmodem_sim_next_from_get_file_info(CoreObject *co,
- AtmodemRespCbData *resp_cb_data, TelSimResult sim_result);
-static void __atmodem_sim_get_file_record(CoreObject *co,
- AtmodemRespCbData *resp_cb_data);
-static void __atmodem_sim_get_file_data(CoreObject *co,
- AtmodemRespCbData *resp_cb_data);
-static TelReturn __atmodem_sim_get_file_info(CoreObject *co,
- AtmodemRespCbData *resp_cb_data);
-static char *__atmodem_sim_get_fac_from_lock_type(TelSimLockType lock_type,
- AtmodemSimCurrSecOp *sec_op, int flag);
-static int __atmodem_sim_get_lock_type(AtmodemSimCurrSecOp sec_op);
-static gboolean __atmodem_convert_scpin_str_to_enum(char* line,
- AtmodemSimSecLockType* lock_type, AtmodemSimSecLockKey* lock_key);
-
-/* Internal Response Functions*/
-static void __atmodem_sim_next_from_read_binary(CoreObject *co,
- AtmodemRespCbData *resp_cb_data,
- TelSimResult sim_result, gboolean decode_ret);
-static void __atmodem_sim_next_from_get_response(CoreObject *co,
- AtmodemRespCbData *resp_cb_data, TelSimResult sim_result);
-
-#if 0 //blocking for the moment
-static TelReturn __atmodem_sim_update_file(CoreObject *co,
- AtmodemRespCbData *resp_cb_data,
- int cmd, TelSimFileId ef,
- int p1, int p2, int p3, char *encoded_data);
-#endif
-static void __atmodem_sim_read_record(CoreObject *co, AtmodemRespCbData *resp_cb_data);
-static void __atmodem_sim_read_binary(CoreObject *co, AtmodemRespCbData *resp_cb_data);
-static TelReturn __atmodem_sim_get_response (CoreObject *co, AtmodemRespCbData *resp_cb_data);
-static void __on_response_atmodem_sim_get_sim_type_internal(CoreObject *co,
- gint result, const void *response, void *user_data);
-static void __on_response_atmodem_sim_get_sim_type(TcorePending *p,
- guint data_len, const void *data, void *user_data);
-static void __on_response_atmodem_sim_get_file_data(TcorePending *p,
- guint data_len, const void *data, void *user_data);
-static void __on_response_atmodem_sim_get_file_info(TcorePending *p,
- guint data_len, const void *data, void *user_data);
-
-#define ATMODEM_SIM_READ_FILE(co, cb, cb_data, fileId, ret) \
-{ \
- AtmodemSimMetaInfo file_meta = {0, }; \
- AtmodemRespCbData *resp_cb_data = NULL; \
- \
- file_meta.file_id = fileId; \
- file_meta.file_result = TEL_SIM_RESULT_FAILURE; \
- \
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, &file_meta, sizeof(AtmodemSimMetaInfo)); \
- \
- ret = __atmodem_sim_get_response(co, resp_cb_data); \
-}
-
-static void __atmodem_sim_set_identity(CoreObject *co, TelSimImsiInfo *imsi)
-{
- gchar new_imsi[15 + 1] = {0, };
- gchar *old_imsi;
-
- memcpy(&new_imsi, imsi->mcc, strlen(imsi->mcc));
- memcpy(&new_imsi[strlen(imsi->mcc)], imsi->mnc, strlen(imsi->mnc));
- memcpy(&new_imsi[strlen(imsi->mcc) + strlen(imsi->mnc)], imsi->msin, strlen(imsi->msin));
-
- /* TODO: This is temporary code, we should use secure storage instead of vconf */
- old_imsi = vconf_get_str("db/telephony/imsi");
- if (old_imsi) {
- if (g_strcmp0(old_imsi, new_imsi) != 0) {
- dbg("New SIM");
- vconf_set_str("db/telephony/imsi", new_imsi);
- tcore_sim_set_identification(co, TRUE);
- } else {
- dbg("Same SIM");
- tcore_sim_set_identification(co, FALSE);
- }
- } else {
- dbg("Old IMSI value is NULL, set IMSI");
- vconf_set_str("db/telephony/imsi", new_imsi);
- tcore_sim_set_identification(co, TRUE);
- }
-}
-
-/* Utility Functions */
-static TelSimResult __atmodem_sim_decode_status_word(unsigned short status_word1,
- unsigned short status_word2)
-{
- TelSimResult rst = TEL_SIM_RESULT_FAILURE;
-
- if (status_word1 == 0x93 && status_word2 == 0x00) {
- /*Failed SIM request command*/
- dbg("error - SIM application toolkit busy [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x94 && status_word2 == 0x00) {
- /*Failed SIM request command*/
- dbg("error - No EF Selected [%x][%x]", status_word1, status_word2);
- } else if (status_word1 == 0x94 && status_word2 == 0x02) {
- /*Failed SIM request command*/
- dbg("error - Out of Range - Invalid address or record number[%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x94 && status_word2 == 0x04) {
- /*Failed SIM request command*/
- dbg("error - File ID not found [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x94 && status_word2 == 0x08) {
- /*Failed SIM request command*/
- dbg("error - File is inconsistent with command - "\
- "Modem not support or USE IPC [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x98 && status_word2 == 0x02) {
- /*Failed SIM request command*/
- dbg("error - CHV not initialized [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x98 && status_word2 == 0x04) {
- /*Failed SIM request command*/
- dbg("error - Access condition not fullfilled [%x][%x]",
- status_word1, status_word2);
- dbg("error -Unsuccessful CHV verification - "\
- "at least one attempt left [%x][%x]",
- status_word1, status_word2);
- dbg("error - Unsuccessful Unblock CHV - at least one attempt left [%x][%x]",
- status_word1, status_word2);
- dbg("error - Authentication failure [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x98 && status_word2 == 0x08) {
- /*Failed SIM request command*/
- dbg("error - Contradiction with CHV status [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x98 && status_word2 == 0x10) {
- /*Failed SIM request command*/
- dbg("error - Contradiction with invalidation status [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x98 && status_word2 == 0x40) {
- /*Failed SIM request command*/
- dbg("error -Unsuccessful CHV verification - no attempt left [%x][%x]",
- status_word1, status_word2);
- dbg("error - Unsuccessful Unblock CHV - no attempt left [%x][%x]",
- status_word1, status_word2);
- dbg("error - CHV blocked [%x][%x]", status_word1, status_word2);
- } else if (status_word1 == 0x67 && status_word2 == 0x00) {
- dbg("error -Incorrect Parameter 3 [%x][%x]", status_word1, status_word2);
- } else if (status_word1 == 0x6B && status_word2 == 0x00) {
- dbg("error -Incorrect Parameter 1 or 2 [%x][%x]", status_word1, status_word2);
- } else if (status_word1 == 0x6D && status_word2 == 0x00) {
- dbg("error -Unknown instruction given as command [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x6E && status_word2 == 0x00) {
- dbg("error -Unknown instruction given as command [%x][%x]",
- status_word1, status_word2);
- } else if (status_word1 == 0x69 && status_word2 == 0x82) {
- dbg("error -Access denied [%x][%x]", status_word1, status_word2);
- } else if (status_word1 == 0x6A && status_word2 == 0x87) {
- dbg("error -Incorrect parameters [%x][%x]", status_word1, status_word2);
- } else if (status_word1 == 0x6A && status_word2 == 0x82) {
- dbg("error -File Not found [%x][%x]", status_word1, status_word2);
- } else if (status_word1 == 0x6A && status_word2 == 0x83) {
- dbg("error -Record Not found [%x][%x]", status_word1, status_word2);
- } else {
- rst = TEL_SIM_RESULT_CARD_ERROR;
- dbg("error -Unknown state [%x][%x]", status_word1, status_word2);
- }
- return rst;
-}
-
-static void __atmodem_sim_update_sim_status(CoreObject *co_sim,
- TelSimCardStatus sim_status)
-{
- TelSimCardStatus curr_sim_status;
-
- /*
- * Send SIM Init status, if not sent already
- */
- (void)tcore_sim_get_status(co_sim, &curr_sim_status);
- if (sim_status != curr_sim_status) {
- TelSimCardStatusInfo sim_status_noti = {0, };
-
- dbg("Change in SIM State - Old State: [0x%02x] --> New State: [0x%02x]",
- curr_sim_status, sim_status);
-
- /* Update SIM Status */
- tcore_sim_set_status(co_sim, sim_status);
- sim_status_noti.status = sim_status;
- sim_status_noti.change_status = TEL_SIM_CHANGE_STATUS_SAME; /* TODO: checkout */
-
- /* Send notification: SIM Status */
- tcore_object_send_notification(co_sim,
- TCORE_NOTIFICATION_SIM_STATUS,
- sizeof(sim_status_noti), &sim_status_noti);
- }
-}
-
-static gboolean __atmodem_convert_scpin_str_to_enum(char* line,
- AtmodemSimSecLockType *lock_type, AtmodemSimSecLockKey *lock_key)
-{
- char *type =NULL, *key = NULL;
- GSList *tokens = NULL;
-
- if(line == NULL)
- return FALSE;
-
- tokens = tcore_at_tok_new(line);
-
- type = g_slist_nth_data(tokens, 0);
- if (!type) {
- err("Type is missing");
- tcore_at_tok_free(tokens);
- return FALSE;
- }
-
- if (g_strcmp0(type, "NO_LOCK") == 0) {
- key = g_slist_nth_data(tokens, 1);
- if (!key) {
- err("Key is missing");
- tcore_at_tok_free(tokens);
- return FALSE;
- }
-
- dbg("type: [%s], key: [%s]", type, key);
- }
-
- if(g_str_has_prefix (type, "NO_SIM"))
- *lock_type = SEC_LOCK_TYPE_NO_SIM;
- else if(g_str_has_prefix (type, "UNAVAIL"))
- *lock_type = SEC_LOCK_TYPE_UNAVAIL;
- else if(g_str_has_prefix (type, "NO_LOCK"))
- *lock_type = SEC_LOCK_TYPE_READY;
- else if(g_str_has_prefix (type, "LOCK_PS"))
- *lock_type = SEC_LOCK_TYPE_PS;
- else if(g_str_has_prefix (type, "LOCK_PF"))
- *lock_type = SEC_LOCK_TYPE_PF ;
- else if(g_str_has_prefix (type, "LOCK_SC"))
- *lock_type = SEC_LOCK_TYPE_SC;
- else if(g_str_has_prefix (type, "LOCK_FD"))
- *lock_type = SEC_LOCK_TYPE_FD;
- else if(g_str_has_prefix (type, "LOCK_PN"))
- *lock_type = SEC_LOCK_TYPE_PN ;
- else if(g_str_has_prefix (type, "LOCK_PU"))
- *lock_type = SEC_LOCK_TYPE_PU ;
- else if(g_str_has_prefix (type, "LOCK_PP"))
- *lock_type = SEC_LOCK_TYPE_PP;
- else if(g_str_has_prefix (type, "LOCK_PC"))
- *lock_type = SEC_LOCK_TYPE_PC;
- else if(g_str_has_prefix (type, "LOCK_SC2"))
- *lock_type = SEC_LOCK_TYPE_SC2 ;
- else if(g_str_has_prefix (type, "LOCK_ACL"))
- *lock_type = SEC_LOCK_TYPE_ACL;
- else if(g_str_has_prefix (type, "LOCK_PUK2"))
- *lock_type = SEC_LOCK_TYPE_PUK2;
- else if(g_str_has_prefix (type, "INIT_COMP"))
- *lock_type = SEC_SIM_INIT_COMPLETED;
- else if(g_str_has_prefix (type, "INIT_ERROR"))
- *lock_type = SEC_SIM_INIT_CRASH;
- else
- *lock_type = SEC_LOCK_TYPE_NONE;
-
- if(g_str_has_prefix (key, "PIN"))
- *lock_key = SEC_LOCK_KEY_PIN;
- else if(g_str_has_prefix (key, "PUK"))
- *lock_key = SEC_LOCK_KEY_PUK;
- else if(g_str_has_prefix (key, "PIN2"))
- *lock_key = SEC_LOCK_KEY_PIN2;
- else if(g_str_has_prefix (key, "PUK2"))
- *lock_key = SEC_LOCK_KEY_PUK2;
- else if(g_str_has_prefix (key, "BLOCKED"))
- *lock_key = SEC_LOCK_KEY_PERM_BLOCKED ;
- else if(g_str_has_prefix (key, "UNLOCKED"))
- *lock_key = SEC_LOCK_KEY_UNLOCKED ;
- else if(g_str_has_prefix (key, "PIN2_DISABLE"))
- *lock_key = SEC_LOCK_KEY_PIN2_DISABLE;
- else
- *lock_key = SEC_LOCK_KEY_NONE;
-
- if(*lock_type == SEC_LOCK_TYPE_READY)
- *lock_key = SEC_LOCK_KEY_UNLOCKED;
-
- if((*lock_type == SEC_LOCK_TYPE_NO_SIM)||(*lock_type == SEC_LOCK_TYPE_UNAVAIL)||
- (*lock_type == SEC_SIM_INIT_COMPLETED)||(*lock_type == SEC_SIM_INIT_CRASH))
- *lock_key = SEC_LOCK_KEY_NONE;
-
- dbg("type: [%d], key: [%d]", *lock_type, *lock_key);
-
- tcore_at_tok_free(tokens);
-
- return TRUE;
-}
-
-static void __on_response_atmodem_sim_get_sim_type_internal(CoreObject *co_sim,
- gint result, const void *response, void *user_data)
-{
- dbg("SIM Response - SIM Type (internal): [\%SCCT]");
-
- /* Get SIM type if SIM is initialized */
- if (result == TEL_SIM_RESULT_SUCCESS) {
- TelSimCardType *sim_type = (TelSimCardType *)response;
-
- /* Update SIM type */
- tcore_sim_set_type(co_sim, *sim_type);
- if (*sim_type != TEL_SIM_CARD_TYPE_UNKNOWN) {
- /* Send SIM Type notification */
- tcore_object_send_notification(co_sim,
- TCORE_NOTIFICATION_SIM_TYPE,
- sizeof(TelSimCardType), sim_type);
- }
- }
-}
-
-static void __on_response_atmodem_sim_get_sim_type(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co_sim = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelSimCardType sim_type = TEL_SIM_CARD_TYPE_UNKNOWN;
-
- TelSimResult result = TEL_SIM_RESULT_FAILURE;
-
- dbg("SIM Response - SIM Type: [\%SCCT]");
-
- tcore_check_return_assert(co_sim != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success) {
- if (at_resp->lines) {
- const gchar *line;
- GSList *tokens;
-
- line = (const gchar *)at_resp->lines->data;
-
- /*
- * Tokenize
- *
- * %SCCT: <state>
- */
- tokens = tcore_at_tok_new(line);
-
- /* <state> */
- if (g_slist_length(tokens) == 1) {
- sim_type = atoi(g_slist_nth_data(tokens, 0));
- dbg("SIM Type: [%d]", sim_type);
-
- result = TEL_SIM_RESULT_SUCCESS;
- }
- else {
- err("Invalid message");
- }
-
- tcore_at_tok_free(tokens);
- }
- }
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result, &sim_type, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-/*
- * Operation - get_sim_type
- *
- * Request -
- * AT-Command: AT%SCCT?
- *
- * Response - sim_type (TelSimCardType)
- * Success: (Single line) -
- * +SCCT: <state>
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static void __atmodem_sim_get_sim_type(CoreObject *co_sim,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co_sim,
- "AT\%SCCT?", "\%SCCT:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_atmodem_sim_get_sim_type, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get SIM Type");
-
- dbg("ret: [%d]", ret);
-}
-
-static void __atmodem_sim_process_sim_status(CoreObject *co,
- TelSimCardStatus sim_card_status)
-{
- switch (sim_card_status) {
- case TEL_SIM_STATUS_SIM_INIT_COMPLETED: {
- TelReturn ret;
-
- dbg("SIM INIT COMPLETED");
-
- ATMODEM_SIM_READ_FILE(co, NULL, NULL, TEL_SIM_EF_IMSI, ret);
- ATMODEM_SIM_READ_FILE(co, NULL, NULL, TEL_SIM_EF_SPDI, ret);
- dbg("ret: [%d]", ret);
-
- return;
- }
-
- case TEL_SIM_STATUS_SIM_INITIALIZING: {
- TelSimCardType sim_type;
-
- dbg("SIM INITIALIZING");
-
- (void)tcore_sim_get_type(co, &sim_type);
- if (sim_type == TEL_SIM_CARD_TYPE_UNKNOWN) {
- /*
- * SIM is initialized for first time, need to
- * fetch SIM type
- */
- __atmodem_sim_get_sim_type(co,
- __on_response_atmodem_sim_get_sim_type_internal, NULL);
-
- return;
- }
- }
- break;
-
- case TEL_SIM_STATUS_CARD_REMOVED:
- dbg("SIM CARD REMOVED");
- tcore_sim_set_type(co, TEL_SIM_CARD_TYPE_UNKNOWN);
- break;
-
- case TEL_SIM_STATUS_CARD_NOT_PRESENT:
- dbg("SIM CARD NOT PRESENT");
- tcore_sim_set_type(co, TEL_SIM_CARD_TYPE_UNKNOWN);
- break;
-
- case TEL_SIM_STATUS_CARD_ERROR:
- dbg("SIM CARD ERROR");
- tcore_sim_set_type(co, TEL_SIM_CARD_TYPE_UNKNOWN);
- break;
-
- default:
- err("SIM Status: [0x%02x]", sim_card_status);
- break;
- }
-
- /* Update SIM Status */
- return __atmodem_sim_update_sim_status(co, sim_card_status);
-}
-
-static void __atmodem_sim_next_from_get_file_data(CoreObject *co_sim,
- AtmodemRespCbData *resp_cb_data,
- TelSimResult sim_result, gboolean decode_ret)
-{
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelSimCardType card_type = TEL_SIM_CARD_TYPE_UNKNOWN;
-
- dbg("Entry");
-
- dbg("[SIM]EF[0x%x] read sim_result[%d] Decode rt[%d]",
- file_meta->file_id, sim_result, decode_ret);
- switch (file_meta->file_id) {
- case TEL_SIM_EF_ELP:
- case TEL_SIM_EF_USIM_PL:
- case TEL_SIM_EF_LP:
- case TEL_SIM_EF_USIM_LI:
- if (decode_ret == TRUE) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- tcore_sim_get_type(co_sim, &card_type);
- /* 2G */
- /*
- * The ME requests the Extended Language Preference.
- * The ME only requests the Language Preference (EFLP) if at
- * least one of the following conditions holds:
- * - EFELP is not available;
- * - EFELP does not contain an entry corresponding to a
- * language specified in ISO 639[30];
- * - the ME does not support any of the languages in EFELP.
- */
- /* 3G */
- /*
- * The ME only requests the Language Preference (EFPL)
- * if at least one of the following conditions holds:
- * - if the EFLI has the value 'FFFF' in its highest
- * priority position
- * - if the ME does not support any of the language codes
- * indicated in EFLI , or if EFLI is not present
- */
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- if (file_meta->file_id == TEL_SIM_EF_LP) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->file_id = TEL_SIM_EF_LP;
- __atmodem_sim_get_file_info(co_sim, resp_cb_data);
- }
- } else if (TEL_SIM_CARD_TYPE_USIM) {
- if (file_meta->file_id == TEL_SIM_EF_LP
- || file_meta->file_id == TEL_SIM_EF_USIM_LI) {
- file_meta->file_id = TEL_SIM_EF_ELP;
- __atmodem_sim_get_file_info(co_sim, resp_cb_data);
- } else {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- }
- }
- }
- break;
-
- case TEL_SIM_EF_ECC:
- tcore_sim_get_type(co_sim, &card_type);
- if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_get_file_record(co_sim, resp_cb_data);
- }
- } else if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- dbg("[SIM DATA] Invalid CardType: [%d]. Unable to handle", card_type);
- }
- break;
-
- case TEL_SIM_EF_IMSI:
- if (resp_cb_data->cb) {
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->imsi, resp_cb_data->cb_data);
- } else {
- /* Update Status */
- __atmodem_sim_update_sim_status(co_sim, TEL_SIM_STATUS_SIM_INIT_COMPLETED);
- }
- break;
-
- case TEL_SIM_EF_MSISDN:
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_get_file_record(co_sim, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_OPL:
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_get_file_record(co_sim, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_PNN:
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_get_file_record(co_sim, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_USIM_CFIS:
- case TEL_SIM_EF_USIM_MWIS:
- case TEL_SIM_EF_USIM_MBI:
- case TEL_SIM_EF_MBDN:
- case TEL_SIM_EF_CPHS_MAILBOX_NUMBERS:
- case TEL_SIM_EF_CPHS_INFORMATION_NUMBERS:
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_get_file_record(co_sim, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_STRING:
- {
- file_meta->files.result = sim_result;
- if (decode_ret == TRUE && sim_result == TEL_SIM_RESULT_SUCCESS) {
- memcpy(file_meta->files.data.cphs_net.full_name, file_meta->files.data.cphs_net.full_name, strlen((char *)file_meta->files.data.cphs_net.full_name));
- }
-
- file_meta->file_id = TEL_SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING;
- file_meta->file_result = TEL_SIM_RESULT_FAILURE;
- file_meta->req_command = TCORE_COMMAND_SIM_GET_CPHS_NET_NAME;
-
- __atmodem_sim_get_file_info(co_sim, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
- if (file_meta->files.result == TEL_SIM_RESULT_SUCCESS)
- file_meta->files.result = TEL_SIM_RESULT_SUCCESS;
-
- if (strlen((char *)file_meta->files.data.cphs_net.full_name))
- memcpy(&file_meta->files.data.cphs_net.full_name,
- &file_meta->files.data.cphs_net.full_name,
- strlen((char *)file_meta->files.data.cphs_net.full_name));
-
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- break;
-
- case TEL_SIM_EF_ICCID:
- case TEL_SIM_EF_SST:
- case TEL_SIM_EF_SPN:
- case TEL_SIM_EF_SPDI:
- case TEL_SIM_EF_OPLMN_ACT:
- case TEL_SIM_EF_CPHS_CPHS_INFO:
- case TEL_SIM_EF_CPHS_CALL_FORWARD_FLAGS:
- case TEL_SIM_EF_CPHS_VOICE_MSG_WAITING:
- case TEL_SIM_EF_CPHS_DYNAMICFLAGS:
- case TEL_SIM_EF_CPHS_DYNAMIC2FLAG:
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE_LINE2:
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- break;
-
- default:
- err("File id not handled [0x%x]", file_meta->file_id);
- break;
- }
-}
-
-static void __atmodem_sim_next_from_get_file_info(CoreObject *co_sim,
- AtmodemRespCbData *resp_cb_data, TelSimResult sim_result)
-{
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelSimCardType card_type = TEL_SIM_CARD_TYPE_UNKNOWN;
-
- dbg("EF[0x%x] access Result[%d]", file_meta->file_id, sim_result);
-
- file_meta->files.result = sim_result;
- memset(&file_meta->files.data, 0x00, sizeof(file_meta->files.data));
-
- if ((file_meta->file_id != TEL_SIM_EF_ELP
- && file_meta->file_id != TEL_SIM_EF_LP
- && file_meta->file_id != TEL_SIM_EF_USIM_PL
- && file_meta->file_id != TEL_SIM_EF_CPHS_CPHS_INFO)
- && (sim_result != TEL_SIM_RESULT_SUCCESS)) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
-
- return;
- }
-
- switch (file_meta->file_id) {
- case TEL_SIM_EF_ELP:
- if (sim_result == TEL_SIM_RESULT_SUCCESS) {
- dbg("[SIM DATA] exist EFELP/PL(0x2F05)");
- __atmodem_sim_get_file_data(co_sim, resp_cb_data);
- } else {
- tcore_sim_get_type(co_sim, &card_type);
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- AtmodemSimMetaInfo file_meta_new = {0,};
-
- dbg("[SIM DATA]SIM_EF_ELP(2F05) access fail. Request SIM_EF_LP(0x6F05) info");
- /* The ME requests the Language Preference (EFLP) if EFELP is not available */
- file_meta_new.file_id = TEL_SIM_EF_LP;
- file_meta_new.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta_new.req_command = TCORE_COMMAND_SIM_GET_LANGUAGE;
-
- memcpy(resp_cb_data->data, &file_meta_new, sizeof(AtmodemSimMetaInfo));
-
- __atmodem_sim_get_file_info(co_sim, resp_cb_data);
- } else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- dbg(" [SIM DATA]fail to get Language information in USIM(EF-LI(6F05),EF-PL(2F05))");
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
-
- return;
- }
- }
- break;
-
- case TEL_SIM_EF_LP:
- if (sim_result == TEL_SIM_RESULT_SUCCESS) {
- dbg("[SIM DATA] exist EFLP/LI(0x6F05)");
- __atmodem_sim_get_file_data(co_sim, resp_cb_data);
- } else {
- tcore_sim_get_type(co_sim, &card_type);
- dbg("[SIM DATA]SIM_EF_LP/LI(6F05) access fail. Current CardType[%d]", card_type);
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- return;
- }
-
- /*
- * If EFLI is not present, then the language selection
- * shall be as defined in EFPL at the MF level
- */
- else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- AtmodemSimMetaInfo file_meta_new = {0,};
-
- dbg("[SIM DATA] try USIM EFPL(0x2F05)");
- file_meta_new.file_id = TEL_SIM_EF_ELP;
- file_meta_new.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta_new.req_command = TCORE_COMMAND_SIM_GET_LANGUAGE;
-
- memcpy(resp_cb_data->data, &file_meta_new, sizeof(AtmodemSimMetaInfo));
-
- __atmodem_sim_get_file_info(co_sim, resp_cb_data);
- }
- }
- break;
-
- case TEL_SIM_EF_USIM_PL:
- if (sim_result == TEL_SIM_RESULT_SUCCESS) {
- dbg("[SIM DATA] exist EFELP/PL(0x2F05)");
- __atmodem_sim_get_file_data(co_sim, resp_cb_data);
- } else {
- /*
- * EFELIand EFPL not present, so set language
- * count as zero and select ECC
- */
- dbg("[SIM DATA] SIM_EF_USIM_PL(2A05) access fail. "\
- "Request SIM_EF_ECC(0x6FB7) info");
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
-
- return;
- }
- break;
-
- case TEL_SIM_EF_ECC:
- tcore_sim_get_type(co_sim, &card_type);
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- __atmodem_sim_get_file_data(co_sim, resp_cb_data);
- } else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- if (file_meta->rec_count > TEL_SIM_ECC_LIST_MAX)
- file_meta->rec_count = TEL_SIM_ECC_LIST_MAX;
-
- file_meta->current_index++;
- __atmodem_sim_get_file_record(co_sim, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_ICCID:
- case TEL_SIM_EF_IMSI:
- case TEL_SIM_EF_SST:
- case TEL_SIM_EF_SPN:
- case TEL_SIM_EF_SPDI:
- case TEL_SIM_EF_CPHS_CALL_FORWARD_FLAGS:
- case TEL_SIM_EF_CPHS_VOICE_MSG_WAITING:
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_STRING:
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
- case TEL_SIM_EF_CPHS_DYNAMICFLAGS:
- case TEL_SIM_EF_CPHS_DYNAMIC2FLAG:
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE_LINE2:
- __atmodem_sim_get_file_data(co_sim, resp_cb_data);
- break;
-
- case TEL_SIM_EF_CPHS_CPHS_INFO:
- if (sim_result == TEL_SIM_RESULT_SUCCESS) {
- tcore_sim_set_cphs_status(co_sim, TRUE);
- __atmodem_sim_update_sim_status(co_sim, TEL_SIM_STATUS_SIM_INIT_COMPLETED);
-
- __atmodem_sim_get_file_data(co_sim, resp_cb_data);
- } else {
- tcore_sim_set_cphs_status(co_sim, FALSE);
- __atmodem_sim_update_sim_status(co_sim, TEL_SIM_STATUS_SIM_INIT_COMPLETED);
-
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- }
- break;
-
-
- case TEL_SIM_EF_USIM_CFIS:
- if (file_meta->rec_count > TEL_SIM_CALL_FORWARDING_TYPE_MAX)
- file_meta->rec_count = TEL_SIM_CALL_FORWARDING_TYPE_MAX;
-
- file_meta->current_index++;
-
- __atmodem_sim_get_file_record(co_sim, resp_cb_data);
- break;
-
- case TEL_SIM_EF_OPL:
- case TEL_SIM_EF_PNN:
- case TEL_SIM_EF_USIM_MWIS:
- case TEL_SIM_EF_USIM_MBI:
- case TEL_SIM_EF_MBDN:
- case TEL_SIM_EF_CPHS_MAILBOX_NUMBERS:
- case TEL_SIM_EF_CPHS_INFORMATION_NUMBERS:
- case TEL_SIM_EF_MSISDN:
- file_meta->current_index++;
-
- __atmodem_sim_get_file_record(co_sim, resp_cb_data);
- break;
-
- default:
- err("Unknown File ID for get File info: [0x%x]", file_meta->file_id);
- break;
- }
-}
-
-static void __on_response_atmodem_sim_get_file_data(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *resp = data;
- CoreObject *co_sim = NULL;
- GSList *tokens = NULL;
- TelSimResult sim_result;
- gboolean dr = FALSE;
- const char *line = NULL;
- char *res = NULL;
- char *tmp = NULL;
- int res_len;
- int sw1 = 0;
- int sw2 = 0;
- TelSimCardType card_type = TEL_SIM_CARD_TYPE_UNKNOWN;
- AtmodemRespCbData *resp_cb_data = (AtmodemRespCbData *) user_data;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- dbg("Entry");
-
- co_sim = tcore_pending_ref_core_object(p);
-
- if (resp->success > 0) {
- dbg("RESPONSE OK");
- if (resp->lines) {
- line = (const char *)resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) < 2) {
- msg("Invalid message");
- tcore_at_tok_free(tokens);
- return;
- }
- }
- sw1 = atoi(g_slist_nth_data(tokens, 0));
- sw2 = atoi(g_slist_nth_data(tokens, 1));
- res = g_slist_nth_data(tokens, 2);
-
- tmp = tcore_at_tok_extract(res);
- tcore_util_hexstring_to_bytes(tmp, &res, (guint *)&res_len);
-
- dbg("Response: [%s] Response length: [%d]", res, res_len);
-
- if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
- sim_result = TEL_SIM_RESULT_SUCCESS;
- file_meta->files.result = sim_result;
-
- dbg("File ID: [0x%x]", file_meta->file_id);
- switch (file_meta->file_id) {
- case TEL_SIM_EF_IMSI: {
- dbg("Data: [%s]", res);
- dr = tcore_sim_decode_imsi((unsigned char *)res, res_len, &file_meta->imsi);
- if (dr == FALSE) {
- err("IMSI decoding failed");
- } else {
- /* Update IMSI */
- tcore_sim_set_imsi(co_sim, &file_meta->imsi);
- }
- }
- break;
-
- case TEL_SIM_EF_ICCID:
- dr = tcore_sim_decode_iccid((unsigned char *)res, res_len,
- file_meta->files.data.iccid);
- break;
-
- case TEL_SIM_EF_ELP: /* 2G EF - 2 bytes decoding */
- case TEL_SIM_EF_USIM_LI: /* 3G EF - 2 bytes decoding */
- case TEL_SIM_EF_USIM_PL: /* 3G EF - same as EFELP, so 2 byte decoding */
- case TEL_SIM_EF_LP: /* 1 byte encoding */
- {
- tcore_sim_get_type(co_sim, &card_type);
- if ((TEL_SIM_CARD_TYPE_GSM == card_type)
- && (file_meta->file_id == TEL_SIM_EF_LP)) {
- /*
- * 2G LP(0x6F05) has 1 byte for each language
- */
- dr = tcore_sim_decode_lp((unsigned char *)res, res_len,
- &file_meta->files.data.language);
- } else {
- /*
- * 3G LI(0x6F05)/PL(0x2F05),
- * 2G ELP(0x2F05) has 2 bytes for each language
- */
- dr = tcore_sim_decode_li((unsigned char *)res, res_len,
- file_meta->file_id, &file_meta->files.data.language);
- }
- }
- break;
-
- case TEL_SIM_EF_SPN:
- dr = tcore_sim_decode_spn((unsigned char *)res, res_len,
- &file_meta->files.data.spn);
- break;
-
- case TEL_SIM_EF_SPDI:
- dr = tcore_sim_decode_spdi((unsigned char *)res, res_len,
- &file_meta->files.data.spdi);
- break;
-
- case TEL_SIM_EF_SST: {
- TelSimServiceTable *svct = NULL;
-
- svct = g_try_new0(TelSimServiceTable, 1);
- tcore_sim_get_type(co_sim, &card_type);
- svct->sim_type = card_type;
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- dr = tcore_sim_decode_sst((unsigned char *)res, res_len,
- svct->table.sst_service);
- } else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- dr = tcore_sim_decode_ust((unsigned char *)res, res_len,
- svct->table.ust_service);
- } else {
- err("Not handled card_type[%d]", card_type);
- }
-
- if (dr == FALSE) {
- err("SST/UST decoding failed");
- } else {
- tcore_sim_set_service_table(co_sim, svct);
- }
-
- /* Free memory */
- g_free(svct);
- }
- break;
-
- case TEL_SIM_EF_ECC: {
- tcore_sim_get_type(co_sim, &card_type);
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- dr = tcore_sim_decode_ecc((unsigned char *)res, res_len,
- &file_meta->files.data.ecc);
- } else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- TelSimEcc *ecc = NULL;
-
- ecc = g_try_new0(TelSimEcc, 1);
- dbg("Index [%d]", file_meta->current_index);
-
- dr = tcore_sim_decode_uecc((unsigned char *)res, res_len, ecc);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.ecc.list[file_meta->files.data.ecc.count],
- ecc, sizeof(TelSimEcc));
- file_meta->files.data.ecc.count++;
- }
-
- /* Free memory */
- g_free(ecc);
- } else {
- dbg("Unknown/Unsupported SIM card Type: [%d]", card_type);
- }
- }
- break;
-
- case TEL_SIM_EF_MSISDN: {
- TelSimSubscriberInfo *msisdn = NULL;
-
- dbg("Index [%d]", file_meta->current_index);
- msisdn = g_try_new0(TelSimSubscriberInfo, 1);
- dr = tcore_sim_decode_msisdn((unsigned char *)res, res_len, msisdn);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.msisdn_list.list[file_meta->files.data.msisdn_list.count],
- msisdn, sizeof(TelSimSubscriberInfo));
-
- file_meta->files.data.msisdn_list.count++;
- }
-
- /* Free memory */
- g_free(msisdn);
- }
- break;
-
- case TEL_SIM_EF_OPL: {
- TelSimOpl *opl = NULL;
-
- dbg("decode w/ index [%d]", file_meta->current_index);
- opl = g_try_new0(TelSimOpl, 1);
-
- dr = tcore_sim_decode_opl((unsigned char *)res, res_len, opl);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.opl.list[file_meta->files.data.opl.opl_count],
- opl, sizeof(TelSimOpl));
-
- file_meta->files.data.opl.opl_count++;
- }
-
- /* Free memory */
- g_free(opl);
- }
- break;
-
- case TEL_SIM_EF_PNN: {
- TelSimPnn *pnn = NULL;
-
- dbg("decode w/ index [%d]", file_meta->current_index);
- pnn = g_try_new0(TelSimPnn, 1);
-
- dr = tcore_sim_decode_pnn((unsigned char *)res, res_len, pnn);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.pnn.list[file_meta->files.data.pnn.pnn_count],
- pnn, sizeof(TelSimPnn));
-
- file_meta->files.data.pnn.pnn_count++;
- }
-
- /* Free memory */
- g_free(pnn);
- }
- break;
-
- case TEL_SIM_EF_OPLMN_ACT:
- /*dr = tcore_sim_decode_oplmnwact(&file_meta->files.data.opwa,
- (unsigned char *)res, res_len);*/
- break;
-
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
- /*dr = tcore_sim_decode_csp(&po->p_cphs->csp,
- p_data->response, p_data->response_len);*/
- break;
-
- case TEL_SIM_EF_USIM_MBI: { /* linear type */
- TelSimMbi *mbi = NULL;
-
- mbi = g_try_new0(TelSimMbi, 1);
- dr = tcore_sim_decode_mbi((unsigned char *)res, res_len, mbi);
- if (dr == TRUE) {
- memcpy(&file_meta->mbi_list.list[file_meta->mbi_list.count],
- mbi, sizeof(TelSimMbi));
- file_meta->mbi_list.count++;
-
- dbg("mbi count[%d]", file_meta->mbi_list.count);
- }
-
- /* Free memory */
- g_free(mbi);
- }
- break;
-
- case TEL_SIM_EF_CPHS_MAILBOX_NUMBERS: /* linear type */
- case TEL_SIM_EF_MBDN: /* linear type */
-#if 0 /* Temporarily blocked, MBDN is NOT suported in Emulator */
- dr = tcore_sim_decode_xdn((unsigned char *)res, res_len,
- file_meta->mb_list[file_meta->current_index-1].alpha_id,
- file_meta->mb_list[file_meta->current_index-1].number);
-
- file_meta->mb_list[file_meta->current_index-1].alpha_id_len =
- strlen(file_meta->mb_list[file_meta->current_index-1].alpha_id);
-
- file_meta->mb_list[file_meta->current_index-1].profile_id =
- file_meta->current_index;
-#endif /* Temporarily blocked, MBDN is NOT suported in Emulator */
- break;
-
- case TEL_SIM_EF_CPHS_VOICE_MSG_WAITING: /* transparent type */
- dr = tcore_sim_decode_vmwf((unsigned char *)res, res_len,
- file_meta->files.data.mw.mw);
- break;
-
- case TEL_SIM_EF_USIM_MWIS: { /* linear type */
- TelSimMwis *mw = NULL;
-
- mw = g_try_new0(TelSimMwis, 1);
-
- dr = tcore_sim_decode_mwis((unsigned char *)res, res_len, mw);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.mw.mw[file_meta->files.data.mw.profile_count],
- mw, sizeof(TelSimMwis));
-
- file_meta->files.data.mw.profile_count++;
- }
-
- /* Free memory */
- g_free(mw);
- }
- break;
-
- case TEL_SIM_EF_CPHS_CALL_FORWARD_FLAGS: /* transparent type */
- dr = tcore_sim_decode_cff((unsigned char *)res, res_len,
- file_meta->files.data.mw.mw);
- break;
-
- case TEL_SIM_EF_USIM_CFIS: /* linear type */
- {
- TelSimCfis *cf = NULL;
-
- cf = g_try_new0(TelSimCfis, 1);
- dr = tcore_sim_decode_cfis((unsigned char *)res, res_len, cf);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.cf.cf[file_meta->files.data.cf.profile_count],
- cf, sizeof(TelSimCfis));
-
- file_meta->files.data.cf.profile_count++;
- }
-
- /* Free memory */
- g_free(cf);
- }
- break;
-
- case TEL_SIM_EF_CPHS_SERVICE_STRING_TABLE:
- dbg("not handled - TEL_SIM_EF_CPHS_SERVICE_STRING_TABLE ");
- break;
-
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_STRING:
- dr = tcore_sim_decode_ons((unsigned char *)res, res_len,
- (unsigned char*)&file_meta->files.data.cphs_net.full_name);
- dbg("file_meta->files.result: [%d] " \
- "file_meta->files.data.cphs_net.full_name[%s]",
- file_meta->files.result,
- file_meta->files.data.cphs_net.full_name);
- break;
-
- case TEL_SIM_EF_CPHS_DYNAMICFLAGS:
- /*dr = tcore_sim_decode_dynamic_flag(&po->p_cphs->dflagsinfo,
- p_data->response, p_data->response_len);*/
- break;
-
- case TEL_SIM_EF_CPHS_DYNAMIC2FLAG:
- /*dr = tcore_sim_decode_dynamic2_flag(&po->p_cphs->d2flagsinfo,
- p_data->response, p_data->response_len);*/
- break;
-
- case TEL_SIM_EF_CPHS_CPHS_INFO:
- /*dr = tcore_sim_decode_cphs_info(&file_meta->files.data.cphs,
- (unsigned char *)res, res_len);*/
- break;
-
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
- dr = tcore_sim_decode_short_ons((unsigned char *)res, res_len,
- (unsigned char*)&file_meta->files.data.cphs_net.short_name);
-
- dbg("file_meta->files.result[%d] "\
- "file_meta->files.data.cphs_net.short_name[%s]",
- file_meta->files.result,
- file_meta->files.data.cphs_net.short_name);
- break;
-
- case TEL_SIM_EF_CPHS_INFORMATION_NUMBERS:
- /*dr = tcore_sim_decode_information_number(&po->p_cphs->infn,
- p_data->response, p_data->response_len);*/
- break;
-
- default:
- dbg("File Decoding Failed - not handled File[0x%x]",
- file_meta->file_id);
- dr = 0;
- break;
- }
- } else {
- sim_result = __atmodem_sim_decode_status_word(sw1, sw2);
- file_meta->files.result = sim_result;
- }
-
- /* Free memory */
- g_free(tmp);
- g_free(res);
-
- /* Free tokens */
- tcore_at_tok_free(tokens);
- } else {
- dbg("RESPONSE NOK");
- dbg("Error - File ID: [0x%x]", file_meta->file_id);
- sim_result = TEL_SIM_RESULT_FAILURE;
- }
-
- /* Get File data */
- __atmodem_sim_next_from_get_file_data(tcore_pending_ref_core_object(p),
- resp_cb_data, sim_result, dr);
-
- dbg("Exit");
-}
-
-static void __on_response_atmodem_sim_get_file_info(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *resp = data;
- CoreObject *co_sim = NULL;
- TelSimResult sim_result;
- GSList *tokens = NULL;
- const char *line = NULL;
- int sw1 = 0;
- int sw2 = 0;
- AtmodemRespCbData *resp_cb_data = (AtmodemRespCbData *)user_data;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- dbg("SIM Response - SIM File info: [+CRSM]");
-
- co_sim = tcore_pending_ref_core_object(p);
-
- if (resp->success > 0) {
- dbg("RESPONSE OK");
- if (resp->lines) {
- line = (const char *)resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) < 2) {
- err("Invalid message");
- tcore_at_tok_free(tokens);
- return;
- }
- }
- sw1 = atoi(g_slist_nth_data(tokens, 0));
- sw2 = atoi(g_slist_nth_data(tokens, 1));
-
- /*1. SIM access success case*/
- if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
- unsigned char tag_len = 0;
- unsigned short record_len = 0;
- char num_of_records = 0;
- unsigned char file_id_len = 0;
- unsigned short file_id = 0;
- unsigned short file_size = 0;
- unsigned short file_type = 0;
- unsigned short arr_file_id = 0;
- int arr_file_id_rec_num = 0;
- guint buf_len = 0;
- TelSimCardType card_type = TEL_SIM_CARD_TYPE_UNKNOWN;
-
- /* handling only last 3 bits */
- unsigned char file_type_tag = 0x07;
- unsigned char *ptr_data;
-
- char *hexData;
- char *tmp;
- char *record_data = NULL;
- hexData = g_slist_nth_data(tokens, 2);
- dbg("hexData: %s", hexData);
- dbg("hexData: %s", hexData + 1);
-
- tmp = tcore_at_tok_extract(hexData);
- tcore_util_hexstring_to_bytes(tmp, &record_data, &buf_len); /*TODO : Check*/
- tcore_util_hex_dump(" ", buf_len, record_data);
- g_free(tmp);
-
- ptr_data = (unsigned char *)record_data;
- tcore_sim_get_type(co_sim, &card_type);
- if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- /*
- ETSI TS 102 221 v7.9.0
- - Response Data
- '62' FCP template tag
- - Response for an EF
- '82' M File Descriptor
- '83' M File Identifier
- 'A5' O Proprietary information
- '8A' M Life Cycle Status Integer
- '8B', '8C' or 'AB' C1 Security attributes
- '80' M File size
- '81' O Total file size
- '88' O Short File Identifier (SFI)
- */
-
- /* rsim.res_len has complete data length received */
-
- /* FCP template tag - File Control Parameters tag*/
- if (*ptr_data == 0x62) {
- /* parse complete FCP tag*/
- /* increment to next byte */
- ptr_data++;
- tag_len = *ptr_data++;
- dbg("tag_len: %02x", tag_len);
- /* FCP file descriptor - file type, accessibility, DF, ADF etc*/
- if (*ptr_data == 0x82) {
- /* increment to next byte */
- ptr_data++;
- /* 2 or 5 value*/
- ptr_data++;
- /* consider only last 3 bits*/
- dbg("file_type_tag: %02x", file_type_tag);
- file_type_tag = file_type_tag & (*ptr_data);
- dbg("file_type_tag: %02x", file_type_tag);
-
- switch (file_type_tag) {
- /* increment to next byte */
- // ptr_data++;
- case 0x1:
- dbg("Getting FileType: [Transparent file type]");
- file_type = ATMODEM_SIM_FILE_TYPE_TRANSPARENT;
-
- /* increment to next byte */
- ptr_data++;
- /* increment to next byte */
- ptr_data++;
- break;
-
- case 0x2:
- dbg("Getting FileType: [Linear fixed file type]");
- /* increment to next byte */
- ptr_data++;
- /* data coding byte - value 21 */
- ptr_data++;
- /* 2bytes */
- memcpy(&record_len, ptr_data, 2);
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(record_len);
- ptr_data = ptr_data + 2;
- num_of_records = *ptr_data++;
- /* Data lossy conversation from enum (int) to unsigned char */
- file_type = ATMODEM_SIM_FILE_TYPE_LINEAR_FIXED;
- break;
-
- case 0x6:
- dbg("Cyclic fixed file type");
- /* increment to next byte */
- ptr_data++;
- /* data coding byte - value 21 */
- ptr_data++;
- /* 2bytes */
- memcpy(&record_len, ptr_data, 2);
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(record_len);
- ptr_data = ptr_data + 2;
- num_of_records = *ptr_data++;
- file_type = ATMODEM_SIM_FILE_TYPE_CYCLIC;
- break;
-
- default:
- dbg("not handled file type [0x%x]", *ptr_data);
- break;
- }
- } else {
- dbg("INVALID FCP received - DEbug!");
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
-
- /*File identifier - 0x84,0x85,0x86 etc are currently ignored and not handled */
- if (*ptr_data == 0x83) {
- /* increment to next byte */
- ptr_data++;
- file_id_len = *ptr_data++;
- dbg("file_id_len: %02x", file_id_len);
-
- memcpy(&file_id, ptr_data, file_id_len);
- dbg("file_id: %x", file_id);
-
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(file_id);
- dbg("file_id: %x", file_id);
-
- ptr_data = ptr_data + 2;
- dbg("Getting FileID=[0x%x]", file_id);
- } else {
- dbg("INVALID FCP received - DEbug!");
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
-
- /* proprietary information */
- if (*ptr_data == 0xA5) {
- unsigned short prop_len;
- /* increment to next byte */
- ptr_data++;
-
- /* length */
- prop_len = *ptr_data;
- dbg("prop_len: %02x", prop_len);
-
- /* skip data */
- ptr_data = ptr_data + prop_len + 1;
- } else {
- dbg("INVALID FCP received - DEbug!");
- }
-
- /* life cycle status integer [8A][length:0x01][status]*/
- /*
- status info b8~b1
- 00000000 : No information given
- 00000001 : creation state
- 00000011 : initialization state
- 000001-1 : operation state -activated
- 000001-0 : operation state -deactivated
- 000011-- : Termination state
- b8~b5 !=0, b4~b1=X : Proprietary
- Any other value : RFU
- */
- if (*ptr_data == 0x8A) {
- /* increment to next byte */
- ptr_data++;
- /* length - value 1 */
- ptr_data++;
-
- switch (*ptr_data) {
- case 0x04:
- case 0x06:
- dbg("<RX> operation state -deactivated");
- ptr_data++;
- break;
-
- case 0x05:
- case 0x07:
- dbg("<RX> operation state -activated");
- ptr_data++;
- break;
-
- default:
- dbg("<RX> DEBUG! LIFE CYCLE STATUS =[0x%x]", *ptr_data);
- ptr_data++;
- break;
- }
- }
-
- /* related to security attributes : currently not handled*/
- if (*ptr_data == 0x86 || *ptr_data == 0x8B || *ptr_data == 0x8C || *ptr_data == 0xAB) {
- /* increment to next byte */
- ptr_data++;
- /* if tag length is 3 */
- if (*ptr_data == 0x03) {
- /* increment to next byte */
- ptr_data++;
- /* EFARR file id */
- memcpy(&arr_file_id, ptr_data, 2);
- /* swap byes */
- ATMODEM_SWAP_BYTES_16(arr_file_id);
- ptr_data = ptr_data + 2;
- arr_file_id_rec_num = *ptr_data++;
- dbg("arr_file_id_rec_num:[%d]", arr_file_id_rec_num);
- } else {
- /* if tag length is not 3 */
- /* ignoring bytes */
- // ptr_data = ptr_data + 4;
- dbg("Useless security attributes, so jump to next tag");
- ptr_data = ptr_data + (*ptr_data + 1);
- }
- } else {
- dbg("INVALID FCP received[0x%x] - DEbug!", *ptr_data);
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
-
- dbg("Current ptr_data value is [%x]", *ptr_data);
-
- /* file size excluding structural info*/
- if (*ptr_data == 0x80) {
- /* for EF file size is body of file and for Linear or cyclic it is
- * number of recXsizeof(one record)
- */
- /* increment to next byte */
- ptr_data++;
- /* length is 1 byte - value is 2 bytes or more */
- ptr_data++;
- memcpy(&file_size, ptr_data, 2);
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(file_size);
- ptr_data = ptr_data + 2;
- } else {
- dbg("INVALID FCP received - DEbug!");
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
-
- /* total file size including structural info*/
- if (*ptr_data == 0x81) {
- int len;
- /* increment to next byte */
- ptr_data++;
- /* length */
- len = *ptr_data;
- dbg("len:[%d]", len);
- /* ignored bytes */
- ptr_data = ptr_data + 3;
- } else {
- dbg("INVALID FCP received - DEbug!");
- /* 0x81 is optional tag?? check out! so do not return -1 from here! */
- }
- /*short file identifier ignored*/
- if (*ptr_data == 0x88) {
- dbg("0x88: Do Nothing");
- /*DO NOTHING*/
- }
- } else {
- dbg("INVALID FCP received - DEbug!");
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
- } else if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- unsigned char gsm_specific_file_data_len = 0;
- /* ignore RFU byte1 and byte2 */
- ptr_data++;
- ptr_data++;
- /* file size */
- // file_size = p_info->response_len;
- memcpy(&file_size, ptr_data, 2);
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(file_size);
- /* parsed file size */
- ptr_data = ptr_data + 2;
- /* file id */
- memcpy(&file_id, ptr_data, 2);
- ATMODEM_SWAP_BYTES_16(file_id);
- dbg("FILE id --> [%x]", file_id);
- ptr_data = ptr_data + 2;
- /* save file type - transparent, linear fixed or cyclic */
- file_type_tag = (*(ptr_data + 7));
-
- switch (*ptr_data) {
- case 0x0:
- /* RFU file type */
- dbg("RFU file type- not handled - Debug!");
- break;
-
- case 0x1:
- /* MF file type */
- dbg("MF file type - not handled - Debug!");
- break;
-
- case 0x2:
- /* DF file type */
- dbg("DF file type - not handled - Debug!");
- break;
-
- case 0x4:
- /* EF file type */
- dbg("EF file type [%d] ", file_type_tag);
- /* increment to next byte */
- ptr_data++;
-
- if (file_type_tag == 0x00 || file_type_tag == 0x01) {
- /* increament to next byte as this byte is RFU */
- ptr_data++;
- file_type =
- (file_type_tag == 0x00) ? ATMODEM_SIM_FILE_TYPE_TRANSPARENT : ATMODEM_SIM_FILE_TYPE_LINEAR_FIXED;
- } else {
- /* increment to next byte */
- ptr_data++;
- /* For a cyclic EF all bits except bit 7 are RFU; b7=1 indicates that */
- /* the INCREASE command is allowed on the selected cyclic file. */
- file_type = ATMODEM_SIM_FILE_TYPE_CYCLIC;
- }
- /* bytes 9 to 11 give SIM file access conditions */
- ptr_data++;
- /* byte 10 has one nibble that is RF U and another for INCREASE which is not used currently */
- ptr_data++;
- /* byte 11 is invalidate and rehabilate nibbles */
- ptr_data++;
- /* byte 12 - file status */
- ptr_data++;
- /* byte 13 - GSM specific data */
- gsm_specific_file_data_len = *ptr_data;
- dbg("gsm_specific_file_data_len:[%d]", gsm_specific_file_data_len);
- ptr_data++;
- /* byte 14 - structure of EF - transparent or linear or cyclic , already saved above */
- ptr_data++;
- /* byte 15 - length of record for linear and cyclic , for transparent it is set to 0x00. */
- record_len = *ptr_data;
- dbg("record length[%d], file size[%d]", record_len, file_size);
- if (record_len != 0)
- num_of_records = (file_size / record_len);
-
- dbg("Number of records [%d]", num_of_records);
- break;
-
- default:
- dbg("not handled file type");
- break;
- }
- } else {
- err("Unknown Card Type - [%d]", card_type);
- }
-
- dbg("req ef[0x%x] resp ef[0x%x] size[%ld] Type[0x%x] NumOfRecords[%ld] RecordLen[%ld]",
- file_meta->file_id, file_id, file_size, file_type, num_of_records, record_len);
-
- file_meta->file_type = file_type;
- file_meta->data_size = file_size;
- file_meta->rec_length = record_len;
- file_meta->rec_count = num_of_records;
- file_meta->current_index = 0; /* reset for new record type EF */
- sim_result = TEL_SIM_RESULT_SUCCESS;
- g_free(record_data);
- } else {
- /*2. SIM access fail case*/
- err("Failed to get ef[0x%x] (file_meta->file_id) ", file_meta->file_id);
- sim_result = __atmodem_sim_decode_status_word(sw1, sw2);
- }
-
- tcore_at_tok_free(tokens);
- } else {
- err("RESPONSE NOK");
- err("Failed to get ef[0x%x] (file_meta->file_id) ", file_meta->file_id);
- sim_result = TEL_SIM_RESULT_FAILURE;
- }
- dbg("Calling __atmodem_sim_next_from_get_file_info");
- __atmodem_sim_next_from_get_file_info(co_sim, resp_cb_data, sim_result);
- dbg("Exit");
-}
-
-static void __atmodem_sim_get_file_record(CoreObject *co_sim, AtmodemRespCbData *resp_cb_data)
-{
- gchar *at_cmd = NULL;
- int p1 = 0;
- int p2 = 0;
- int p3 = 0;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelReturn ret = TEL_RETURN_FAILURE;
-
- dbg("Entry File-id:[0x%02x]", file_meta->file_id);
-
- /* According to TS 102 221, values of p1, p2, p3 can be as below:
- * 11.1.5 READ RECORD
- * P1: Record number
- * P2: Mode, see table 11.11
- * Lc: Not present
- * Data: Not present
- * Le: Number of bytes to be read (P3)
- */
-
- p1 = (unsigned char) file_meta->current_index;
- p2 = (unsigned char) 0x04; /* 0x4 for absolute mode */
- p3 = (unsigned char) file_meta->rec_length;
-
- at_cmd = g_strdup_printf("AT+CRSM=%d, %d",
- ATMODEM_SIM_ACCESS_READ_RECORD, file_meta->file_id);
-
- ret = tcore_at_prepare_and_send_request(co_sim,
- at_cmd, "+CRSM:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_atmodem_sim_get_file_data, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get File Record");
-
- dbg("ret:[%d]", ret);
- g_free(at_cmd);
-
- dbg("Exit");
-}
-
-static void __atmodem_sim_get_file_data(CoreObject *co_sim,
- AtmodemRespCbData *resp_cb_data)
-{
- gchar *at_cmd = NULL;
- int p1 = 0;
- int p2 = 0;
- int p3 = 0;
- int offset = 0;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelReturn ret = TEL_RETURN_FAILURE;
-
- dbg("Entry File-id:[0x%02x]", file_meta->file_id);
-
- /*
- * According to TS 102 221, values of P1, P2, P3 can be as below:
- * 11.1.3 READ BINARY
- * P1: See table 11.10
- * P2: Offset low
- * Lc: Not present
- * Data: Not present
- * Le: Number of bytes to be read (P3)
- */
-
- p1 = (unsigned char) (offset & 0xFF00) >> 8;
- p2 = (unsigned char) offset & 0x00FF; /* offset low */
- p3 = (unsigned char) file_meta->data_size;
-
- if (file_meta->file_id == TEL_SIM_EF_IMSI
- || file_meta->file_id == TEL_SIM_EF_SPN
- || file_meta->file_id == TEL_SIM_EF_LP)
- at_cmd = g_strdup_printf("AT+CRSM=%d, %d ",
- ATMODEM_SIM_ACCESS_READ_BINARY, file_meta->file_id);
- else
- at_cmd = g_strdup_printf("AT+CRSM=%d, %d, %d, %d, %d",
- ATMODEM_SIM_ACCESS_READ_BINARY, file_meta->file_id, p1, p2, p3);
-
- ret = tcore_at_prepare_and_send_request(co_sim,
- at_cmd, "+CRSM:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_atmodem_sim_get_file_data, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get File Data");
-
- dbg("ret:[%d]", ret);
- g_free(at_cmd);
-
- dbg("Exit");
-}
-
-static TelReturn __atmodem_sim_get_file_info(CoreObject *co_sim,
- AtmodemRespCbData *resp_cb_data)
-{
- gchar *at_cmd = NULL;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelReturn ret = TEL_RETURN_FAILURE;
-
- dbg("Entry File-id:[0x%02x]", file_meta->file_id);
-
- at_cmd = g_strdup_printf("AT+CRSM=%d, %d",
- ATMODEM_SIM_ACCESS_GET_RESPONSE, file_meta->file_id);
-
- ret = tcore_at_prepare_and_send_request(co_sim,
- at_cmd, "+CRSM:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_atmodem_sim_get_file_info, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get File Info");
-
- g_free(at_cmd);
- dbg("Exit");
- return ret;
-}
-
-static char *__atmodem_sim_get_fac_from_lock_type(TelSimLockType lock_type,
- AtmodemSimCurrSecOp *sec_op, int flag)
-{
- char *fac = NULL;
- switch(lock_type) {
- case TEL_SIM_LOCK_PS:
- fac = "PS";
- if (flag == ENABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_SIM_ENABLE;
- else if (flag == DISABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_SIM_DISABLE;
- else
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_SIM_STATUS;
- break;
-
- case TEL_SIM_LOCK_SC:
- fac = "SC";
- if (flag == ENABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_PIN1_ENABLE;
- else if (flag == DISABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_PIN1_DISABLE;
- else
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_PIN1_STATUS;
- break;
-
- case TEL_SIM_LOCK_FD:
- fac = "FD";
- if (flag == ENABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_FDN_ENABLE;
- else if (flag == DISABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_FDN_DISABLE;
- else
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_FDN_STATUS;
- break;
-
- case TEL_SIM_LOCK_PN:
- fac = "PN";
- if (flag == ENABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_NET_ENABLE;
- else if (flag == DISABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_NET_DISABLE;
- else
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_NET_STATUS;
- break;
-
- case TEL_SIM_LOCK_PU:
- fac = "PU";
- if (flag == ENABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_NS_ENABLE;
- else if (flag == DISABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_NS_DISABLE;
- else
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_NS_STATUS;
- break;
-
- case TEL_SIM_LOCK_PP:
- fac = "PP";
- if (flag == ENABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_SP_ENABLE;
- else if (flag == DISABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_SP_DISABLE;
- else
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_SP_STATUS;
- break;
-
- case TEL_SIM_LOCK_PC:
- fac = "PC";
- if (flag == ENABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_CP_ENABLE;
- else if (flag == DISABLE_FLAG)
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_CP_DISABLE;
- else
- *sec_op = ATMODEM_SIM_CURR_SEC_OP_CP_STATUS;
- break;
-
- default:
- err("Unhandled sim lock type [%d]", lock_type);
- }
-
- return fac;
-}
-
-static void __atmodem_sim_next_from_read_binary(CoreObject *co,
- AtmodemRespCbData *resp_cb_data, TelSimResult sim_result, gboolean decode_ret)
-{
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelSimCardType card_type = TEL_SIM_CARD_TYPE_UNKNOWN;
-
- dbg("Entry");
-
- dbg("[SIM]EF[0x%x] read sim_result[%d] Decode rt[%d]",
- file_meta->file_id, sim_result, decode_ret);
- switch (file_meta->file_id) {
- case TEL_SIM_EF_ELP:
- case TEL_SIM_EF_USIM_PL:
- case TEL_SIM_EF_LP:
- case TEL_SIM_EF_USIM_LI:
- if (decode_ret == TRUE) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- tcore_sim_get_type(co, &card_type);
- /* 2G */
- /* The ME requests the Extended Language Preference.
- * The ME only requests the Language Preference (EFLP)
- * if at least one of the following conditions holds:
- * - EFELP is not available;
- * - EFELP does not contain an entry corresponding to
- * a language specified in ISO 639[30];
- * - the ME does not support any of the languages in EFELP.
- */
- /* 3G */
- /*
- * The ME only requests the Language Preference (EFPL)
- * if at least one of the following conditions holds:
- * - if the EFLI has the value 'FFFF' in its highest
- * priority position
- * - if the ME does not support any of the language
- * codes indicated in EFLI , or if EFLI is not present
- */
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- if (file_meta->file_id == TEL_SIM_EF_LP) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->file_id = TEL_SIM_EF_LP;
- __atmodem_sim_get_response(co, resp_cb_data);
- }
- } else if (TEL_SIM_CARD_TYPE_USIM) {
- if (file_meta->file_id == TEL_SIM_EF_LP
- || file_meta->file_id == TEL_SIM_EF_USIM_LI) {
- file_meta->file_id = TEL_SIM_EF_ELP;
- __atmodem_sim_get_response(co, resp_cb_data);
- } else {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- }
- }
- }
- break;
-
- case TEL_SIM_EF_ECC:
- tcore_sim_get_type(co, &card_type);
- if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_read_record(co, resp_cb_data);
- }
- } else if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- dbg("[SIM DATA]Invalid CardType[%d] Unable to handle", card_type);
- }
- break;
-
- case TEL_SIM_EF_IMSI:
- __atmodem_sim_update_sim_status(co, TEL_SIM_STATUS_SIM_INIT_COMPLETED);
- break;
-
- case TEL_SIM_EF_MSISDN:
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_read_record(co, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_OPL:
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_read_record(co, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_PNN:
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_read_record(co, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_USIM_CFIS:
- case TEL_SIM_EF_USIM_MWIS:
- case TEL_SIM_EF_USIM_MBI:
- case TEL_SIM_EF_MBDN:
- case TEL_SIM_EF_CPHS_MAILBOX_NUMBERS:
- case TEL_SIM_EF_CPHS_INFORMATION_NUMBERS:
- if (file_meta->current_index == file_meta->rec_count) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- } else {
- file_meta->current_index++;
- __atmodem_sim_read_record(co, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_STRING:
- {
- file_meta->files.result = sim_result;
- if (decode_ret == TRUE && sim_result == TEL_SIM_RESULT_SUCCESS) {
- memcpy(file_meta->files.data.cphs_net.full_name,
- file_meta->files.data.cphs_net.full_name,
- strlen((char *)file_meta->files.data.cphs_net.full_name));
- }
-
- file_meta->file_id = TEL_SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING;
- file_meta->file_result = TEL_SIM_RESULT_FAILURE;
- __atmodem_sim_get_response(co, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
- if (file_meta->files.result == TEL_SIM_RESULT_SUCCESS) {
- file_meta->files.result = TEL_SIM_RESULT_SUCCESS;
- }
- if (strlen((char *)file_meta->files.data.cphs_net.full_name)) {
- memcpy(&file_meta->files.data.cphs_net.full_name,
- &file_meta->files.data.cphs_net.full_name,
- strlen((char *)file_meta->files.data.cphs_net.full_name));
- }
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- break;
-
- case TEL_SIM_EF_ICCID:
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data.iccid, resp_cb_data->cb_data);
- break;
-
- case TEL_SIM_EF_SST:
- case TEL_SIM_EF_SPN:
- case TEL_SIM_EF_SPDI:
- case TEL_SIM_EF_OPLMN_ACT:
- case TEL_SIM_EF_CPHS_CPHS_INFO:
- case TEL_SIM_EF_CPHS_CALL_FORWARD_FLAGS:
- case TEL_SIM_EF_CPHS_VOICE_MSG_WAITING:
- case TEL_SIM_EF_CPHS_DYNAMICFLAGS:
- case TEL_SIM_EF_CPHS_DYNAMIC2FLAG:
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE_LINE2:
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- break;
-
- default:
- err("File id not handled [0x%x]", file_meta->file_id);
- break;
- }
-}
-
-static void __atmodem_sim_next_from_get_response(CoreObject *co,
- AtmodemRespCbData *resp_cb_data, TelSimResult sim_result)
-{
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelSimCardType card_type = TEL_SIM_CARD_TYPE_UNKNOWN;
-
- dbg("EF[0x%x] access Result[%d]", file_meta->file_id, sim_result);
-
- file_meta->files.result = sim_result;
- memset(&file_meta->files.data, 0x00, sizeof(file_meta->files.data));
-
- if ((file_meta->file_id != TEL_SIM_EF_ELP
- && file_meta->file_id != TEL_SIM_EF_LP
- && file_meta->file_id != TEL_SIM_EF_USIM_PL
- && file_meta->file_id != TEL_SIM_EF_CPHS_CPHS_INFO)
- && (sim_result != TEL_SIM_RESULT_SUCCESS)) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
-
- return;
- }
-
- switch (file_meta->file_id) {
- case TEL_SIM_EF_ELP: {
- if (sim_result == TEL_SIM_RESULT_SUCCESS) {
- dbg("[SIM DATA] exist EFELP/PL(0x2F05)");
- __atmodem_sim_read_binary(co, resp_cb_data);
- } else {
- tcore_sim_get_type(co, &card_type);
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- AtmodemSimMetaInfo file_meta_new = {0,};
-
- dbg("[SIM DATA]SIM_EF_ELP(2F05) access fail. Request SIM_EF_LP(0x6F05) info");
- /* The ME requests the Language Preference (EFLP) if EFELP is not available */
- file_meta_new.file_id = TEL_SIM_EF_LP;
- file_meta_new.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta_new.req_command = TCORE_COMMAND_SIM_GET_LANGUAGE;
-
- memcpy(resp_cb_data->data, &file_meta_new, sizeof(AtmodemSimMetaInfo));
-
- __atmodem_sim_get_response(co, resp_cb_data);
- } else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- dbg(" [SIM DATA]fail to get Language information "\
- "in USIM(EF-LI(6F05),EF-PL(2F05))");
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- return;
- }
- }
- }
- break;
-
- case TEL_SIM_EF_LP: {
- if (sim_result == TEL_SIM_RESULT_SUCCESS) {
- dbg("[SIM DATA] exist EFLP/LI(0x6F05)");
- __atmodem_sim_read_binary(co, resp_cb_data);
- } else {
- tcore_sim_get_type(co, &card_type);
- dbg("[SIM DATA]SIM_EF_LP/LI(6F05) access fail. Current CardType[%d]", card_type);
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- return;
- }
- /*
- * If EFLI is not present, then the language selection
- * shall be as defined in EFPL at the MF level
- */
- else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- AtmodemSimMetaInfo file_meta_new = {0,};
-
- dbg("[SIM DATA] try USIM EFPL(0x2F05)");
- file_meta_new.file_id = TEL_SIM_EF_ELP;
- file_meta_new.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta_new.req_command = TCORE_COMMAND_SIM_GET_LANGUAGE;
-
- memcpy(resp_cb_data->data, &file_meta_new, sizeof(AtmodemSimMetaInfo));
-
- __atmodem_sim_get_response(co, resp_cb_data);
- }
- }
- }
- break;
-
- case TEL_SIM_EF_USIM_PL: {
- if (sim_result == TEL_SIM_RESULT_SUCCESS) {
- dbg("[SIM DATA] exist EFELP/PL(0x2F05)");
- __atmodem_sim_read_binary(co, resp_cb_data);
- } else {
- /*
- * EFELIand EFPL not present, so set language count
- * as zero and select ECC
- */
- dbg("[SIM DATA]SIM_EF_USIM_PL(2A05) access fail. "\
- "Request SIM_EF_ECC(0x6FB7) info");
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
-
- return;
- }
- }
- break;
-
- case TEL_SIM_EF_ECC: {
- tcore_sim_get_type(co, &card_type);
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- __atmodem_sim_read_binary(co, resp_cb_data);
- } else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- if (file_meta->rec_count > TEL_SIM_ECC_LIST_MAX)
- file_meta->rec_count = TEL_SIM_ECC_LIST_MAX;
-
- file_meta->current_index++;
- __atmodem_sim_read_record(co, resp_cb_data);
- }
- }
- break;
-
- case TEL_SIM_EF_ICCID:
- case TEL_SIM_EF_IMSI:
- case TEL_SIM_EF_SST:
- case TEL_SIM_EF_SPN:
- case TEL_SIM_EF_SPDI:
- case TEL_SIM_EF_CPHS_CALL_FORWARD_FLAGS:
- case TEL_SIM_EF_CPHS_VOICE_MSG_WAITING:
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_STRING:
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
- case TEL_SIM_EF_CPHS_DYNAMICFLAGS:
- case TEL_SIM_EF_CPHS_DYNAMIC2FLAG:
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE_LINE2:
- __atmodem_sim_read_binary(co, resp_cb_data);
- break;
-
- case TEL_SIM_EF_CPHS_CPHS_INFO: {
- if (sim_result == TEL_SIM_RESULT_SUCCESS) {
- tcore_sim_set_cphs_status(co, TRUE);
- __atmodem_sim_update_sim_status(co, TEL_SIM_STATUS_SIM_INIT_COMPLETED);
-
- __atmodem_sim_read_binary(co, resp_cb_data);
- } else {
- tcore_sim_set_cphs_status(co, FALSE);
- __atmodem_sim_update_sim_status(co, TEL_SIM_STATUS_SIM_INIT_COMPLETED);
-
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)sim_result,
- &file_meta->files.data, resp_cb_data->cb_data);
- }
- }
- break;
-
-
- case TEL_SIM_EF_USIM_CFIS: {
- if (file_meta->rec_count > TEL_SIM_CALL_FORWARDING_TYPE_MAX)
- file_meta->rec_count = TEL_SIM_CALL_FORWARDING_TYPE_MAX;
-
- file_meta->current_index++;
- __atmodem_sim_read_record(co, resp_cb_data);
- }
- break;
-
- case TEL_SIM_EF_OPL:
- case TEL_SIM_EF_PNN:
- case TEL_SIM_EF_USIM_MWIS:
- case TEL_SIM_EF_USIM_MBI:
- case TEL_SIM_EF_MBDN:
- case TEL_SIM_EF_CPHS_MAILBOX_NUMBERS:
- case TEL_SIM_EF_CPHS_INFORMATION_NUMBERS:
- case TEL_SIM_EF_MSISDN:
- file_meta->current_index++;
- __atmodem_sim_read_record(co, resp_cb_data);
- break;
-
- case TEL_SIM_EF_SMSP: {
- AtmodemSimPrivateInfo *priv_info = NULL;
-
- priv_info = tcore_sim_ref_userdata(co);
-
- dbg("SMSP info set to tcore : count:[%d], rec_len:[%d]",
- file_meta->rec_count, file_meta->rec_length);
- priv_info->smsp_count = file_meta->rec_count;
- priv_info->smsp_rec_len = file_meta->rec_length;
- }
- break;
-
- default:
- dbg("error - File id for get file info [0x%x]", file_meta->file_id);
- break;
- }
- return;
-}
-
-#if 0 //blocking for the moment
-static void __on_response_atmodem_sim_update_file(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *resp = data;
- CoreObject *co_sim = NULL;
- GSList *tokens = NULL;
- TelSimResult sim_result = TEL_SIM_RESULT_CARD_ERROR;
- const char *line;
- AtmodemRespCbData *resp_cb_data = (AtmodemRespCbData *)user_data;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- dbg("Entry");
-
- co_sim = tcore_pending_ref_core_object(p);
-
- dbg("file_id:[0x%x]", file_meta->file_id);
-
- if (resp->success > 0) {
- int sw1 = 0;
- int sw2 = 0;
- dbg("RESPONSE OK");
- if (resp->lines) {
- line = (const char *)resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) != 2) {
- err("Invalid message");
- goto out;
- }
- sw1 = atoi(g_slist_nth_data(tokens, 0));
- sw2 = atoi(g_slist_nth_data(tokens, 1));
- }
-
- if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
- sim_result = TEL_SIM_RESULT_SUCCESS;
- } else {
- sim_result = __atmodem_sim_decode_status_word(sw1, sw2);
- }
- } else {
- err("RESPONSE NOK");
- sim_result = TEL_SIM_RESULT_FAILURE;
- }
-out:
- /* Send Response */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)sim_result,
- NULL, resp_cb_data->cb_data);
-
- tcore_at_tok_free(tokens);
- dbg("Exit");
-}
-#endif
-
-static void __on_response_atmodem_sim_read_data(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *resp = data;
- CoreObject *co = NULL;
- GSList *tokens = NULL;
- TelSimResult sim_result;
- gboolean dr = FALSE;
- const char *line = NULL;
- char *res = NULL;
- char *tmp = NULL;
- guint res_len;
- int sw1 = 0;
- int sw2 = 0;
- TelSimCardType card_type = TEL_SIM_CARD_TYPE_UNKNOWN;
- AtmodemRespCbData *resp_cb_data = (AtmodemRespCbData *) user_data;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- dbg("Entry");
-
- co = tcore_pending_ref_core_object(p);
-
- if (resp->success > 0) {
- dbg("RESPONSE OK");
- if (resp->lines) {
- line = (const char *)resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) < 2) {
- err("Invalid message");
- tcore_at_tok_free(tokens);
- return;
- }
- }
- sw1 = atoi(g_slist_nth_data(tokens, 0));
- sw2 = atoi(g_slist_nth_data(tokens, 1));
- res = g_slist_nth_data(tokens, 2);
-
- tmp = tcore_at_tok_extract(res);
- tcore_util_hexstring_to_bytes(tmp, &res, &res_len);
- dbg("Response: [%s] Response length: [%d]", res, res_len);
-
- if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
- sim_result = TEL_SIM_RESULT_SUCCESS;
- file_meta->files.result = sim_result;
-
- dbg("File ID: [0x%x]", file_meta->file_id);
- switch (file_meta->file_id) {
- case TEL_SIM_EF_IMSI: {
- dbg("Data: [%s]", res);
- dr = tcore_sim_decode_imsi((unsigned char *)res,
- res_len, &file_meta->imsi);
- if (dr == FALSE) {
- err("IMSI decoding failed");
- } else {
- __atmodem_sim_set_identity(co, &file_meta->imsi);
-
- /* Update IMSI */
- tcore_sim_set_imsi(co, &file_meta->imsi);
- }
- }
- break;
-
- case TEL_SIM_EF_ICCID: {
- dr = tcore_sim_decode_iccid((unsigned char *)res, res_len,
- file_meta->files.data.iccid);
- }
- break;
-
- case TEL_SIM_EF_ELP: /* 2G EF - 2 bytes decoding */
- case TEL_SIM_EF_USIM_LI: /* 3G EF - 2 bytes decoding */
- case TEL_SIM_EF_USIM_PL: /* 3G EF - same as EFELP, so 2 byte decoding */
- case TEL_SIM_EF_LP: /* 1 byte encoding */
- {
- tcore_sim_get_type(co, &card_type);
- if ((TEL_SIM_CARD_TYPE_GSM == card_type)
- && (file_meta->file_id == TEL_SIM_EF_LP)) {
- /*
- * 2G LP(0x6F05) has 1 byte for each language
- */
- dr = tcore_sim_decode_lp((unsigned char *)res,
- res_len, &file_meta->files.data.language);
- } else {
- /*
- * 3G LI(0x6F05)/PL(0x2F05),
- * 2G ELP(0x2F05) has 2 bytes for each language
- */
- dr = tcore_sim_decode_li((unsigned char *)res, res_len,
- file_meta->file_id, &file_meta->files.data.language);
- }
- }
- break;
-
- case TEL_SIM_EF_SPN:
- dr = tcore_sim_decode_spn((unsigned char *)res,
- res_len, &file_meta->files.data.spn);
- break;
-
- case TEL_SIM_EF_SPDI:
- dr = tcore_sim_decode_spdi((unsigned char *)res,
- res_len, &file_meta->files.data.spdi);
- break;
-
- case TEL_SIM_EF_SST: {
- TelSimServiceTable *svct = NULL;
-
- svct = g_try_new0(TelSimServiceTable, 1);
- tcore_sim_get_type(co, &card_type);
- svct->sim_type = card_type;
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- dr = tcore_sim_decode_sst((unsigned char *)res,
- res_len, svct->table.sst_service);
- } else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- dr = tcore_sim_decode_ust((unsigned char *)res,
- res_len, svct->table.ust_service);
- } else {
- err("Not handled card_type[%d]", card_type);
- }
-
- if (dr == FALSE) {
- err("SST/UST decoding failed");
- } else {
- tcore_sim_set_service_table(co, svct);
- }
-
- /* Free memory */
- g_free(svct);
- }
- break;
-
- case TEL_SIM_EF_ECC: {
- tcore_sim_get_type(co, &card_type);
- if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- dr = tcore_sim_decode_ecc((unsigned char *)res,
- res_len, &file_meta->files.data.ecc);
- } else if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- TelSimEcc *ecc = NULL;
-
- ecc = g_try_new0(TelSimEcc, 1);
- dbg("Index [%d]", file_meta->current_index);
-
- dr = tcore_sim_decode_uecc((unsigned char *)res, res_len, ecc);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.ecc.list[file_meta->files.data.ecc.count],
- ecc, sizeof(TelSimEcc));
- file_meta->files.data.ecc.count++;
- }
-
- /* Free memory */
- g_free(ecc);
- } else {
- dbg("Unknown/Unsupported SIM card Type: [%d]", card_type);
- }
- }
- break;
-
- case TEL_SIM_EF_MSISDN: {
- TelSimSubscriberInfo *msisdn = NULL;
-
- dbg("Index [%d]", file_meta->current_index);
- msisdn = g_try_new0(TelSimSubscriberInfo, 1);
- dr = tcore_sim_decode_msisdn((unsigned char *)res, res_len, msisdn);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.msisdn_list.list[file_meta->files.data.msisdn_list.count],
- msisdn, sizeof(TelSimSubscriberInfo));
-
- file_meta->files.data.msisdn_list.count++;
- }
-
- /* Free memory */
- g_free(msisdn);
- }
- break;
-
- case TEL_SIM_EF_OPL: {
- TelSimOpl *opl = NULL;
-
- dbg("decode w/ index [%d]", file_meta->current_index);
- opl = g_try_new0(TelSimOpl, 1);
-
- dr = tcore_sim_decode_opl((unsigned char *)res, res_len, opl);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.opl.list[file_meta->files.data.opl.opl_count],
- opl, sizeof(TelSimOpl));
-
- file_meta->files.data.opl.opl_count++;
- }
-
- /* Free memory */
- g_free(opl);
- }
- break;
-
- case TEL_SIM_EF_PNN: {
- TelSimPnn *pnn = NULL;
-
- dbg("decode w/ index [%d]", file_meta->current_index);
- pnn = g_try_new0(TelSimPnn, 1);
-
- dr = tcore_sim_decode_pnn((unsigned char *)res, res_len, pnn);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.pnn.list[file_meta->files.data.pnn.pnn_count],
- pnn, sizeof(TelSimPnn));
-
- file_meta->files.data.pnn.pnn_count++;
- }
-
- /* Free memory */
- g_free(pnn);
- }
- break;
-
- case TEL_SIM_EF_OPLMN_ACT:
- /*dr = tcore_sim_decode_oplmnwact(&file_meta->files.data.opwa,
- (unsigned char *)res, res_len);*/
- break;
-
- case TEL_SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
- /*dr = tcore_sim_decode_csp(&po->p_cphs->csp,
- p_data->response, p_data->response_len);*/
- break;
-
- case TEL_SIM_EF_USIM_MBI: { /* linear type */
- TelSimMbi *mbi = NULL;
-
- mbi = g_try_new0(TelSimMbi, 1);
- dr = tcore_sim_decode_mbi((unsigned char *)res, res_len, mbi);
- if (dr == TRUE) {
- memcpy(&file_meta->mbi_list.list[file_meta->mbi_list.count],
- mbi, sizeof(TelSimMbi));
- file_meta->mbi_list.count++;
-
- dbg("mbi count[%d]", file_meta->mbi_list.count);
- }
-
- /* Free memory */
- g_free(mbi);
- }
- break;
-
- case TEL_SIM_EF_CPHS_MAILBOX_NUMBERS: /* linear type */
- case TEL_SIM_EF_MBDN: /* linear type */
-#if 0 /* Temporarily blocked, MBDN is NOT suported in Emulator */
- dr = tcore_sim_decode_xdn((unsigned char *)res, res_len,
- file_meta->mb_list[file_meta->current_index-1].alpha_id,
- file_meta->mb_list[file_meta->current_index-1].number);
- file_meta->mb_list[file_meta->current_index-1].alpha_id_len =
- strlen(file_meta->mb_list[file_meta->current_index-1].alpha_id);
- file_meta->mb_list[file_meta->current_index-1].profile_id =
- file_meta->current_index;
-#endif /* Temporarily blocked, MBDN is NOT suported in Emulator */
- break;
-
- case TEL_SIM_EF_CPHS_VOICE_MSG_WAITING: /* transparent type */
- dr = tcore_sim_decode_vmwf((unsigned char *)res,
- res_len, file_meta->files.data.mw.mw);
- break;
-
- case TEL_SIM_EF_USIM_MWIS: { /* linear type */
- TelSimMwis *mw = NULL;
-
- mw = g_try_new0(TelSimMwis, 1);
-
- dr = tcore_sim_decode_mwis((unsigned char *)res, res_len, mw);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.mw.mw[file_meta->files.data.mw.profile_count],
- mw, sizeof(TelSimMwis));
- file_meta->files.data.mw.profile_count++;
- }
-
- /* Free memory */
- g_free(mw);
- }
- break;
-
- case TEL_SIM_EF_CPHS_CALL_FORWARD_FLAGS: /* transparent type */
- dr = tcore_sim_decode_cff((unsigned char *)res,
- res_len, file_meta->files.data.mw.mw);
- break;
-
- case TEL_SIM_EF_USIM_CFIS: { /* linear type */
- TelSimCfis *cf = NULL;
-
- cf = g_try_new0(TelSimCfis, 1);
- dr = tcore_sim_decode_cfis((unsigned char *)res, res_len, cf);
- if (dr == TRUE) {
- memcpy(&file_meta->files.data.cf.cf[file_meta->files.data.cf.profile_count],
- cf, sizeof(TelSimCfis));
- file_meta->files.data.cf.profile_count++;
- }
-
- /* Free memory */
- g_free(cf);
- }
- break;
-
- case TEL_SIM_EF_CPHS_SERVICE_STRING_TABLE:
- dbg("not handled - TEL_SIM_EF_CPHS_SERVICE_STRING_TABLE ");
- break;
-
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_STRING:
- dr = tcore_sim_decode_ons((unsigned char *)res,
- res_len,
- (unsigned char*)&file_meta->files.data.cphs_net.full_name);
- dbg("file_meta->files.result[%d],file_meta->files.data.cphs_net.full_name[%s]",
- file_meta->files.result, file_meta->files.data.cphs_net.full_name);
- break;
-
- case TEL_SIM_EF_CPHS_DYNAMICFLAGS:
- /*dr = tcore_sim_decode_dynamic_flag(&po->p_cphs->dflagsinfo,
- p_data->response, p_data->response_len);*/
- break;
-
- case TEL_SIM_EF_CPHS_DYNAMIC2FLAG:
- /*dr = tcore_sim_decode_dynamic2_flag(&po->p_cphs->d2flagsinfo, p_data->response,
- p_data->response_len);*/
- break;
-
- case TEL_SIM_EF_CPHS_CPHS_INFO:
- /*dr = tcore_sim_decode_cphs_info(&file_meta->files.data.cphs,
- (unsigned char *)res, res_len);*/
- break;
-
- case TEL_SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
- dr = tcore_sim_decode_short_ons((unsigned char *)res, res_len,
- (unsigned char*)&file_meta->files.data.cphs_net.short_name);
- dbg("file_meta->files.result[%d],file_meta->files.data.cphs_net.short_name[%s]",
- file_meta->files.result, file_meta->files.data.cphs_net.short_name);
- break;
-
- case TEL_SIM_EF_CPHS_INFORMATION_NUMBERS:
- /*dr = tcore_sim_decode_information_number(&po->p_cphs->infn,
- p_data->response, p_data->response_len);*/
- break;
-
- default:
- dbg("File Decoding Failed - not handled File[0x%x]", file_meta->file_id);
- dr = 0;
- break;
- }
- } else {
- sim_result = __atmodem_sim_decode_status_word(sw1, sw2);
- file_meta->files.result = sim_result;
- }
-
- /* Free memory */
- g_free(tmp);
- g_free(res);
-
- /* Free tokens */
- tcore_at_tok_free(tokens);
- } else {
- err("RESPONSE NOK");
- dbg("Error - File ID: [0x%x]", file_meta->file_id);
- sim_result = TEL_SIM_RESULT_FAILURE;
- }
-
- /* Get File data */
- __atmodem_sim_next_from_read_binary(tcore_pending_ref_core_object(p),
- resp_cb_data, sim_result, dr);
-
- dbg("Exit");
-}
-
-static void __on_response_atmodem_sim_get_response(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *resp = data;
- CoreObject *co = NULL;
- TelSimResult sim_result;
- GSList *tokens = NULL;
- const char *line = NULL;
- int sw1 = 0;
- int sw2 = 0;
- AtmodemRespCbData *resp_cb_data = (AtmodemRespCbData *)user_data;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- dbg("SIM Response - SIM File info: [+CRSM]");
-
- co = tcore_pending_ref_core_object(p);
-
- if (resp->success > 0) {
- dbg("RESPONSE OK");
- if (resp->lines) {
- line = (const char *)resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) < 2) {
- err("Invalid message");
- tcore_at_tok_free(tokens);
- return;
- }
- }
- sw1 = atoi(g_slist_nth_data(tokens, 0));
- sw2 = atoi(g_slist_nth_data(tokens, 1));
-
- /*1. SIM access success case*/
- if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
- unsigned char tag_len = 0;
- unsigned short record_len = 0;
- char num_of_records = 0;
- unsigned char file_id_len = 0;
- unsigned short file_id = 0;
- unsigned short file_size = 0;
- unsigned short file_type = 0;
- unsigned short arr_file_id = 0;
- int arr_file_id_rec_num = 0;
- TelSimCardType card_type = TEL_SIM_CARD_TYPE_UNKNOWN;
-
- /* handling only last 3 bits */
- unsigned char file_type_tag = 0x07;
- unsigned char *ptr_data;
-
- char *hexData;
- char *tmp;
- char *record_data = NULL;
- guint record_data_len;
- hexData = g_slist_nth_data(tokens, 2);
- dbg("hexData: %s", hexData);
- dbg("hexData: %s", hexData + 1);
-
- tmp = tcore_at_tok_extract(hexData);
- tcore_util_hexstring_to_bytes(tmp, &record_data, &record_data_len);
- tcore_util_hex_dump(" ", record_data_len, record_data);
- g_free(tmp);
-
- ptr_data = (unsigned char *)record_data;
- tcore_sim_get_type(co, &card_type);
- if (TEL_SIM_CARD_TYPE_USIM == card_type) {
- /*
- * ETSI TS 102 221 v7.9.0
- * - Response Data
- * '62' FCP template tag
- *
- * - Response for an EF
- * '82' M File Descriptor
- * '83' M File Identifier
- * 'A5' O Proprietary information
- * '8A' M Life Cycle Status Integer
- * '8B', '8C' or 'AB' C1 Security attributes
- * '80' M File size
- * '81' O Total file size
- * '88' O Short File Identifier (SFI)
- */
-
- /* rsim.res_len has complete data length received */
-
- /* FCP template tag - File Control Parameters tag*/
- if (*ptr_data == 0x62) {
- /* parse complete FCP tag*/
- /* increment to next byte */
- ptr_data++;
- tag_len = *ptr_data++;
- dbg("tag_len: %02x", tag_len);
- /* FCP file descriptor - file type, accessibility, DF, ADF etc*/
- if (*ptr_data == 0x82) {
- /* increment to next byte */
- ptr_data++;
- /* 2 or 5 value*/
- ptr_data++;
- /* consider only last 3 bits*/
- dbg("file_type_tag: %02x", file_type_tag);
- file_type_tag = file_type_tag & (*ptr_data);
- dbg("file_type_tag: %02x", file_type_tag);
-
- switch (file_type_tag) {
- /* increment to next byte */
- // ptr_data++;
- case 0x1:
- dbg("Getting FileType: [Transparent file type]");
- file_type = ATMODEM_SIM_FILE_TYPE_TRANSPARENT;
-
- /* increment to next byte */
- ptr_data++;
- /* increment to next byte */
- ptr_data++;
- break;
-
- case 0x2:
- dbg("Getting FileType: [Linear fixed file type]");
- /* increment to next byte */
- ptr_data++;
- /* data coding byte - value 21 */
- ptr_data++;
- /* 2bytes */
- memcpy(&record_len, ptr_data, 2);
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(record_len);
- ptr_data = ptr_data + 2;
- num_of_records = *ptr_data++;
- /* Data lossy conversation from enum (int) to unsigned char */
- file_type = ATMODEM_SIM_FILE_TYPE_LINEAR_FIXED;
- break;
-
- case 0x6:
- dbg("Cyclic fixed file type");
- /* increment to next byte */
- ptr_data++;
- /* data coding byte - value 21 */
- ptr_data++;
- /* 2bytes */
- memcpy(&record_len, ptr_data, 2);
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(record_len);
- ptr_data = ptr_data + 2;
- num_of_records = *ptr_data++;
- file_type = ATMODEM_SIM_FILE_TYPE_CYCLIC;
- break;
-
- default:
- dbg("not handled file type [0x%x]", *ptr_data);
- break;
- }
- } else {
- dbg("INVALID FCP received - DEbug!");
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
-
- /*File identifier - 0x84,0x85,0x86 etc are currently ignored and not handled */
- if (*ptr_data == 0x83) {
- /* increment to next byte */
- ptr_data++;
- file_id_len = *ptr_data++;
- dbg("file_id_len: %02x", file_id_len);
-
- memcpy(&file_id, ptr_data, file_id_len);
- dbg("file_id: %x", file_id);
-
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(file_id);
- dbg("file_id: %x", file_id);
-
- ptr_data = ptr_data + 2;
- dbg("Getting FileID=[0x%x]", file_id);
- } else {
- dbg("INVALID FCP received - DEbug!");
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
-
- /* proprietary information */
- if (*ptr_data == 0xA5) {
- unsigned short prop_len;
- /* increment to next byte */
- ptr_data++;
-
- /* length */
- prop_len = *ptr_data;
- dbg("prop_len: %02x", prop_len);
-
- /* skip data */
- ptr_data = ptr_data + prop_len + 1;
- } else {
- dbg("INVALID FCP received - DEbug!");
- }
-
- /* life cycle status integer [8A][length:0x01][status]*/
- /*
- status info b8~b1
- 00000000 : No information given
- 00000001 : creation state
- 00000011 : initialization state
- 000001-1 : operation state -activated
- 000001-0 : operation state -deactivated
- 000011-- : Termination state
- b8~b5 !=0, b4~b1=X : Proprietary
- Any other value : RFU
- */
- if (*ptr_data == 0x8A) {
- /* increment to next byte */
- ptr_data++;
- /* length - value 1 */
- ptr_data++;
-
- switch (*ptr_data) {
- case 0x04:
- case 0x06:
- dbg("<RX> operation state -deactivated");
- ptr_data++;
- break;
-
- case 0x05:
- case 0x07:
- dbg("<RX> operation state -activated");
- ptr_data++;
- break;
-
- default:
- dbg("<RX> DEBUG! LIFE CYCLE STATUS =[0x%x]", *ptr_data);
- ptr_data++;
- break;
- }
- }
-
- /* related to security attributes : currently not handled*/
- if (*ptr_data == 0x86 || *ptr_data == 0x8B || *ptr_data == 0x8C || *ptr_data == 0xAB) {
- /* increment to next byte */
- ptr_data++;
- /* if tag length is 3 */
- if (*ptr_data == 0x03) {
- /* increment to next byte */
- ptr_data++;
- /* EFARR file id */
- memcpy(&arr_file_id, ptr_data, 2);
- /* swap byes */
- ATMODEM_SWAP_BYTES_16(arr_file_id);
- ptr_data = ptr_data + 2;
- arr_file_id_rec_num = *ptr_data++;
- dbg("arr_file_id_rec_num:[%d]", arr_file_id_rec_num);
- } else {
- /* if tag length is not 3 */
- /* ignoring bytes */
- // ptr_data = ptr_data + 4;
- dbg("Useless security attributes, so jump to next tag");
- ptr_data = ptr_data + (*ptr_data + 1);
- }
- } else {
- dbg("INVALID FCP received[0x%x] - DEbug!", *ptr_data);
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
-
- dbg("Current ptr_data value is [%x]", *ptr_data);
-
- /* file size excluding structural info*/
- if (*ptr_data == 0x80) {
- /* for EF file size is body of file and for Linear or cyclic it is
- * number of recXsizeof(one record)
- */
- /* increment to next byte */
- ptr_data++;
- /* length is 1 byte - value is 2 bytes or more */
- ptr_data++;
- memcpy(&file_size, ptr_data, 2);
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(file_size);
- ptr_data = ptr_data + 2;
- } else {
- dbg("INVALID FCP received - DEbug!");
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
-
- /* total file size including structural info*/
- if (*ptr_data == 0x81) {
- int len;
- /* increment to next byte */
- ptr_data++;
- /* length */
- len = *ptr_data;
- dbg("len:[%d]", len);
- /* ignored bytes */
- ptr_data = ptr_data + 3;
- } else {
- dbg("INVALID FCP received - DEbug!");
- /* 0x81 is optional tag?? check out! so do not return -1 from here! */
- }
- /*short file identifier ignored*/
- if (*ptr_data == 0x88) {
- dbg("0x88: Do Nothing");
- /*DO NOTHING*/
- }
- } else {
- dbg("INVALID FCP received - DEbug!");
- tcore_at_tok_free(tokens);
- g_free(record_data);
- return;
- }
- } else if (TEL_SIM_CARD_TYPE_GSM == card_type) {
- unsigned char gsm_specific_file_data_len = 0;
- /* ignore RFU byte1 and byte2 */
- ptr_data++;
- ptr_data++;
- /* file size */
- // file_size = p_info->response_len;
- memcpy(&file_size, ptr_data, 2);
- /* swap bytes */
- ATMODEM_SWAP_BYTES_16(file_size);
- /* parsed file size */
- ptr_data = ptr_data + 2;
- /* file id */
- memcpy(&file_id, ptr_data, 2);
- ATMODEM_SWAP_BYTES_16(file_id);
- dbg("FILE id --> [%x]", file_id);
- ptr_data = ptr_data + 2;
- /* save file type - transparent, linear fixed or cyclic */
- file_type_tag = (*(ptr_data + 7));
-
- switch (*ptr_data) {
- case 0x0:
- /* RFU file type */
- dbg("RFU file type- not handled - Debug!");
- break;
-
- case 0x1:
- /* MF file type */
- dbg("MF file type - not handled - Debug!");
- break;
-
- case 0x2:
- /* DF file type */
- dbg("DF file type - not handled - Debug!");
- break;
-
- case 0x4:
- /* EF file type */
- dbg("EF file type [%d] ", file_type_tag);
- /* increment to next byte */
- ptr_data++;
-
- if (file_type_tag == 0x00 || file_type_tag == 0x01) {
- /* increament to next byte as this byte is RFU */
- ptr_data++;
- file_type =
- (file_type_tag == 0x00) ? ATMODEM_SIM_FILE_TYPE_TRANSPARENT : ATMODEM_SIM_FILE_TYPE_LINEAR_FIXED;
- } else {
- /* increment to next byte */
- ptr_data++;
- /* For a cyclic EF all bits except bit 7 are RFU; b7=1 indicates that */
- /* the INCREASE command is allowed on the selected cyclic file. */
- file_type = ATMODEM_SIM_FILE_TYPE_CYCLIC;
- }
- /* bytes 9 to 11 give SIM file access conditions */
- ptr_data++;
- /* byte 10 has one nibble that is RF U and another for INCREASE which is not used currently */
- ptr_data++;
- /* byte 11 is invalidate and rehabilate nibbles */
- ptr_data++;
- /* byte 12 - file status */
- ptr_data++;
- /* byte 13 - GSM specific data */
- gsm_specific_file_data_len = *ptr_data;
- dbg("gsm_specific_file_data_len:[%d]", gsm_specific_file_data_len);
- ptr_data++;
- /* byte 14 - structure of EF - transparent or linear or cyclic , already saved above */
- ptr_data++;
- /* byte 15 - length of record for linear and cyclic , for transparent it is set to 0x00. */
- record_len = *ptr_data;
- dbg("record length[%d], file size[%d]", record_len, file_size);
- if (record_len != 0)
- num_of_records = (file_size / record_len);
-
- dbg("Number of records [%d]", num_of_records);
- break;
-
- default:
- dbg("not handled file type");
- break;
- }
- } else {
- err("Unknown Card Type - [%d]", card_type);
- }
-
- dbg("req ef[0x%x] resp ef[0x%x] size[%ld] Type[0x%x] "\
- "NumOfRecords[%ld] RecordLen[%ld]",
- file_meta->file_id, file_id, file_size,
- file_type, num_of_records, record_len);
-
- file_meta->file_type = file_type;
- file_meta->data_size = file_size;
- file_meta->rec_length = record_len;
- file_meta->rec_count = num_of_records;
- file_meta->current_index = 0; /* reset for new record type EF */
- sim_result = TEL_SIM_RESULT_SUCCESS;
- g_free(record_data);
- } else {
- /*2. SIM access fail case*/
- err("Failed to get ef[0x%x] (file_meta->file_id) ", file_meta->file_id);
- sim_result = __atmodem_sim_decode_status_word(sw1, sw2);
- }
-
- tcore_at_tok_free(tokens);
- } else {
- err("RESPONSE NOK");
- err("Failed to get ef[0x%x] (file_meta->file_id)",
- file_meta->file_id);
- sim_result = TEL_SIM_RESULT_FAILURE;
- }
-
- dbg("Calling __atmodem_sim_next_from_get_response");
- __atmodem_sim_next_from_get_response(co, resp_cb_data, sim_result);
- dbg("Exit");
-}
-
-#if 0 //blocking for the moment
-static TelReturn __atmodem_sim_update_file(CoreObject *co,
- AtmodemRespCbData *resp_cb_data,
- int cmd, TelSimFileId ef,
- int p1, int p2, int p3, char *encoded_data)
-{
- char *cmd_str = NULL;
- TelReturn ret = TEL_RETURN_FAILURE;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- dbg("Entry File-id:[0x%02x]", file_meta->file_id);
-
- cmd_str = g_strdup_printf("AT+CRSM=%d,%d,%d,%d,%d,\"%s\"",
- cmd, ef, p1, p2, p3, encoded_data);
-
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, "+CRSM:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_atmodem_sim_update_file, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Update SIM File");
-
- tcore_free(encoded_data);
- g_free(cmd_str);
-
- dbg("Exit");
- return ret;
-}
-#endif
-
-static void __atmodem_sim_read_record(CoreObject *co,
- AtmodemRespCbData *resp_cb_data)
-{
- gchar *at_cmd = NULL;
- int p1 = 0;
- int p2 = 0;
- int p3 = 0;
- AtmodemSimMetaInfo *file_meta = (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelReturn ret = TEL_RETURN_FAILURE;
-
- dbg("Entry File-id:[0x%02x]", file_meta->file_id);
-
- /* According to TS 102 221, values of p1, p2, p3 can be as below:
- * 11.1.5 READ RECORD
- * P1: Record number
- * P2: Mode, see table 11.11
- * Lc: Not present
- * Data: Not present
- * Le: Number of bytes to be read (P3)
- */
- p1 = (unsigned char) file_meta->current_index;
- p2 = (unsigned char) 0x04; /* 0x4 for absolute mode */
- p3 = (unsigned char) file_meta->rec_length;
-
- at_cmd = g_strdup_printf("AT+CRSM=%d, %d, %d, %d, %d",
- ATMODEM_SIM_ACCESS_READ_RECORD, file_meta->file_id, p1, p2, p3);
-
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, "+CRSM:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_atmodem_sim_read_data, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get File Record");
-
- dbg("ret:[%d]", ret);
- g_free(at_cmd);
-
- dbg("Exit");
-}
-
-static void __atmodem_sim_read_binary(CoreObject *co, AtmodemRespCbData *resp_cb_data)
-{
- gchar *at_cmd = NULL;
- int p1 = 0;
- int p2 = 0;
- int p3 = 0;
- int offset = 0;
- AtmodemSimMetaInfo *file_meta = (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelReturn ret = TEL_RETURN_FAILURE;
-
- dbg("Entry File-id:[0x%02x]", file_meta->file_id);
-
- /*
- * According to TS 102 221, values of P1, P2, P3 can be as below:
- * 11.1.3 READ BINARY
- * P1: See table 11.10
- * P2: Offset low
- * Lc: Not present
- * Data: Not present
- * Le: Number of bytes to be read (P3)
- */
- p1 = (unsigned char) (offset & 0xFF00) >> 8;
- p2 = (unsigned char) offset & 0x00FF; /* offset low */
- p3 = (unsigned char) file_meta->data_size;
-
- if (file_meta->file_id == TEL_SIM_EF_SPDI)
- at_cmd = g_strdup_printf("AT+CRSM=%d, %d",
- ATMODEM_SIM_ACCESS_READ_BINARY, file_meta->file_id);
- else
- at_cmd = g_strdup_printf("AT+CRSM=%d, %d, %d, %d, %d",
- ATMODEM_SIM_ACCESS_READ_BINARY, file_meta->file_id, p1, p2, p3);
-
- ret = tcore_at_prepare_and_send_request(co, at_cmd, "+CRSM:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_atmodem_sim_read_data, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get File Data");
-
- dbg("ret:[%d]", ret);
- g_free(at_cmd);
-
- dbg("Exit");
-}
-
-static TelReturn __atmodem_sim_get_response(CoreObject *co, AtmodemRespCbData *resp_cb_data)
-{
- gchar *at_cmd = NULL;
- AtmodemSimMetaInfo *file_meta =
- (AtmodemSimMetaInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
- TelReturn ret = TEL_RETURN_FAILURE;
-
- dbg("Entry File-id:[0x%02x]", file_meta->file_id);
-
- at_cmd = g_strdup_printf("AT+CRSM=%d, %d",
- ATMODEM_SIM_ACCESS_GET_RESPONSE, file_meta->file_id);
-
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, "+CRSM:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_atmodem_sim_get_response, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get File Info");
-
- g_free(at_cmd);
- dbg("Exit");
- return ret;
-}
-
-static int __atmodem_sim_get_lock_type(AtmodemSimCurrSecOp sec_op)
-{
- switch(sec_op) {
- case ATMODEM_SIM_CURR_SEC_OP_SIM_DISABLE :
- case ATMODEM_SIM_CURR_SEC_OP_SIM_ENABLE :
- case ATMODEM_SIM_CURR_SEC_OP_SIM_STATUS :
- return TEL_SIM_LOCK_PS;
- case ATMODEM_SIM_CURR_SEC_OP_PIN1_DISABLE :
- case ATMODEM_SIM_CURR_SEC_OP_PIN1_ENABLE :
- case ATMODEM_SIM_CURR_SEC_OP_PIN1_STATUS :
- return TEL_SIM_LOCK_SC;
- case ATMODEM_SIM_CURR_SEC_OP_FDN_DISABLE :
- case ATMODEM_SIM_CURR_SEC_OP_FDN_ENABLE :
- case ATMODEM_SIM_CURR_SEC_OP_FDN_STATUS :
- return TEL_SIM_LOCK_FD;
- case ATMODEM_SIM_CURR_SEC_OP_NET_DISABLE :
- case ATMODEM_SIM_CURR_SEC_OP_NET_ENABLE :
- case ATMODEM_SIM_CURR_SEC_OP_NET_STATUS :
- return TEL_SIM_LOCK_PN;
- case ATMODEM_SIM_CURR_SEC_OP_NS_DISABLE :
- case ATMODEM_SIM_CURR_SEC_OP_NS_ENABLE :
- case ATMODEM_SIM_CURR_SEC_OP_NS_STATUS :
- return TEL_SIM_LOCK_PU;
- case ATMODEM_SIM_CURR_SEC_OP_SP_DISABLE :
- case ATMODEM_SIM_CURR_SEC_OP_SP_ENABLE :
- case ATMODEM_SIM_CURR_SEC_OP_SP_STATUS :
- return TEL_SIM_LOCK_PP;
- case ATMODEM_SIM_CURR_SEC_OP_CP_DISABLE :
- case ATMODEM_SIM_CURR_SEC_OP_CP_ENABLE :
- case ATMODEM_SIM_CURR_SEC_OP_CP_STATUS :
- return TEL_SIM_LOCK_PC ;
- default :
- err("Invalid sec op [%d]", sec_op);
- return -1;
- }
-}
-
-/* Notifications */
-/*
- * Notification: +SCSIM: <SIM state>
- *
- * Possible values of <SIM state> can be
- * 0 SIM not present
- * 1 PIN verification needed
- * 2 PIN verification not needed - Ready
- * 3 PIN verified - Ready
- * 4 PUK verification needed
- * 5 SIM permanently blocked
- * 6 SIM Error
- * 7 ready for attach (+COPS)
- * 8 SIM Technical Problem
- * 9 SIM Removed
- * 10 SIM Reactivating
- * 11 SIM Reactivated
- * 12 SIM SMS Caching Completed. (Sent only when SMS caching enabled)
- * 99 SIM State Unknown
- */
-static gboolean on_notification_atmodem_sim_status(CoreObject *co,
- const void *event_info, void *user_data)
-{
- GSList *lines = (GSList *)event_info;
- const gchar *line = (const gchar *)lines->data;
- TelSimCardStatus sim_status = TEL_SIM_STATUS_SIM_INITIALIZING;
- AtmodemSimSecLockType locktype = SEC_LOCK_TYPE_NONE;
- AtmodemSimSecLockKey lockkey = SEC_LOCK_KEY_NONE;
-
- if (__atmodem_convert_scpin_str_to_enum((char *)line, &locktype, &lockkey) == FALSE)
- return TRUE;
-
- switch (locktype) {
- case SEC_LOCK_TYPE_READY:
- if (lockkey == SEC_LOCK_KEY_UNLOCKED)
- sim_status = TEL_SIM_STATUS_SIM_INITIALIZING;
- else
- sim_status = TEL_SIM_STATUS_UNKNOWN;
- break;
-
- case SEC_LOCK_TYPE_PS:
- sim_status = TEL_SIM_STATUS_SIM_LOCK_REQUIRED;
- break;
-
- case SEC_LOCK_TYPE_PF:
- sim_status = TEL_SIM_STATUS_CARD_ERROR;
- break;
-
- case SEC_LOCK_TYPE_SC:
- switch (lockkey) {
- case SEC_LOCK_KEY_UNLOCKED:
- break;
-
- case SEC_LOCK_KEY_PIN:
- sim_status = TEL_SIM_STATUS_SIM_PIN_REQUIRED;
- break;
-
- case SEC_LOCK_KEY_PUK:
- sim_status = TEL_SIM_STATUS_SIM_PUK_REQUIRED;
- break;
-
- case SEC_LOCK_KEY_PERM_BLOCKED:
- sim_status = TEL_SIM_STATUS_CARD_BLOCKED;
- break;
-
- default:
- err("Not handled SEC Lock key: [%d]", lockkey);
- sim_status = TEL_SIM_STATUS_UNKNOWN;
- break;
- }
- break;
-
- case SEC_LOCK_TYPE_FD:
- break;
-
- case SEC_LOCK_TYPE_PN:
- if (SEC_LOCK_KEY_PIN)
- sim_status = TEL_SIM_STATUS_SIM_NCK_REQUIRED;
- else
- sim_status = TEL_SIM_STATUS_UNKNOWN;
- break;
-
- case SEC_LOCK_TYPE_PU:
- if (SEC_LOCK_KEY_PIN)
- sim_status = TEL_SIM_STATUS_SIM_NSCK_REQUIRED;
- else
- sim_status = TEL_SIM_STATUS_UNKNOWN;
- break;
-
- case SEC_LOCK_TYPE_PP:
- if (SEC_LOCK_KEY_PIN)
- sim_status = TEL_SIM_STATUS_SIM_SPCK_REQUIRED;
- else
- sim_status = TEL_SIM_STATUS_UNKNOWN;
- break;
-
- case SEC_LOCK_TYPE_PC:
- if (SEC_LOCK_KEY_PIN)
- sim_status = TEL_SIM_STATUS_SIM_CCK_REQUIRED;
- else
- sim_status = TEL_SIM_STATUS_UNKNOWN;
- break;
-
- case SEC_LOCK_TYPE_SC2:
- case SEC_LOCK_TYPE_PUK2:
- break;
-
- case SEC_LOCK_TYPE_NO_SIM:
- sim_status = TEL_SIM_STATUS_CARD_NOT_PRESENT;
- break;
-
- case SEC_LOCK_TYPE_UNAVAIL:
- case SEC_SIM_INIT_CRASH:
- sim_status = TEL_SIM_STATUS_CARD_ERROR;
- break;
-
- case SEC_SIM_INIT_COMPLETED:
- sim_status = TEL_SIM_STATUS_SIM_INIT_COMPLETED;
- break;
-
- case SEC_PB_INIT_COMPLETED:
- break;
-
- default:
- err("Not handled SEC lock type: [%d]", locktype);
- sim_status = TEL_SIM_STATUS_UNKNOWN;
- break;
- }
-
- __atmodem_sim_process_sim_status(co, sim_status);
-
- return TRUE;
-}
-
-/* Response Functions */
-static void on_response_atmodem_sim_verify_pins(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- AtmodemRespCbData *resp_cb_data = user_data;
- CoreObject *co_sim = tcore_pending_ref_core_object(p);
- TelSimResult result = TEL_SIM_RESULT_FAILURE;
- AtmodemSimCurrSecOp *sec_op = NULL;
- TelSimSecPinResult verify_pin_resp = {0, };
-
- dbg("Entry");
-
- tcore_check_return_assert(co_sim != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- sec_op = (AtmodemSimCurrSecOp *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (*sec_op == ATMODEM_SIM_CURR_SEC_OP_PIN1_VERIFY) {
- TelSimCardStatus status;
-
- verify_pin_resp.pin_type = TEL_SIM_PIN_TYPE_PIN1;
-
- tcore_sim_get_status(co_sim, &status);
- if (status != TEL_SIM_STATUS_SIM_INIT_COMPLETED) {
- /*Update sim status*/
- __atmodem_sim_update_sim_status(co_sim,
- TEL_SIM_STATUS_SIM_INITIALIZING);
- }
- } else if (*sec_op == ATMODEM_SIM_CURR_SEC_OP_PIN2_VERIFY) {
- verify_pin_resp.pin_type = TEL_SIM_PIN_TYPE_PIN2;
- }
-
- if (at_resp && at_resp->success) {
- dbg("SIM Verify Pin Response- [OK]");
- result = TEL_SIM_RESULT_SUCCESS;
-
- } else {
- err("SIM Verify Pin Response- [NOK]");
-
- /* Update retry count */
- verify_pin_resp.retry_count = 3;
- }
-
- /*Invoke callback*/
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result,
- &verify_pin_resp, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_sim_verify_puks(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- AtmodemRespCbData *resp_cb_data = user_data;
- CoreObject *co_sim = tcore_pending_ref_core_object(p);
- TelSimResult result = TEL_SIM_RESULT_FAILURE;
- AtmodemSimCurrSecOp *sec_op = NULL;
- TelSimSecPukResult verify_puk_resp = {0, };
-
- dbg("Entry");
-
- tcore_check_return_assert(co_sim != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- sec_op = (AtmodemSimCurrSecOp *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (*sec_op == ATMODEM_SIM_CURR_SEC_OP_PUK1_VERIFY) {
- verify_puk_resp.puk_type = TEL_SIM_PUK_TYPE_PUK1;
- } else if (*sec_op == ATMODEM_SIM_CURR_SEC_OP_PUK2_VERIFY) {
- verify_puk_resp.puk_type = TEL_SIM_PUK_TYPE_PUK2;
- }
- if (at_resp && at_resp->success) {
- dbg("SIM Verify Puk Response- [OK]");
- result = TEL_SIM_RESULT_SUCCESS;
- } else {
- err("SIM Verify Puk Response- [NOK]");
-
- /* Update retry count */
- verify_puk_resp.retry_count = 3;
- }
-
- /*Invoke callback*/
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result,
- &verify_puk_resp,
- resp_cb_data->cb_data);
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_sim_change_pins(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- AtmodemRespCbData *resp_cb_data = user_data;
- CoreObject *co_sim = tcore_pending_ref_core_object(p);
- TelSimResult result = TEL_SIM_RESULT_FAILURE;
- AtmodemSimCurrSecOp *sec_op = NULL;
- TelSimSecPinResult change_pin_resp = {0, };
-
- dbg("Entry");
-
- tcore_check_return_assert(co_sim != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- sec_op = (AtmodemSimCurrSecOp *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (at_resp && at_resp->success) {
- dbg("SIM Change Pin Response- [OK]");
-
- result = TEL_SIM_RESULT_SUCCESS;
-
- if (*sec_op == ATMODEM_SIM_CURR_SEC_OP_PIN1_CHANGE) {
- change_pin_resp.pin_type = TEL_SIM_PIN_TYPE_PIN1;
- } else if (*sec_op == ATMODEM_SIM_CURR_SEC_OP_PIN2_CHANGE) {
- change_pin_resp.pin_type = TEL_SIM_PIN_TYPE_PIN2;
- }
-
- /*Invoke callback*/
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result,
- &change_pin_resp, resp_cb_data->cb_data);
- }
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_sim_disable_facility(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- AtmodemRespCbData *resp_cb_data = user_data;
- CoreObject *co_sim = tcore_pending_ref_core_object(p);
- TelSimResult result = TEL_SIM_RESULT_FAILURE;
- AtmodemSimCurrSecOp *sec_op = NULL;
- TelSimFacilityResult disable_facility_resp = {0, };
-
- dbg("Entry");
-
- tcore_check_return_assert(co_sim != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- sec_op = (AtmodemSimCurrSecOp *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (at_resp && at_resp->success) {
- int lock_type;
- dbg("SIM Disable Facility Response- [OK]");
-
- lock_type = __atmodem_sim_get_lock_type(*sec_op);
- if (lock_type == -1) {
- result = TEL_SIM_RESULT_INVALID_PARAMETER;
-
- /*Invoke callback*/
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result,
- NULL, resp_cb_data->cb_data);
- atmodem_destroy_resp_cb_data(resp_cb_data);
- return;
- }
-
- disable_facility_resp.type = lock_type;
- result = TEL_SIM_RESULT_SUCCESS;
-
- /*Invoke callback*/
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result,
- &disable_facility_resp, resp_cb_data->cb_data);
- }
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_sim_enable_facility(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- AtmodemRespCbData *resp_cb_data = user_data;
- CoreObject *co_sim = tcore_pending_ref_core_object(p);
- TelSimResult result = TEL_SIM_RESULT_FAILURE;
- AtmodemSimCurrSecOp *sec_op = NULL;
- TelSimFacilityResult enable_facility_resp = {0, };
-
- dbg("Entry");
-
- tcore_check_return_assert(co_sim != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- sec_op = (AtmodemSimCurrSecOp *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (at_resp && at_resp->success) {
- int lock_type;
- dbg("SIM Enable Facility Response- [OK]");
-
- lock_type = __atmodem_sim_get_lock_type(*sec_op);
- if (lock_type == -1) {
- result = TEL_SIM_RESULT_INVALID_PARAMETER;
-
- /*Invoke callback*/
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result,
- NULL, resp_cb_data->cb_data);
- atmodem_destroy_resp_cb_data(resp_cb_data);
- return;
- }
-
- enable_facility_resp.type = lock_type;
- result = TEL_SIM_RESULT_SUCCESS;
-
- /*Invoke callback*/
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result,
- &enable_facility_resp,
- resp_cb_data->cb_data);
- }
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_sim_get_facility(TcorePending *p, guint data_len,
- const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- AtmodemRespCbData *resp_cb_data = user_data;
- CoreObject *co_sim = tcore_pending_ref_core_object(p);
- TelSimResult result = TEL_SIM_RESULT_FAILURE;
- AtmodemSimCurrSecOp *sec_op = NULL;
- TelSimFacilityInfo get_facility_resp = {0, };
-
- dbg("Entry");
-
- tcore_check_return_assert(co_sim != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- sec_op = (AtmodemSimCurrSecOp *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (at_resp && at_resp->success) {
- GSList *tokens = NULL;
- const char *line;
- int lock_type;
-
- dbg("SIM Get Facility Response- [OK]");
-
- lock_type = __atmodem_sim_get_lock_type(*sec_op);
- if (lock_type == -1) {
- result = TEL_SIM_RESULT_INVALID_PARAMETER;
- goto out;
- }
- if (at_resp->lines) {
- line = (const char *)at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) != 1) {
- err("Invalid message");
- tcore_at_tok_free(tokens);
- goto out;
- }
- get_facility_resp.f_status = atoi(g_slist_nth_data(tokens, 0));
- get_facility_resp.type = lock_type;
- result = TEL_SIM_RESULT_SUCCESS;
- }
-
- tcore_at_tok_free(tokens);
- } else {
- err("SIM Get Facility Response- [NOK]");
- }
-out:
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co_sim, (gint)result, &get_facility_resp, resp_cb_data->cb_data);
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-/* SIM Operations */
-/*
- * Operation - get_imsi
- *
- * Request -
- * AT-Command: AT+CRSM= <command>[,<fileid>[,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]]
- * where,
- * <command>
- * 176 READ BINARY
- * 178 READ RECORD
- * 192 GET RESPONSE
- * 214 UPDATE BINARY
- * 220 UPDATE RECORD
- * 242 STATUS
- *
- * <fileid>
- * 28423 meaning IMSI file (6F07)
- * 28473 meaning ACM file (6F39)
- * 28481 meaning PUKT file (6F41)
- * 28482 meaning SMS file (6F42)
- *
- * <P1>, <P2>, <P3>
- * Integer type defining the request.
- * These parameters are mandatory for every command, except GET RESPONSE and STATUS.
- *
- * <data>
- * Information which shall be written to the SIM
- *
- * <pathid>
- * String type, contains the path of an elementary file on the SIM/USIM in hexadecimal format
- *
- * <status>
- * 0 not active
- * 1 active
- *
- * Success:
- * OK
- * +CRSM: <sw1>,<sw2>[,<response>]
- *
- * <sw1>, <sw2>
- * Integer type containing the SIM information
- *
- * <response>
- * Response of successful completion of the command previously issued
- *
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_sim_get_imsi (CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemSimMetaInfo file_meta = {0, };
- AtmodemRespCbData *resp_cb_data = NULL;
-
- dbg("Entry");
-
- file_meta.file_id = TEL_SIM_EF_IMSI;
- file_meta.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta.req_command = TCORE_COMMAND_SIM_GET_IMSI;
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &file_meta, sizeof(AtmodemSimMetaInfo));
-
- return __atmodem_sim_get_file_info(co, resp_cb_data);
-}
-
-static TelReturn atmodem_sim_get_ecc (CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemSimMetaInfo file_meta = {0, };
- AtmodemRespCbData *resp_cb_data = NULL;
-
- dbg("Entry");
-
- file_meta.file_id = TEL_SIM_EF_ECC;
- file_meta.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta.req_command = TCORE_COMMAND_SIM_GET_ECC;
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &file_meta, sizeof(AtmodemSimMetaInfo));
-
- return __atmodem_sim_get_file_info(co, resp_cb_data);
-}
-
-static TelReturn atmodem_sim_get_spdi (CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemSimMetaInfo file_meta = {0, };
- AtmodemRespCbData *resp_cb_data = NULL;
-
- dbg("Entry");
-
- file_meta.file_id = TEL_SIM_EF_SPDI;
- file_meta.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta.req_command = TCORE_COMMAND_SIM_GET_SP_DISPLAY_INFO;
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &file_meta, sizeof(AtmodemSimMetaInfo));
-
- return __atmodem_sim_get_file_info(co, resp_cb_data);
-}
-
-static TelReturn atmodem_sim_get_cfis (CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemSimMetaInfo file_meta = {0, };
- AtmodemRespCbData *resp_cb_data = NULL;
-
- dbg("Entry");
-
- file_meta.file_id = TEL_SIM_EF_USIM_CFIS;
- file_meta.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta.req_command = TCORE_COMMAND_SIM_GET_CALL_FORWARDING_INFO;
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &file_meta, sizeof(AtmodemSimMetaInfo));
-
- return __atmodem_sim_get_file_info(co, resp_cb_data);
-}
-
-static TelReturn atmodem_sim_get_spn (CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemSimMetaInfo file_meta = {0, };
- AtmodemRespCbData *resp_cb_data = NULL;
-
- dbg("Entry");
-
- file_meta.file_id = TEL_SIM_EF_SPN;
- file_meta.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta.req_command = TCORE_COMMAND_SIM_GET_SPN;
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &file_meta, sizeof(AtmodemSimMetaInfo));
-
- return __atmodem_sim_get_file_info(co, resp_cb_data);
-}
-
-static TelReturn atmodem_sim_get_language (CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- AtmodemSimMetaInfo file_meta = {0, };
- AtmodemRespCbData *resp_cb_data = NULL;
-
- dbg("Entry");
-
- file_meta.file_id = TEL_SIM_EF_LP;
- file_meta.file_result = TEL_SIM_RESULT_FAILURE;
- file_meta.req_command = TCORE_COMMAND_SIM_GET_LANGUAGE;
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &file_meta, sizeof(AtmodemSimMetaInfo));
-
- return __atmodem_sim_get_file_info(co, resp_cb_data);
-}
-
-/*
- * Operation - verify_pins/verify_puks/change_pins
- *
- * Request -
- * For SIM PIN
- * AT-Command: AT+CPIN= <pin> [, <newpin>]
- * where,
- * <pin>, <newpin>
- * String type values
- *
- * For SIM PIN2
- * AT-Command: AT+CPIN2= <puk2/oldpin2> [, <newpin2>]andAT+CPIN2=<oldpin2>
- * where,
- * <puk2/pin2>, <newpin2>
- * String type values
- *
- * Success:
- * OK
- *
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_sim_verify_pins(CoreObject *co,
- const TelSimSecPinPw *request,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- TelReturn ret = TEL_RETURN_FAILURE;
- AtmodemRespCbData *resp_cb_data = NULL;
- AtmodemSimCurrSecOp sec_op;
- gchar *cmd_str = NULL;
-
- dbg("Entry");
-
- if (request->pin_type == TEL_SIM_PIN_TYPE_PIN1) {
- sec_op = ATMODEM_SIM_CURR_SEC_OP_PIN1_VERIFY;
- } else if (request->pin_type == TEL_SIM_PIN_TYPE_PIN2) {
- sec_op = ATMODEM_SIM_CURR_SEC_OP_PIN2_VERIFY;
- } else {
- err("Invalid pin type [%d]", request->pin_type);
- return TEL_RETURN_INVALID_PARAMETER;
- }
-
- cmd_str = g_strdup_printf("AT+CPIN=\"%s\"", request->pw);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &sec_op, sizeof(sec_op));
-
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_sim_verify_pins, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "SIM Verify PIN");
-
- g_free(cmd_str);
- return ret;
-}
-
-static TelReturn atmodem_sim_verify_puks(CoreObject *co,
- const TelSimSecPukPw *request,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- TelReturn ret = TEL_RETURN_FAILURE;
- AtmodemRespCbData *resp_cb_data = NULL;
- AtmodemSimCurrSecOp sec_op;
- gchar *cmd_str = NULL;
-
- dbg("Entry");
-
- if (request->puk_type == TEL_SIM_PUK_TYPE_PUK1) {
- sec_op = ATMODEM_SIM_CURR_SEC_OP_PUK1_VERIFY;
- } else if (request->puk_type == TEL_SIM_PUK_TYPE_PUK2) {
- sec_op = ATMODEM_SIM_CURR_SEC_OP_PUK2_VERIFY;
- } else {
- err("Invalid puk type [%d]", request->puk_type);
- return TEL_RETURN_INVALID_PARAMETER;
- }
-
- cmd_str = g_strdup_printf("AT+CPIN=\"%s\", \"%s\"",
- request->puk_pw, request->new_pin_pw);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &sec_op, sizeof(sec_op));
-
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_sim_verify_puks, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "SIM Verify PUK");
-
- g_free(cmd_str);
- return ret;
-}
-
-static TelReturn atmodem_sim_change_pins(CoreObject *co,
- const TelSimSecChangePinPw *request,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- TelReturn ret = TEL_RETURN_FAILURE;
- AtmodemRespCbData *resp_cb_data = NULL;
- AtmodemSimCurrSecOp sec_op;
- gchar *cmd_str = NULL;
-
- dbg("Entry");
-
- if (request->pin_type == TEL_SIM_PIN_TYPE_PIN1) {
- sec_op = ATMODEM_SIM_CURR_SEC_OP_PIN1_CHANGE;
- } else if (request->pin_type == TEL_SIM_PIN_TYPE_PIN2) {
- sec_op = ATMODEM_SIM_CURR_SEC_OP_PIN2_CHANGE;
- } else {
- err("Invalid pin type [%d]", request->pin_type);
- return TEL_RETURN_INVALID_PARAMETER;
- }
-
- cmd_str = g_strdup_printf("AT+CPIN=\"%s\", \"%s\"", request->old_pw, request->new_pw);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &sec_op, sizeof(sec_op));
-
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_sim_change_pins, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "SIM Change PIN");
-
- g_free(cmd_str);
- return ret;
-}
-
-/*
- * Operation - disable_facility/enable_facility/get_facility
- *
- * Request -
- * AT-Command: AT+CLCK = <fac>, <mode> [, <passwd> [, <class>]]
- * where,
- * <fac>
- * SIM facility
- *
- * <mode>
- * 0 unlock
- * 1 lock
- * 2 query status
- *
- * <passwd>
- * Password string
- *
- * <status>
- * 0 not active
- * 1 active
- *
- * Success: when <mode>=2:
- * OK
- * +CLCK: <status>[,<class1> [<CR><LF>
- * +CLCK: <status>,<class2> [...]]
- *
- * Failure:
- */
-static TelReturn atmodem_sim_disable_facility(CoreObject *co,
- const TelSimFacilityPw *request,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- TelReturn ret = TEL_RETURN_FAILURE;
- AtmodemRespCbData *resp_cb_data = NULL;
- AtmodemSimCurrSecOp sec_op;
- gchar *cmd_str = NULL;
- char *fac = "SC";
- int mode = 0; /*mode = 0 for disable lock*/
-
- dbg("Entry");
-
- fac = __atmodem_sim_get_fac_from_lock_type(request->lock_type,
- &sec_op, DISABLE_FLAG);
- if (!fac)
- return TEL_RETURN_INVALID_PARAMETER;
-
- cmd_str = g_strdup_printf("AT+CLCK=\"%s\", %d, \"%s\"",
- fac, mode, request->pw);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &sec_op, sizeof(sec_op));
-
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, "+CLCK:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_sim_disable_facility, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "SIM Disable Facility");
-
- g_free(cmd_str);
- return ret;
-}
-
-static TelReturn atmodem_sim_enable_facility(CoreObject *co,
- const TelSimFacilityPw *request,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- TelReturn ret = TEL_RETURN_FAILURE;
- AtmodemRespCbData *resp_cb_data = NULL;
- AtmodemSimCurrSecOp sec_op;
- gchar *cmd_str = NULL;
- char *fac = "SC";
- int mode = 1; /*mode = 1 for enable lock*/
-
- dbg("Entry");
-
- fac = __atmodem_sim_get_fac_from_lock_type(request->lock_type,
- &sec_op, ENABLE_FLAG);
- if (!fac)
- return TEL_RETURN_INVALID_PARAMETER;
-
- cmd_str = g_strdup_printf("AT+CLCK=\"%s\", %d, \"%s\"",
- fac, mode, request->pw);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &sec_op, sizeof(sec_op));
-
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, "+CLCK:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_sim_enable_facility, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "SIM Disable Facility");
-
- g_free(cmd_str);
- return ret;
-}
-
-static TelReturn atmodem_sim_get_facility(CoreObject *co,
- TelSimLockType lock_type,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- TelReturn ret = TEL_RETURN_FAILURE;
- AtmodemRespCbData *resp_cb_data = NULL;
- AtmodemSimCurrSecOp sec_op;
- gchar *cmd_str = NULL;
- char *fac = "SC";
- int mode = 2; /*mode = 2 for Get Facility*/
-
- dbg("Entry");
-
- fac = __atmodem_sim_get_fac_from_lock_type(lock_type,
- &sec_op, 0);
- if (!fac)
- return TEL_RETURN_INVALID_PARAMETER;
-
- cmd_str = g_strdup_printf("AT+CLCK=\"%s\", %d", fac, mode);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &sec_op, sizeof(sec_op));
-
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, "+CLCK:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_sim_get_facility, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "SIM Get Facility");
-
- g_free(cmd_str);
- return ret;
-}
-
-/* SIM Operations */
-static TcoreSimOps atmodem_sim_ops = {
- .get_imsi = atmodem_sim_get_imsi,
- .get_ecc = atmodem_sim_get_ecc,
- .get_iccid = NULL,
- .get_language = atmodem_sim_get_language,
- .set_language = NULL,
- .get_callforwarding_info = atmodem_sim_get_cfis,
- .get_messagewaiting_info = NULL,
- .set_messagewaiting_info = NULL,
- .get_mailbox_info = NULL,
- .set_mailbox_info = NULL,
- .get_msisdn = NULL,
- .get_spn = atmodem_sim_get_spn,
- .get_cphs_netname = NULL,
- .get_sp_display_info = atmodem_sim_get_spdi,
- .req_authentication = NULL,
- .verify_pins = atmodem_sim_verify_pins,
- .verify_puks = atmodem_sim_verify_puks,
- .change_pins = atmodem_sim_change_pins,
- .disable_facility = atmodem_sim_disable_facility,
- .enable_facility = atmodem_sim_enable_facility,
- .get_facility = atmodem_sim_get_facility,
- .get_lock_info = NULL,
- .req_apdu = NULL,
- .req_atr = NULL
-};
-
-gboolean atmodem_sim_init(TcorePlugin *p, CoreObject *co_sim)
-{
- dbg("Entry");
-
- /* Set operations */
- tcore_sim_set_ops(co_sim, &atmodem_sim_ops);
-
- /* Add Callbacks */
- tcore_object_add_callback(co_sim, "\%SCSIM:",
- on_notification_atmodem_sim_status, NULL);
-
- dbg("Exit");
- return TRUE;
-}
-
-void atmodem_sim_exit(TcorePlugin *plugin, CoreObject *co_sim)
-{
- dbg("Entry");
-}
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-#include <server.h>
-#include <plugin.h>
-#include <core_object.h>
-#include <hal.h>
-#include <queue.h>
-#include <storage.h>
-#include <at.h>
-
-#include <co_sms.h>
-
-#include "atmodem_sms.h"
-#include "atmodem_common.h"
-
-#define CR '\r'
-#define CTRL_Z '\x1A'
-
-#define AT_MT_UNREAD 0 /* Received and Unread */
-#define AT_MT_READ 1 /* Received and Read */
-#define AT_MO_UNSENT 2 /* Unsent */
-#define AT_MO_SENT 3 /* Sent */
-#define AT_ALL 4 /* Unknown */
-
-#define ATMODEM_NUM_PLAN_ID(sca) (gchar)(sca & 0x0F)
-#define ATMODEM_TYPE_OF_NUM(sca) (gchar)((sca & 0x70) >> 4)
-
-/* SCA 12 bytes long and TDPU is 164 bytes long */
-#define PDU_LEN_MAX 176
-#define HEX_PDU_LEN_MAX ((PDU_LEN_MAX * 2) + 1)
-
-#define ATMODEM_SIM_TON_INTERNATIONAL 1
-#define ATMODEM_SIM_TON_NATIONAL 2
-
-/*
- * Notification - SMS-DELIVER
- * +CMT = [<alpha>],<length><CR><LF><pdu> (PDU mode enabled)
- *
- * where,
- * <alpha> alpha_id
- * <length> length of the PDU
- * <pdu> Incomming SMS PDU
- *
- * Notification - SMS-STATUS-REPORT
- * +CDS: <length><CR><LF><pdu> (PDU mode enabled)
- *
- * where,
- * <length> length of the PDU
- * <pdu> Incomming SMS PDU
- *
- */
-static gboolean on_notification_atmodem_sms_incoming_msg(CoreObject *co,
- const void *event_info, void *user_data)
-{
- GSList *tokens = NULL;
- GSList *lines = NULL;
- char *line = NULL;
- int pdu_len = 0, no_of_tokens = 0;
- gchar *byte_pdu = NULL;
- guint buf_len = 0;
-
- TelSmsDatapackageInfo incoming_msg = {{0}, };
- int sca_length = 0;
- dbg("Enter");
-
- lines = (GSList *)event_info;
- if (2 != g_slist_length(lines)) {
- err("Invalid number of lines for +CMT. Must be 2");
- return TRUE;
- }
- line = (char *)g_slist_nth_data(lines, 0); /* Fetch Line 1 */
- if (!line) {
- err("Line 1 is invalid");
- return TRUE;
- }
- dbg("Line 1: [%s]", line);
- tokens = tcore_at_tok_new(line); /* Split Line 1 into tokens */
- no_of_tokens = g_slist_length(tokens);
-
- /*
- * Incoming SMS: +CMT
- * Number of tokens: 2
- *
- * Incoming SMS-STATUS-REPORT: +CDS
- * Number of tokens: 1
- */
- if (2 == no_of_tokens) {
- /* Token 0: Alpha ID */
- dbg("Alpha ID: [0x%x]", g_slist_nth_data(tokens, 0));
-
- /* Token 1: PDU Length */
- pdu_len = atoi((char *)g_slist_nth_data(tokens, 1));
- dbg("pdu_len: [%d]", pdu_len);
- } else if (1 == no_of_tokens) {
- /* 0: PDU Length */
- pdu_len = atoi((char *)g_slist_nth_data(tokens, 0));
- dbg("pdu_len: [%d]", pdu_len);
- }
-
- /* Fetch Line 2 */
- line = (char *)g_slist_nth_data(lines, 1);
- if (!line) {
- err("Line 2 is invalid");
- tcore_at_tok_free(tokens);
- return TRUE;
- }
- dbg("Line 2: [%s]", line);
-
- /* Convert to Bytes */
- tcore_util_hexstring_to_bytes(line, &byte_pdu, &buf_len);
-
- sca_length = byte_pdu[0];
- dbg("SCA length = %d", sca_length);
-
- if (sca_length) {
- gchar *decoded_sca;
- guint encoded_sca_len;
- /*
- * byte_pdu[1] - sca_address_type
- * Excluding sca_address_type and copy SCA
- */
- encoded_sca_len = sca_length - 1;
- decoded_sca =
- tcore_util_convert_bcd_to_ascii(&byte_pdu[2], encoded_sca_len, encoded_sca_len*2);
- dbg("Decoded SCA: [%s]", decoded_sca);
- g_strlcpy(incoming_msg.sca.number, decoded_sca, strlen(decoded_sca)+1);
- tcore_free(decoded_sca);
-
- /*SCA Conversion for Address type*/
- incoming_msg.sca.ton = ATMODEM_TYPE_OF_NUM(byte_pdu[1]);
- incoming_msg.sca.npi = ATMODEM_NUM_PLAN_ID(byte_pdu[1]);
- dbg("TON: [%d] NPI: [%d] SCA: [%s]",
- incoming_msg.sca.ton, incoming_msg.sca.npi,
- incoming_msg.sca.number);
- }
- else {
- dbg("NO SCA Present");
- }
-
-
- /* TPDU */
- incoming_msg.tpdu_length = pdu_len;
- memcpy(incoming_msg.tpdu,
- &byte_pdu[sca_length+1], incoming_msg.tpdu_length);
-
- /* Send notification */
- tcore_object_send_notification(co,
- TCORE_NOTIFICATION_SMS_INCOM_MSG,
- sizeof(TelSmsDatapackageInfo), &incoming_msg);
-
- tcore_at_tok_free(tokens);
- g_free(byte_pdu);
-
- return TRUE;
-}
-
-static gboolean on_notification_atmodem_sms_device_ready(CoreObject *co,
- const void *event_info, void *user_data)
-{
- gboolean sms_status = TRUE;
-
- dbg("SMS notification - [Device Ready]");
-
- /* Set Device Ready */
- tcore_sms_set_ready_status(co, sms_status);
-
- /* Send notification: SMS Device ready */
- tcore_object_send_notification(co,
- TCORE_NOTIFICATION_SMS_DEVICE_READY,
- sizeof(sms_status), &sms_status);
-
- return TRUE;
-}
-
-static void on_response_atmodem_sms_send_more_msg(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
-
- dbg("Enter");
-
- if (at_resp && at_resp->success)
- dbg("Response OK for AT+CMMS: More msgs to send!!");
- else
- err("Response NOK for AT+CMMS: More msgs to send");
-
- /* Need not send any response */
-}
-
-static void on_response_atmodem_sms_send_sms(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelSmsResult result = TEL_SMS_RESULT_FAILURE;/*TODO: CMS error mapping required */
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success) {
- dbg("Response OK");
- if (at_resp->lines) {
- const gchar *line;
- gchar* line_token;
- GSList *tokens = NULL;
- gint msg_ref = 0;
-
- line = (const gchar *)at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- line_token = g_slist_nth_data(tokens, 0);
- if (line_token != NULL) {
- /*Response from MODEM for send SMS: +CMGS: <mr>[,<ackpdu>]*/
- /*Message Reference is not used by MSG_SERVER and application.So Filling only result*/
- msg_ref = atoi(line_token);
-
- dbg("Message Reference: [%d]", msg_ref);
-
- result = TEL_SMS_RESULT_SUCCESS;
- } else {
- dbg("No Message Reference received");
- }
- tcore_at_tok_free(tokens);
- }
- } else {
- err("Response NOK");
- }
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_sms_get_count(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- TelSmsStoredMsgCountInfo count_info = {0, };
-
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- GSList *tokens = NULL;
- TelSmsResult result = TEL_SMS_RESULT_FAILURE;
-
- dbg("Enter");
-
- if (at_resp && at_resp->success) {
- dbg("RESPONSE OK");
- if (at_resp->lines) {
- char *line = NULL, *line_token = NULL;
-
- line = (char *)at_resp->lines->data;
- dbg("line: [%s]",line);
-
- /*
- * Tokenize
- *
- * +CPMS: <used1>, <total1>, <used2>, <total2>, <used3>, <total3>
- */
- tokens = tcore_at_tok_new(line);
-
- /* <used1> */
- line_token = g_slist_nth_data(tokens, 0);
- if (line_token == NULL) {
- err("Line Token for used count is NULL");
- goto ERROR;
- }
- count_info.used_count = atoi(line_token);
-
- /* <total1> */
- line_token = g_slist_nth_data(tokens, 1);
- if (line_token == NULL) {
- err("Line Token for Total count is NULL");
- goto ERROR;
- }
- count_info.total_count = atoi(line_token);
-
- dbg("Count - used: [%d] total: [%d]",
- count_info.used_count, count_info.total_count);
- result = TEL_SMS_RESULT_SUCCESS;
- }
- else {
- err("Invalid Response Received: NO Lines Present");
- }
- }
- else {
- err("RESPONSE NOK");
- }
-
-ERROR:
- /* Invoke callback in case of error*/
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &count_info, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-
- tcore_at_tok_free(tokens);
-}
-
-static void on_response_atmodem_sms_send_deliver_report(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelSmsResult result = TEL_SMS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success)
- result = TEL_SMS_RESULT_SUCCESS;
-
- dbg("Send Deliver Report: [%s]",
- (result == TEL_SMS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_sms_set_sca(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelSmsResult result = TEL_SMS_RESULT_FAILURE;
- dbg("Enter");
-
- if (at_resp && at_resp->success) {
- dbg("Response OK");
- result = TEL_SMS_RESULT_SUCCESS;
- } else {
- err("Response NOK");
- }
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_sms_get_sca(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelSmsSca sca_resp = { 0, };
- TelSmsResult result = TEL_SMS_RESULT_FAILURE;
- dbg("Enter");
-
- if (at_resp && at_resp->success) {
- dbg("Response OK");
- if (at_resp->lines) {
- GSList *tokens = NULL;
- const char *sca_tok_addr;
- gchar *line = NULL, *sca_addr = NULL, *sca_toa = NULL;
-
- line = (char *)at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- sca_tok_addr = g_slist_nth_data(tokens, 0);
- sca_toa = g_slist_nth_data(tokens, 1);
-
- sca_addr = tcore_at_tok_extract(sca_tok_addr);
- dbg("SCA: [%s] SCA-TOA: [%s]", sca_addr, sca_toa);
- if ((NULL != sca_addr) && (NULL != sca_toa)) {
- gchar *sca;
- guint sca_len = 0;
- tcore_util_hexstring_to_bytes(sca_addr, &sca, &sca_len); /*TODO : Check*/
- memcpy(sca_resp.number, sca, sca_len);
- g_free(sca);
-
- /* Type-of-Address */
- if (145 == atoi(sca_toa)) {
- sca_resp.ton = ATMODEM_SIM_TON_INTERNATIONAL;
- } else {
- sca_resp.ton = ATMODEM_SIM_TON_NATIONAL;
- }
- sca_resp.npi = 0;/* TODO */
- result = TEL_SMS_RESULT_SUCCESS;
- } else {
- err("SCA is NULL");
- }
- tcore_at_tok_free(tokens);
- g_free(sca_addr);
- } else {
- err("Invalid Response.No Lines Received");
- }
- } else {
- err("Response NOK");
- }
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &sca_resp, resp_cb_data->cb_data);
-
- /* Free callback data */
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-/* SMS Operations */
-/*
- * Operation - send_sms
- *
- * Request -
- * AT-Command: AT+CMGS
- * For PDU mode (+CMGF=0):
- * +CMGS=<length><CR>
- * PDU is given<ctrl-Z/ESC>
- * where,
- * <length> Length of the pdu.
- * <PDU> PDU to send.
- *
- * Response -
- *+CMGS: <mr>[,<ackpdu>]
- * OK
- * Failure:
- * +CMS ERROR: <error>
- */
-static TelReturn atmodem_sms_send_sms(CoreObject *co,
- const TelSmsSendInfo *send_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
- TcorePending *pending;
- TcoreAtRequest *at_req;
- TcoreHal *hal;
- TcoreAT *at;
- TcoreQueue *queue;
- TelReturn ret = TEL_RETURN_FAILURE;
- AtmodemRespCbData *resp_cb_data;
-
- const unsigned char *tpdu_byte_data;
- gint tpdu_byte_len, pdu_byte_len;
- char buf[HEX_PDU_LEN_MAX];
- char pdu[PDU_LEN_MAX];
-
- dbg("Enter");
-
- /*get HAL*/
- hal = tcore_object_get_hal(co);
- if (hal == NULL) {
- err("HAL is NULL");
- return ret;
- }
-
- tpdu_byte_data = send_info->send_data.tpdu;
-
- /* TPDU length is in byte */
- tpdu_byte_len = send_info->send_data.tpdu_length;
-
- /* Prepare PDU for hex encoding */
- pdu_byte_len = tcore_util_encode_pdu(&(send_info->send_data.sca),
- tpdu_byte_data, tpdu_byte_len, pdu);
-
- tcore_util_encode_hex((unsigned char *) pdu, pdu_byte_len, buf);
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /*
- * More messages
- * Use same Radio Resource Channel :More Messages to send
- */
- if (send_info->more_msgs > 0) {
- /* AT Command: More Msgs to Send */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+CMMS=1", "+CMMS:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_sms_send_more_msg, NULL,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, NULL, "More Msgs to Send");
- }
- /* AT-Command : Send SMS */
- at_cmd = g_strdup_printf("AT+CMGS=%d\r%s%x", tpdu_byte_len, buf, 0x1A);
-
- /* Create AT-Command Request */
- at_req = tcore_at_request_new(at_cmd, "+CMGS:", TCORE_AT_COMMAND_TYPE_SINGLELINE);
- if (at_req == NULL) {
- err("Request is NULL");
- atmodem_destroy_resp_cb_data(resp_cb_data);
- g_free(at_cmd);
- return TEL_RETURN_FAILURE;
- }
-
- /* Create Pending Request */
- pending = tcore_pending_new(co, 0);
- if (pending == NULL) {
- err("Pending is NULL");
- atmodem_destroy_resp_cb_data(resp_cb_data);
- g_free(at_cmd);
- return TEL_RETURN_FAILURE;
- }
-
- tcore_pending_set_request_data(pending, 0, at_req);
- tcore_pending_link_request(pending, NULL);
- tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
- tcore_pending_set_response_callback(pending, on_response_atmodem_sms_send_sms, resp_cb_data);
- tcore_pending_set_send_callback(pending, on_send_atmodem_request, NULL);
- tcore_pending_set_timeout_callback(pending, NULL, NULL);
-
- at = tcore_hal_get_at(hal);
- tcore_at_set_request(at, at_req);
-
- queue = tcore_hal_ref_queue(hal);
- tcore_queue_push(queue, pending);
-
- ret = tcore_hal_send_data(hal, strlen(at_cmd), at_cmd);
- dbg("ret: [0x%x]", ret);
-
- /* Free resources */
- g_free(at_cmd);
-
- return ret;
-}
-
-/*
- * Operation - get_sms_count_in_sim
- *
- * Request -
- * AT-Command: AT+CPMS
- * +CPMS=<mem1>[, <mem2>[,<mem3>]]
- * where
- * <mem1> memory storage to read.
- *
- * Response -
- * Success: (Single-line output)
- * +CPMS: <mem1>,<used1>,<total1>,<mem2>,<used2>,<total2>,
- * <mem3>,<used3>,<total3>
- * OK
- *
- * Failure:
- * +CMS ERROR: <error>
- */
-static TelReturn atmodem_sms_get_count(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
-
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
- dbg("Enter");
-
- /*AT Command*/
- at_cmd = g_strdup_printf("AT+CPMS=\"SM\"");
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, "+CPMS",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_sms_get_count, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get SMS Count");
-
- /* Free resources */
- g_free(at_cmd);
-
- return ret;
-}
-
-/*
- * Operation - send_deliver_report
- *
- * Request -
- * Modem Takes care of sending the ACK to the network
- *
- * Response -
- * Success: Default response always SUCCESS posted
- *
- */
-static TelReturn atmodem_sms_send_deliver_report(CoreObject *co,
- const TelSmsDeliverReportInfo *dr_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
- dbg("Enter");
-
- /*AT Command*/
- if(dr_info->report== TEL_SMS_DELIVERY_REPORT_SUCCESS)
- at_cmd = g_strdup_printf("AT+CNMA=0%s", "\r");
- else
- at_cmd = g_strdup_printf("AT+CNMA=2,3%s%x%s", "/n", 0x00ff00, "");
-
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_sms_send_deliver_report, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Send deliver Report");
-
- /* Free resources */
- g_free(at_cmd);
- return ret;
-}
-
-/*
- * Operation - set SCA
- *
- * Request -
- * AT-Command: AT+CSCA
- * AT+CSCA=<sca>[,<tosca>]
- * where
- * <sca> Service center number
- * <tosca> address type of SCA
- *
- * Response -
- * Success: No result
- * OK
- *
- * Failure:
- * +CMS ERROR: <error>
- */
- static TelReturn atmodem_sms_set_sca(CoreObject *co,
- const TelSmsSca *sca,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
-
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
- gint address_type;
-
- address_type = ((sca->ton << 4) | sca->npi ) | 0x80;
-
- /* AT Command */
- at_cmd = g_strdup_printf("AT+CSCA=\"%s\",%d", sca->number, address_type);
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_sms_set_sca, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Set SCA");
-
- /* Free resources */
- g_free(at_cmd);
-
- return ret;
-}
-
-/*
- * Operation - get SCA
- *
- * Request -
- * AT-Command: AT+CSCA?
- *
- * Response -
- * Success: Single-Line
- * +CSCA: <sca>,<tosca>
- * OK
- * where
- * <sca> Service center number
- * <tosca> address type of SCA
- *
- */
- static TelReturn atmodem_sms_get_sca(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd;
-
- AtmodemRespCbData *resp_cb_data;
- TelReturn ret;
- dbg("Enter");
-
- /* AT Command */
- at_cmd = g_strdup_printf("AT+CSCA?");
-
- /* Response callback data */
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, "+CSCA",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_sms_get_sca, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get SCA");
-
- /* Free resources */
- g_free(at_cmd);
-
- return ret;
-}
-
-/* SMS Operations */
-static TcoreSmsOps atmodem_sms_ops = {
- .send_sms = atmodem_sms_send_sms,
- .read_in_sim = NULL,
- .write_in_sim = NULL,
- .delete_in_sim = NULL,
- .get_count = atmodem_sms_get_count,
- .set_cb_config = NULL,
- .get_cb_config = NULL,
- .get_parameters = NULL, /* TODO - After implemented in imc code */
- .set_parameters = NULL, /* TODO - After implemented in imc code */
- .send_deliver_report = atmodem_sms_send_deliver_report,
- .set_sca = atmodem_sms_set_sca,
- .get_sca = atmodem_sms_get_sca,
- .set_memory_status = NULL,
- .set_message_status = NULL
-};
-
-gboolean atmodem_sms_init(TcorePlugin *p, CoreObject *co)
-{
- dbg("Entry");
-
- /* Set operations */
- tcore_sms_set_ops(co, &atmodem_sms_ops);
-
- /* Add Callbacks */
- tcore_object_add_callback(co,
- "\e+CMT:",
- on_notification_atmodem_sms_incoming_msg, NULL);
- tcore_object_add_callback(co,
- "\%SCDEV",
- on_notification_atmodem_sms_device_ready, NULL);
-
- dbg("Exit");
- return TRUE;
-}
-
-void atmodem_sms_exit(TcorePlugin *p, CoreObject *co)
-{
- dbg("Exit");
-}
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-#include <server.h>
-#include <plugin.h>
-#include <core_object.h>
-#include <hal.h>
-#include <queue.h>
-#include <storage.h>
-#include <at.h>
-
-#include <co_ss.h>
-
-#include "atmodem_ss.h"
-#include "atmodem_common.h"
-
-/* AT+CUSD = [<n> [, <str> [, <dcs>]]]
- * where,
- * <n>
- * 0 Disable
- * 1 Enable
- * 2 Cancel the session
- *
- * <str>
- * Ussd string
- *
- * <dcs>
- * Decoding format
- */
-static gboolean on_notification_atmodem_ss_ussd(CoreObject *co,
- const void *event_data, void *user_data)
-{
- gchar *cmd;
- gchar *resp_str = NULL;
- guchar *dcs_str = NULL;
- TelUtilAlphabetFormat dcs = TEL_UTIL_ALPHABET_FORMAT_SMS_DEFAULT;
- gushort len;
- GSList *tokens = NULL;
- GSList *lines = NULL;
- gint ussd_status = 0;
- TelSsUssdNoti ussd_noti = {0,};
-
- lines = (GSList *) event_data;
- if (g_slist_length(lines) != 1) {
- dbg("Unsolicited message but multiple lines");
- return TRUE;
- }
-
- cmd = (gchar *)lines->data;
- tokens = tcore_at_tok_new(cmd);
-
- /* Parse USSD status */
- resp_str = g_slist_nth_data(tokens, 0);
- if (NULL == resp_str) {
- err("Status is missing from +CUSD Notification");
- goto out;
- } else {
- ussd_status = atoi(resp_str);
- dbg("USSD status[%d]", ussd_status);
-
- if (ussd_status < TEL_SS_USSD_STATUS_NO_ACTION_REQUIRED ||
- ussd_status > TEL_SS_USSD_STATUS_TIME_OUT) {
- err("Invalid USSD status");
- goto out;
- }
-
- /*
- * When network terminated the USSD session,
- * no need to send notification to application
- */
- if (ussd_status == TEL_SS_USSD_STATUS_TERMINATED_BY_NETWORK) {
- /* Destroy USSD session, if any exists */
- UssdSession *ussd_session = tcore_ss_ussd_get_session(co);
- if (ussd_session)
- tcore_ss_ussd_destroy_session(ussd_session);
-
- goto out;
- }
-
- /* Parse USSD string */
- resp_str = g_slist_nth_data(tokens, 1);
-
- resp_str = tcore_at_tok_extract(resp_str);
- if (resp_str) {
- len = strlen((gchar *)resp_str);
- dbg("USSD String: [%s] Length: [%d]", resp_str, len);
- } else {
- dbg("USSD strings is missing from +CUSD Notification");
- goto out;
- }
-
- dcs_str = g_slist_nth_data(tokens, 2);
- }
-
- if (dcs_str) {
- dcs = tcore_util_get_cbs_coding_scheme(atoi((gchar *)dcs_str));
- } else {
- warn("No DCS string! Using default DCS value");
- }
-
- ussd_noti.str = tcore_malloc0(len+1);
- tcore_util_convert_str_to_utf8(ussd_noti.str,
- &len, dcs, (const guchar *)resp_str, len+1);
- ussd_noti.status = ussd_status;
-
- /* Send notification */
- tcore_object_send_notification(co,
- TCORE_NOTIFICATION_SS_USSD,
- sizeof(TelSsUssdNoti), (void *)&ussd_noti);
-
- tcore_free(resp_str);
- tcore_free(ussd_noti.str);
-
-out:
- tcore_at_tok_free(tokens);
- return TRUE;
-}
-
-static gboolean __atmodem_ss_convert_modem_class_to_class(gint classx,
- TelSsClass *class)
-{
- switch (classx) {
- case 7:
- *class = TEL_SS_CLASS_ALL_TELE;
- break;
-
- case 1:
- *class = TEL_SS_CLASS_VOICE;
- break;
-
- case 2:
- *class = TEL_SS_CLASS_ALL_DATA_TELE;
- break;
-
- case 4:
- *class = TEL_SS_CLASS_FAX;
- break;
-
- case 8:
- *class = TEL_SS_CLASS_SMS;
- break;
-
- case 16:
- *class = TEL_SS_CLASS_ALL_CS_SYNC;
- break;
-
- case 32:
- *class = TEL_SS_CLASS_ALL_CS_ASYNC;
- break;
-
- case 64:
- *class = TEL_SS_CLASS_ALL_DEDI_PS;
- break;
-
- case 128:
- *class = TEL_SS_CLASS_ALL_DEDI_PAD;
- break;
-
- default:
- err("Invalid modem class: [%d]", classx);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static guint __atmodem_ss_convert_class_to_atmodem_class(TelSsClass class)
-{
- switch (class) {
- case TEL_SS_CLASS_ALL_TELE:
- return 7;
-
- case TEL_SS_CLASS_VOICE:
- return 1;
-
- case TEL_SS_CLASS_ALL_DATA_TELE:
- return 2;
-
- case TEL_SS_CLASS_FAX:
- return 4;
-
- case TEL_SS_CLASS_SMS:
- return 8;
-
- case TEL_SS_CLASS_ALL_CS_SYNC:
- return 16;
-
- case TEL_SS_CLASS_ALL_CS_ASYNC:
- return 32;
-
- case TEL_SS_CLASS_ALL_DEDI_PS:
- return 64;
-
- case TEL_SS_CLASS_ALL_DEDI_PAD:
- return 128;
-
- default:
- dbg("Unsupported class: [%d], returning default value 7", class);
- return 7;
- }
-}
-
-static gboolean __atmodem_ss_convert_barring_type_to_facility(TelSsBarringType type,
- gchar **facility)
-{
- switch (type) {
- case TEL_SS_CB_TYPE_BAOC:
- *facility = "AO";
- break;
-
- case TEL_SS_CB_TYPE_BOIC:
- *facility = "OI";
- break;
-
- case TEL_SS_CB_TYPE_BOIC_NOT_HC:
- *facility = "OX";
- break;
-
- case TEL_SS_CB_TYPE_BAIC:
- *facility = "AI";
- break;
-
- case TEL_SS_CB_TYPE_BIC_ROAM:
- *facility = "IR";
- break;
-
- case TEL_SS_CB_TYPE_AB:
- *facility = "AB";
- break;
-
- case TEL_SS_CB_TYPE_AOB:
- *facility = "AG";
- break;
-
- case TEL_SS_CB_TYPE_AIB:
- *facility = "AC";
- break;
-
- case TEL_SS_CB_TYPE_NS:
- *facility = "NS";
- break;
-
- default:
- err("Unspported type: [%d]", type);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean __atmodem_ss_convert_forwarding_mode_to_modem_mode(TelSsForwardMode mode,
- guint *modex)
-{
- switch (mode) {
- case TEL_SS_CF_MODE_DISABLE:
- *modex = 0;
- break;
-
- case TEL_SS_CF_MODE_ENABLE:
- *modex = 1;
- break;
-
- case TEL_SS_CF_MODE_REGISTER:
- *modex = 3;
- break;
-
- case TEL_SS_CF_MODE_DEREGISTER:
- *modex = 4;
- break;
-
- default:
- err("Unspported mode: [%d]", mode);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean __atmodem_ss_convert_forwarding_condition_to_modem_reason(TelSsForwardCondition condition,
- guint *reason)
-{
- switch (condition) {
- case TEL_SS_CF_COND_CFU:
- *reason = 0;
- break;
-
- case TEL_SS_CF_COND_CFB:
- *reason = 1;
- break;
-
- case TEL_SS_CF_COND_CFNRY:
- *reason = 2;
- break;
-
- case TEL_SS_CF_COND_CFNRC:
- *reason = 3;
- break;
-
- case TEL_SS_CF_COND_ALL:
- *reason = 4;
- break;
-
- case TEL_SS_CF_COND_ALL_CFC:
- *reason = 5;
- break;
-
- default:
- dbg("Unsupported condition: [%d]", condition);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean __atmodem_ss_convert_modem_cli_dev_status_cli_status(TelSsCliType cli_type,
- gint dev_status, gint *status)
-{
- if (cli_type == TEL_SS_CLI_CLIR) {
- switch (dev_status) {
- case 0:
- *status = TEL_CLIR_STATUS_DEFAULT;
- break;
-
- case 1:
- *status = TEL_CLIR_STATUS_INVOCATION;
- break;
-
- case 2:
- *status = TEL_CLIR_STATUS_SUPPRESSION;
- break;
- default:
- err("Invalid dev status: [%d]", dev_status);
- return FALSE;
- }
- } else { //CLIP, COLP,COLR,CNAP.
- switch (dev_status) {
- case 0:
- *status = TEL_SS_CLI_DISABLE;
- break;
-
- case 1:
- *status = TEL_SS_CLI_ENABLE;
- break;
-
- default:
- err("Invalid dev status: [%d]", dev_status);
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean __atmodem_ss_convert_modem_cli_net_status_cli_status(TelSsCliType cli_type, gint net_status,
- gint *status)
-{
- if (cli_type == TEL_SS_CLI_CLIR) {
- switch (net_status) {
- case 0:
- *status = TEL_CLIR_STATUS_NOT_PROVISIONED;
- break;
- case 1:
- *status = TEL_CLIR_STATUS_PROVISIONED;
- break;
- case 2:
- *status = TEL_CLIR_STATUS_UNKNOWN;
- break;
- case 3:
- *status = TEL_CLIR_STATUS_TEMP_RESTRICTED;
- break;
- case 4:
- *status = TEL_CLIR_STATUS_TEMP_ALLOWED;
- break;
- default:
- err("Invalid clir net status: [%d]", net_status);
- return FALSE;
- }
- } else { //CLIP, COLP,COLR,CNAP.
- switch (net_status) {
- case 0:
- *status = TEL_SS_CLI_NOT_PROVISIONED;
- break;
- case 1:
- *status = TEL_SS_CLI_PROVISIONED;
- break;
- case 2:
- *status = TEL_SS_CLI_UNKNOWN;
- break;
- default:
- err("Invalid status: [%d]", net_status);
- return FALSE;
- }
- }
- return TRUE;
-}
-
-
-/* SS Responses */
-static void on_response_atmodem_ss_set_barring(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success)
- result = TEL_SS_RESULT_SUCCESS;
-
- dbg("Setting Barring status: [%s]",
- (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_ss_get_barring_status(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelSsBarringResp barring_resp = {0,};
- TelSsBarringGetInfo *req_info;
- gint valid_records = 0;
- GSList *resp_data = NULL;
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- req_info = (TelSsBarringGetInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (at_resp) {
- if (at_resp->lines && at_resp->success) {
- resp_data = (GSList *) at_resp->lines;
- barring_resp.record_num= g_slist_length(resp_data);
- dbg("Total records: [%d]", barring_resp.record_num);
- }
- else {
- err("RESPONSE - [NOK]");
- }
- } else {
- err("No response data");
- }
-
- if (barring_resp.record_num > 0) {
- barring_resp.records = tcore_malloc0(
- (barring_resp.record_num) * sizeof(TelSsBarringInfoRecord));
- for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
- const gchar *line;
- GSList *tokens = NULL;
-
- line = (const gchar *) resp_data->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) > 0) {
- gchar *classx_str;
- gchar *status = NULL;
-
- status = g_slist_nth_data(tokens, 0);
- if (!status) {
- dbg("Status is missing");
- tcore_at_tok_free(tokens);
- continue;
- }
-
- if (atoi(status) == 1) {
- barring_resp.records[valid_records].enable = TRUE;
- } else {
- barring_resp.records[valid_records].enable = FALSE;
- }
-
- classx_str = g_slist_nth_data(tokens, 1);
- if (!classx_str) {
- dbg("Class error. Setting to the requested class: [%d]", req_info->class);
- barring_resp.records[valid_records].class = req_info->class;
- } else {
- if (__atmodem_ss_convert_modem_class_to_class(atoi(classx_str),
- &(barring_resp.records[valid_records].class)) == FALSE) {
- tcore_at_tok_free(tokens);
- continue;
- }
- }
-
- barring_resp.records[valid_records].type= req_info->type;
- result = TEL_SS_RESULT_SUCCESS;
- valid_records++;
- } else {
- err("Invalid response message");
- }
- tcore_at_tok_free(tokens);
- }
- }
-
- dbg("Getting Barring status: [%s]",
- (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
- barring_resp.record_num = valid_records;
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &barring_resp, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-
- if (barring_resp.records) {
- tcore_free(barring_resp.records);
- }
-}
-
-static void on_response_atmodem_ss_change_barring_password(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success)
- result = TEL_SS_RESULT_SUCCESS;
-
- dbg("Change Barring Password: [%s]",
- (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_ss_set_forwarding(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success)
- result = TEL_SS_RESULT_SUCCESS;
-
- dbg("Set Forwarding Status: [%s]",
- (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_ss_get_forwarding_status(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelSsForwardingResp forwarding_resp = {0,};
- TelSsForwardGetInfo *req_info;
- gint valid_records = 0;
- GSList *resp_data = NULL;
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- req_info = (TelSsForwardGetInfo *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (at_resp) {
- if (at_resp->lines && at_resp->success) {
- resp_data = (GSList *) at_resp->lines;
- forwarding_resp.record_num= g_slist_length(resp_data);
- dbg("Total records: [%d]", forwarding_resp.record_num);
- }
- else {
- err("RESPONSE - [NOK]");
- }
- } else {
- err("No response data");
- }
-
- if (forwarding_resp.record_num > 0) {
- forwarding_resp.records = tcore_malloc0(
- (forwarding_resp.record_num) * sizeof(TelSsForwardingInfoRecord));
- for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
- const gchar *line;
- GSList *tokens = NULL;
-
- line = (const gchar *) resp_data->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) > 0) {
- gchar *classx_str;
- gchar *status = NULL;
- gchar *number = NULL;
- gchar *time_str = NULL;
-
- status = g_slist_nth_data(tokens, 0);
- if (!status) {
- dbg("Status is missing");
- tcore_at_tok_free(tokens);
- continue;
- }
-
- if (atoi(status) == 1) {
- forwarding_resp.records[valid_records].enable = TRUE;
- } else {
- forwarding_resp.records[valid_records].enable = FALSE;
- }
-
- classx_str = g_slist_nth_data(tokens, 1);
- if (!classx_str) {
- dbg("Class error. Setting to the requested class: [%d]", req_info->class);
- forwarding_resp.records[valid_records].class = req_info->class;
- } else {
- if (__atmodem_ss_convert_modem_class_to_class(atoi(classx_str),
- &(forwarding_resp.records[valid_records].class)) == FALSE) {
- tcore_at_tok_free(tokens);
- continue;
- }
- }
-
- number = g_slist_nth_data(tokens, 2);
- if (number)
- memcpy((forwarding_resp.records[valid_records].number),
- number, strlen(number));
-
- time_str = g_slist_nth_data(tokens, 6);
- if (time_str)
- forwarding_resp.records[valid_records].wait_time = atoi(time_str);
-
- forwarding_resp.records[valid_records].condition = req_info->condition;
-
- result = TEL_SS_RESULT_SUCCESS;
- valid_records++;
- } else {
- err("Invalid response message");
- }
- tcore_at_tok_free(tokens);
- }
- }
-
- dbg("Getting Forwarding Status: [%s]",
- (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
- forwarding_resp.record_num = valid_records;
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &forwarding_resp, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-
- if (forwarding_resp.records) {
- tcore_free(forwarding_resp.records);
- }
-}
-
-static void on_response_atmodem_ss_set_waiting(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success)
- result = TEL_SS_RESULT_SUCCESS;
-
- dbg("Set Waiting Status: [%s]",
- (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_ss_get_waiting_status(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelSsWaitingResp waiting_resp = {0,};
- TelSsClass *class;
- gint valid_records = 0;
- GSList *resp_data = NULL;
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- class = (TelSsClass *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (at_resp) {
- if (at_resp->lines && at_resp->success) {
- resp_data = (GSList *) at_resp->lines;
- waiting_resp.record_num= g_slist_length(resp_data);
- dbg("Total records: [%d]", waiting_resp.record_num);
- }
- else {
- err("RESPONSE - [NOK]");
- }
- } else {
- err("No response data");
- }
-
- if (waiting_resp.record_num > 0) {
- waiting_resp.records = tcore_malloc0(
- (waiting_resp.record_num) * sizeof(TelSsWaitingInfo));
- for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
- const gchar *line;
- GSList *tokens = NULL;
-
- line = (const gchar *) resp_data->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) > 0) {
- gchar *classx_str;
- gchar *status = NULL;
-
- status = g_slist_nth_data(tokens, 0);
- if (!status) {
- dbg("Status is missing");
- tcore_at_tok_free(tokens);
- continue;
- }
-
- if (atoi(status) == 1) {
- waiting_resp.records[valid_records].enable= TRUE;
- } else {
- waiting_resp.records[valid_records].enable = FALSE;
- }
-
- classx_str = g_slist_nth_data(tokens, 1);
- if (!classx_str) {
- dbg("Class error. Setting to the requested class: [%d]", *class);
- waiting_resp.records[valid_records].class = *class;
- } else {
- if (__atmodem_ss_convert_modem_class_to_class(atoi(classx_str),
- &(waiting_resp.records[valid_records].class)) == FALSE) {
- tcore_at_tok_free(tokens);
- continue;
- }
- }
-
- result = TEL_SS_RESULT_SUCCESS;
- valid_records++;
- } else {
- err("Invalid response message");
- }
- tcore_at_tok_free(tokens);
- }
- }
-
- dbg("Getting Waiting Status: [%s]",
- (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
- waiting_resp.record_num = valid_records;
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result,
- &waiting_resp, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-
- if (waiting_resp.records)
- tcore_free(waiting_resp.records);
-}
-
-static void on_response_atmodem_ss_get_cli_status(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelSsCliResp cli_resp = {0,};
- TelSsCliType *cli_type;
- GSList *tokens = NULL;
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- cli_type = (TelSsCliType *)ATMODEM_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- if (*cli_type == TEL_SS_CLI_CDIP) {
- err("Unsupported CLI type: [%d]", *cli_type);
- result = TEL_SS_RESULT_INVALID_PARAMETER;
- goto out;
- }
-
- if (at_resp && at_resp->success) {
- const gchar *line;
- gchar *status = NULL;
- gint net_status;
- gint dev_status;
-
- if (!at_resp->lines) {
- err("Invalid response message");
- goto out;
- }
- line = (const gchar *)at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) < 1) {
- err("Invalid response message");
- goto out;
- }
-
- dbg("RESPONSE OK");
- status = g_slist_nth_data(tokens, 0);
- if (!status) {
- err("dev_status is missing");
- goto out;
- }
- if (!__atmodem_ss_convert_modem_cli_dev_status_cli_status(*cli_type,
- atoi(status), &dev_status))
- goto out;
-
- status = g_slist_nth_data(tokens, 1);
- if (!status) {
- err("net_status is missing");
- goto out;
- }
- if (!__atmodem_ss_convert_modem_cli_net_status_cli_status(*cli_type,
- atoi(status), &net_status))
- goto out;
-
- switch (*cli_type){
- case TEL_SS_CLI_CLIR:
- cli_resp.status.clir.net_status = net_status;
- cli_resp.status.clir.dev_status = dev_status;
- break;
-
- case TEL_SS_CLI_CLIP:
- cli_resp.status.clip.net_status = net_status;
- cli_resp.status.clip.dev_status = dev_status;
- break;
-
- case TEL_SS_CLI_COLP:
- cli_resp.status.colp.net_status = net_status;
- cli_resp.status.colp.dev_status = dev_status;
- break;
-
- case TEL_SS_CLI_COLR:
- cli_resp.status.colr.net_status = net_status;
- cli_resp.status.colr.dev_status = dev_status;
- break;
-
- case TEL_SS_CLI_CNAP:
- cli_resp.status.cnap.net_status = net_status;
- cli_resp.status.cnap.dev_status = dev_status;
- break;
-
- default:
- err("Unsupported CLI type: [%d]", *cli_type);
- result = TEL_SS_RESULT_INVALID_PARAMETER;
- goto out;
- }
-
- cli_resp.type = *cli_type;
- } else {
- err("RESPONSE NOK");
- }
-
-out:
- tcore_at_tok_free(tokens);
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result,
- &cli_resp, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-static void on_response_atmodem_ss_send_ussd_request(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- AtmodemRespCbData *resp_cb_data = user_data;
- TelSsUssdResp ussd_resp = {0,};
- UssdSession *ussd_s = NULL;
-
-
- TelSsResult result = TEL_SS_RESULT_FAILURE; // TODO: CMEE error mapping is required
- dbg("Enter");
-
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- ussd_s = tcore_ss_ussd_get_session(co);
- tcore_check_return(ussd_s != NULL);
-
- tcore_ss_ussd_get_session_type(ussd_s, &ussd_resp.type);
-
- if (at_resp && at_resp->success)
- result = TEL_SS_RESULT_SUCCESS;
-
- dbg("Send Ussd Request: [%s]",
- (result == TEL_SS_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
-
- tcore_ss_ussd_destroy_session(ussd_s);
-
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &ussd_resp, resp_cb_data->cb_data);
-
- atmodem_destroy_resp_cb_data(resp_cb_data);
-}
-
-/* SS Operations */
-/*
- * Operation - set_barring/get_barring_status
- *
- * Request -
- * AT-Command: AT+CLCK=<fac>,<mode>[,<passwd>[,<class>]]
- * where,
- * <fac>
- * Barring facility type. Ref #TelSsBarringType
- *
- * <mode>
- * 0 unlock
- * 1 lock
- * 2 query status
- *
- * <passwd>
- * Barring Password
- *
- * <class>
- * SS class. Ref #TelSsClass
- *
- * <status>
- * 0 not active
- * 1 active
- *
- * Success: when <mode>=2:
- * OK
- * +CLCK: <status>[,<class1> [<CR><LF>
- * +CLCK: <status>,<class2> [...]]
- *
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_ss_set_barring(CoreObject *co,
- const TelSsBarringInfo *barring_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- guint mode;
- guint classx;
- gchar *facility = NULL;
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- if (barring_info->enable == TRUE)
- mode = 1;
- else
- mode = 0;
-
- if (__atmodem_ss_convert_barring_type_to_facility(
- barring_info->type, &facility) == FALSE) {
- err("Invalid arguments");
- return ret;
- }
-
- classx = __atmodem_ss_convert_class_to_atmodem_class(barring_info->class);
-
- dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
-
- /* AT-Command */
- at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,\"%s\",%d",
- facility, mode, barring_info->pwd, classx);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_ss_set_barring, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Barring");
-
- g_free(at_cmd);
- return ret;
-}
-
-static TelReturn atmodem_ss_get_barring_status(CoreObject *co,
- const TelSsBarringGetInfo *get_barring_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- guint mode;
- guint classx;
- gchar *facility = NULL;
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- mode = 2; /* query status - mode is fixed to 2 */
-
- if (__atmodem_ss_convert_barring_type_to_facility(
- get_barring_info->type, &facility) == FALSE) {
- err("Invalid arguments");
- return ret;
- }
-
- classx = __atmodem_ss_convert_class_to_atmodem_class(get_barring_info->class);
-
- dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
-
- /* AT-Command */
- at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,,%d",
- facility, mode, classx);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- (void *)get_barring_info, sizeof(TelSsBarringGetInfo));
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, "+CLCK",
- TCORE_AT_COMMAND_TYPE_MULTILINE,
- NULL,
- on_response_atmodem_ss_get_barring_status, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Barring Status");
-
- g_free(at_cmd);
- return ret;
-}
-
-/*
- * Operation - change_barring_password
- *
- * Request -
- * AT-Command: AT+CPWD= <fac>,<oldpwd>,<newpwd>
- * where,
- * <fac>
- * Barring facility type. Ref #TelSsBarringType
- * Eg: "AB" All Barring services
- *
- * <oldpwd>
- * Old Barring Password
- *
- * <newpwd>
- * New Barring Password
- *
- * Success:
- * OK
- *
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_ss_change_barring_password(CoreObject *co,
- const TelSsBarringPwdInfo *barring_pwd_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- if (barring_pwd_info->old_pwd== NULL || barring_pwd_info->new_pwd == NULL) {
- err("Invalid data");
- return ret;
- }
-
- dbg("Old password: [%s], New password: [%s]",
- barring_pwd_info->old_pwd, barring_pwd_info->new_pwd);
-
- at_cmd = g_strdup_printf("AT+CPWD=\"%s\",\"%s\",\"%s\"", "AB",
- barring_pwd_info->old_pwd, barring_pwd_info->new_pwd);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_ss_change_barring_password, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Change Barring Password");
-
- g_free(at_cmd);
- return ret;
-}
-
-/*
- * Operation - set_forwarding/get_forwarding_status
- *
- * Request -
- * AT-Command: AT+CCFC=<reason>,<mode>[,<number>[,<type>[,<class>[,<subaddr>[,<satype>[,<time>]]]]]]
- * where,
- * <reason>
- * Forwarding Condition. Ref #TelSsForwardCondition
- *
- * <mode>
- * Forwarding Mode. Ref #TelSsForwardMode
- * 0 disable
- * 1 enable
- * 2 query status
- * 3 registration
- * 4 erasure
- *
- *
- * <number>
- * Call Forwarding Number
- *
- * <type>
- * Default 145 when available string includes "+"
- * Otherwise 129
- *
- * <subaddr>
- * Parameter String type subaddress of format specified by <satype>
- *
- * <satype>
- * Parameter type of subaddress octet in integer format
- * Default 128
- *
- * <time>
- * Parameter time in seconds to wait before call is forwarded
- * Default 20, but only when <reason>=2 (no reply) is enabled
- *
- * <class>
- * SS class. Ref #TelSsClass
- *
- * <status>
- * 0 not active
- * 1 active
- *
- * Success: when <mode>=2:
- * OK
- * +CCFC: <status>,<class1>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][<CR><LF>
- * +CCFC: <status>,<class2>[,<number>,<type>[,<subaddr>,<satype>[,<time>]]][...]]
- *
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_ss_set_forwarding(CoreObject *co,
- const TelSsForwardInfo *forwarding_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- gchar *tmp_cmd = NULL;
- guint classx;
- guint reason;
- guint mode;
- guint num_type;
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- classx = __atmodem_ss_convert_class_to_atmodem_class(forwarding_info->class);
-
- if (__atmodem_ss_convert_forwarding_mode_to_modem_mode(
- forwarding_info->mode, &mode) == FALSE) {
- err("Invalid arguments");
- return ret;
- }
-
- if (__atmodem_ss_convert_forwarding_condition_to_modem_reason(
- forwarding_info->condition, &reason) == FALSE) {
- err("Invalid arguments");
- return ret;
- }
-
- if (forwarding_info->number[0] == '+')
- num_type = 145;
- else
- num_type = 129;
-
- dbg("classx: [%d], reason:[%d], mode: [%d]", classx, reason, mode);
-
- if (mode == 3) /* TEL_SS_CF_MODE_REGISTER */
- tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,\"%s\",%d,%d",
- reason, mode, forwarding_info->number, num_type, classx);
- else
- tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d",
- reason, mode, classx);
-
- if (reason == 2) /* TEL_SS_CF_COND_CFNRY */
- at_cmd = g_strdup_printf("%s,,,%d", tmp_cmd, forwarding_info->wait_time);
- else
- at_cmd = g_strdup_printf("%s", tmp_cmd);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_ss_set_forwarding, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Forwarding");
-
- g_free(tmp_cmd);
- g_free(at_cmd);
- return ret;
-}
-
-static TelReturn atmodem_ss_get_forwarding_status(CoreObject *co,
- const TelSsForwardGetInfo *get_forwarding_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- guint classx;
- guint reason;
- guint mode = 2; /* query status */
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- classx = __atmodem_ss_convert_class_to_atmodem_class(get_forwarding_info->class);
-
- if (__atmodem_ss_convert_forwarding_condition_to_modem_reason(
- get_forwarding_info->condition, &reason) == FALSE) {
- err("Invalid arguments");
- return ret;
- }
-
- dbg("classx: [%d], reason: [%d], mode: [%d]", classx, reason, mode);
-
- at_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, mode, classx);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- (void *)get_forwarding_info, sizeof(TelSsForwardGetInfo));
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, "+CCFC",
- TCORE_AT_COMMAND_TYPE_MULTILINE,
- NULL,
- on_response_atmodem_ss_get_forwarding_status, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Forwarding Status");
-
- g_free(at_cmd);
- return ret;
-}
-
-/*
- * Operation - set_waiting/get_waiting_status
- *
- * Request -
- * AT-Command: AT+CCWA=[<n>[,<mode>[,<class>]]]
- * where,
- * <n>
- * Parameter Sets/shows the result code presentation status to the TE.
- * 0 presentation status is disabled to TE(default)
- * 1 presentation status is enabled to TE
- *
- * <mode>
- * 0 Disable call waiting
- * 1 Enable call waiting
- * 2 Query status
- *
- * <class>
- * SS class. Ref #TelSsClass
- *
- * <status>
- * 0 not active
- * 1 active
- *
- * Success: when <mode>=2:
- * OK
- * +CCWA: <status>,<class1>
- * +CCWA: <status>,<class2>
- *
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_ss_set_waiting(CoreObject *co,
- const TelSsWaitingInfo *waiting_info,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- guint classx;
- guint mode;
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- if (waiting_info->enable == TRUE)
- mode = 1;
- else
- mode = 0;
-
- classx = __atmodem_ss_convert_class_to_atmodem_class(waiting_info->class);
-
- dbg("mode: [%d], class: [%d]", mode, classx);
-
- at_cmd = g_strdup_printf("AT+CCWA=1,%d,%d", mode, classx);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_ss_set_waiting, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Waiting");
-
- g_free(at_cmd);
- return ret;
-}
-
-static TelReturn atmodem_ss_get_waiting_status(CoreObject *co,
- TelSsClass ss_class,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- guint classx;
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- classx = __atmodem_ss_convert_class_to_atmodem_class(ss_class);
-
- dbg("class: [%d]", classx);
-
- at_cmd = g_strdup_printf("AT+CCWA=1,2,%d", classx);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data,
- &ss_class, sizeof(TelSsClass));
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, "+CCWA",
- TCORE_AT_COMMAND_TYPE_MULTILINE,
- NULL,
- on_response_atmodem_ss_get_waiting_status, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Waiting Status");
-
- g_free(at_cmd);
- return ret;
-}
-
-/*
- * Operation - get_cli_status
- *
- * Request -
- * AT-Command:
- * For CLIR: AT+CLIR?
- * For CLIP: AT+CLIP?
- * For COLP: AT+COLP?
- * For COLR: AT+COLR?
- * For CNAP: AT+CNAP?
- *
- * Success:
- * OK
- * +CLIR: <n>,<m>
- *
- * where,
- * <m> All CLI except CLIR
- * 0 Not provisioned
- * 1 Provisioned
- * 2 Unknown
- *
- *<m> For CLIR
- * 0 Not provisioned
- * 1 Provisioned in permanent mode
- * 2 Unknown (e.g. no network, etc.)
- * 3 Temporary mode presentation restricted
- * 4 Temporary mode presentation allowed
- *
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_ss_get_cli_status(CoreObject *co,
- TelSsCliType cli_type,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- gchar *cmd_prefix = NULL;
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- switch (cli_type) {
- case TEL_SS_CLI_CLIR:
- cmd_prefix = "+CLIR";
- break;
-
- case TEL_SS_CLI_CLIP:
- cmd_prefix = "+CLIP";
- break;
-
- case TEL_SS_CLI_COLP:
- cmd_prefix = "+COLP";
- break;
-
- case TEL_SS_CLI_COLR:
- cmd_prefix = "+COLR";
- break;
-
- case TEL_SS_CLI_CNAP:
- cmd_prefix = "+CNAP";
- break;
-
- case TEL_SS_CLI_CDIP:
- default:
- dbg("Unsupported CLI type: [%d]", cli_type);
- return ret;
- }
-
- at_cmd = g_strdup_printf("AT%s?", cmd_prefix);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, &cli_type, sizeof(TelSsCliType));
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, cmd_prefix,
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- on_response_atmodem_ss_get_cli_status, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Cli Status");
-
- g_free(at_cmd);
- return ret;
-}
-
-/*
- * Operation - send_ussd_request
- *
- * Request -
- * AT-Command: AT+CUSD = [<n> [, <str> [, <dcs>]]]
- * where,
- * <n>
- * 0 Disable the result code presentation to the TE(default)
- * 1 Enable the result code presentation to the TE
- * 2 Cancel session (not applicable to read command response)
- *
- * <str>
- * USSD string
- *
- * <dcs>
- * Cell Broadcast Data Coding Scheme. Default value is 0.
- *
- * Success:
- * OK
- *
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn atmodem_ss_send_ussd_request(CoreObject *co,
- const TelSsUssdInfo *ussd_request,
- TcoreObjectResponseCallback cb, void *cb_data)
-{
- gchar *at_cmd = NULL;
- UssdSession *ussd_s = NULL;
- AtmodemRespCbData *resp_cb_data = NULL;
- TelReturn ret = TEL_RETURN_INVALID_PARAMETER;
-
- ussd_s = tcore_ss_ussd_get_session(co);
- if (!ussd_s) {
- dbg("USSD session does not exist");
- tcore_ss_ussd_create_session(co, ussd_request->type,
- (void *)ussd_request->str,
- strlen((gchar *)ussd_request->str));
- } else {
- if (ussd_request->type == TEL_SS_USSD_TYPE_USER_INIT) {
- err("USSD session exists");
- return TEL_RETURN_OPERATION_NOT_SUPPORTED;
- }
- tcore_ss_ussd_set_session_type(ussd_s, ussd_request->type);
- }
-
- at_cmd = g_strdup_printf("AT+CUSD=1,\"%s\",%d", ussd_request->str, 0x0f);
-
- resp_cb_data = atmodem_create_resp_cb_data(cb, cb_data, NULL, 0);
-
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_atmodem_ss_send_ussd_request, resp_cb_data,
- on_send_atmodem_request, NULL);
- ATMODEM_CHECK_REQUEST_RET(ret, resp_cb_data, "Send Ussd Request");
-
- g_free(at_cmd);
- return ret;
-}
-
-/* SS Operations */
-static TcoreSsOps atmodem_ss_ops = {
- .set_barring = atmodem_ss_set_barring,
- .get_barring_status = atmodem_ss_get_barring_status,
- .change_barring_password = atmodem_ss_change_barring_password,
- .set_forwarding = atmodem_ss_set_forwarding,
- .get_forwarding_status = atmodem_ss_get_forwarding_status,
- .set_waiting = atmodem_ss_set_waiting,
- .get_waiting_status = atmodem_ss_get_waiting_status,
- .set_cli = NULL,
- .get_cli_status = atmodem_ss_get_cli_status,
- .send_ussd_request = atmodem_ss_send_ussd_request
-};
-
-gboolean atmodem_ss_init(TcorePlugin *p, CoreObject *co)
-{
- dbg("Entry");
-
- /* Set operations */
- tcore_ss_set_ops(co, &atmodem_ss_ops);
-
- /* Add Callbacks */
- tcore_object_add_callback(co,
- "+CUSD:",
- on_notification_atmodem_ss_ussd, NULL);
-
- dbg("Exit");
- return TRUE;
-}
-
-void atmodem_ss_exit(TcorePlugin *p, CoreObject *co)
-{
- dbg("Exit");
-}
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <glib.h>
+
+#include <tcore.h>
+#include <plugin.h>
+#include <hal.h>
+#include <server.h>
+
+#include "s_common.h"
+#include "s_sim.h"
+#include "s_ps.h"
+#include "s_call.h"
+#include "s_ss.h"
+#include "s_sms.h"
+#include "s_network.h"
+#include "s_modem.h"
+
+static void on_hal_recv(TcoreHal *hal,
+ unsigned int data_len, const void *data, void *user_data)
+{
+ hook_hex_dump(RX, data_len, data);
+}
+
+static enum tcore_hook_return on_hal_send(TcoreHal *hal,
+ unsigned int data_len, void *data, void *user_data)
+{
+ hook_hex_dump(TX, data_len, data);
+ return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+static gboolean on_load()
+{
+ dbg("LOAD!!!");
+
+ return TRUE;
+}
+
+static gboolean on_init(TcorePlugin *p)
+{
+ TcoreHal *h;
+
+ dbg("INIT!!!");
+
+ if (!p) {
+ err("Plug-in is NULL");
+ return FALSE;
+ }
+
+ h = tcore_server_find_hal(tcore_plugin_ref_server(p), "vmodem");
+ if (!h) {
+ err("HAL is NULL");
+ return FALSE;
+ }
+
+ tcore_hal_add_send_hook(h, on_hal_send, p);
+ tcore_hal_add_recv_callback(h, on_hal_recv, p);
+
+ /* Initialize Modules */
+ s_modem_init(p, h);
+ s_network_init(p, h);
+ s_sim_init(p, h);
+ s_ps_init(p, h);
+ s_call_init(p, h);
+ s_ss_init(p, h);
+ s_sms_init(p, h);
+#ifndef TEST_AT_SOCKET
+ tcore_hal_set_power(h, TRUE);
+#endif
+
+ /* Send "CPAS" command to invoke POWER UP NOTI */
+ s_modem_send_poweron(p);
+
+ dbg("Init - Successful");
+
+ return TRUE;
+}
+
+static void on_unload(TcorePlugin *p)
+{
+ TcoreHal *h;
+
+ dbg("UNLOAD!!!");
+
+ if (!p) {
+ err("Plug-in is NULL");
+ return;
+ }
+
+ h = tcore_server_find_hal(tcore_plugin_ref_server(p), "vmodem");
+ if (h) {
+ tcore_hal_remove_send_hook(h, on_hal_send);
+ tcore_hal_remove_recv_callback(h, on_hal_recv);
+ }
+
+ /* De-initialize Modules */
+ s_modem_exit(p);
+ s_network_exit(p);
+ s_sim_exit(p);
+ s_ps_exit(p);
+ s_call_exit(p);
+ s_ss_exit(p);
+ s_sms_exit(p);
+}
+
+/* ATMODEM plug-in descriptor */
+struct tcore_plugin_define_desc plugin_define_desc = {
+ .name = "ATMODEM",
+ .priority = TCORE_PLUGIN_PRIORITY_MID,
+ .version = 1,
+ .load = on_load,
+ .init = on_init,
+ .unload = on_unload
+};
+++ /dev/null
-/*
- * tel-plugin-atmodem
- *
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-#include <plugin.h>
-#include <hal.h>
-#include <server.h>
-#include <queue.h>
-#include <core_object.h>
-#include <at.h>
-
-#include "atmodem_common.h"
-#include "atmodem_sim.h"
-#include "atmodem_ps.h"
-#include "atmodem_call.h"
-#include "atmodem_ss.h"
-#include "atmodem_sms.h"
-#include "atmodem_network.h"
-#include "atmodem_modem.h"
-
-/* Initializer Table */
-TcoreObjectInitializer atmodem_init_table = {
- .modem_init = atmodem_modem_init,
- .sim_init = atmodem_sim_init,
- .sat_init = NULL,
- .sap_init = NULL,
- .network_init = atmodem_network_init,
- .ps_init = atmodem_ps_init,
- .call_init = atmodem_call_init,
- .ss_init = atmodem_ss_init,
- .sms_init = atmodem_sms_init,
- .phonebook_init = NULL,
- .gps_init = NULL,
-};
-
-/* Deinitializer Table */
-TcoreObjectDeinitializer atmodem_deinit_table = {
- .modem_deinit = atmodem_modem_exit,
- .sim_deinit = atmodem_sim_exit,
- .sat_deinit = NULL,
- .sap_deinit = NULL,
- .network_deinit = atmodem_network_exit,
- .ps_deinit = atmodem_ps_exit,
- .call_deinit = atmodem_call_exit,
- .ss_deinit = atmodem_ss_exit,
- .sms_deinit = atmodem_sms_exit,
- .phonebook_deinit = NULL,
- .gps_deinit = NULL,
-};
-
-static gboolean on_load()
-{
- dbg("Load!!!");
-
- return TRUE;
-}
-
-static gboolean on_init(TcorePlugin *p)
-{
- dbg("Init!!!");
-
- tcore_check_return_value(p != NULL, FALSE);
-
- /* Initialize Modules (Core Objects) */
- if (tcore_object_init_objects(p, &atmodem_init_table)
- != TEL_RETURN_SUCCESS) {
- err("Failed to initialize Core Objects");
- return FALSE;
- }
-
- /* Power ON modem */
- (void)g_idle_add((GSourceFunc)atmodem_modem_power_on_modem, (gpointer)p);
-
- dbg("Init - Successful");
- return TRUE;
-}
-
-static void on_unload(TcorePlugin *p)
-{
- dbg("Unload!!!");
- tcore_check_return(p != NULL);
-
- /* Deinitialize Modules (Core Objects) */
- tcore_object_deinit_objects(p, &atmodem_deinit_table);
-}
-
-struct tcore_plugin_define_desc plugin_define_desc = {
- .name = "atmodem",
- .priority = TCORE_PLUGIN_PRIORITY_MID,
- .version = 1,
- .load = on_load,
- .init = on_init,
- .unload = on_unload
-};
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <tcore.h>
+#include <hal.h>
+#include <core_object.h>
+#include <plugin.h>
+#include <queue.h>
+#include <server.h>
+#include <co_call.h>
+#include <user_request.h>
+#include <at.h>
+
+#include "s_common.h"
+#include "s_call.h"
+
+static enum tcore_call_status _call_status(unsigned int status)
+{
+ switch (status) {
+ case 0:
+ return TCORE_CALL_STATUS_ACTIVE;
+ case 1:
+ return TCORE_CALL_STATUS_HELD;
+ case 2:
+ return TCORE_CALL_STATUS_DIALING;
+ case 3:
+ return TCORE_CALL_STATUS_ALERT;
+ case 4:
+ return TCORE_CALL_STATUS_INCOMING;
+ case 5:
+ return TCORE_CALL_STATUS_WAITING;
+ case 6:
+ return TCORE_CALL_STATUS_DIALING; //connecting not exist. set to dialing
+ case 7:
+ return TCORE_CALL_STATUS_IDLE;
+ default:
+ return TCORE_CALL_STATUS_IDLE;
+ break;
+ }
+
+ return TCORE_CALL_STATUS_IDLE;
+}
+
+static enum tcore_call_type _call_type(int type)
+{
+ switch (type) {
+ case 0:
+ return TCORE_CALL_TYPE_VOICE;
+ case 1:
+ return TCORE_CALL_TYPE_VIDEO;
+ default:
+ break;
+ }
+
+ err("invalid call type, returing default call type as voice");
+ return TCORE_CALL_TYPE_VOICE;
+}
+
+static void _call_branch_by_status(CoreObject *co,
+ CallObject *call_obj, enum tcore_call_status call_state)
+{
+ guint call_id;
+ enum tcore_call_type call_type;
+ enum tcore_call_status state;
+ TcorePlugin *p = tcore_object_ref_plugin(co);
+
+ state = tcore_call_object_get_status(call_obj);
+
+ dbg("Call State - Present : [%d] New: [%d]", state, call_state);
+ if (call_state == state) {
+ dbg("No change in Call State...");
+ return;
+ }
+
+ call_type = tcore_call_object_get_type(call_obj);
+ call_id = tcore_call_object_get_id(call_obj);
+
+ /* Update Call status */
+ tcore_call_object_set_status(call_obj, call_state);
+
+ if (call_type == TCORE_CALL_TYPE_VOICE) { /* Voice call notification */
+ switch (call_state) {
+ case TCORE_CALL_STATUS_ACTIVE: {
+ struct tnoti_call_status_active data = {0,};
+
+ data.type = call_type;
+ data.id = call_id;
+
+ /* Send notification */
+ tcore_server_send_notification (tcore_plugin_ref_server(p), co,
+ TNOTI_CALL_STATUS_ACTIVE,
+ sizeof(struct tnoti_call_status_active), &data);
+ }
+ break;
+ case TCORE_CALL_STATUS_HELD: {
+ struct tnoti_call_status_held data = {0,};
+
+ data.type = call_type;
+ data.id = call_id;
+
+ /* Send notification */
+ tcore_server_send_notification (tcore_plugin_ref_server(p), co,
+ TNOTI_CALL_STATUS_HELD,
+ sizeof(struct tnoti_call_status_held), &data);
+ }
+ break;
+ case TCORE_CALL_STATUS_DIALING: {
+ struct tnoti_call_status_dialing data = {0,};
+
+ data.type = call_type;
+ data.id = call_id;
+
+ /* Send notification */
+ tcore_server_send_notification (tcore_plugin_ref_server(p), co,
+ TNOTI_CALL_STATUS_DIALING,
+ sizeof(struct tnoti_call_status_dialing), &data);
+ }
+ break;
+ case TCORE_CALL_STATUS_ALERT: {
+ struct tnoti_call_status_alert data = {0,};
+
+ data.type = call_type;
+ data.id = call_id;
+
+ /* Send notification */
+ tcore_server_send_notification (tcore_plugin_ref_server(p), co,
+ TNOTI_CALL_STATUS_ALERT,
+ sizeof(struct tnoti_call_status_alert), &data);
+ }
+ break;
+ case TCORE_CALL_STATUS_INCOMING:
+ case TCORE_CALL_STATUS_WAITING: {
+ struct tnoti_call_status_incoming data = {0,};
+
+ data.type = call_type;
+ data.id = call_id;
+ tcore_call_object_get_number(call_obj, data.cli.number);
+ data.cli.mode = tcore_call_object_get_cli_mode(call_obj);
+ data.cna.mode = tcore_call_object_get_cna_mode(call_obj);
+ tcore_call_object_get_name(call_obj, data.cna.name);
+ data.forward = FALSE;
+ data.active_line = tcore_call_object_get_active_line(call_obj);
+
+ /* Send notification */
+ tcore_server_send_notification (tcore_plugin_ref_server(p), co,
+ TNOTI_CALL_STATUS_INCOMING,
+ sizeof(struct tnoti_call_status_incoming), &data);
+ }
+ break;
+ case TCORE_CALL_STATUS_IDLE: {
+ struct tnoti_call_status_idle idle;
+
+ idle.id = call_id;
+ /* TODO - get proper call end cause. */
+ idle.cause = CALL_END_CAUSE_NONE;
+ idle.type = TCORE_CALL_TYPE_VOICE;
+
+ /* Send notification */
+ tcore_server_send_notification (tcore_plugin_ref_server(p), co,
+ TNOTI_CALL_STATUS_IDLE,
+ sizeof(struct tnoti_call_status_idle), &idle);
+
+ /* Free Call object */
+ tcore_call_object_free(co, call_obj);
+ }
+ break;
+ default:
+ /*Do nothing*/
+ dbg("Default case executed.");
+ }
+ } else {
+ err("Unknown Call type: [%d]", call_type);
+ }
+}
+
+static void _handle_call_get_call_list(CoreObject *co,
+ gboolean flag, void *data)
+{
+ gint call_id;
+ gint direction;
+ gint mode;
+ enum tcore_call_status state;
+ gint mpty;
+ gint ton = 0;
+ GSList *tokens = NULL;
+ gchar *resp = NULL;
+ gchar *line;
+ gchar *num = NULL;
+ gint num_type;
+ gchar number[MAX_CALL_NUMBER_LEN + 1] = {0, };
+ GSList *lines = data;
+ CallObject *call_obj = NULL;
+
+ while (lines != NULL) {
+ line = (gchar *)lines->data;
+ /* point to next node */
+ lines = lines->next;
+
+ /* free previous tokens*/
+ tcore_at_tok_free(tokens);
+
+ tokens = tcore_at_tok_new(line);
+
+ resp = g_slist_nth_data(tokens, 0);
+ if (NULL == resp) {
+ err("Invalid call_id");
+ continue;
+ }
+ call_id = atoi(resp);
+
+ resp = g_slist_nth_data(tokens, 1);
+ if (NULL == resp) {
+ err("Invalid direction");
+ continue;
+ }
+ direction = (atoi(resp) == 0) ? 1 : 0;
+
+ resp = g_slist_nth_data(tokens, 2);
+ if (NULL == resp) {
+ err("Invalid state");
+ continue;
+ }
+ state = _call_status(atoi(resp));
+
+ resp = g_slist_nth_data(tokens, 3);
+ if (NULL == resp) {
+ err("Invalid mode");
+ continue;
+ }
+ mode = _call_type(atoi(resp));
+
+ resp = g_slist_nth_data(tokens, 4);
+ if (NULL == resp) {
+ err("Invalid mpty");
+ continue;
+ }
+ mpty = atoi(resp);
+
+ resp = g_slist_nth_data(tokens, 5);
+ if (NULL == resp) {
+ err("Number is NULL");
+ } else {
+ /* Strike off double quotes */
+ num = tcore_at_tok_extract(resp);
+ dbg("Number: [%s]", num);
+
+ resp = g_slist_nth_data(tokens, 6);
+ if (!resp) {
+ err("Invalid Number type");
+ } else {
+ num_type = atoi(resp);
+
+ /* Check if number is International or National */
+ ton = ((num_type) >> 4) & 0x07;
+ if (ton == 1 && num[0] != '+') {
+ /* International number */
+ number[0] = '+';
+ memcpy(&number[1], num, strlen(num));
+ } else {
+ memcpy(number, num, strlen(num));
+ }
+ }
+ g_free(num);
+ }
+
+ dbg("Call ID: [%d] Direction: [%s] Call Type: [%d] " \
+ "Multi-party: [%s] Number: [%s] Type-of-Number: [%d] State: [%d]", \
+ call_id, (direction ? "Outgoing" : "Incoming"),
+ mode, (mpty ? "YES" : "NO"), number, ton, state);
+
+ call_obj = tcore_call_object_find_by_id(co, call_id);
+ if (NULL == call_obj) {
+ call_obj = tcore_call_object_new(co, call_id);
+ if (NULL == call_obj) {
+ err("Unable to create call object");
+ continue;
+ }
+ }
+
+ /* Set Call parameters */
+ tcore_call_object_set_type(call_obj, mode);
+ tcore_call_object_set_direction(call_obj, direction);
+ tcore_call_object_set_multiparty_state(call_obj, mpty);
+ if (number[0] != '\0')
+ tcore_call_object_set_cli_info(call_obj,
+ TCORE_CALL_CLI_MODE_PRESENT, TCORE_CALL_NO_CLI_CAUSE_NONE, number, strlen(number));
+ else
+ tcore_call_object_set_cli_info(call_obj,
+ TCORE_CALL_CLI_MODE_UNAVAILABLE, TCORE_CALL_NO_CLI_CAUSE_UNAVAILABLE, number, strlen(number));
+ tcore_call_object_set_active_line(call_obj, 0);
+
+ if (flag == TRUE)
+ _call_branch_by_status(co, call_obj, state);
+ else
+ tcore_call_object_set_status(call_obj, state);
+ }
+}
+
+static void _on_response_call_get_call_list(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ CoreObject *co = tcore_pending_ref_core_object(p);
+ GSList *lines = NULL;
+ gint count;
+ gboolean *flag = NULL;
+
+ dbg("Entry");
+
+ if (co == NULL) {
+ err("co missing.");
+ return;
+ }
+
+ flag = (gboolean *)user_data;
+
+ if (at_resp && at_resp->success) {
+ if (NULL == at_resp->lines) {
+ err("invalid response received");
+ return;
+ }
+
+ lines = (GSList *)at_resp->lines;
+ count = g_slist_length(lines);
+ dbg("Total records : %d", g_slist_length(lines));
+ if (0 == count) {
+ err("Call count is zero");
+ return;
+ }
+
+ dbg("RESPONSE OK");
+
+ /* Process +CLCC notification parameter */
+ _handle_call_get_call_list(co, *flag, lines);
+ } else {
+ err("RESPONSE NOK");
+ }
+}
+
+static int _call_get_call_list(CoreObject *co, gboolean flag)
+{
+ gboolean*data = NULL;
+ guint ret = -1;
+ dbg("Entry");
+
+ if (NULL == co) {
+ err("Core Object is NULL");
+ return ret;
+ }
+ /* Response callback data */
+ data = g_try_malloc(sizeof (flag));
+ *data = flag;
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co,
+ "AT+CLCC","+CLCC",
+ TCORE_AT_MULTILINE,
+ NULL,
+ _on_response_call_get_call_list, data,
+ NULL, NULL, 0, NULL, NULL);
+
+ return ret;
+}
+
+
+// NOTIFICATION
+static void __on_notification_call_incoming(CoreObject *co,
+ guint call_id, const void *data)
+{
+ GSList *list = NULL;
+ GSList *tokens = NULL;
+ gchar *resp = NULL;
+ gchar *line;
+ gboolean direction = TRUE;
+ gint mode;
+ gpointer state;
+ enum tcore_call_status call_state;
+ gint mpty;
+ gint ton = 0;
+ gchar *num = NULL;
+ gchar number[MAX_CALL_NUMBER_LEN + 1] = {0, };
+ GSList *lines = (GSList *)data;
+ CallObject *call_obj = NULL;
+
+ dbg("Entry");
+
+ /* Check call with 'Incoming' status already exist */
+ list = tcore_call_object_find_by_status(co, TCORE_CALL_STATUS_INCOMING);
+ if (list != NULL) {
+ err("Incoming Call already exist... Skip!!!");
+ return;
+ }
+
+ call_obj = tcore_call_object_find_by_id(co, call_id);
+ if (call_obj != NULL) {
+ err("co with same id already exist. skip");
+ return;
+ }
+
+ /* Create Call object */
+ call_obj = tcore_call_object_new(co, (guint)call_id);
+ if (NULL == call_obj) {
+ err(" Unable to create call object");
+ return;
+ }
+
+ lines = (GSList *)data;
+ if (lines == NULL) {
+ err("Invalid response received");
+ return;
+ }
+
+ line = (gchar *)lines->data;
+
+ /* Tokenize */
+ tokens = tcore_at_tok_new(line);
+
+ state = g_slist_nth_data(tokens, 2);
+ if (NULL == state) {
+ err("State is missing");
+ goto out;
+ }
+ call_state = _call_status(atoi(state));
+
+ resp = g_slist_nth_data(tokens, 3);
+ if (NULL == resp) {
+ err("Invalid mode");
+ goto out;
+ }
+ mode = _call_type(atoi(resp));
+
+ resp = g_slist_nth_data(tokens, 4);
+ if (NULL == resp) {
+ err("Invalid mpty");
+ goto out;
+ }
+ mpty = atoi(resp);
+
+ resp = g_slist_nth_data(tokens, 5);
+ if (NULL == resp) {
+ err("Number is NULL");
+ } else {
+ /* Strike off double quotes */
+ num = tcore_at_tok_extract(resp);
+ dbg("Number: [%s]", num);
+
+ memcpy(number, num, strlen(num));
+ number[strlen(num)] = '\0';
+ g_free(num);
+ }
+
+ dbg("Call ID: [%d] Direction: [%s] Call Type: [%d] " \
+ "Multi-party: [%s] Number: [%s] Type-of-Number: [%d] State: [%d]", \
+ call_id, (direction ? "Outgoing" : "Incoming"),
+ mode, (mpty ? "YES" : "NO"), number, ton, call_state); /* Set Call parameters */
+
+ /* Update Call Object */
+ tcore_call_object_set_type(call_obj, mode);
+ tcore_call_object_set_direction(call_obj, direction);
+ tcore_call_object_set_multiparty_state(call_obj, mpty);
+ if (number[0] != '\0')
+ tcore_call_object_set_cli_info(call_obj,
+ TCORE_CALL_CLI_MODE_PRESENT, TCORE_CALL_NO_CLI_CAUSE_NONE, number, strlen(number));
+ else
+ tcore_call_object_set_cli_info(call_obj,
+ TCORE_CALL_CLI_MODE_UNAVAILABLE, TCORE_CALL_NO_CLI_CAUSE_UNAVAILABLE, number, strlen(number));
+ tcore_call_object_set_active_line(call_obj, 0);
+
+ /* Send notification */
+ _call_branch_by_status(co, call_obj, call_state);
+
+out:
+ /* Free tokens */
+ tcore_at_tok_free(tokens);
+}
+
+static void __on_notification_call_status(CoreObject *co,
+ guint call_id, enum tcore_call_status call_state)
+{
+ CallObject *call_obj = NULL;
+
+ switch (call_state) {
+ case TCORE_CALL_STATUS_ACTIVE:
+ case TCORE_CALL_STATUS_HELD:
+ case TCORE_CALL_STATUS_ALERT:
+ case TCORE_CALL_STATUS_IDLE: {
+ call_obj = tcore_call_object_find_by_id(co, call_id);
+ if (call_obj == NULL) {
+ err("Unable to find Call Object - Call ID: [%d]", call_id);
+ return;
+ }
+
+ /* Send notification to application */
+ _call_branch_by_status(co, call_obj, call_state);
+ }
+ break;
+
+ case TCORE_CALL_STATUS_DIALING: {
+ call_obj = tcore_call_object_find_by_id(co, call_id);
+ if (!call_obj) {
+ call_obj = tcore_call_object_new(co, call_id);
+ if (!call_obj) {
+ err("Unable to create Call Object");
+ return;
+ }
+ }
+
+ /*
+ * Make request to get current Call list.
+ * Update CallObject with <number>
+ * and send notification to application
+ */
+ _call_get_call_list(co, TRUE);
+ }
+ break;
+
+ default:
+ err("Unhandled Call Status: [%d]", call_state);
+ break;
+ }
+}
+
+static gboolean on_notification_call_status(CoreObject *co,
+ const void *data, void *user_data)
+{
+ GSList *tokens = NULL;
+ GSList *lines = NULL;
+ const gchar *line = NULL;
+ gchar *state = NULL, *call_handle = NULL;
+ enum tcore_call_status status;
+ guint call_id;
+
+ dbg("Entry");
+
+ lines = (GSList *)data;
+ if (lines == NULL) {
+ err("Invalid response received");
+ return TRUE;
+ }
+
+ line = (gchar *)lines->data;
+
+ /* Tokenize */
+ tokens = tcore_at_tok_new(line);
+ call_handle = g_slist_nth_data(tokens, 0);
+ if (NULL == call_handle) {
+ err("call_id missing");
+ goto out;
+ }
+ call_id = atoi(call_handle);
+
+ state = g_slist_nth_data(tokens, 2);
+ if (NULL == state) {
+ err("State is missing");
+ goto out;
+ }
+ status = _call_status(atoi(state));
+
+ dbg("Call ID: [%d] Call Status: [%d]", call_id, status);
+
+ switch (status) {
+ case TCORE_CALL_STATUS_INCOMING:
+ case TCORE_CALL_STATUS_WAITING:
+ dbg("Incoming/Waiting Call...");
+ __on_notification_call_incoming(co, call_id, data);
+ break;
+
+ default:
+ __on_notification_call_status(co, call_id, status);
+ break;
+ }
+
+out:
+ /* Free tokens */
+ tcore_at_tok_free(tokens);
+ return TRUE;
+}
+
+static gboolean on_notification_call_cssu_info(CoreObject *co,
+ const void *event_data, void *user_data)
+{
+ GSList *tokens = NULL;
+ enum tcore_notification_command command = TNOTI_UNKNOWN;
+ gchar *resp = NULL;
+ gchar *cmd = 0;
+ gint local_index = 0;
+ gint code2 = -1;
+ gchar number[MAX_CALL_NUMBER_LEN + 1] = {'\0',};
+ TcorePlugin *p = NULL;
+
+ dbg("Entry");
+
+ if (1 != g_slist_length((GSList *) event_data)) {
+ err("unsolicited msg but multiple line");
+ return TRUE;
+ }
+
+ cmd = (gchar *) ((GSList *) event_data)->data;
+ dbg("ss notification message[%s]", cmd);
+
+ tokens = tcore_at_tok_new(cmd);
+
+ /* parse <code2> */
+ resp = g_slist_nth_data(tokens, 0);
+ if (NULL == resp) {
+ err("Code2 is missing from %CSSU indiaction");
+ tcore_at_tok_free(tokens);
+ return TRUE;
+ }
+ code2 = atoi(resp);
+
+ /* parse [ <index>, <number>] */
+ if ((resp = g_slist_nth_data(tokens, 1)))
+ local_index = atoi(resp);
+
+ if ((resp = g_slist_nth_data(tokens, 2))) {
+ resp = tcore_at_tok_extract((const gchar *)resp);
+ memcpy(number, resp, strlen(resp));
+ number[strlen(resp)] = '\0';;
+ g_free(resp);
+ }
+ dbg("+CSSU: <code2>: %d <index>: %d <number>: %s ", code2, local_index, number);
+
+ /* <code2> - other values will be ignored */
+ switch (code2) {
+ case 0:
+ command = TNOTI_CALL_INFO_FORWARDED;
+ break;
+
+ case 2:
+ command = TNOTI_CALL_INFO_HELD;
+ break;
+
+ case 3:
+ command = TNOTI_CALL_INFO_ACTIVE;
+ break;
+
+ case 4:
+ command = TNOTI_CALL_INFO_JOINED;
+ break;
+
+ case 7:
+ case 8:
+ command = TNOTI_CALL_INFO_TRANSFERED_CALL;
+ break;
+
+ case 9:
+ command = TNOTI_CALL_INFO_DEFLECTED;
+ break;
+
+ default:
+ dbg("Unsupported +CSSU notification: [%d]", code2);
+ break;
+ }
+
+ p = tcore_object_ref_plugin(co);
+
+ if (command != TNOTI_UNKNOWN)
+ tcore_server_send_notification(tcore_plugin_ref_server(p), co,
+ command, 0, NULL);
+
+ tcore_at_tok_free(tokens);
+ return TRUE;
+}
+
+/* Response */
+static void on_response_call_outgoing(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_dial resp = {0, };
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_DIAL,
+ sizeof(struct tresp_call_dial), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_answer(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_answer resp = {0, };
+ struct treq_call_answer *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_answer*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_ANSWER,
+ sizeof(struct tresp_call_answer), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_release(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_end resp = {0, };
+ struct treq_call_end *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_end*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ resp.type = req_buf->type;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_END,
+ sizeof(struct tresp_call_end), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_hold(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_hold resp = {0, };
+ struct treq_call_hold *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_hold*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_HOLD,
+ sizeof(struct tresp_call_hold), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_active(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_active resp = {0, };
+ struct treq_call_active *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_active*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_ACTIVE,
+ sizeof(struct tresp_call_active), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_swap(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_swap resp = {0, };
+ struct treq_call_swap *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_swap*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_SWAP,
+ sizeof(struct tresp_call_swap), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_join(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_join resp = {0, };
+ struct treq_call_join *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_join*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_JOIN,
+ sizeof(struct tresp_call_join), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_split(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_split resp = {0, };
+ struct treq_call_split *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_split*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_SPLIT,
+ sizeof(struct tresp_call_split), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_deflect(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_deflect resp = {0, };
+ struct treq_call_deflect *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_deflect*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_DEFLECT,
+ sizeof(struct tresp_call_deflect), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_call_transfer(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_call_transfer resp = {0, };
+ struct treq_call_transfer *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("Response: [OK]");
+ resp.err = CALL_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = CALL_ERROR_UNKNOWN;
+ /*
+ * TODO -
+ * need to map CME error and final response
+ * error to TelCallResult
+ */
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_call_transfer*) tcore_user_request_ref_data( ur, 0);
+ resp.id = req_buf->id;
+ tcore_user_request_send_response(ur,
+ TRESP_CALL_TRANSFER,
+ sizeof(struct tresp_call_transfer), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+ /* Request */
+static TReturn s_call_outgoing( CoreObject *o, UserRequest *ur)
+{
+ gchar *at_cmd;
+ const gchar *clir;
+ gchar *num;
+ struct treq_call_dial *dial_info = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ dial_info = (struct treq_call_dial*)tcore_user_request_ref_data( ur, 0);
+
+ if (dial_info->type == CALL_TYPE_VIDEO) {
+ err("Video call is not supported in atmodem");
+ return TCORE_RETURN_EPERM;
+ }
+
+ if (!strncmp(dial_info->number, "*31#", 4)) {
+ dbg("clir suppression");
+ clir = "i";
+ num = (gchar *)&(dial_info->number[4]);
+ } else if (!strncmp(dial_info->number, "#31#", 4)) {
+ dbg("clir invocation");
+ clir = "I";
+ num = (gchar *)&(dial_info->number[4]);
+ } else {
+ dbg("set clir state to default");
+ clir = "";
+ num = (gchar *)dial_info->number;
+ }
+
+ /* AT-Command */
+ at_cmd = g_strdup_printf("ATD%s%s;", num, clir);
+ dbg(" at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_outgoing, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_answer( CoreObject *o, UserRequest *ur)
+{
+ gchar *at_cmd;
+ struct treq_call_answer *ans_info = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ ans_info = (struct treq_call_answer*)tcore_user_request_ref_data( ur, 0);
+
+ if (ans_info->type == CALL_ANSWER_TYPE_ACCEPT) {
+ /* AT-Command */
+ at_cmd = g_strdup_printf("%s", "ATA");
+ } else if (ans_info->type == CALL_ANSWER_TYPE_REJECT) {
+ /* AT-Command */
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=0");
+ } else if (ans_info->type == CALL_ANSWER_TYPE_REPLACE) {
+ /* AT-Command */
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=1");
+ } else if (ans_info->type == CALL_ANSWER_TYPE_HOLD_ACCEPT) {
+ /* AT-Command */
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
+ } else {
+ err("Unsupported call answer type");
+ return ret;
+ }
+
+ /* AT-Command */
+ dbg(" at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_answer, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_release( CoreObject *o, UserRequest *ur)
+{
+ gchar *at_cmd;
+ struct treq_call_end *end_info = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ end_info = (struct treq_call_end*)tcore_user_request_ref_data( ur, 0);
+
+ if (end_info->type == CALL_END_TYPE_ALL) {
+ /* AT-Command */
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=8");
+ } else if (end_info->type == CALL_END_TYPE_DEFAULT) {
+ /* AT-Command */
+ at_cmd = g_strdup_printf("%s%d", "AT+CHLD=1",end_info->id);
+ } else if (end_info->type == CALL_END_TYPE_ACTIVE_ALL) {
+ /* AT-Command */
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=1");
+ } else if (end_info->type == CALL_END_TYPE_HOLD_ALL) {
+ /* AT-Command */
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=0");
+ } else {
+ err("Unsupported call end type");
+ return TCORE_RETURN_FAILURE;
+ }
+
+ /* AT-Command */
+ dbg(" at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_release, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_hold( CoreObject *o, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *at_cmd;
+
+ dbg("Entry");
+
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
+ dbg("at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_hold, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_active( CoreObject *o, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *at_cmd;
+
+ dbg("Entry");
+
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
+ dbg("at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_active, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_swap( CoreObject *o, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *at_cmd;
+
+ dbg("Entry");
+
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=2");
+ dbg("at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_swap, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_join( CoreObject *o, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *at_cmd;
+
+ dbg("Entry");
+
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=3");
+ dbg("at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_join, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_split( CoreObject *o, UserRequest *ur)
+{
+ gchar *at_cmd;
+ struct treq_call_split *split_info = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ split_info = (struct treq_call_split*)tcore_user_request_ref_data( ur, 0);
+
+ at_cmd = g_strdup_printf("%s%d", "AT+CHLD=2", split_info->id);
+
+ /* AT-Command */
+ dbg(" at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_split, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_deflect( CoreObject *o, UserRequest *ur)
+{
+ gchar *at_cmd;
+ struct treq_call_deflect *deflect_info = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ deflect_info = (struct treq_call_deflect*)tcore_user_request_ref_data( ur, 0);
+
+ at_cmd = g_strdup_printf("AT+CTFR=%s", deflect_info->number);
+ dbg("at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_deflect, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_call_transfer( CoreObject *o, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *at_cmd;
+
+ dbg("Entry");
+
+ at_cmd = g_strdup_printf("%s", "AT+CHLD=4");
+ dbg("at command : %s", at_cmd);
+
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_call_transfer, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+/* Call Operations */
+static struct tcore_call_operations call_ops = {
+ .dial = s_call_outgoing,
+ .answer = s_call_answer,
+ .end = s_call_release,
+ .hold = s_call_hold,
+ .active = s_call_active,
+ .swap = s_call_swap,
+ .join = s_call_join,
+ .split = s_call_split,
+ .deflect = s_call_deflect,
+ .transfer = s_call_transfer,
+ .start_cont_dtmf = NULL,
+ .stop_cont_dtmf = NULL,
+ .send_burst_dtmf = NULL,
+ .set_sound_path = NULL,
+ .set_sound_volume_level = NULL,
+ .get_sound_volume_level = NULL,
+ .set_sound_mute_status = NULL,
+ .get_sound_mute_status = NULL,
+ .set_preferred_voice_subscription = NULL,
+ .get_preferred_voice_subscription = NULL,
+};
+
+gboolean s_call_init(TcorePlugin *p, TcoreHal *h)
+{
+ CoreObject *o = NULL;
+
+ dbg("entry");
+
+ o = tcore_call_new(p, "call", &call_ops, h);
+ if (!o)
+ return FALSE;
+
+ tcore_object_add_callback( o, "+SCLCC", on_notification_call_status, NULL);
+ tcore_object_add_callback( o, "+CSSU:", on_notification_call_cssu_info, NULL);
+
+ return TRUE;
+}
+
+void s_call_exit( TcorePlugin *p)
+{
+ CoreObject *o;
+
+ o = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL);
+
+ tcore_call_free(o);
+}
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+
+
+#include "s_common.h"
+
+#include <plugin.h>
+
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#define bitsize(type) (sizeof(type) * 8)
+
+#define copymask(type) ((0xffffffff) >> (32 - bitsize(type)))
+
+#define MASK(width, offset, data) \
+ (((width) == bitsize(data)) ? (data) : \
+ ((((copymask(data) << (bitsize(data) - ((width) % bitsize(data)))) & copymask(data)) >> (offset)) & (data))) \
+
+
+#define MASK_AND_SHIFT(width, offset, shift, data) \
+ ((((signed) (shift)) < 0) ? \
+ MASK((width), (offset), (data)) << -(shift) : \
+ MASK((width), (offset), (data)) >> (((signed) (shift)))) \
+
+char _util_unpackb(const char *src, int pos, int len);
+char _util_convert_byte_hexChar(char val);
+
+char _util_unpackb(const char *src, int pos, int len)
+{
+ char result = 0;
+ int rshift = 0;
+
+ src += pos / 8;
+ pos %= 8;
+
+ rshift = MAX(8 - (pos + len), 0);
+
+ if (rshift > 0) {
+ result = MASK_AND_SHIFT(len, pos, rshift, (unsigned char)*src);
+ } else {
+ result = MASK(8 - pos, pos, (unsigned char)*src);
+ src++;
+ len -= 8 - pos;
+
+ if (len > 0) result = (result << len) | (*src >> (8 - len)); // if any bits left
+ }
+
+ return result;
+}
+
+char _util_convert_byte_hexChar(char val)
+{
+ char hex_char;
+
+ if (val <= 9) {
+ hex_char = (char) (val + '0');
+ } else if (val >= 10 && val <= 15) {
+ hex_char = (char) (val - 10 + 'A');
+ } else {
+ hex_char = '0';
+}
+
+ return (hex_char);
+}
+
+gboolean util_byte_to_hex(const char *byte_pdu, char *hex_pdu, int num_bytes)
+{
+ int i;
+ char nibble;
+ int buf_pos = 0;
+
+ for (i = 0; i < num_bytes * 2; i++) {
+ nibble = _util_unpackb(byte_pdu, buf_pos, 4);
+ buf_pos += 4;
+ hex_pdu[i] = _util_convert_byte_hexChar(nibble);
+ }
+
+ return TRUE;
+}
+
+void util_hex_dump(char *pad, int size, const void *data)
+{
+ char buf[255] = {0, };
+ char hex[4] = {0, };
+ int i;
+ unsigned const char *p;
+
+ if (size <= 0) {
+ msg("%sno data", pad);
+ return;
+ }
+
+ p = (unsigned const char *)data;
+
+ snprintf(buf, 255, "%s%04X: ", pad, 0);
+ for (i = 0; i<size; i++) {
+ snprintf(hex, 4, "%02X ", p[i]);
+ strcat(buf, hex);
+
+ if ((i + 1) % 8 == 0) {
+ if ((i + 1) % 16 == 0) {
+ msg("%s", buf);
+ memset(buf, 0, 255);
+ snprintf(buf, 255, "%s%04X: ", pad, i + 1);
+ }
+ else {
+ strcat(buf, " ");
+ }
+ }
+ }
+
+ msg("%s", buf);
+}
+
+void hook_hex_dump(enum direction_e d, int size, const void *data)
+{
+ char *direction;
+
+ if (d == TX)
+ direction = (char *)"TX";
+ else
+ direction = (char *)"RX";
+
+ msg("=== %s data DUMP =====", direction);
+ util_hex_dump((char *)" ", size, data);
+ msg("=== %s data DUMP =====", direction);
+
+}
+
+unsigned int util_assign_message_sequence_id(TcorePlugin *p)
+{
+ struct global_data *gd;
+
+ if (!p) {
+ dbg("plugin is NULL");
+ return -1;
+ }
+
+ gd = tcore_plugin_ref_user_data(p);
+ if (!gd) {
+ dbg("global data is NULL");
+ return -1;
+ }
+
+ if (gd->msg_auto_id_current == 0) {
+ gd->msg_auto_id_current = gd->msg_auto_id_start;
+ dbg("pending_auto_id_current is 0, reset to start");
+ }
+ else if (gd->msg_auto_id_current >= gd->msg_auto_id_end) {
+ gd->msg_auto_id_current = gd->msg_auto_id_start;
+ dbg("pending_auto_id_current is over, reset to start");
+ }
+ else {
+ gd->msg_auto_id_current++;
+ }
+
+ dbg("message_sequence_id = %d", gd->msg_auto_id_current);
+
+ return gd->msg_auto_id_current;
+}
+
+gboolean util_add_waiting_job(GQueue *queue, unsigned int id, UserRequest *ur)
+{
+ struct work_queue_data *wqd;
+
+ if (!queue)
+ return FALSE;
+
+ wqd = calloc(sizeof(struct work_queue_data), 1);
+ if (!wqd)
+ return FALSE;
+
+ wqd->id = id;
+ wqd->ur = tcore_user_request_ref(ur);
+ g_queue_push_tail(queue, wqd);
+
+ dbg("id = %d, ur = 0x%x", wqd->id, wqd->ur);
+ return TRUE;
+}
+
+UserRequest *util_pop_waiting_job(GQueue *queue, unsigned int id)
+{
+ int i = 0;
+ UserRequest *ur;
+ struct work_queue_data *wqd;
+
+ if (!queue)
+ return NULL;
+
+
+ dbg("before waiting job count: %d", g_queue_get_length(queue));
+
+ do {
+ wqd = g_queue_peek_nth(queue, i);
+ if (!wqd)
+ return NULL;
+
+ if (wqd->id == id) {
+ wqd = g_queue_pop_nth(queue, i);
+ break;
+ }
+
+ i++;
+ } while (wqd != NULL);
+
+ dbg("after waiting job count: %d", g_queue_get_length(queue));
+
+ if (!wqd)
+ return NULL;
+
+ ur = wqd->ur;
+ free(wqd);
+
+ return ur;
+}
+
+unsigned char util_hexCharToInt(char c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ return (c - 'A' + 10);
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ {
+ dbg("invalid charater!!");
+ return -1;
+ }
+}
+
+char * util_hexStringToBytes(char * s)
+{
+ char * ret;
+ int i;
+ int sz;
+
+ if (s == NULL)
+ return NULL;
+
+ sz = strlen(s);
+
+ ret = calloc((sz/2)+1, 1);
+
+ dbg("Convert String to Binary!!");
+
+ for (i = 0; i < sz; i += 2) {
+ ret[i / 2] = (char) ((util_hexCharToInt(s[i]) << 4) | util_hexCharToInt(s[i + 1]));
+ dbg("[%02x]", ret[i/2]);
+ }
+
+ return ret;
+}
+
+void on_send_at_request(TcorePending *p,
+ gboolean send_status, void *user_data)
+{
+ dbg("Send - [%s]",
+ (send_status == TRUE ? "OK" : "NOK"));
+}
+
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+
+#include <tcore.h>
+#include <hal.h>
+#include <core_object.h>
+#include <plugin.h>
+#include <queue.h>
+#include <co_modem.h>
+#include <storage.h>
+#include <server.h>
+#include <at.h>
+
+#include "s_common.h"
+#include "s_modem.h"
+
+#if 0
+enum cp_state {
+ CP_STATE_OFFLINE,
+ CP_STATE_CRASH_RESET,
+ CP_STATE_CRASH_EXIT,
+ CP_STATE_BOOTING,
+ CP_STATE_ONLINE,
+ CP_STATE_NV_REBUILDING,
+ CP_STATE_LOADER_DONE,
+};
+
+static gboolean on_sys_event_modem_power(CoreObject *co_modem, const void *event_info, void *user_data)
+{
+ struct tnoti_modem_power modem_power;
+ enum cp_state *state;
+
+ state = (enum cp_state*)event_info;
+ dbg("state : (0x%x)", *state);
+
+ if ( *state == CP_STATE_OFFLINE || *state == CP_STATE_CRASH_RESET ) {
+
+ tcore_modem_set_powered(co_modem, FALSE);
+
+ if ( *state == CP_STATE_OFFLINE )
+ modem_power.state = MODEM_STATE_OFFLINE;
+ else
+ modem_power.state = MODEM_STATE_ERROR;
+
+ } else {
+ dbg("useless state : (0x%x)", *state);
+ return TRUE;
+ }
+
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_modem)), co_modem, TNOTI_MODEM_POWER,
+ sizeof(struct tnoti_modem_power), &modem_power);
+
+ return TRUE;
+}
+#endif
+
+static gboolean on_event_modem_power(CoreObject *co_modem,
+ const void *event_info, void *user_data)
+{
+ struct treq_modem_set_flightmode flight_mode_set;
+ struct tnoti_modem_power modem_power;
+ UserRequest *ur;
+ TcoreHal *h;
+ Storage *strg;
+
+ strg = tcore_server_find_storage(tcore_plugin_ref_server(tcore_object_ref_plugin(co_modem)), "vconf");
+ flight_mode_set.enable = tcore_storage_get_bool(strg, STORAGE_KEY_FLIGHT_MODE_BOOL);
+
+ h = tcore_object_get_hal(co_modem);
+
+ tcore_hal_set_power_state(h, TRUE);
+
+ ur = tcore_user_request_new(NULL, NULL);
+ tcore_user_request_set_data(ur, sizeof(struct treq_modem_set_flightmode), &flight_mode_set);
+ tcore_user_request_set_command(ur, TREQ_MODEM_SET_FLIGHTMODE);
+ tcore_object_dispatch_request(co_modem, ur);
+
+#if 0 /* To be opened later */
+ ur = tcore_user_request_new(NULL, NULL);
+ tcore_user_request_set_command(ur, TREQ_MODEM_GET_IMEI);
+ tcore_object_dispatch_request(co_modem, ur);
+
+ ur = tcore_user_request_new(NULL, NULL);
+ tcore_user_request_set_command(ur, TREQ_MODEM_GET_VERSION);
+ tcore_object_dispatch_request(co_modem, ur);
+#endif
+ tcore_modem_set_powered(co_modem, TRUE);
+
+ modem_power.state = MODEM_STATE_ONLINE;
+
+ /* Send notification */
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_modem)),
+ co_modem,
+ TNOTI_MODEM_POWER,
+ sizeof(struct tnoti_modem_power), &modem_power);
+
+ return TRUE;
+}
+
+static gboolean on_event_modem_phone_state(CoreObject *co_modem,
+ const void *event_info, void *user_data)
+{
+ GSList *lines = (GSList *)event_info;
+ const gchar *line;
+
+ dbg("Modem Power notification - [+SCFUN]");
+
+ if (g_slist_length((GSList *)lines) != 1) {
+ err("+SCFUN unsolicited message expected to be "
+ "Single line but received multiple lines");
+ return TRUE;
+ }
+
+ line = (const gchar *)lines->data;
+ if (line != NULL) {
+ GSList *tokens;
+ char *resp;
+ guint state = 0;
+
+ tokens = tcore_at_tok_new(line);
+ resp = g_slist_nth_data(tokens, 0);
+ dbg("resp: [%s]", resp);
+
+ /* <CP state> */
+ if (resp)
+ state = atoi(resp);
+ dbg("Flight mode State: [%s]", (state ? "OFF" : "ON"));
+
+ /* Set Flight mode */
+ tcore_modem_set_flight_mode_state(co_modem, !state);
+
+ tcore_at_tok_free(tokens);
+ }
+
+ return TRUE;
+}
+
+/* Modem Responses */
+static void on_response_poweron(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+
+ if(at_resp && at_resp->success > 0) {
+ dbg("RESPONSE OK");
+ on_event_modem_power(tcore_pending_ref_core_object(p), NULL, NULL);
+ } else{
+ dbg("RESPONSE NOK");
+ s_modem_send_poweron(tcore_pending_ref_plugin(p));
+ }
+}
+
+static void on_response_modem_set_flight_mode(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ CoreObject *co_modem = NULL;
+ UserRequest *ur = NULL;
+ struct tresp_modem_set_flightmode flight_resp = {0, };
+ const struct treq_modem_set_flightmode *flight_req;
+
+ dbg("Enter");
+
+ co_modem = tcore_pending_ref_core_object(p);
+ ur = tcore_pending_ref_user_request(p);
+ flight_req = tcore_user_request_ref_data(ur, NULL);
+ dbg("req_data->enable: [%d]", flight_req->enable);
+
+ if (at_resp && at_resp->success) {
+ Storage *strg;
+ gboolean flight_mode_state = FALSE;
+
+ if (flight_req->enable == 1)
+ flight_mode_state = TRUE;
+
+ strg = tcore_server_find_storage(tcore_plugin_ref_server(tcore_object_ref_plugin(co_modem)), "vconf");
+ tcore_storage_set_bool(strg, STORAGE_KEY_FLIGHT_MODE_BOOL, flight_mode_state);
+
+ flight_resp.result = TCORE_RETURN_SUCCESS;
+
+ /* Update Core Object */
+ (void)tcore_modem_set_flight_mode_state(co_modem, flight_mode_state);
+ } else
+ flight_resp.result = TCORE_RETURN_FAILURE;
+
+ dbg("Setting Modem Flight mode - [%s] - [%s]",
+ ((flight_req->enable == 1) ? "ON": "OFF"),
+ (flight_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
+
+ if (ur) {
+ if (tcore_user_request_ref_communicator(ur) != NULL) {
+ /* Send Response */
+ tcore_user_request_send_response(ur,
+ TRESP_MODEM_SET_FLIGHTMODE,
+ sizeof(struct tresp_modem_set_flightmode), &flight_resp);
+ } else if (flight_resp.result == TCORE_RETURN_SUCCESS) {
+ struct tnoti_modem_flight_mode flight_mode;
+
+ /* Boot-up Request */
+ err("ur is NULL");
+
+ memset(&flight_mode, 0x0, sizeof(struct tnoti_modem_flight_mode));
+
+ flight_mode.enable = flight_req->enable;
+ dbg("Boot-up: Modem Flight mode - [%s]",
+ (flight_req->enable ? "ON": "OFF"));
+
+ /* Send notification */
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_modem)),
+ co_modem,
+ TNOTI_MODEM_FLIGHT_MODE,
+ sizeof(struct tnoti_modem_flight_mode), &flight_mode);
+ }
+ }
+ else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_modem_get_imei(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+ struct tresp_modem_get_imei imei_resp= {0, };
+
+ dbg("Enter");
+
+ if (at_resp) {
+ if (at_resp->lines) {
+ const gchar *line;
+ GSList *tokens = NULL;
+
+ line = (const gchar *)at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) == 1) {
+ if (at_resp->success) {
+ dbg("RESPONSE - [OK]");
+ g_strlcpy(imei_resp.imei,
+ (const gchar *)g_slist_nth_data(tokens, 0),
+ 16+1);
+ dbg("IMEI: [%s]", imei_resp.imei);
+
+ imei_resp.result = TCORE_RETURN_SUCCESS;
+ } else {
+ err("RESPONSE - [NOK]");
+ err("[%s]", g_slist_nth_data(tokens, 0));
+ }
+ } else {
+ err("Invalid response message");
+ imei_resp.result = TCORE_RETURN_FAILURE;
+ }
+ tcore_at_tok_free(tokens);
+ }
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_MODEM_GET_IMEI,
+ sizeof(struct tresp_modem_get_imei),
+ &imei_resp);
+ } else {
+ err("ur is NULL");
+ }
+
+}
+
+static void on_response_modem_get_version(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+ struct tresp_modem_get_version version_resp= {0, };
+
+ dbg("Enter");
+
+ if (at_resp) {
+ if (at_resp->lines) {
+ const gchar *line;
+ GSList *tokens = NULL;
+
+ line = (const gchar *)at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) > 0) {
+ if (at_resp->success) {
+ gchar *sw_ver = NULL, *hw_ver = NULL;
+ gchar *calib_date = NULL, *p_code = NULL;
+
+ sw_ver = g_slist_nth_data(tokens, 0);
+ hw_ver = g_slist_nth_data(tokens, 1);
+ calib_date = g_slist_nth_data(tokens, 2);
+ p_code = g_slist_nth_data(tokens, 3);
+
+ g_strlcpy(version_resp.software,
+ sw_ver, 32 + 1);
+ g_strlcpy(version_resp.hardware,
+ hw_ver, 32 + 1);
+ g_strlcpy(version_resp.calibration,
+ calib_date, 32 + 1);
+ g_strlcpy(version_resp.product_code,
+ p_code, 32 + 1);
+
+ dbg("Version - Software: [%s] Hardware: [%s] "
+ "Calibration date: [%s] Product Code: [%s]",
+ sw_ver, hw_ver, calib_date, p_code);
+
+ version_resp.result = TCORE_RETURN_SUCCESS;
+ } else {
+ err("RESPONSE - [NOK]");
+ err("[%s]", g_slist_nth_data(tokens, 0));
+ }
+ } else {
+ err("Invalid response message");
+ version_resp.result = TCORE_RETURN_FAILURE;
+ }
+
+ /* Free resources */
+ tcore_at_tok_free(tokens);
+ }
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_MODEM_GET_VERSION,
+ sizeof(struct tresp_modem_get_version), &version_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+/* Requests */
+static TReturn power_on(CoreObject *co_modem, UserRequest *ur)
+{
+ dbg("Modem Power ON request: NOT supported!!!");
+
+ return TCORE_RETURN_ENOSYS;
+}
+
+static TReturn power_off(CoreObject *co_modem, UserRequest *ur)
+{
+ struct tnoti_modem_power modem_power;
+ modem_power.state = MODEM_STATE_OFFLINE;
+
+ tcore_modem_set_powered(co_modem, FALSE);
+
+ /* Send notification */
+ tcore_server_send_notification( tcore_plugin_ref_server(tcore_object_ref_plugin(co_modem)),
+ co_modem,
+ TNOTI_MODEM_POWER,
+ sizeof(struct tnoti_modem_power), &modem_power);
+
+ return TCORE_RETURN_SUCCESS;
+}
+
+static TReturn power_reset(CoreObject *co_modem, UserRequest *ur)
+{
+ dbg("Modem Power RESET request: NOT supported!!!");
+
+ return TCORE_RETURN_ENOSYS;
+}
+
+static TReturn get_imei(CoreObject *co_modem, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ ret = tcore_prepare_and_send_at_request(co_modem,
+ "AT+CGSN", NULL,
+ TCORE_AT_NUMERIC,
+ ur,
+ on_response_modem_get_imei, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+
+static TReturn get_version(CoreObject *co_modem, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ ret = tcore_prepare_and_send_at_request(co_modem, "AT+CGMR", NULL,
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_modem_get_version, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+
+static TReturn set_flight_mode(CoreObject *co_modem, UserRequest *ur)
+{
+ gchar *at_cmd;
+ guint power_mode;
+ const struct treq_modem_set_flightmode *req_data;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ req_data = tcore_user_request_ref_data(ur, NULL);
+
+ dbg("req_data->enable: [%d]", req_data->enable);
+ if (req_data->enable) {
+ dbg("Flight mode - [ON]");
+ power_mode = 0;
+ } else {
+ dbg("Flight mode - [OFF]");
+ power_mode = 1;
+ }
+
+ /* AT-Command */
+ at_cmd = g_strdup_printf("AT+CFUN=%d", power_mode);
+
+ ret = tcore_prepare_and_send_at_request(co_modem, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_modem_set_flight_mode, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn get_flight_mode(CoreObject *co_modem, UserRequest *ur)
+{
+ struct tresp_modem_get_flightmode resp_data;
+ TReturn ret;
+
+ memset(&resp_data, 0x0, sizeof(struct tresp_modem_get_flightmode));
+
+ resp_data.enable = tcore_modem_get_flight_mode_state(co_modem);
+ resp_data.result = TCORE_RETURN_SUCCESS;
+ dbg("Get Flight mode: Flight mdoe: [%s]", (resp_data.enable ? "ON" : "OFF"));
+
+ ret = tcore_user_request_send_response(ur,
+ TRESP_MODEM_GET_FLIGHTMODE,
+ sizeof(struct tresp_modem_get_flightmode), &resp_data);
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+
+/** Modem operations */
+static struct tcore_modem_operations modem_ops = {
+ .power_on = power_on,
+ .power_off = power_off,
+ .power_reset = power_reset,
+ .set_flight_mode = set_flight_mode,
+ .get_imei = get_imei,
+ .get_version = get_version,
+ .get_flight_mode = get_flight_mode,
+};
+
+gboolean s_modem_init(TcorePlugin *p, TcoreHal *h)
+{
+ CoreObject *co_modem;
+
+ co_modem = tcore_modem_new(p, "modem", &modem_ops, h);
+ if (!co_modem) {
+ err("Core object is NULL");
+ return FALSE;
+ }
+
+#if 0
+ tcore_object_add_callback(co_modem, EVENT_SYS_NOTI_MODEM_POWER, on_sys_event_modem_power, NULL);
+#endif
+
+ tcore_object_add_callback(co_modem,
+ "+SCFUN:",
+ on_event_modem_phone_state, NULL);
+
+ return TRUE;
+}
+
+void s_modem_exit(TcorePlugin *p)
+{
+ CoreObject *co_modem;
+
+ if (!p) {
+ err("Plugin is NULL");
+ return;
+ }
+
+ co_modem = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_MODEM);
+
+ tcore_modem_free(co_modem);
+}
+
+gboolean s_modem_send_poweron(TcorePlugin *p)
+{
+ CoreObject *co_modem = NULL;
+ UserRequest *ur = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ co_modem = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_MODEM);
+ ur = tcore_user_request_new(NULL, NULL);
+
+ ret = tcore_prepare_and_send_at_request(co_modem,
+ "AT+CPAS", "+CPAS",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_poweron, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS)
+ tcore_user_request_unref(ur);
+
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ return TRUE;
+}
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <tcore.h>
+#include <hal.h>
+#include <core_object.h>
+#include <plugin.h>
+#include <queue.h>
+#include <co_ps.h>
+#include <co_network.h>
+#include <server.h>
+#include <storage.h>
+#include <at.h>
+
+#include "s_common.h"
+#include "s_network.h"
+
+#define ATMODEM_NETWORK_BASE_16 16
+
+typedef enum {
+ ATMDOEM_NETWORK_ACT_GSM, /* GSM */
+ ATMDOEM_NETWORK_ACT_GSM_COMPACT, /* GSM Compact */
+ ATMDOEM_NETWORK_ACT_UTRAN, /* UTRAN */
+ ATMDOEM_NETWORK_ACT_GSM_EGPRS, /* GSM w/EGPRS */
+ ATMDOEM_NETWORK_ACT_UTRAN_HSDPA, /* UTRAN w/HSDPA */
+ ATMDOEM_NETWORK_ACT_UTRAN_HSUPA, /* UTRAN w/HSUPA */
+ ATMDOEM_NETWORK_ACT_UTRAN_HSDPA_HSUPA, /* UTRAN w/HSDPA and HSUPA */
+ ATMDOEM_NETWORK_ACT_E_UTRAN, /* E-UTRAN */
+} AtmodemNetworkAct;
+
+#define AT_CREG_STAT_NOT_REG 0 /* not registered, MT is not currently searching a new operator to register to */
+#define AT_CREG_STAT_REG_HOME 1 /* registered, home network */
+#define AT_CREG_STAT_SEARCHING 2 /* not registered, but MT is currently searching a new operator to register to */
+#define AT_CREG_STAT_REG_DENIED 3 /* registration denied */
+#define AT_CREG_STAT_UNKNOWN 4 /* unknown */
+#define AT_CREG_STAT_REG_ROAM 5 /* registered, roaming */
+
+#if 0
+static unsigned int lookup_tbl_net_status[] = {
+ [AT_CREG_STAT_NOT_REG] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
+ [AT_CREG_STAT_REG_HOME] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
+ [AT_CREG_STAT_SEARCHING] = NETWORK_SERVICE_DOMAIN_STATUS_SEARCH,
+ [AT_CREG_STAT_REG_DENIED] = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY,
+ [AT_CREG_STAT_UNKNOWN] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
+ [AT_CREG_STAT_REG_ROAM] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
+};
+#endif
+
+#define AT_COPS_MODE_AUTOMATIC 0 /* automatic (<oper> field is ignored) */
+#define AT_COPS_MODE_MANUAL 1 /* manual (<oper> field shall be present, and <AcT> optionally) */
+#define AT_COPS_MODE_DEREGISTER 2 /* deregister from network */
+#define AT_COPS_MODE_SET_ONLY 3 /* set only <format> */
+
+#define AT_COPS_FORMAT_LONG_ALPHANUMERIC 0 /* long format alphanumeric <oper> */
+#define AT_COPS_FORMAT_SHORT_ALPHANUMERIC 1 /* short format alphanumeric <oper> */
+#define AT_COPS_FORMAT_NUMERIC 2 /* numeric <oper> */
+
+#define AT_COPS_ACT_GSM 0 /* GSM */
+#define AT_COPS_ACT_GSM_COMPACT 1 /* GSM Compact */
+#define AT_COPS_ACT_UTRAN 2 /* UTRAN */
+#define AT_COPS_ACT_GSM_EGPRS 3 /* GSM w/EGPRS */
+#define AT_COPS_ACT_UTRAN_HSDPA 4 /* UTRAN w/HSDPA */
+#define AT_COPS_ACT_UTRAN_HSUPA 5 /* UTRAN w/HSUPA */
+#define AT_COPS_ACT_UTRAN_HSDPA_HSUPA 6 /* UTRAN w/HSDPA and HSUPA */
+#define AT_COPS_ACT_E_UTRAN 7 /* E-UTRAN */
+
+static unsigned int lookup_tbl_access_technology[] = {
+ [AT_COPS_ACT_GSM] = NETWORK_ACT_GSM,
+ [AT_COPS_ACT_GSM_COMPACT] = NETWORK_ACT_GSM,
+ [AT_COPS_ACT_UTRAN] = NETWORK_ACT_UTRAN,
+ [AT_COPS_ACT_GSM_EGPRS] = NETWORK_ACT_EGPRS,
+ [AT_COPS_ACT_UTRAN_HSDPA] = NETWORK_ACT_UTRAN,
+ [AT_COPS_ACT_UTRAN_HSUPA] = NETWORK_ACT_UTRAN,
+ [AT_COPS_ACT_UTRAN_HSDPA_HSUPA] = NETWORK_ACT_UTRAN,
+ [AT_COPS_ACT_E_UTRAN] = NETWORK_ACT_GSM_UTRAN,
+};
+
+static gboolean get_serving_network(CoreObject *o, UserRequest *ur);
+
+static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *co_network)
+{
+ Server *s;
+ Storage *strg;
+ void *handle;
+ char query[255] = {0, };
+ GHashTableIter iter;
+ gpointer key, value;
+ GHashTable *result = NULL, *row = NULL;
+ struct tcore_network_operator_info *noi = NULL;
+ int count = 0;
+
+ s = tcore_plugin_ref_server(p);
+ strg = tcore_server_find_storage(s, "database");
+
+ handle = tcore_storage_create_handle(strg, "/opt/dbspace/.mcc_mnc_oper_list.db");
+ if (!handle) {
+ err("fail to create database handle");
+ return;
+ }
+
+ snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list");
+
+ result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+ (GDestroyNotify) g_hash_table_destroy);
+
+ tcore_storage_read_query_database(strg, handle, query, NULL, result, 4);
+
+ g_hash_table_iter_init(&iter, result);
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ row = value;
+ noi = calloc(sizeof(struct tcore_network_operator_info), 1);
+ snprintf(noi->mcc, 4, "%s",(const gchar *)(g_hash_table_lookup(row, "1")));
+ snprintf(noi->mnc, 4, "%s",(const gchar *)(g_hash_table_lookup(row, "2")));
+ snprintf(noi->name, 41, "%s",(const gchar *)(g_hash_table_lookup(row, "3")));
+ snprintf(noi->country, 4, "%s",(const gchar *)(g_hash_table_lookup(row, "0")));
+
+ tcore_network_operator_info_add(co_network, noi);
+ g_free(noi);
+ noi = NULL;
+
+ count++;
+ }
+
+ dbg("count = %d", count);
+
+ g_hash_table_destroy(result);
+
+ tcore_storage_remove_handle(strg, handle);
+}
+
+static enum telephony_network_service_domain_status __atmodem_network_map_stat(guint stat)
+{
+ switch (stat) {
+ case 0:
+ return NETWORK_SERVICE_DOMAIN_STATUS_NO;
+ case 1:
+ return NETWORK_SERVICE_DOMAIN_STATUS_FULL;
+ case 2:
+ return NETWORK_SERVICE_DOMAIN_STATUS_SEARCH;
+ case 3:
+ return NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY;
+ case 4:
+ return NETWORK_SERVICE_DOMAIN_STATUS_NO;
+ case 5:
+ return NETWORK_SERVICE_DOMAIN_STATUS_FULL;
+ default:
+ return NETWORK_SERVICE_DOMAIN_STATUS_NO;
+ }
+}
+
+static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type,
+ int act, int cs_status, int ps_status)
+{
+ enum telephony_network_service_type ret;
+
+ ret = prev_type;
+
+ switch (act) {
+ case NETWORK_ACT_NOT_SPECIFIED:
+ ret = NETWORK_SERVICE_TYPE_UNKNOWN;
+ break;
+
+ case NETWORK_ACT_GSM:
+ if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE)
+ ret = NETWORK_SERVICE_TYPE_2_5G_EDGE;
+ else
+ ret = NETWORK_SERVICE_TYPE_2G;
+ break;
+
+ case NETWORK_ACT_IS95A:
+ case NETWORK_ACT_IS95B:
+ ret = NETWORK_SERVICE_TYPE_2G;
+ break;
+
+ case NETWORK_ACT_CDMA_1X:
+ case NETWORK_ACT_GPRS:
+ ret = NETWORK_SERVICE_TYPE_2_5G;
+ break;
+
+ case NETWORK_ACT_EGPRS:
+ return NETWORK_SERVICE_TYPE_2_5G_EDGE;
+ break;
+
+ case NETWORK_ACT_UMTS:
+ ret = NETWORK_SERVICE_TYPE_3G;
+ break;
+
+ case NETWORK_ACT_EVDO_REV0:
+ case NETWORK_ACT_CDMA_1X_EVDO_REV0:
+ case NETWORK_ACT_EVDO_REVA:
+ case NETWORK_ACT_CDMA_1X_EVDO_REVA:
+ case NETWORK_ACT_EVDV:
+ ret = NETWORK_SERVICE_TYPE_3G;
+ break;
+ default :
+ /*Do Nothing*/
+ dbg ("Default Case executed.");
+ }
+
+ if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) {
+ ret = NETWORK_SERVICE_TYPE_NO_SERVICE;
+ }
+ else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) {
+ if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
+ /* no change */
+ }
+ else {
+ ret = NETWORK_SERVICE_TYPE_SEARCH;
+ }
+ }
+ else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) {
+ if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
+ /* no change */
+ }
+ else {
+ ret = NETWORK_SERVICE_TYPE_EMERGENCY;
+ }
+ }
+
+ return ret;
+}
+
+/* Notifications */
+static gboolean on_notification_atmodem_cs_network_info(CoreObject *co_network,
+ const void *event_info, void *user_data)
+{
+ GSList *lines = NULL;
+ gchar *line = NULL;
+
+ dbg("Network notification - CS network info: [+CREG]");
+
+ lines = (GSList *)event_info;
+ if (g_slist_length(lines) != 1) {
+ err("+CREG unsolicited message expected to be Single line "
+ "but received multiple lines");
+ return TRUE;
+ }
+
+ line = (gchar *) (lines->data);
+ if (line != NULL) {
+ struct tnoti_network_registration_status registration_status = {0, };
+ struct tnoti_network_location_cellinfo cell_info = {0, };
+ GSList *tokens = NULL;
+ gchar *token_str;
+ guint stat = 0, act = 0, lac = 0, ci = 0;
+
+ /*
+ * Tokenize
+ *
+ * +CREG: <stat>[,<lac>,<ci>[,<AcT>]]
+ */
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) < 1) {
+ err("Invalid notification message");
+ goto out;
+ }
+
+ /* <stat> */
+ if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
+ err("No <stat> in +CREG");
+ goto out;
+ }
+ stat = __atmodem_network_map_stat(atoi(token_str)); /*TODO : Confirm*/
+ (void)tcore_network_set_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, stat);
+
+ /* <lac> */
+ if ((token_str = g_slist_nth_data(tokens, 1))) {
+ token_str = tcore_at_tok_extract((const gchar *)token_str);
+
+ lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
+
+ /* Update Location Area Code (lac) information */
+ (void)tcore_network_set_lac(co_network, lac);
+
+ g_free(token_str);
+ } else {
+ dbg("No <lac> in +CREG");
+ (void)tcore_network_get_lac(co_network, &lac);
+ }
+
+ /* <ci> */
+ if ((token_str = g_slist_nth_data(tokens, 2))) {
+ token_str = tcore_at_tok_extract((const gchar *)token_str);
+
+ ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
+
+ /* Update Cell ID (ci) information */
+ (void)tcore_network_set_cell_id(co_network, ci);
+
+ g_free(token_str);
+ } else {
+ dbg("No <ci> in +CREG");
+ (void)tcore_network_get_cell_id(co_network, &ci);
+ }
+
+ /* <AcT> */
+ if ((token_str = g_slist_nth_data(tokens, 3))) {
+ act = lookup_tbl_access_technology[atoi(token_str)]; /*TODO : Modify this mapping*/
+ (void)tcore_network_set_access_technology(co_network, act);
+ } else {
+ dbg("No <AcT> in +CREG");
+ (void)tcore_network_get_access_technology(co_network, &act);
+ }
+ dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d", stat, lac, ci, act);
+
+ /* Send Notification - Network (CS) Registration status */
+ registration_status.cs_domain_status = stat;
+
+ tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ®istration_status.ps_domain_status);
+
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
+ co_network,
+ TNOTI_NETWORK_REGISTRATION_STATUS,
+ sizeof(struct tnoti_network_registration_status), ®istration_status);
+
+#if 0 /* TODO : Implement Roaming State */
+ switch (stat) {
+ case TEL_NETWORK_REG_STATUS_ROAMING:
+ roam_state = TRUE; // no break
+ case TEL_NETWORK_REG_STATUS_REGISTERED:
+ Fetch Network name - Internal request
+ (void)__atmodem_network_fetch_nw_name(co_network,
+ __on_response_atmodem_network_fetch_nw_name_internal, NULL);
+ break;
+ default:
+ break;
+ }
+
+ tcore_network_set_roaming_state(co_network, roam_state);
+#endif
+
+ /* Send Notification - Cell info */
+ cell_info.lac = (gint)lac;
+ cell_info.cell_id = (gint)ci;
+
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
+ co_network,
+ TNOTI_NETWORK_LOCATION_CELLINFO,
+ sizeof(struct tnoti_network_location_cellinfo), &cell_info);
+
+out:
+ /* Free resource */
+ tcore_at_tok_free(tokens);
+ }
+
+ return TRUE;
+}
+
+static gboolean on_notification_atmodem_ps_network_info(CoreObject *co_network,
+ const void *event_info, void *user_data)
+{
+ GSList *lines = NULL;
+ gchar *line = NULL;
+
+ dbg("Network notification - PS network info: [+CGREG]");
+
+ lines = (GSList *)event_info;
+ if (g_slist_length(lines) != 1) {
+ err("+CGREG unsolicited message expected to be Single line "
+ "but received multiple lines");
+ return TRUE;
+ }
+
+ line = (gchar *) (lines->data);
+ if (line != NULL) {
+ struct tnoti_network_registration_status registration_status = {0, };
+ struct tnoti_network_location_cellinfo cell_info = {0, };
+ enum telephony_network_service_type service_type = 0;
+ GSList *tokens = NULL;
+ gchar *token_str;
+ guint act = 0, lac = 0, ci = 0, rac = 0;
+ enum telephony_network_service_domain_status cs_status;
+ enum telephony_network_service_domain_status ps_status;
+
+ /*
+ * Tokenize
+ *
+ * +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]]
+ */
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) < 1) {
+ err("Invalid notification message");
+ goto out;
+ }
+
+ /* <stat> */
+ if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) {
+ err("No <stat> in +CGREG");
+ goto out;
+ }
+ ps_status = __atmodem_network_map_stat(atoi(token_str));
+ (void)tcore_network_set_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status);
+
+ /* <lac> */
+ if ((token_str = g_slist_nth_data(tokens, 1))) {
+ token_str = tcore_at_tok_extract((const gchar *)token_str);
+
+ lac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
+
+ /* Update Location Area Code (lac) information */
+ (void)tcore_network_set_lac(co_network, lac);
+
+ g_free(token_str);
+ } else {
+ dbg("No <lac> in +CGREG");
+ (void)tcore_network_get_lac(co_network, &lac);
+ }
+
+ /* <ci> */
+ if ((token_str = g_slist_nth_data(tokens, 2))) {
+ token_str = tcore_at_tok_extract((const gchar *)token_str);
+
+ ci = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
+
+ /* Update Cell ID (ci) information */
+ (void)tcore_network_set_cell_id(co_network, ci);
+
+ g_free(token_str);
+ } else {
+ dbg("No <ci> in +CGREG");
+ (void)tcore_network_get_cell_id(co_network, &ci);
+ }
+
+ /* <AcT> */
+ if ((token_str = g_slist_nth_data(tokens, 3))) {
+ act = lookup_tbl_access_technology[atoi(token_str)];
+ (void)tcore_network_set_access_technology(co_network, act);
+ } else {
+ dbg("No <AcT> in +CGREG");
+ (void)tcore_network_get_access_technology(co_network, &act);
+ }
+
+ /* <rac> */
+ if ((token_str = g_slist_nth_data(tokens, 4))) {
+ token_str = tcore_at_tok_extract((const gchar *)token_str);
+
+ rac = (guint)strtol(token_str, NULL, ATMODEM_NETWORK_BASE_16);
+
+ /* Update Routing Area Code (rac) information */
+ (void)tcore_network_set_rac(co_network, rac);
+
+ g_free(token_str);
+ } else {
+ err("No <ci> in +CGREG");
+ (void)tcore_network_get_rac(co_network, &rac);
+ }
+ dbg("<stat>: %d <lac>: 0x%x <ci>: 0x%x <AcT>: %d <rac>: 0x%x", ps_status, lac, ci, act, rac);
+
+ /* Send Notification - Network (PS) Registration status */
+ registration_status.ps_domain_status = ps_status;
+
+ (void)tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
+
+ service_type = _get_service_type(service_type, act, cs_status, ps_status);
+ dbg("service_type = %d", service_type);
+ registration_status.service_type = service_type;
+ tcore_network_set_service_type(co_network, service_type);
+
+ (void)tcore_network_get_service_status(co_network, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, ®istration_status.cs_domain_status);
+
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
+ co_network,
+ TNOTI_NETWORK_REGISTRATION_STATUS,
+ sizeof(struct tnoti_network_registration_status), ®istration_status);
+
+#if 0 /* TODO : Implement roaming state */
+ Set Roaming state
+ if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING)
+ roam_state = TRUE;
+
+ tcore_network_set_roaming_state(co_network, roam_state);
+#endif
+
+ /* Send Notification - Cell info */
+ cell_info.lac = lac;
+ cell_info.cell_id = ci;
+
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
+ co_network,
+ TNOTI_NETWORK_LOCATION_CELLINFO,
+ sizeof(struct tnoti_network_location_cellinfo), &cell_info);
+
+ get_serving_network(co_network, NULL);
+
+out:
+ /* Free resource */
+ tcore_at_tok_free(tokens);
+ }
+
+ return TRUE;
+}
+
+static gboolean on_notification_atmodem_network_rssi(CoreObject *co_network,
+ const void *event_info, void *user_data)
+{
+ GSList *lines;
+ const gchar *line = NULL;
+
+ dbg("Network notification - Icon (rssi) info: [+CIEV]");
+
+ lines = (GSList *)event_info;
+ if (g_slist_length(lines) != 1) {
+ err("+CIEV unsolicited message expected to be "
+ "Single line but received multiple lines");
+ return TRUE;
+ }
+
+ line = (const gchar *)lines->data;
+ if (line != NULL) {
+ GSList *tokens;
+ guint descriptor;
+ guint value;
+ static struct tnoti_network_icon_info net_icon_info = {0xff,0,0,0};
+
+ tokens = tcore_at_tok_new(line);
+
+ /* <desc> */
+ descriptor = atoi(g_slist_nth_data(tokens, 0));
+ dbg("Descriptor: [%s]", (descriptor == 10 ? "RSSI"
+ : (descriptor == 15 ? "Battery" : "Unknown")));
+
+ /* <value> */
+ value = atoi(g_slist_nth_data(tokens, 1));
+
+ switch (descriptor) {
+ case 10:
+ dbg("RSSI Level: [%d]", value);
+ net_icon_info.type = NETWORK_ICON_INFO_RSSI;
+ net_icon_info.rssi = value;
+
+ /* Send Notification - Network Rssi */
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_network)),
+ co_network,
+ TNOTI_NETWORK_ICON_INFO,
+ sizeof(struct tnoti_network_icon_info),
+ &net_icon_info);
+ break;
+ case 15:
+ dbg("Battery Level: [%d]", value);
+ break;
+ default:
+ warn("Unknown descriptor: [%d]", descriptor);
+ break;
+ }
+
+ /* Free resource */
+ tcore_at_tok_free(tokens);
+ }
+
+ return TRUE;
+}
+
+static void __on_response_atmodem_network_registration(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ dbg("Entry");
+
+ if (at_resp && at_resp->success) {
+ dbg("Network Registration - [OK]");
+ } else {
+ err("Network Registration - [NOK]");
+ }
+}
+
+static void __atmodem_network_register_to_network(CoreObject *co_network)
+{
+ TReturn ret;
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_network,
+ "AT+COPS=0", NULL,
+ TCORE_AT_NO_RESULT,
+ NULL,
+ __on_response_atmodem_network_registration, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("Sending Network Registration request: [%s]",
+ (ret == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
+}
+
+static void on_sim_resp_hook_get_netname(UserRequest *ur, enum tcore_response_command command, unsigned int data_len,
+ const void *data, void *user_data)
+{
+ const struct tresp_sim_read *resp = data;
+ CoreObject *o = user_data;
+ struct tnoti_network_registration_status regist_status;
+
+ if (command == TRESP_SIM_GET_SPN) {
+ dbg("OK SPN GETTING!!");
+ dbg("resp->result = 0x%x", resp->result);
+ dbg("resp->data.spn.display_condition = 0x%x", resp->data.spn.display_condition);
+ dbg("resp->data.spn.spn = [%s]", resp->data.spn.spn);
+
+ tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *)resp->data.spn.spn);
+
+ /**
+ * display condition
+ * bit[0]: 0 = display of registered PLMN name not required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
+ * 1 = display of registered PLMN name required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
+ * bit[1]: 0 = display of the service provider name is required when registered PLMN is neither HPLMN nor a PLMN in the service provider PLMN list
+ * 1 = display of the service provider name is not required when registered PLMN is neither HPLMN nor a PLMN in the service provider PLMN list
+ */
+ if (resp->data.spn.display_condition & 0x01) {
+ tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+ }
+ if ((resp->data.spn.display_condition & 0x02) == 0) {
+ tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
+ }
+ if ((resp->data.spn.display_condition & 0x03) == 0x01) {
+ tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
+ }
+ }
+
+ tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, ®ist_status.cs_domain_status);
+ tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ®ist_status.ps_domain_status);
+ tcore_network_get_service_type(o, ®ist_status.service_type);
+ regist_status.roaming_status = tcore_network_get_roaming_state(o);
+
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
+ TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), ®ist_status);
+}
+
+/* Hooks */
+static enum tcore_hook_return on_hook_sim_init(Server *s, CoreObject *source,
+ enum tcore_notification_command command,
+ unsigned int data_len, void *data, void *user_data)
+{
+ const struct tnoti_sim_status *sim = data;
+ UserRequest *ur = NULL;
+
+ if (sim->sim_status == SIM_STATUS_INIT_COMPLETED) {
+ CoreObject *co_network = (CoreObject *)user_data;
+ dbg("SIM Initialized!!! Attach to Network");
+
+ /*
+ * TODO - Check for selection_mode
+ * Need to check if it is Manual or Automatic and based on
+ * that need to initiate Network Registration accordingly.
+ */
+ __atmodem_network_register_to_network(co_network);
+
+ /* Need to get SPN when sim initialization complete */
+ ur = tcore_user_request_new(NULL, NULL);
+ tcore_user_request_set_command(ur, TREQ_SIM_GET_SPN);
+ tcore_user_request_set_response_hook(ur, on_sim_resp_hook_get_netname, user_data);
+ tcore_object_dispatch_request(source, ur);
+ }
+ return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+/* Network Responses */
+static void on_response_network_search(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ struct tresp_network_search nw_resp;
+ UserRequest *ur = NULL;
+ int count;
+ GSList *tokens = NULL;
+
+ dbg("Enter");
+
+ memset(&nw_resp, 0x0, sizeof(struct tresp_network_search));
+ nw_resp.result = TCORE_RETURN_FAILURE;
+
+ if (at_resp && at_resp->success) {
+ const gchar *line;
+ GSList *net_token = NULL;
+ gchar *resp;
+
+ if (!at_resp->lines) {
+ err("invalid response received");
+ goto END;
+ }
+
+ line = (char *) at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ nw_resp.list_count = g_slist_length(tokens);
+ if (nw_resp.list_count < 1) {
+ err("invalid message");
+ goto END;
+ }
+
+ dbg("RESPONSE OK");
+ count = 0;
+ for (count = 0; count < nw_resp.list_count; count++) {
+ net_token = tcore_at_tok_new(g_slist_nth_data(tokens, count));
+ if (NULL == net_token)
+ continue;
+
+ /* Status */
+ resp = tcore_at_tok_nth(net_token, 0);
+ if (resp != NULL) {
+ nw_resp.list [count].status = atoi(resp);
+ dbg("Status: [%d]", nw_resp.list [count].status);
+ }
+
+ /* Name */
+ if ((resp = tcore_at_tok_nth(net_token, 1))) {
+ gchar *name = NULL;
+
+ name = tcore_at_tok_extract(resp);
+ dbg("name: [%s]", resp);
+
+ g_strlcpy(nw_resp.list[count].name, name, 41);
+ /* Emulator gives network name as # terminated string*/
+ if (nw_resp.list[count].name[5] == '#')
+ nw_resp.list[count].name[5] = '\0';
+
+ g_free(name);
+ }
+
+ /* Short Alpha name */
+ if ((resp = tcore_at_tok_nth(net_token, 2))) {
+ /* Short Alpha name
+ dbg("Short Alpha name[%s]", resp);
+ plmn_list.network_list[count].network_identity.short_name =
+ tcore_at_tok_extract(resp); */
+ }
+
+ /* PLMN ID */
+ if ((resp = tcore_at_tok_nth(net_token, 3))) {
+ char *plmn = NULL;
+
+ plmn = tcore_at_tok_extract(resp);
+ dbg("PLMN ID: [%s]", resp);
+
+ g_strlcpy(nw_resp.list[count].plmn, plmn, 6);
+
+ g_free(plmn);
+ }
+
+ /* Parse Access Technology */
+ if ((resp = tcore_at_tok_nth(tokens, 4))) {
+ if (strlen(resp) > 0) {
+ gint act = atoi(resp);
+ dbg("AcT: [%d]", act);
+ nw_resp.list[count].act = lookup_tbl_access_technology[act];
+ }
+ } else {
+ nw_resp.list[count].act = NETWORK_ACT_UMTS;
+ }
+
+ dbg("[%d] Status: [%d] name: [%s] PLMN: [%s] AcT: [%d]",
+ count,
+ nw_resp.list [count].status,
+ nw_resp.list [count].name,
+ nw_resp.list [count].plmn,
+ nw_resp.list [count].act);
+
+ tcore_at_tok_free(net_token);
+ }
+
+ nw_resp.result = TCORE_RETURN_SUCCESS;
+ }
+ else {
+ err("RESPONSE NOK");
+ err("CME Error[%s]",(char *)(at_resp->lines ? at_resp->lines->data : "Unknown"));
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_NETWORK_SEARCH,
+ sizeof(struct tresp_network_search), &nw_resp);
+ }
+ else {
+ err("ur is NULL");
+ }
+
+END:
+ dbg("Network search : [%s]",
+ (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
+
+ tcore_at_tok_free(tokens);
+}
+
+static void on_response_network_get_plmn_selection_mode(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ struct tresp_network_get_plmn_selection_mode nw_resp = {0, };
+ UserRequest *ur = NULL;
+ GSList *tokens = NULL;
+
+ dbg("Enter");
+
+ nw_resp.result = TCORE_RETURN_FAILURE; //TODO - CME Error mapping required.
+
+ if (at_resp && at_resp->success) {
+ const gchar *line;
+ gint mode;
+
+ if (!at_resp->lines) {
+ err("invalid response received");
+ goto END;
+ }
+
+ line = (char *) at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) < 1) {
+ msg("invalid message");
+ goto END;
+ }
+ dbg("RESPONSE OK");
+
+ mode = atoi(tcore_at_tok_nth(tokens, 0));
+ if (mode == 0)
+ nw_resp.mode = NETWORK_SELECT_MODE_AUTOMATIC;
+ else if (mode == 1)
+ nw_resp.mode = NETWORK_SELECT_MODE_MANUAL;
+
+ dbg("selection mode[%d]", nw_resp.mode);
+ nw_resp.result = TCORE_RETURN_SUCCESS;
+ } else {
+ err("RESPONSE NOK");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_NETWORK_GET_PLMN_SELECTION_MODE,
+ sizeof(struct tresp_network_get_plmn_selection_mode), &nw_resp);
+ } else {
+ err("ur is NULL");
+ }
+
+END:
+ dbg("Get selection mode : [%s]",
+ (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
+
+ /* Free resource*/
+ tcore_at_tok_free(tokens);
+}
+
+static void on_response_network_set_plmn_selection_mode(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ struct tresp_network_set_plmn_selection_mode nw_resp;
+ UserRequest *ur = NULL;
+
+ dbg("Enter");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ dbg("RESPONSE OK");
+ nw_resp.result = TCORE_RETURN_SUCCESS;
+ } else {
+ err("RESPONSE NOK");
+ if (at_resp->lines)
+ err("CME Error[%s]",(char *)at_resp->lines->data);
+ nw_resp.result = TCORE_RETURN_FAILURE;
+ }
+ } else {
+ err("Response: [NOK]");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_NETWORK_SET_PLMN_SELECTION_MODE,
+ sizeof(struct tresp_network_set_plmn_selection_mode), &nw_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_network_get_serving_network(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ struct tresp_network_get_serving_network nw_resp = {0, };
+ enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
+ UserRequest *ur = NULL;
+ GSList *tokens = NULL;
+ char *plmn = NULL;
+ CoreObject *co_network = tcore_pending_ref_core_object(p);
+ guint lac = 0;
+
+ dbg("Enter");
+
+ if (at_resp && at_resp->success) {
+ const gchar *line;
+ int num_lines, count;
+ char *local_data = NULL;
+
+ if (!at_resp->lines) {
+ err("invalid response received");
+ nw_resp.result = TCORE_RETURN_FAILURE;
+ goto END;
+ }
+
+ dbg("RESPONSE OK");
+ nw_resp.result = TCORE_RETURN_SUCCESS;
+
+ num_lines = g_slist_length(at_resp->lines);
+ dbg("number of lines: %d", num_lines);
+
+ for(count = 0; count < num_lines; count++) {
+ line = g_slist_nth_data(at_resp->lines, count);
+ tokens = tcore_at_tok_new(line);
+ // mode
+ if ((local_data = tcore_at_tok_nth(tokens, 0))) {
+ dbg("mode : %s", local_data);
+ }
+ // format
+ if ((local_data = tcore_at_tok_nth(tokens, 1))) {
+ dbg("format : %s", local_data);
+ }
+ //plmn
+ if ((plmn = tcore_at_tok_nth(tokens, 2))) {
+ dbg("plmn : %s", plmn);
+ g_strlcpy(nw_resp.plmn, plmn, 6);
+ tcore_network_set_plmn(co_network, nw_resp.plmn);
+ if (!g_strcmp0(nw_resp.plmn, "11111")) {
+ /* In case of emulator, need to show "SDK" on indicator instead of "11111" */
+ tcore_network_set_network_name(co_network, TCORE_NETWORK_NAME_TYPE_FULL, "SDK");
+ }
+ }
+ //act
+ if ((local_data = tcore_at_tok_nth(tokens, 3))) {
+ dbg("AcT : %s", local_data);
+ act = lookup_tbl_access_technology[atoi(local_data)];
+ }
+ nw_resp.act = act;
+
+ (void)tcore_network_get_lac(co_network, &lac);
+ dbg("lac : %x", lac);
+
+ nw_resp.gsm.lac = lac;
+
+ tcore_at_tok_free(tokens);
+ }
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_NETWORK_GET_SERVING_NETWORK,
+ sizeof(struct tresp_network_get_serving_network), &nw_resp);
+ } else {
+ struct tnoti_network_change network_change;
+
+ memset(&network_change, 0, sizeof(struct tnoti_network_change));
+ memcpy(network_change.plmn, nw_resp.plmn, 6);
+ network_change.act = act;
+ network_change.gsm.lac = lac;
+
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(p)),
+ tcore_pending_ref_core_object(p),
+ TNOTI_NETWORK_CHANGE,
+ sizeof(struct tnoti_network_change), &network_change);
+ }
+
+END:
+ dbg("Get serving network : [%s]",
+ (nw_resp.result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
+}
+
+/* Requests */
+static TReturn search_network(CoreObject *co_network, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_network,
+ "AT+COPS=?", "+COPS",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_network_search, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+
+
+static TReturn set_plmn_selection_mode(CoreObject *co_network, UserRequest *ur)
+{
+ gchar *at_cmd;
+ struct treq_network_set_plmn_selection_mode *mode_info = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ mode_info = (struct treq_network_set_plmn_selection_mode*)tcore_user_request_ref_data( ur, 0 );
+
+ if (mode_info->mode == NETWORK_SELECT_MODE_AUTOMATIC) {
+ at_cmd = g_strdup_printf("AT+COPS=0");
+ dbg(" Mode - Automatic: -- %s", at_cmd);
+ } else {
+ gint act;
+
+ switch (mode_info->act) {
+ case NETWORK_ACT_GSM:
+ case NETWORK_ACT_GPRS:
+ case NETWORK_ACT_EGPRS:
+ act = 0;
+ break;
+ case NETWORK_ACT_UMTS:
+ case NETWORK_ACT_GSM_UTRAN:
+ act = 2;
+ break;
+ default:
+ err("Unsupported AcT: [%d]", mode_info->act);
+ return ret;
+ }
+ at_cmd = g_strdup_printf("AT+COPS=1,2,\"%s\",%d", mode_info->plmn, act);
+ }
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_network, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_network_set_plmn_selection_mode, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn get_plmn_selection_mode(CoreObject *co_network, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_network,
+ "AT+COPS?", "+COPS",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_network_get_plmn_selection_mode, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+
+static TReturn get_serving_network(CoreObject *co_network, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_network,
+ "AT+COPS?", "+COPS",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_network_get_serving_network, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+
+/** Network operations */
+static struct tcore_network_operations network_ops = {
+ .search = search_network,
+ .set_plmn_selection_mode = set_plmn_selection_mode,
+ .get_plmn_selection_mode = get_plmn_selection_mode,
+ .set_service_domain = NULL,
+ .get_service_domain = NULL,
+ .set_band = NULL,
+ .get_band = NULL,
+ .set_preferred_plmn = NULL,
+ .get_preferred_plmn = NULL,
+ .set_order = NULL,
+ .get_order = NULL,
+ .set_power_on_attach = NULL,
+ .get_power_on_attach = NULL,
+ .set_cancel_manual_search = NULL,
+ .get_serving_network = get_serving_network,
+};
+
+gboolean s_network_init(TcorePlugin *p, TcoreHal *h)
+{
+ CoreObject *co_network;
+
+ co_network = tcore_network_new(p, "umts_network", &network_ops, h);
+ if (!co_network) {
+ err("Core object is NULL");
+ return FALSE;
+ }
+
+ /* Add Callbacks */
+ tcore_object_add_callback(co_network,
+ "+CREG:",
+ on_notification_atmodem_cs_network_info, NULL);
+ tcore_object_add_callback(co_network,
+ "+CGREG:",
+ on_notification_atmodem_ps_network_info, NULL);
+ tcore_object_add_callback(co_network,
+ "+CIEV:",
+ on_notification_atmodem_network_rssi, NULL);
+
+ /* Add notification hook */
+ tcore_server_add_notification_hook(tcore_plugin_ref_server(p),
+ TNOTI_SIM_STATUS,
+ on_hook_sim_init, co_network);
+
+ _insert_mcc_mnc_oper_list(p, co_network);
+
+ return TRUE;
+}
+
+void s_network_exit(TcorePlugin *p)
+{
+ CoreObject *co_network;
+
+ if (!p) {
+ err("Plugin is NULL");
+ return;
+ }
+
+ co_network = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_NETWORK);
+
+ tcore_network_free(co_network);
+}
+
--- /dev/null
+/**
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
+ * Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <arpa/inet.h>
+
+#include <fcntl.h>
+
+#include <tcore.h>
+#include <hal.h>
+#include <core_object.h>
+#include <plugin.h>
+#include <queue.h>
+#include <co_ps.h>
+#include <co_context.h>
+#include <user_request.h>
+#include <server.h>
+#include <util.h>
+#include <type/ps.h>
+#include <at.h>
+
+#include "s_common.h"
+#include "s_ps.h"
+
+static void __notify_context_status_changed(CoreObject *co_ps, guchar context_id, gint status)
+{
+ Server *server;
+ struct tnoti_ps_call_status ps_call_status;
+
+ dbg("Entry");
+
+ ps_call_status.context_id = (guint)context_id;
+ ps_call_status.state = status;
+ ps_call_status.result = TCORE_RETURN_SUCCESS;
+
+ dbg("Sending PS Call Status Notification - Context ID: [%d] Context State: [%d]",
+ ps_call_status.context_id, ps_call_status.state);
+
+ /* Send PS CALL Status Notification */
+ server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps));
+ tcore_server_send_notification(server, co_ps,
+ TNOTI_PS_CALL_STATUS,
+ sizeof(struct tnoti_ps_call_status),
+ &ps_call_status);
+
+ dbg("Exit");
+}
+
+static void on_response_undefine_context_cmd(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *resp = data;
+
+ dbg("Entered");
+
+ if (resp && resp->success) {
+ dbg("Response Ok");
+ return;
+ }
+ dbg("Response NOk");
+}
+
+static void __send_undefine_context_cmd(CoreObject *co_ps, CoreObject *ps_context)
+{
+ char *at_cmd;
+ int context_id = 0;
+ TReturn ret;
+
+ dbg("Entered");
+
+ /*Getting Context ID from Core Object*/
+ context_id = tcore_context_get_id(ps_context);
+
+ at_cmd = g_strdup_printf("AT+CGDCONT=0,%d", context_id);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_ps,
+ at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ NULL,
+ on_response_undefine_context_cmd, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resource */
+ g_free(at_cmd);
+
+ return;
+}
+
+static void __ps_setup_pdp(CoreObject *co_ps, gint result,
+ const gchar *netif_name, void *user_data)
+{
+ CoreObject *ps_context = user_data;
+ guchar context_id;
+
+ CHECK_AND_RETURN(ps_context != NULL);
+
+ dbg("Enter");
+
+ if (result < 0) {
+ err("Failed to setup PDP");
+
+ /* Deactivate PDP context */
+ __send_undefine_context_cmd(co_ps, ps_context);
+
+ return;
+ }
+
+ dbg("devname = [%s]", netif_name);
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ __notify_context_status_changed(co_ps, context_id, 1);
+
+ dbg("Exit");
+}
+
+static void __on_response_get_ipconfiguration(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ CoreObject *co_ps = tcore_pending_ref_core_object(p);
+ CoreObject *ps_context = user_data;
+ const TcoreATResponse *at_resp = data;
+ guchar context_id;
+ GSList *p_cur = NULL;
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ if (at_resp && at_resp->success) {
+ for (p_cur = at_resp->lines; p_cur != NULL; p_cur = p_cur->next) {
+ const gchar *line;
+ GSList *tokens = NULL;
+
+ line = (const char *) p_cur->data;
+ tokens = tcore_at_tok_new(line);
+
+ if (g_slist_length(tokens) >= 2) {
+ gchar *pdp_type = NULL, *apn = NULL;
+ gchar *ip = NULL, *pdp_address = NULL, *p_cid = NULL;
+
+ p_cid = g_slist_nth_data(tokens, 0);
+ dbg("cid: %d", p_cid);
+
+ /* Send IP Configuration noti only on the requested CID. */
+ if (atoi(p_cid) && (context_id == (unsigned int)atoi(p_cid))) {
+ TcoreHal *hal = tcore_object_get_hal(co_ps);
+
+ pdp_type = g_slist_nth_data(tokens, 1);
+ dbg("PDP type: %s", pdp_type);
+
+ if (pdp_type != NULL) {
+ apn = g_slist_nth_data(tokens, 2);
+ dbg("APN: %s", apn);
+ }
+ if (apn != NULL) {
+ ip = g_slist_nth_data(tokens, 3);
+ pdp_address = tcore_at_tok_extract(ip);
+ dbg("IP address: %s", ip);
+ }
+
+ (void)tcore_context_set_address(ps_context, (const char*)pdp_address);
+ g_free(pdp_address);
+
+ dbg("Adding default DNS pri: 8.8.8.8 sec: 8.8.4.4");
+
+ tcore_context_set_dns1(ps_context, "8.8.8.8");
+ tcore_context_set_dns2(ps_context, "8.8.4.4");
+
+ /* Mount network interface */
+ if (tcore_hal_setup_netif(hal, co_ps, __ps_setup_pdp, ps_context, context_id, TRUE)
+ != TCORE_RETURN_SUCCESS) {
+ err("Setup network interface failed");
+ return;
+ }
+ } else {
+ err("No matched response with CID: %d", atoi(p_cid));
+ }
+ }
+ }
+ }else {
+ err("Response NOK");
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ __notify_context_status_changed(co_ps, context_id, 3);
+ }
+}
+
+static void __get_ipconfiguration(CoreObject *co_ps, CoreObject *ps_context)
+{
+ TReturn ret;
+
+ dbg("Enter");
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_ps,
+ "AT+CGDCONT?", NULL,
+ TCORE_AT_NO_RESULT,
+ NULL,
+ __on_response_get_ipconfiguration,
+ ps_context,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS){
+ err("Failed to prepare and send AT request");
+
+ /* Deactivate PDP context */
+ __send_undefine_context_cmd(co_ps, ps_context);
+ }
+
+ dbg("Exit");
+}
+
+static void __on_response_attach_ps(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ CoreObject *co_ps = tcore_pending_ref_core_object(p);
+ CoreObject *ps_context = user_data;
+ const TcoreATResponse *at_resp = data;
+ guchar context_id;
+
+ CHECK_AND_RETURN(at_resp != NULL);
+ CHECK_AND_RETURN(ps_context != NULL);
+
+ if (at_resp && at_resp->success) {
+ __get_ipconfiguration(co_ps, ps_context);
+ return;
+ }
+
+ err("Response NOK");
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ __notify_context_status_changed(co_ps, context_id, 3);
+
+ dbg("Exit");
+}
+
+static void __attach_ps(CoreObject *co_ps, CoreObject *ps_context)
+{
+ TReturn ret;
+
+ dbg("Enter");
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_ps,
+ "ATD*99***1#", NULL,
+ TCORE_AT_NO_RESULT,
+ NULL,
+ __on_response_attach_ps, ps_context,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS){
+ err("Failed to prepare and send AT request");
+
+ /* Deactivate PDP context */
+ __send_undefine_context_cmd(co_ps, ps_context);
+ }
+
+ dbg("Exit");
+}
+
+static void on_response_ps_activate_context(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ CoreObject *co_ps = tcore_pending_ref_core_object(p);
+ const TcoreATResponse *at_resp = data;
+ CoreObject *ps_context = user_data;
+
+ dbg("Enter");
+
+ CHECK_AND_RETURN(at_resp != NULL);
+ CHECK_AND_RETURN(ps_context != NULL);
+
+ if (at_resp && at_resp->success) {
+ dbg("Response OK");
+ __attach_ps(co_ps, ps_context);
+ } else {
+ guchar context_id;
+
+ err("Response NOK");
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ __notify_context_status_changed(co_ps, context_id, 3);
+ }
+
+ dbg("Exit");
+}
+
+static void on_response_ps_deactivate_context(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ CoreObject *co_ps = tcore_pending_ref_core_object(p);
+ TcoreHal *hal = tcore_object_get_hal(co_ps);
+ const TcoreATResponse *at_resp = data;
+ CoreObject *ps_context = user_data;
+ guchar context_id;
+
+ dbg("Enter");
+
+ CHECK_AND_RETURN(at_resp != NULL);
+ CHECK_AND_RETURN(ps_context != NULL);
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ /*
+ * AT+CGACT = 0 is returning NO CARRIER or an error. Just test if the
+ * response contains NO CARRIER else decode CME error.
+ */
+ if (at_resp && at_resp->success) {
+ const gchar *line;
+
+ line = (const gchar *)at_resp->lines->data;
+ if (g_strcmp0(line, "NO CARRIER") != 0) {
+ err("%s", line);
+ err("Context %d has not been deactivated", context_id);
+
+ goto out;
+ }
+ }
+
+ __notify_context_status_changed(co_ps, context_id, 3);
+
+ if (tcore_hal_setup_netif(hal, co_ps, NULL, NULL, context_id, FALSE) != TCORE_RETURN_SUCCESS)
+ err("Failed to disable network interface");
+
+out:
+ dbg("Exit");
+}
+
+static void on_response_ps_define_context(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
+ CoreObject *ps_context = (CoreObject *) user_data;
+ CoreObject *co_ps = tcore_pending_ref_core_object(p);
+ guchar context_id;
+ gint curr_call_status;
+
+ dbg("entry");
+
+ CHECK_AND_RETURN(at_resp != NULL);
+ CHECK_AND_RETURN(ps_context != NULL);
+
+ if (at_resp && at_resp->success) {
+ dbg("Response OK");
+ curr_call_status = 0;
+ tcore_context_set_state(co_ps, CONTEXT_STATE_ACTIVATED);
+ }else {
+ err("ERROR[%s]",at_resp->final_response);
+ curr_call_status = 3;
+ }
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ __notify_context_status_changed(co_ps, context_id, curr_call_status);
+}
+
+/*
+ * Operation - PDP Context Activate
+ *
+ * Request -
+ * AT-Command: AT+CGACT= [<state> [, <cid> [, <cid> [,...]]]]
+ *
+ * where,
+ * <state>
+ * indicates the state of PDP context activation
+ *
+ * 1 activated
+ *
+ * <cid>
+ * It is a numeric parameter which specifies a particular PDP context definition
+ *
+ * Response -
+ * Success: (No Result)
+ * OK
+ * Failure:
+ * +CME ERROR: <error>
+ */
+static TReturn activate_ps_context(CoreObject *o, CoreObject *ps_context, void* user_data)
+{
+ gchar *at_cmd = NULL;
+ TReturn ret;
+ guchar context_id;
+
+ dbg("Entry");
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ at_cmd = g_strdup_printf("AT+CGACT=1,%d", context_id);
+ dbg(" at command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o,
+ at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ NULL,
+ on_response_ps_activate_context, ps_context,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS){
+ err("AT request failed. Send notification for call status [DISCONNECTED]");
+
+ __notify_context_status_changed(o, context_id, 3);
+ }
+ g_free(at_cmd);
+ dbg("Exit");
+
+ return ret;
+}
+
+/*
+ * Operation - PDP Context Deactivate
+ *
+ * Request -
+ * AT-Command: AT+CGACT= [<state> [, <cid> [, <cid> [,...]]]]
+ *
+ * where,
+ * <state>
+ * indicates the state of PDP context activation
+ *
+ * 0 deactivated
+ *
+ * <cid>
+ * It is a numeric parameter which specifies a particular PDP context definition
+ *
+ * Response -
+ * Success: (No Result)
+ * OK
+ * Failure:
+ * +CME ERROR: <error>
+ */
+static TReturn deactivate_ps_context(CoreObject *o, CoreObject *ps_context, void* user_data)
+{
+ gchar *at_cmd = NULL;
+ TReturn ret;
+ guchar context_id;
+
+ dbg("Entry");
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+
+ at_cmd = g_strdup_printf("AT+CGACT=0,%d", context_id);
+ dbg(" at command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o,
+ at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ NULL,
+ on_response_ps_deactivate_context, ps_context,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS){
+ err("AT request failed. Send notification for call status [DISCONNECTED]");
+ __notify_context_status_changed(o, context_id, 3);
+ }
+ g_free(at_cmd);
+ dbg("Exit");
+
+ return ret;
+}
+
+/*
+ * Operation - Define PDP Context
+ *
+ * Request -
+ * AT-Command: AT+CGDCONT= [<cid> [, <PDP_type> [, <APN> [, <PDP_addr> [,
+ * <d_comp> [, <h_comp> [, <pd1> [... [, pdN]]]]]]]]]
+ * where,
+ * <cid>
+ * It is a numeric parameter, which specifies a particular PDP context definition
+ *
+ * <PDP_type>
+ * "IP" Internet Protocol (IETF STD 5)
+ * "IPV6" Internet Protocol, version 6 (IETF RFC 2460)
+ * "IPV4V6" Virtual <PDP_type>introduced to handle dual IP stack UE capability (see 3GPP
+ * TS 24.301[83])
+ *
+ * <APN>
+ * Access Point Name
+ *
+ * <PDP_address>
+ * It is the string parameter that identifies the MT in the address space applicable to the PDP
+ * The allocated address may be read using the command +CGPADDR command
+ *
+ * <d_comp>
+ * A numeric parameter that controls PDP data compression
+ * 0 off
+ * 1 on
+ * 2 V.42 bis
+ *
+ * <h_comp>
+ * A numeric parameter that controls PDP header compression
+ * 0 off
+ * 1 on
+ * 2 RFC1144
+ * 3 RFC2507
+ * 4 RFC3095
+ *
+ * <pd1>...<pdN>
+ * zero to N string parameters whose meanings are specific to the <PDP_type>
+ *
+ * Response -
+ * Success: (No Result)
+ * OK
+ * Failure:
+ * +CME ERROR: <error>
+ */
+static TReturn define_ps_context(CoreObject *o, CoreObject *ps_context, void *user_data)
+{
+ guchar context_id = 0;
+ gchar *at_cmd = NULL;
+ gchar *apn = NULL;
+ gchar *pdp_type_str = NULL;
+ gint pdp_type;
+ gint d_comp;
+ gint h_comp;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ context_id = tcore_context_get_id(ps_context);
+ dbg("Context ID : %d", context_id);
+ pdp_type = tcore_context_get_type(ps_context);
+ dbg("PDP Type : %d", pdp_type);
+
+ switch (pdp_type) {
+ case CONTEXT_TYPE_X25:
+ dbg("CONTEXT_TYPE_X25");
+ pdp_type_str = g_strdup("X.25");
+ break;
+
+ case CONTEXT_TYPE_IP:
+ dbg("CONTEXT_TYPE_IP");
+ pdp_type_str = g_strdup("IP");
+ break;
+
+ case CONTEXT_TYPE_PPP:
+ dbg("CONTEXT_TYPE_PPP");
+ pdp_type_str = g_strdup("PPP");
+ break;
+
+ case CONTEXT_TYPE_IPV6:
+ dbg("CONTEXT_TYPE_IPV6");
+ pdp_type_str = g_strdup("IPV6");
+ break;
+
+ default:
+ /*PDP Type not supported*/
+ dbg("Unsupported PDP type: %d", pdp_type);
+ goto error;
+ }
+
+ d_comp = tcore_context_get_data_compression(ps_context);
+ h_comp = tcore_context_get_header_compression(ps_context);
+ apn = tcore_context_get_apn(ps_context);
+
+ /* AT-Command */
+ at_cmd = g_strdup_printf("AT+CGDCONT=%d,\"%s\",\"%s\",,%d,%d",
+ context_id, pdp_type_str, apn, d_comp, h_comp);
+ dbg("AT-Command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o,
+ at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ NULL,
+ on_response_ps_define_context, ps_context,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+
+ g_free(pdp_type_str);
+ g_free(at_cmd);
+ g_free(apn);
+
+ if (ret == TCORE_RETURN_SUCCESS)
+ goto out;
+
+error:
+ err("Failed to prepare and send AT request");
+ __notify_context_status_changed(o, context_id, 3);
+
+out:
+ dbg("Exit");
+ return ret;
+}
+
+/* PS Operations */
+static struct tcore_ps_operations ps_ops = {
+ .define_context = define_ps_context,
+ .activate_context = activate_ps_context,
+ .deactivate_context = deactivate_ps_context
+};
+
+
+gboolean s_ps_init(TcorePlugin *p, TcoreHal *h)
+{
+ CoreObject *o;
+
+ dbg("Entry");
+ o = tcore_ps_new(p, "umts_ps", &ps_ops, h);
+ if (!o)
+ return FALSE;
+
+ dbg("Exit");
+ return TRUE;
+}
+
+void s_ps_exit(TcorePlugin *p)
+{
+ CoreObject *o;
+
+ o = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_PS);
+ CHECK_AND_RETURN(o != NULL);
+
+ tcore_ps_free(o);
+ dbg("Exit");
+}
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <tcore.h>
+#include <hal.h>
+#include <core_object.h>
+#include <plugin.h>
+#include <server.h>
+#include <queue.h>
+#include <co_sim.h>
+#include <storage.h>
+#include <user_request.h>
+#include <at.h>
+
+#include "s_common.h"
+#include "s_sim.h"
+
+#define SIM_ACCESS_READ_BINARY 176
+#define SIM_ACCESS_READ_RECORD 178
+#define SIM_ACCESS_GET_RESPONSE 192
+#define SIM_ACCESS_UPDATE_BINARY 214
+#define SIM_ACCESS_UPDATE_RECORD 220
+
+#define SIM_ICCID "89914500020137312178"
+
+
+#define ALLOC_METAINFO() do { \
+ file_meta = g_malloc0(sizeof(sim_meta_info_t)); \
+ dbg("Allocated - file_meta: [%p]", file_meta); \
+} while (0)
+
+#define FREE_METAINFO() do { \
+ dbg("Freeing - file_meta: [%p]", file_meta); \
+} while (0)
+
+#define SWAP_BYTES_16(x) \
+{ \
+ unsigned short int local_data = *(unsigned short int *)&(x); \
+ local_data = ((local_data & 0xff00) >> 8) | \
+ ((local_data & 0x00ff) << 8); \
+ *(unsigned short int *)&(x) = local_data; \
+}
+
+typedef enum {
+ SIM_FILE_TYPE_DEDICATED = 0x00, /**< Dedicated */
+ SIM_FILE_TYPE_TRANSPARENT = 0x01, /**< Transparent -binary type*/
+ SIM_FILE_TYPE_LINEAR_FIXED = 0x02, /**< Linear fixed - record type*/
+ SIM_FILE_TYPE_CYCLIC = 0x04, /**< Cyclic - record type*/
+ SIM_FILE_TYPE_INVALID_TYPE = 0xFF /**< Invalid type */
+} sim_file_type_t;
+
+typedef enum {
+ SIM_CURR_SEC_OP_PIN1_VERIFY,
+ SIM_CURR_SEC_OP_PIN2_VERIFY,
+ SIM_CURR_SEC_OP_PUK1_VERIFY,
+ SIM_CURR_SEC_OP_PUK2_VERIFY,
+ SIM_CURR_SEC_OP_SIM_VERIFY,
+ SIM_CURR_SEC_OP_ADM_VERIFY,
+ SIM_CURR_SEC_OP_PIN1_CHANGE,
+ SIM_CURR_SEC_OP_PIN2_CHANGE,
+ SIM_CURR_SEC_OP_PIN1_ENABLE,
+ SIM_CURR_SEC_OP_PIN1_DISABLE,
+ SIM_CURR_SEC_OP_PIN2_ENABLE,
+ SIM_CURR_SEC_OP_PIN2_DISABLE, // 10
+ SIM_CURR_SEC_OP_SIM_ENABLE,
+ SIM_CURR_SEC_OP_SIM_DISABLE,
+ SIM_CURR_SEC_OP_NET_ENABLE,
+ SIM_CURR_SEC_OP_NET_DISABLE,
+ SIM_CURR_SEC_OP_NS_ENABLE,
+ SIM_CURR_SEC_OP_NS_DISABLE,
+ SIM_CURR_SEC_OP_SP_ENABLE,
+ SIM_CURR_SEC_OP_SP_DISABLE,
+ SIM_CURR_SEC_OP_CP_ENABLE,
+ SIM_CURR_SEC_OP_CP_DISABLE, // 20
+ SIM_CURR_SEC_OP_FDN_ENABLE,
+ SIM_CURR_SEC_OP_FDN_DISABLE,
+ SIM_CURR_SEC_OP_PIN1_STATUS,
+ SIM_CURR_SEC_OP_PIN2_STATUS,
+ SIM_CURR_SEC_OP_FDN_STATUS,
+ SIM_CURR_SEC_OP_NET_STATUS,
+ SIM_CURR_SEC_OP_NS_STATUS,
+ SIM_CURR_SEC_OP_SP_STATUS,
+ SIM_CURR_SEC_OP_CP_STATUS,
+ SIM_CURR_SEC_OP_SIM_STATUS,
+ SIM_CURR_SEC_OP_SIM_UNKNOWN = 0xff
+} sim_sec_op_t;
+
+typedef enum {
+ SEC_LOCK_TYPE_NONE =0,
+ SEC_LOCK_TYPE_READY, /* ME is not locked */
+ SEC_LOCK_TYPE_PS, /* PH-SIM, Lock Phone to SIM/UICC card(MT asks password when other than current SIM/UICC card inserted; MT may remember certain amount of
+ previously used cards thus not requiring password when they are inserted ) */
+ SEC_LOCK_TYPE_PF, /* PH-FSIM, Lock Phone to the very First inserted SIM/UICC card ( MT asks password when other than the first SIM/UICC card is inserted ) */
+ SEC_LOCK_TYPE_SC, /*Lock SIM/UICC card ( SIM asks password in ME power-up and when this command is issued ) */
+ SEC_LOCK_TYPE_FD, /* SIM card or active application in the UICC(GSM or USIM) fixed dialing memory feature */
+ SEC_LOCK_TYPE_PN, /* Network Personalization */
+ SEC_LOCK_TYPE_PU, /* Network subset Personalization */
+ SEC_LOCK_TYPE_PP, /* Service Provider Personalization */
+ SEC_LOCK_TYPE_PC, /* Corporate Personalization */
+ SEC_LOCK_TYPE_SC2, /* Lock PIN2 ( ... ) */
+ SEC_LOCK_TYPE_PUK2, /* Lock PUK2 (... ) */
+ SEC_LOCK_TYPE_ACL, /* ACL */
+
+ SEC_LOCK_TYPE_NO_SIM, /* SIM is not inserted */
+ SEC_LOCK_TYPE_UNAVAIL, /* SIM is inserted but can not communicate with SIM ( SIM interface error ) */
+ SEC_SIM_INIT_COMPLETED, /* SIM Initialize Completed */
+ SEC_PB_INIT_COMPLETED, /* Phonebook Initialize Completed*/
+ SEC_SIM_INIT_CRASH, /* SIM Crash request from SMC lab*/
+
+ SEC_LOCK_TYPE_MAX
+} sim_sec_lock_type_t;
+
+typedef enum {
+ SEC_LOCK_KEY_NONE,
+ SEC_LOCK_KEY_UNLOCKED, /* Not necessary */
+ SEC_LOCK_KEY_PIN, /* PIN required as a password */
+ SEC_LOCK_KEY_PUK, /* 0PUK required as a password */
+ SEC_LOCK_KEY_PIN2, /* PIN2 required as a password */
+ SEC_LOCK_KEY_PUK2, /* PUK2 required as a password */
+ SEC_LOCK_KEY_PERM_BLOCKED, /* PIN Permanent Blocked */
+ SEC_LOCK_KEY_PIN2_DISABLE, /* PIN2 Lock Disabled*/
+ SEC_LOCK_KEY_MAX
+} sim_sec_lock_key_t;
+
+typedef struct {
+ guint smsp_count; /**< SMSP record count */
+ guint smsp_rec_len; /**< SMSP record length */
+} sim_private_info_t;
+
+typedef struct {
+ gboolean b_valid; /**< Valid or not */
+ guint rec_length; /**< Length of one record in file */
+ guint rec_count; /**< Number of records in file */
+ guint data_size; /**< File size */
+ guint current_index; /**< Current index to read */
+ sim_file_type_t file_type; /**< File type and structure */
+// sim_sec_op_t sec_op; /**< Current index to read */
+ struct tel_sim_mbi_list mbi_list; /**< Mailbox List */
+ struct tel_sim_mb_number mb_list[SIM_MSP_CNT_MAX*5]; /**< Mailbox number */
+ enum tel_sim_file_id file_id; /**< Current file id */
+ TReturn file_result; /**< File access result */
+ struct tresp_sim_read files; /**< File read data */
+ enum tcore_request_command req_command; /**< Request command Id */
+ struct tel_sim_imsi imsi; /**< Stored locally as of now,
+ Need to store in secure storage*/
+} sim_meta_info_t;
+
+/* Request Function Declaration */
+//static TReturn __sim_get_imsi(CoreObject *co_sim, UserRequest *ur);
+static TReturn __sim_get_ecc(CoreObject *co_sim, UserRequest *ur);
+static TReturn __sim_get_spdi(CoreObject *co_sim, UserRequest *ur);
+static TReturn __sim_get_spn(CoreObject *co_sim, UserRequest *ur);
+static TReturn __sim_get_language(CoreObject *co_sim, UserRequest *ur);
+static TReturn __sim_get_cfis(CoreObject *co_sim, UserRequest *ur);
+
+static TReturn s_sim_verify_pins(CoreObject *co_sim, UserRequest *ur);
+static TReturn s_sim_verify_puks(CoreObject *co_sim, UserRequest *ur);
+static TReturn s_sim_change_pins(CoreObject *co_sim, UserRequest *ur);
+static TReturn s_sim_disable_facility(CoreObject *co_sim, UserRequest *ur);
+static TReturn s_sim_enable_facility(CoreObject *co_sim, UserRequest *ur);
+static TReturn s_sim_get_facility(CoreObject *co_sim, UserRequest *ur);
+static TReturn s_sim_read_file(CoreObject *co_sim, UserRequest *ur);
+
+/* Utility Function Declaration */
+static TReturn __sim_decode_status_word(unsigned short status_word1, unsigned short status_word2);
+static void __sim_update_sim_status(CoreObject *co_sim, enum tel_sim_status sim_status);
+static void __sim_get_sim_type(CoreObject *co_sim);
+static const char *__sim_get_fac_from_lock_type(enum tel_sim_facility_type lock_type);
+//static int __sim_get_lock_type(sim_sec_op_t sec_op);
+static gboolean __convert_scpin_str_to_enum(char* line,
+ sim_sec_lock_type_t* lock_type, sim_sec_lock_key_t* lock_key);
+
+/* Internal Response Functions*/
+static void __sim_next_from_read_data(CoreObject *co_sim, UserRequest *ur,
+ sim_meta_info_t *file_meta, enum tel_sim_access_result sim_result, gboolean decode_ret);
+static void __sim_next_from_get_response(CoreObject *co_sim, UserRequest *ur,
+ sim_meta_info_t *file_meta, enum tel_sim_access_result sim_result, gboolean decode_ret);
+static void __sim_read_record(CoreObject *co_sim, UserRequest *ur, sim_meta_info_t *file_meta);
+static void __sim_read_binary(CoreObject *co_sim, UserRequest *ur, sim_meta_info_t *file_meta);
+static TReturn __sim_get_response(CoreObject *co_sim, UserRequest *ur, sim_meta_info_t *file_meta);
+static void __on_response_sim_get_sim_type(TcorePending *p,
+ gint data_len, const void *data, void *user_data);
+
+static enum tcore_response_command __find_resp_command(UserRequest *ur);
+static gchar __util_hexchar_to_int(gchar c);
+static gboolean __util_hexstring_to_bytes(gchar *hex_str,
+ gchar **bytes, guint *bytes_len);
+
+#define SIM_READ_FILE(co_sim, cb, cb_data, fileId, ret) do { \
+ sim_meta_info_t *file_meta = {0, }; \
+ \
+ ALLOC_METAINFO(); \
+ file_meta->file_id = fileId; \
+ file_meta->file_result = SIM_ACCESS_FAILED; \
+ \
+ ret = __sim_get_response(co_sim, NULL, file_meta); \
+} while (0)
+
+static gchar __util_hexchar_to_int(gchar c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ return (c - 'A' + 10);
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else {
+ err("Invalid charater!!");
+ return -1;
+ }
+}
+
+static gboolean __util_hexstring_to_bytes(gchar *hex_str,
+ gchar **bytes, guint *bytes_len)
+{
+ gchar *byte_str;
+ guint hex_str_len;
+ guint i;
+
+ if (hex_str == NULL)
+ return FALSE;
+
+ hex_str_len = strlen(hex_str);
+
+ byte_str = g_malloc0((hex_str_len / 2) + 1);
+
+ dbg("Convert String to Binary!!!");
+ for (i = 0; i < hex_str_len; i += 2) {
+ byte_str[i / 2] = (gchar)((__util_hexchar_to_int(hex_str[i]) << 4)
+ | __util_hexchar_to_int(hex_str[i + 1]));
+ msg(" [%02x]", byte_str[i / 2]);
+ }
+
+ *bytes_len = (hex_str_len / 2);
+ *bytes = byte_str;
+
+ return TRUE;
+}
+static enum tcore_response_command __find_resp_command(UserRequest *ur)
+{
+ enum tcore_request_command command;
+
+ command = tcore_user_request_get_command(ur);
+ switch (command) {
+ case TREQ_SIM_VERIFY_PINS:
+ return TRESP_SIM_VERIFY_PINS;
+
+ case TREQ_SIM_VERIFY_PUKS:
+ return TRESP_SIM_VERIFY_PUKS;
+
+ case TREQ_SIM_CHANGE_PINS:
+ return TRESP_SIM_CHANGE_PINS;
+
+ case TREQ_SIM_GET_FACILITY_STATUS:
+ return TRESP_SIM_GET_FACILITY_STATUS;
+
+ case TREQ_SIM_DISABLE_FACILITY:
+ return TRESP_SIM_DISABLE_FACILITY;
+
+ case TREQ_SIM_ENABLE_FACILITY:
+ return TRESP_SIM_ENABLE_FACILITY;
+
+ case TREQ_SIM_GET_LOCK_INFO:
+ return TRESP_SIM_GET_LOCK_INFO;
+
+ case TREQ_SIM_TRANSMIT_APDU:
+ return TRESP_SIM_TRANSMIT_APDU;
+
+ case TREQ_SIM_GET_ATR:
+ return TRESP_SIM_GET_ATR;
+
+ case TREQ_SIM_GET_ECC:
+ return TRESP_SIM_GET_ECC;
+
+ case TREQ_SIM_GET_LANGUAGE:
+ return TRESP_SIM_GET_LANGUAGE;
+
+ case TREQ_SIM_SET_LANGUAGE:
+ return TRESP_SIM_SET_LANGUAGE;
+
+ case TREQ_SIM_GET_ICCID:
+ return TRESP_SIM_GET_ICCID;
+
+ case TREQ_SIM_GET_MAILBOX:
+ return TRESP_SIM_GET_MAILBOX;
+
+ case TREQ_SIM_SET_MAILBOX:
+ return TRESP_SIM_SET_MAILBOX;
+
+ case TREQ_SIM_GET_CALLFORWARDING:
+ return TRESP_SIM_GET_CALLFORWARDING;
+
+ case TREQ_SIM_SET_CALLFORWARDING:
+ return TRESP_SIM_SET_CALLFORWARDING;
+
+ case TREQ_SIM_GET_MESSAGEWAITING:
+ return TRESP_SIM_GET_MESSAGEWAITING;
+
+ case TREQ_SIM_SET_MESSAGEWAITING:
+ return TRESP_SIM_SET_MESSAGEWAITING;
+
+ case TREQ_SIM_GET_CPHS_INFO:
+ return TRESP_SIM_GET_CPHS_INFO;
+
+ case TREQ_SIM_GET_MSISDN:
+ return TRESP_SIM_GET_MSISDN;
+
+ case TREQ_SIM_GET_SPN:
+ return TRESP_SIM_GET_SPN;
+
+ case TREQ_SIM_GET_SPDI:
+ return TRESP_SIM_GET_SPDI;
+
+ case TREQ_SIM_GET_OPL:
+ return TRESP_SIM_GET_OPL;
+
+ case TREQ_SIM_GET_PNN:
+ return TRESP_SIM_GET_PNN;
+
+ case TREQ_SIM_GET_CPHS_NETNAME:
+ return TRESP_SIM_GET_CPHS_NETNAME;
+
+ case TREQ_SIM_GET_OPLMNWACT:
+ return TRESP_SIM_GET_OPLMNWACT;
+
+ case TREQ_SIM_REQ_AUTHENTICATION:
+ return TRESP_SIM_REQ_AUTHENTICATION;
+
+ case TREQ_SIM_GET_SERVICE_TABLE:
+ return TRESP_SIM_GET_SERVICE_TABLE;
+
+ case TREQ_SIM_SET_POWERSTATE:
+ return TRESP_SIM_SET_POWERSTATE;
+
+ default:
+ err("Unknown/Unmapped Request command: [0x%x]", command);
+ break;
+ }
+ return TRESP_UNKNOWN;
+}
+
+#if 0
+static void __sim_set_identity(CoreObject *co_sim, struct tel_sim_imsi *imsi)
+{
+ gchar new_imsi[15 + 1] = {0, };
+ gchar *old_imsi;
+
+ memcpy(&new_imsi, imsi->mcc, strlen(imsi->mcc));
+ memcpy(&new_imsi[strlen(imsi->mcc)], imsi->mnc, strlen(imsi->mnc));
+ memcpy(&new_imsi[strlen(imsi->mcc) + strlen(imsi->mnc)], imsi->msin, strlen(imsi->msin));
+
+ /* TODO: This is temporary code, we should use secure storage instead of vconf */
+ old_imsi = vconf_get_str("db/telephony/imsi");
+ if (old_imsi) {
+ if (g_strcmp0(old_imsi, new_imsi) != 0) {
+ dbg("New SIM");
+ vconf_set_str("db/telephony/imsi", new_imsi);
+ tcore_sim_set_identification(co_sim, TRUE);
+ } else {
+ dbg("Same SIM");
+ tcore_sim_set_identification(co_sim, FALSE);
+ }
+ } else {
+ dbg("Old IMSI value is NULL, set IMSI");
+ vconf_set_str("db/telephony/imsi", new_imsi);
+ tcore_sim_set_identification(co_sim, TRUE);
+ }
+}
+#endif
+
+/* Utility Functions */
+static TReturn __sim_decode_status_word(unsigned short status_word1,
+ unsigned short status_word2)
+{
+ TReturn rst = SIM_ACCESS_FAILED;
+
+ if (status_word1 == 0x93 && status_word2 == 0x00) {
+ rst = SIM_ACCESS_FAILED;
+ /*Failed SIM request command*/
+ dbg("error - SIM application toolkit busy [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x94 && status_word2 == 0x00) {
+ rst = SIM_ACCESS_FAILED;
+ /*Failed SIM request command*/
+ dbg("error - No EF Selected [%x][%x]", status_word1, status_word2);
+ } else if (status_word1 == 0x94 && status_word2 == 0x02) {
+ rst = SIM_ACCESS_FAILED;
+ /*Failed SIM request command*/
+ dbg("error - Out of Range - Invalid address or record number[%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x94 && status_word2 == 0x04) {
+ rst = SIM_ACCESS_FILE_NOT_FOUND;
+ /*Failed SIM request command*/
+ dbg("error - File ID not found [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x94 && status_word2 == 0x08) {
+ rst = SIM_ACCESS_FAILED; /* MOdem not support */
+ /*Failed SIM request command*/
+ dbg("error - File is inconsistent with command - "\
+ "Modem not support or USE IPC [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x98 && status_word2 == 0x02) {
+ rst = SIM_ACCESS_CONDITION_NOT_SATISFIED;
+ /*Failed SIM request command*/
+ dbg("error - CHV not initialized [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x98 && status_word2 == 0x04) {
+ rst = SIM_ACCESS_CONDITION_NOT_SATISFIED;
+ /*Failed SIM request command*/
+ dbg("error - Access condition not fullfilled [%x][%x]",
+ status_word1, status_word2);
+ dbg("error -Unsuccessful CHV verification - "\
+ "at least one attempt left [%x][%x]",
+ status_word1, status_word2);
+ dbg("error - Unsuccessful Unblock CHV - at least one attempt left [%x][%x]",
+ status_word1, status_word2);
+ dbg("error - Authentication failure [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x98 && status_word2 == 0x08) {
+ rst = SIM_ACCESS_CONDITION_NOT_SATISFIED;
+ /*Failed SIM request command*/
+ dbg("error - Contradiction with CHV status [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x98 && status_word2 == 0x10) {
+ rst = SIM_ACCESS_CONDITION_NOT_SATISFIED;
+ /*Failed SIM request command*/
+ dbg("error - Contradiction with invalidation status [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x98 && status_word2 == 0x40) {
+ rst = SIM_ACCESS_CONDITION_NOT_SATISFIED;
+ /*Failed SIM request command*/
+ dbg("error -Unsuccessful CHV verification - no attempt left [%x][%x]",
+ status_word1, status_word2);
+ dbg("error - Unsuccessful Unblock CHV - no attempt left [%x][%x]",
+ status_word1, status_word2);
+ dbg("error - CHV blocked [%x][%x]", status_word1, status_word2);
+ } else if (status_word1 == 0x67 && status_word2 == 0x00) {
+ rst = SIM_ACCESS_FAILED;
+ dbg("error -Incorrect Parameter 3 [%x][%x]", status_word1, status_word2);
+ } else if (status_word1 == 0x6B && status_word2 == 0x00) {
+ rst = SIM_ACCESS_FAILED;
+ dbg("error -Incorrect Parameter 1 or 2 [%x][%x]", status_word1, status_word2);
+ } else if (status_word1 == 0x6D && status_word2 == 0x00) {
+ rst = SIM_ACCESS_CONDITION_NOT_SATISFIED;
+ dbg("error -Unknown instruction given as command [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x6E && status_word2 == 0x00) {
+ rst = SIM_ACCESS_CONDITION_NOT_SATISFIED;
+ dbg("error -Unknown instruction given as command [%x][%x]",
+ status_word1, status_word2);
+ } else if (status_word1 == 0x69 && status_word2 == 0x82) {
+ rst = SIM_ACCESS_CONDITION_NOT_SATISFIED;
+ dbg("error -Access denied [%x][%x]", status_word1, status_word2);
+ } else if (status_word1 == 0x6A && status_word2 == 0x87) {
+ rst = SIM_ACCESS_FAILED;
+ dbg("error -Incorrect parameters [%x][%x]", status_word1, status_word2);
+ } else if (status_word1 == 0x6A && status_word2 == 0x82) {
+ rst = SIM_ACCESS_FILE_NOT_FOUND; // not sure of the SW1 and SW2 meaning here
+ dbg("error -File Not found [%x][%x]", status_word1, status_word2);
+ } else if (status_word1 == 0x6A && status_word2 == 0x83) {
+ rst = SIM_ACCESS_FILE_NOT_FOUND; // not sure of the SW1 and SW2 meaning here
+ dbg("error -Record Not found [%x][%x]", status_word1, status_word2);
+ } else {
+ rst = SIM_ACCESS_CARD_ERROR;
+ dbg("error -Unknown state [%x][%x]", status_word1, status_word2);
+ }
+ return rst;
+}
+
+static void __sim_update_sim_status(CoreObject *co_sim,
+ enum tel_sim_status sim_status)
+{
+ enum tel_sim_status curr_sim_status;
+
+ /*
+ * Send SIM Init status, if not sent already
+ */
+ curr_sim_status = tcore_sim_get_status(co_sim);
+ if (sim_status != curr_sim_status) {
+ Server *s;
+ struct tnoti_sim_status sim_status_noti = {0, };
+
+ dbg("Change in SIM State - Old State: [0x%02x] --> New State: [0x%02x]",
+ curr_sim_status, sim_status);
+
+ /* Update SIM Status */
+ tcore_sim_set_status(co_sim, sim_status);
+ sim_status_noti.sim_status = sim_status;
+ sim_status_noti.b_changed = FALSE; /* TODO: checkout */
+
+ s = tcore_plugin_ref_server(tcore_object_ref_plugin(co_sim));
+
+ /* Send notification: SIM Status */
+ tcore_server_send_notification(s, co_sim,
+ TNOTI_SIM_STATUS,
+ sizeof(struct tnoti_sim_status), &sim_status_noti);
+ }
+}
+
+static gboolean __convert_scpin_str_to_enum(char* line,
+ sim_sec_lock_type_t *lock_type, sim_sec_lock_key_t *lock_key)
+{
+ char *type =NULL, *key = NULL;
+ GSList *tokens = NULL;
+
+ if(line == NULL)
+ return FALSE;
+
+ tokens = tcore_at_tok_new(line);
+
+ type = g_slist_nth_data(tokens, 0);
+ if (!type) {
+ err("Type is missing");
+ tcore_at_tok_free(tokens);
+ return FALSE;
+ }
+
+ if (g_strcmp0(type, "NO_LOCK") == 0) {
+ key = g_slist_nth_data(tokens, 1);
+ if (!key) {
+ err("Key is missing");
+ tcore_at_tok_free(tokens);
+ return FALSE;
+ }
+
+ dbg("type: [%s], key: [%s]", type, key);
+ }
+
+ if(g_str_has_prefix (type, "NO_SIM"))
+ *lock_type = SEC_LOCK_TYPE_NO_SIM;
+ else if(g_str_has_prefix (type, "UNAVAIL"))
+ *lock_type = SEC_LOCK_TYPE_UNAVAIL;
+ else if(g_str_has_prefix (type, "NO_LOCK"))
+ *lock_type = SEC_LOCK_TYPE_READY;
+ else if(g_str_has_prefix (type, "LOCK_PS"))
+ *lock_type = SEC_LOCK_TYPE_PS;
+ else if(g_str_has_prefix (type, "LOCK_PF"))
+ *lock_type = SEC_LOCK_TYPE_PF ;
+ else if(g_str_has_prefix (type, "LOCK_SC"))
+ *lock_type = SEC_LOCK_TYPE_SC;
+ else if(g_str_has_prefix (type, "LOCK_FD"))
+ *lock_type = SEC_LOCK_TYPE_FD;
+ else if(g_str_has_prefix (type, "LOCK_PN"))
+ *lock_type = SEC_LOCK_TYPE_PN ;
+ else if(g_str_has_prefix (type, "LOCK_PU"))
+ *lock_type = SEC_LOCK_TYPE_PU ;
+ else if(g_str_has_prefix (type, "LOCK_PP"))
+ *lock_type = SEC_LOCK_TYPE_PP;
+ else if(g_str_has_prefix (type, "LOCK_PC"))
+ *lock_type = SEC_LOCK_TYPE_PC;
+ else if(g_str_has_prefix (type, "LOCK_SC2"))
+ *lock_type = SEC_LOCK_TYPE_SC2 ;
+ else if(g_str_has_prefix (type, "LOCK_ACL"))
+ *lock_type = SEC_LOCK_TYPE_ACL;
+ else if(g_str_has_prefix (type, "LOCK_PUK2"))
+ *lock_type = SEC_LOCK_TYPE_PUK2;
+ else if(g_str_has_prefix (type, "INIT_COMP"))
+ *lock_type = SEC_SIM_INIT_COMPLETED;
+ else if(g_str_has_prefix (type, "INIT_ERROR"))
+ *lock_type = SEC_SIM_INIT_CRASH;
+ else
+ *lock_type = SEC_LOCK_TYPE_NONE;
+
+ if(g_str_has_prefix (key, "PIN"))
+ *lock_key = SEC_LOCK_KEY_PIN;
+ else if(g_str_has_prefix (key, "PUK"))
+ *lock_key = SEC_LOCK_KEY_PUK;
+ else if(g_str_has_prefix (key, "PIN2"))
+ *lock_key = SEC_LOCK_KEY_PIN2;
+ else if(g_str_has_prefix (key, "PUK2"))
+ *lock_key = SEC_LOCK_KEY_PUK2;
+ else if(g_str_has_prefix (key, "BLOCKED"))
+ *lock_key = SEC_LOCK_KEY_PERM_BLOCKED ;
+ else if(g_str_has_prefix (key, "UNLOCKED"))
+ *lock_key = SEC_LOCK_KEY_UNLOCKED ;
+ else if(g_str_has_prefix (key, "PIN2_DISABLE"))
+ *lock_key = SEC_LOCK_KEY_PIN2_DISABLE;
+ else
+ *lock_key = SEC_LOCK_KEY_NONE;
+
+ if(*lock_type == SEC_LOCK_TYPE_READY)
+ *lock_key = SEC_LOCK_KEY_UNLOCKED;
+
+ if((*lock_type == SEC_LOCK_TYPE_NO_SIM)||(*lock_type == SEC_LOCK_TYPE_UNAVAIL)||
+ (*lock_type == SEC_SIM_INIT_COMPLETED)||(*lock_type == SEC_SIM_INIT_CRASH))
+ *lock_key = SEC_LOCK_KEY_NONE;
+
+ dbg("type: [%d], key: [%d]", *lock_type, *lock_key);
+
+ tcore_at_tok_free(tokens);
+
+ return TRUE;
+}
+
+static void __on_response_sim_get_sim_type(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
+ CoreObject *co_sim = tcore_pending_ref_core_object(p);
+ enum tel_sim_type sim_type = SIM_TYPE_UNKNOWN;
+
+ dbg("SIM Response - SIM Type: [+SCCT]");
+
+ CHECK_AND_RETURN(co_sim != NULL);
+
+ if (at_resp && at_resp->success) {
+ if (at_resp->lines) {
+ const gchar *line;
+ GSList *tokens;
+
+ line = (const gchar *)at_resp->lines->data;
+
+ /*
+ * Tokenize
+ *
+ * %SCCT: <state>
+ */
+ tokens = tcore_at_tok_new(line);
+
+ /* <state> */
+ if (g_slist_length(tokens) == 1) {
+ sim_type = atoi(g_slist_nth_data(tokens, 0));
+
+ dbg("SIM Type: [%d]", sim_type);
+
+ /* Update SIM type */
+ tcore_sim_set_type(co_sim, sim_type);
+ }
+ else {
+ err("Invalid message");
+ }
+
+ tcore_at_tok_free(tokens);
+ }
+ }
+}
+
+/*
+ * Operation - get_sim_type
+ *
+ * Request -
+ * AT-Command: AT%SCCT?
+ *
+ * Response - sim_type (enum tel_sim_type)
+ * Success: (Single line) -
+ * +SCCT: <state>
+ * OK
+ * Failure:
+ * +CME ERROR: <error>
+ */
+static void __sim_get_sim_type(CoreObject *co_sim)
+{
+ TReturn ret;
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ "AT\%SCCT?", "+SCCT:",
+ TCORE_AT_SINGLELINE,
+ NULL,
+ __on_response_sim_get_sim_type, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+}
+
+static void __sim_process_sim_status(CoreObject *co_sim,
+ enum tel_sim_status sim_card_status)
+{
+ switch (sim_card_status) {
+ case SIM_STATUS_INIT_COMPLETED: {
+ TReturn ret;
+
+ dbg("SIM INIT COMPLETED");
+
+ SIM_READ_FILE(co_sim, NULL, NULL, SIM_EF_IMSI, ret);
+ dbg("ret: [%d]", ret);
+ SIM_READ_FILE(co_sim, NULL, NULL, SIM_EF_SPN, ret);
+ dbg("ret: [%d]", ret);
+
+ return;
+ }
+
+ case SIM_STATUS_INITIALIZING: {
+ enum tel_sim_type sim_type;
+
+ dbg("SIM INITIALIZING");
+
+ sim_type = tcore_sim_get_type(co_sim);
+ if (sim_type == SIM_TYPE_UNKNOWN) {
+ /*
+ * SIM is initialized for first time, need to
+ * fetch SIM type
+ */
+ dbg("Fetching SIM type");
+ __sim_get_sim_type(co_sim);
+
+ return;
+ }
+ }
+ break;
+
+ case SIM_STATUS_CARD_REMOVED:
+ case SIM_STATUS_CARD_NOT_PRESENT:
+ case SIM_STATUS_CARD_ERROR:
+ dbg("SIM CARD ERROR [0x%02x]", sim_card_status);
+ tcore_sim_set_type(co_sim, SIM_TYPE_UNKNOWN);
+ return __sim_update_sim_status(co_sim, sim_card_status);
+ break;
+
+ default:
+ err("SIM Status: [0x%02x]", sim_card_status);
+ break;
+ }
+}
+
+static const char *__sim_get_fac_from_lock_type(enum tel_sim_facility_type lock_type)
+{
+ char *fac = NULL;
+ switch(lock_type) {
+ case SIM_FACILITY_PS:
+ fac = (char *)"PS";
+ break;
+
+ case SIM_FACILITY_SC:
+ fac = (char *)"SC";
+ break;
+
+ case SIM_FACILITY_FD:
+ fac = (char *)"FD";
+ break;
+
+ case SIM_FACILITY_PN:
+ fac = (char *)"PN";
+ break;
+
+ case SIM_FACILITY_PU:
+ fac = (char *)"PU";
+ break;
+
+ case SIM_FACILITY_PP:
+ fac = (char *)"PP";
+ break;
+
+ case SIM_FACILITY_PC:
+ fac = (char *)"PC";
+ break;
+
+ default:
+ err("Unhandled sim lock type [%d]", lock_type);
+ }
+
+ return fac;
+}
+
+static void __sim_next_from_read_data(CoreObject *co_sim, UserRequest *ur,
+ sim_meta_info_t *file_meta, enum tel_sim_access_result sim_result, gboolean decode_ret)
+{
+ enum tel_sim_type card_type = SIM_TYPE_UNKNOWN;
+
+ dbg("Entry");
+
+ dbg("[SIM]EF[0x%x] read sim_result[%d] Decode rt[%d]",
+ file_meta->file_id, sim_result, decode_ret);
+ switch (file_meta->file_id) {
+ case SIM_EF_ELP:
+ case SIM_EF_USIM_PL:
+ case SIM_EF_LP:
+ case SIM_EF_USIM_LI:
+ if (decode_ret == TRUE) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ } else {
+ card_type = tcore_sim_get_type(co_sim);
+ /* 2G */
+ /* The ME requests the Extended Language Preference.
+ * The ME only requests the Language Preference (EFLP)
+ * if at least one of the following conditions holds:
+ * - EFELP is not available;
+ * - EFELP does not contain an entry corresponding to
+ * a language specified in ISO 639[30];
+ * - the ME does not support any of the languages in EFELP.
+ */
+ /* 3G */
+ /*
+ * The ME only requests the Language Preference (EFPL)
+ * if at least one of the following conditions holds:
+ * - if the EFLI has the value 'FFFF' in its highest
+ * priority position
+ * - if the ME does not support any of the language
+ * codes indicated in EFLI , or if EFLI is not present
+ */
+ if (SIM_TYPE_GSM == card_type) {
+ if (file_meta->file_id == SIM_EF_LP) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ } else {
+ file_meta->file_id = SIM_EF_LP;
+ ur = tcore_user_request_ref(ur);
+ __sim_get_response(co_sim, ur, file_meta);
+ }
+ } else if (SIM_TYPE_USIM) {
+ if (file_meta->file_id == SIM_EF_LP
+ || file_meta->file_id == SIM_EF_USIM_LI) {
+ file_meta->file_id = SIM_EF_ELP;
+ ur = tcore_user_request_ref(ur);
+ __sim_get_response(co_sim, ur, file_meta);
+ } else {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ }
+ }
+ }
+ break;
+
+ case SIM_EF_ECC:
+ card_type = tcore_sim_get_type(co_sim);
+ if (SIM_TYPE_USIM == card_type) {
+ if (file_meta->current_index == file_meta->rec_count) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ } else {
+ file_meta->current_index++;
+ ur = tcore_user_request_ref(ur);
+ __sim_read_record(co_sim, ur, file_meta);
+ }
+ } else if (SIM_TYPE_GSM == card_type) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ } else {
+ dbg("[SIM DATA]Invalid CardType[%d] Unable to handle", card_type);
+ }
+ break;
+
+ case SIM_EF_IMSI:
+ __sim_update_sim_status(co_sim, SIM_STATUS_INIT_COMPLETED);
+ break;
+
+#if MSISDN_SUPPORTED
+ case SIM_EF_MSISDN:
+ if (file_meta->current_index == file_meta->rec_count) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ } else {
+ file_meta->current_index++;
+ ur = tcore_user_request_ref(ur);
+ __sim_read_record(co_sim, ur, file_meta);
+ }
+ break;
+#endif
+
+ case SIM_EF_OPL:
+ if (file_meta->current_index == file_meta->rec_count) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ } else {
+ file_meta->current_index++;
+ ur = tcore_user_request_ref(ur);
+ __sim_read_record(co_sim, ur, file_meta);
+ }
+ break;
+
+ case SIM_EF_PNN:
+ if (file_meta->current_index == file_meta->rec_count) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ } else {
+ file_meta->current_index++;
+ ur = tcore_user_request_ref(ur);
+ __sim_read_record(co_sim, ur, file_meta);
+ }
+ break;
+
+ case SIM_EF_USIM_CFIS:
+ case SIM_EF_USIM_MWIS:
+ case SIM_EF_USIM_MBI:
+ case SIM_EF_MBDN:
+ case SIM_EF_CPHS_MAILBOX_NUMBERS:
+ case SIM_EF_CPHS_INFORMATION_NUMBERS:
+ if (file_meta->current_index == file_meta->rec_count) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ } else {
+ file_meta->current_index++;
+ ur = tcore_user_request_ref(ur);
+ __sim_read_record(co_sim, ur, file_meta);
+ }
+ break;
+
+ case SIM_EF_CPHS_OPERATOR_NAME_STRING:
+ {
+ file_meta->files.result = sim_result;
+ if (decode_ret == TRUE && sim_result == SIM_ACCESS_SUCCESS) {
+ memcpy(file_meta->files.data.cphs_net.full_name,
+ file_meta->files.data.cphs_net.full_name,
+ strlen((char *)file_meta->files.data.cphs_net.full_name));
+ }
+
+ file_meta->file_id = SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ ur = tcore_user_request_ref(ur);
+ __sim_get_response(co_sim, ur, file_meta);
+ }
+ break;
+
+ case SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
+ if (sim_result == SIM_ACCESS_SUCCESS) {
+ file_meta->files.result = SIM_ACCESS_SUCCESS;
+ }
+
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ break;
+
+ case SIM_EF_ICCID:
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ break;
+
+ case SIM_EF_SST:
+ case SIM_EF_SPN:
+ case SIM_EF_SPDI:
+ case SIM_EF_OPLMN_ACT:
+ case SIM_EF_CPHS_CPHS_INFO:
+ case SIM_EF_CPHS_CALL_FORWARD_FLAGS:
+ case SIM_EF_CPHS_VOICE_MSG_WAITING:
+ case SIM_EF_CPHS_DYNAMICFLAGS:
+ case SIM_EF_CPHS_DYNAMIC2FLAG:
+ case SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
+ case SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE_LINE2:
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ break;
+
+ default:
+ err("File id not handled [0x%x]", file_meta->file_id);
+ break;
+ }
+}
+
+static void __sim_next_from_get_response(CoreObject *co_sim, UserRequest *ur,
+ sim_meta_info_t *file_meta, enum tel_sim_access_result sim_result, gboolean decode_ret)
+{
+ enum tel_sim_type card_type = SIM_TYPE_UNKNOWN;
+
+ dbg("EF[0x%x] access Result[%d]", file_meta->file_id, sim_result);
+
+ file_meta->files.result = sim_result;
+ memset(&file_meta->files.data, 0x00, sizeof(file_meta->files.data));
+
+ if ((file_meta->file_id != SIM_EF_ELP
+ && file_meta->file_id != SIM_EF_LP
+ && file_meta->file_id != SIM_EF_USIM_PL
+ && file_meta->file_id != SIM_EF_CPHS_CPHS_INFO
+ && file_meta->file_id != SIM_EF_MSISDN
+ && file_meta->file_id != SIM_EF_ICCID)
+ && (sim_result != SIM_ACCESS_SUCCESS)) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+
+ return;
+ }
+
+ switch (file_meta->file_id) {
+ case SIM_EF_ELP: {
+ if (sim_result == SIM_ACCESS_SUCCESS) {
+ dbg("[SIM DATA] exist EFELP/PL(0x2F05)");
+ ur = tcore_user_request_ref(ur);
+ __sim_read_binary(co_sim, ur, file_meta);
+ } else {
+ card_type = tcore_sim_get_type(co_sim);
+ if (SIM_TYPE_GSM == card_type) {
+ dbg("[SIM DATA]SIM_EF_ELP(2F05) access fail. Request SIM_EF_LP(0x6F05) info");
+
+ /* The ME requests the Language Preference (EFLP) if EFELP is not available */
+ file_meta->file_id = SIM_EF_LP;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_LANGUAGE;
+
+ ur = tcore_user_request_ref(ur);
+ __sim_get_response(co_sim, ur, file_meta);
+ } else if (SIM_TYPE_USIM == card_type) {
+ dbg(" [SIM DATA]fail to get Language information "\
+ "in USIM(EF-LI(6F05),EF-PL(2F05))");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ return;
+ }
+ }
+ }
+ break;
+
+ case SIM_EF_LP: {
+ if (sim_result == SIM_ACCESS_SUCCESS) {
+ dbg("[SIM DATA] exist EFLP/LI(0x6F05)");
+ ur = tcore_user_request_ref(ur);
+ __sim_read_binary(co_sim, ur, file_meta);
+ } else {
+ card_type = tcore_sim_get_type(co_sim);
+ dbg("[SIM DATA]SIM_EF_LP/LI(6F05) access fail. Current CardType[%d]", card_type);
+ if (SIM_TYPE_GSM == card_type) {
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ return;
+ }
+ /*
+ * If EFLI is not present, then the language selection
+ * shall be as defined in EFPL at the MF level
+ */
+ else if (SIM_TYPE_USIM == card_type) {
+ dbg("[SIM DATA] try USIM EFPL(0x2F05)");
+
+ file_meta->file_id = SIM_EF_ELP;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_LANGUAGE;
+
+ ur = tcore_user_request_ref(ur);
+ __sim_get_response(co_sim, ur, file_meta);
+ }
+ }
+ }
+ break;
+
+ case SIM_EF_USIM_PL: {
+ if (sim_result == SIM_ACCESS_SUCCESS) {
+ dbg("[SIM DATA] exist EFELP/PL(0x2F05)");
+ ur = tcore_user_request_ref(ur);
+ __sim_read_binary(co_sim, ur, file_meta);
+ } else {
+ /*
+ * EFELIand EFPL not present, so set language count
+ * as zero and select ECC
+ */
+ dbg("[SIM DATA]SIM_EF_USIM_PL(2A05) access fail. "\
+ "Request SIM_EF_ECC(0x6FB7) info");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+
+ return;
+ }
+ }
+ break;
+
+ case SIM_EF_ECC: {
+ card_type = tcore_sim_get_type(co_sim);
+ if (SIM_TYPE_GSM == card_type) {
+ ur = tcore_user_request_ref(ur);
+ __sim_read_binary(co_sim, ur, file_meta);
+ } else if (SIM_TYPE_USIM == card_type) {
+ if (file_meta->rec_count > SIM_ECC_RECORD_CNT_MAX)
+ file_meta->rec_count = SIM_ECC_RECORD_CNT_MAX;
+
+ file_meta->current_index++;
+ ur = tcore_user_request_ref(ur);
+ __sim_read_record(co_sim, ur, file_meta);
+ } else {
+ tcore_sim_set_ecc_list(co_sim, NULL);
+ if (ur) {
+ tcore_user_request_send_response(ur, __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+ }
+ }
+ }
+ break;
+
+ case SIM_EF_ICCID: {
+ if (sim_result == SIM_ACCESS_SUCCESS) {
+ __sim_read_binary(co_sim, ur, file_meta);
+ } else {
+ /* Emulator does not support ICCID, thus need to send dummy ICCID for SDK ITC test */
+ g_strlcpy(file_meta->files.data.iccid.iccid, SIM_ICCID, SIM_ICCID_LEN_MAX);
+ file_meta->files.result = SIM_ACCESS_SUCCESS;
+ if (tcore_user_request_ref_communicator(ur)) { //external call
+ tcore_user_request_send_response(ur, __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+ }
+ }
+ }
+ break;
+
+ case SIM_EF_IMSI:
+ case SIM_EF_SST:
+ case SIM_EF_SPN:
+ case SIM_EF_SPDI:
+ case SIM_EF_CPHS_CALL_FORWARD_FLAGS:
+ case SIM_EF_CPHS_VOICE_MSG_WAITING:
+ case SIM_EF_CPHS_OPERATOR_NAME_STRING:
+ case SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
+ case SIM_EF_CPHS_DYNAMICFLAGS:
+ case SIM_EF_CPHS_DYNAMIC2FLAG:
+ case SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
+ case SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE_LINE2:
+ ur = tcore_user_request_ref(ur);
+ __sim_read_binary(co_sim, ur, file_meta);
+ break;
+
+ case SIM_EF_CPHS_CPHS_INFO: {
+ if (sim_result == SIM_ACCESS_SUCCESS) {
+ tcore_sim_set_cphs_status(co_sim, TRUE);
+ __sim_update_sim_status(co_sim, SIM_STATUS_INIT_COMPLETED);
+
+ ur = tcore_user_request_ref(ur);
+ __sim_read_binary(co_sim, ur, file_meta);
+ } else {
+ tcore_sim_set_cphs_status(co_sim, FALSE);
+ __sim_update_sim_status(co_sim, SIM_STATUS_INIT_COMPLETED);
+
+ dbg("Sending response");
+
+ file_meta->files.result = sim_result;
+ tcore_user_request_send_response(ur,
+ __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+
+ /* TODO: Check if required */
+ FREE_METAINFO();
+ }
+ }
+ break;
+
+
+ case SIM_EF_USIM_CFIS: {
+ if (file_meta->rec_count > SIM_CF_RECORD_CNT_MAX)
+ file_meta->rec_count = SIM_CF_RECORD_CNT_MAX;
+
+ file_meta->current_index++;
+ ur = tcore_user_request_ref(ur);
+ __sim_read_record(co_sim, ur, file_meta);
+ }
+ break;
+
+ case SIM_EF_MSISDN: {
+ if (sim_result == SIM_ACCESS_SUCCESS) {
+ __sim_read_record(co_sim, ur, file_meta);
+ } else {
+ /* Emulator does not support MSISDN, thus need to send MSISDN count as ZERO for SDK ITC test */
+ file_meta->files.data.msisdn_list.count = 0;
+ file_meta->files.result = SIM_ACCESS_SUCCESS;
+ if (tcore_user_request_ref_communicator(ur)) { //external call
+ tcore_user_request_send_response(ur, __find_resp_command(ur),
+ sizeof(struct tresp_sim_read), &file_meta->files);
+ }
+ }
+ }
+ break;
+ case SIM_EF_OPL:
+ case SIM_EF_PNN:
+ case SIM_EF_USIM_MWIS:
+ case SIM_EF_USIM_MBI:
+ case SIM_EF_MBDN:
+ case SIM_EF_CPHS_MAILBOX_NUMBERS:
+ case SIM_EF_CPHS_INFORMATION_NUMBERS:
+ file_meta->current_index++;
+ ur = tcore_user_request_ref(ur);
+ __sim_read_record(co_sim, ur, file_meta);
+ break;
+#if 0
+ case SIM_SST_SMS_PARAMS: {
+ sim_private_info_t *priv_info = NULL;
+
+ priv_info = tcore_sim_ref_userdata(co_sim);
+
+ dbg("SMSP info set to tcore : count:[%d], rec_len:[%d]",
+ file_meta->rec_count, file_meta->rec_length);
+ priv_info->smsp_count = file_meta->rec_count;
+ priv_info->smsp_rec_len = file_meta->rec_length;
+ }
+ break;
+#endif
+ default:
+ dbg("error - File id for get file info [0x%x]", file_meta->file_id);
+ break;
+ }
+ return;
+}
+
+static void __on_response_sim_read_data(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *resp = data;
+ CoreObject *co_sim = NULL;
+ GSList *tokens = NULL;
+ enum tel_sim_access_result sim_result;
+ gboolean dr = FALSE;
+ const char *line = NULL;
+ char *res = NULL;
+ char *tmp = NULL;
+ guint res_len;
+ int sw1 = 0;
+ int sw2 = 0;
+ enum tel_sim_type card_type = SIM_TYPE_UNKNOWN;
+ sim_meta_info_t *file_meta = (sim_meta_info_t *)user_data;
+ UserRequest *ur;
+
+ dbg("Entry");
+
+ co_sim = tcore_pending_ref_core_object(p);
+ ur = tcore_pending_ref_user_request(p);
+
+ if (resp->success > 0) {
+ dbg("RESPONSE OK");
+ if (resp->lines) {
+ line = (const char *)resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) < 2) {
+ err("Invalid message");
+ tcore_at_tok_free(tokens);
+ return;
+ }
+ }
+ sw1 = atoi(g_slist_nth_data(tokens, 0));
+ sw2 = atoi(g_slist_nth_data(tokens, 1));
+ res = g_slist_nth_data(tokens, 2);
+
+ tmp = tcore_at_tok_extract(res);
+ __util_hexstring_to_bytes(tmp, &res, &res_len);
+ dbg("Response: [%s] Response length: [%d]", res, res_len);
+
+ if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
+ sim_result = SIM_ACCESS_SUCCESS;
+ file_meta->files.result = sim_result;
+
+ dbg("File ID: [0x%x]", file_meta->file_id);
+ switch (file_meta->file_id) {
+ case SIM_EF_IMSI: {
+ dbg("Data: [%s]", res);
+ dr = tcore_sim_decode_imsi(&file_meta->imsi,
+ (unsigned char *)res, res_len);
+ if (dr == FALSE) {
+ err("IMSI decoding failed");
+ } else {
+ //__sim_set_identity(co_sim, &file_meta->imsi);
+
+ /* Update IMSI */
+ tcore_sim_set_imsi(co_sim, &file_meta->imsi);
+ }
+ }
+ break;
+
+ case SIM_EF_ICCID: {
+ dr = tcore_sim_decode_iccid(&file_meta->files.data.iccid,
+ (unsigned char *)res, res_len);
+ }
+ break;
+
+ case SIM_EF_ELP: /* 2G EF - 2 bytes decoding */
+ case SIM_EF_USIM_LI: /* 3G EF - 2 bytes decoding */
+ case SIM_EF_USIM_PL: /* 3G EF - same as EFELP, so 2 byte decoding */
+ case SIM_EF_LP: /* 1 byte encoding */
+ {
+ card_type = tcore_sim_get_type(co_sim);
+ if ((SIM_TYPE_GSM == card_type)
+ && (file_meta->file_id == SIM_EF_LP)) {
+ /*
+ * 2G LP(0x6F05) has 1 byte for each language
+ */
+ dr = tcore_sim_decode_lp(&file_meta->files.data.language,
+ (unsigned char *)res, res_len);
+ } else {
+ /*
+ * 3G LI(0x6F05)/PL(0x2F05),
+ * 2G ELP(0x2F05) has 2 bytes for each language
+ */
+ dr = tcore_sim_decode_li(file_meta->file_id, &file_meta->files.data.language,
+ (unsigned char *)res, res_len);
+ }
+ }
+ break;
+
+ case SIM_EF_SPN:
+ dr = tcore_sim_decode_spn(&file_meta->files.data.spn,
+ (unsigned char *)res, res_len);
+ tcore_sim_set_spn(co_sim, &file_meta->files.data.spn);
+ dbg("SIM SPN: [%s]", file_meta->files.data.spn.spn);
+ break;
+
+ case SIM_EF_SPDI:
+ dr = tcore_sim_decode_spdi(&file_meta->files.data.spdi,
+ (unsigned char *)res, res_len);
+ break;
+
+ case SIM_EF_SST: {
+ struct tel_sim_service_table *svct = NULL;
+
+ card_type = tcore_sim_get_type(co_sim);
+ file_meta->files.data.svct.sim_type = card_type;
+ if (SIM_TYPE_GSM == card_type) {
+ dr = tcore_sim_decode_sst(&file_meta->files.data.svct.table.sst,
+ (unsigned char *)res, res_len);
+ } else if (SIM_TYPE_USIM == card_type) {
+ dr = tcore_sim_decode_ust(&file_meta->files.data.svct.table.ust,
+ (unsigned char *)res, res_len);
+ } else {
+ err("Not handled card_type[%d]", card_type);
+ }
+
+ if (dr == FALSE) {
+ err("SST decoding failed");
+ } else {
+ tcore_sim_set_service_table(co_sim, svct);
+ }
+
+ /* Free memory */
+ g_free(svct);
+ }
+ break;
+
+ case SIM_EF_ECC: {
+ card_type = tcore_sim_get_type(co_sim);
+ if (SIM_TYPE_GSM == card_type) {
+ dr = tcore_sim_decode_ecc(&file_meta->files.data.ecc,
+ (unsigned char *)res, res_len);
+ } else if (SIM_TYPE_USIM == card_type) {
+ struct tel_sim_ecc *ecc = NULL;
+
+ ecc = g_try_new0(struct tel_sim_ecc, 1);
+ dbg("Index [%d]", file_meta->current_index);
+
+ dr = tcore_sim_decode_uecc(ecc, (unsigned char *)res, res_len);
+ if (dr == TRUE) {
+ memcpy(&file_meta->files.data.ecc.ecc[file_meta->files.data.ecc.ecc_count],
+ ecc, sizeof(struct tel_sim_ecc));
+ file_meta->files.data.ecc.ecc_count++;
+ }
+
+ /* Free memory */
+ g_free(ecc);
+ } else {
+ dbg("Unknown/Unsupported SIM card Type: [%d]", card_type);
+ }
+ }
+ break;
+
+ case SIM_EF_MSISDN: {
+ struct tel_sim_msisdn *msisdn = NULL;
+
+ dbg("Index [%d]", file_meta->current_index);
+ msisdn = g_try_new0(struct tel_sim_msisdn, 1);
+ dr = tcore_sim_decode_msisdn(msisdn, (unsigned char *)res, res_len);
+ if (dr == TRUE) {
+ memcpy(&file_meta->files.data.msisdn_list.msisdn[file_meta->files.data.msisdn_list.count],
+ msisdn, sizeof(struct tel_sim_msisdn));
+
+ file_meta->files.data.msisdn_list.count++;
+ }
+
+ /* Free memory */
+ g_free(msisdn);
+ }
+ break;
+
+ case SIM_EF_OPL: {
+ struct tel_sim_opl *opl = NULL;
+
+ dbg("decode w/ index [%d]", file_meta->current_index);
+ opl = g_try_new0(struct tel_sim_opl, 1);
+
+ dr = tcore_sim_decode_opl(opl, (unsigned char *)res, res_len);
+ if (dr == TRUE) {
+ memcpy(&file_meta->files.data.opl.list[file_meta->files.data.opl.opl_count],
+ opl, sizeof(struct tel_sim_opl));
+
+ file_meta->files.data.opl.opl_count++;
+ }
+
+ /* Free memory */
+ g_free(opl);
+ }
+ break;
+
+ case SIM_EF_PNN: {
+ struct tel_sim_pnn *pnn = NULL;
+
+ dbg("decode w/ index [%d]", file_meta->current_index);
+ pnn = g_try_new0(struct tel_sim_pnn, 1);
+
+ dr = tcore_sim_decode_pnn(pnn, (unsigned char *)res, res_len);
+ if (dr == TRUE) {
+ memcpy(&file_meta->files.data.pnn.list[file_meta->files.data.pnn.pnn_count],
+ pnn, sizeof(struct tel_sim_pnn));
+
+ file_meta->files.data.pnn.pnn_count++;
+ }
+
+ /* Free memory */
+ g_free(pnn);
+ }
+ break;
+
+ case SIM_EF_OPLMN_ACT:
+ /*dr = tcore_sim_decode_oplmnwact(&file_meta->files.data.opwa,
+ (unsigned char *)res, res_len);*/
+ break;
+
+ case SIM_EF_CPHS_CUSTOMER_SERVICE_PROFILE:
+ /*dr = tcore_sim_decode_csp(&po->p_cphs->csp,
+ p_data->response, p_data->response_len);*/
+ break;
+
+ case SIM_EF_USIM_MBI: { /* linear type */
+ struct tel_sim_mbi *mbi = NULL;
+
+ mbi = g_try_new0(struct tel_sim_mbi, 1);
+ dr = tcore_sim_decode_mbi(mbi, (unsigned char *)res, res_len);
+ if (dr == TRUE) {
+ memcpy(&file_meta->mbi_list.mbi[file_meta->mbi_list.profile_count],
+ mbi, sizeof(struct tel_sim_mbi));
+ file_meta->mbi_list.profile_count++;
+
+ dbg("mbi count[%d]", file_meta->mbi_list.profile_count);
+ }
+
+ /* Free memory */
+ g_free(mbi);
+ }
+ break;
+
+ case SIM_EF_CPHS_MAILBOX_NUMBERS: /* linear type */
+ case SIM_EF_MBDN: /* linear type */
+#if 0 /* Temporarily blocked, MBDN is NOT suported in Emulator */
+ dr = tcore_sim_decode_xdn((unsigned char *)res, res_len,
+ file_meta->mb_list[file_meta->current_index-1].alpha_id,
+ file_meta->mb_list[file_meta->current_index-1].number);
+ file_meta->mb_list[file_meta->current_index-1].alpha_id_len =
+ strlen(file_meta->mb_list[file_meta->current_index-1].alpha_id);
+ file_meta->mb_list[file_meta->current_index-1].profile_id =
+ file_meta->current_index;
+#endif /* Temporarily blocked, MBDN is NOT suported in Emulator */
+ break;
+
+ case SIM_EF_CPHS_VOICE_MSG_WAITING: /* transparent type */
+ dr = tcore_sim_decode_vmwf(&file_meta->files.data.mw.cphs_mw,
+ (unsigned char *)res, res_len);
+ break;
+
+ case SIM_EF_USIM_MWIS: { /* linear type */
+ struct tel_sim_mw *mw = NULL;
+
+ mw = g_try_new0(struct tel_sim_mw, 1);
+
+ dr = tcore_sim_decode_mwis(mw, (unsigned char *)res, res_len);
+ if (dr == TRUE) {
+ memcpy(&file_meta->files.data.mw.mw_list.mw[file_meta->files.data.mw.mw_list.profile_count],
+ mw, sizeof(struct tel_sim_mw));
+ file_meta->files.data.mw.mw_list.profile_count++;
+ }
+
+ /* Free memory */
+ g_free(mw);
+ }
+ break;
+
+ case SIM_EF_CPHS_CALL_FORWARD_FLAGS: /* transparent type */
+ dr = tcore_sim_decode_cff(&file_meta->files.data.cf.cphs_cf,
+ (unsigned char *)res, res_len);
+ break;
+
+ case SIM_EF_USIM_CFIS: { /* linear type */
+ struct tel_sim_cfis *cf = NULL;
+
+ cf = g_try_new0(struct tel_sim_cfis, 1);
+ dr = tcore_sim_decode_cfis(cf, (unsigned char *)res, res_len);
+ if (dr == TRUE) {
+ memcpy(&file_meta->files.data.cf.cf_list.cf[file_meta->files.data.cf.cf_list.profile_count],
+ cf, sizeof(struct tel_sim_cfis));
+
+ file_meta->files.data.cf.cf_list.profile_count++;
+ }
+
+ /* Free memory */
+ g_free(cf);
+ }
+ break;
+
+ case SIM_EF_CPHS_SERVICE_STRING_TABLE:
+ dbg("not handled - SIM_EF_CPHS_SERVICE_STRING_TABLE ");
+ break;
+
+ case SIM_EF_CPHS_OPERATOR_NAME_STRING:
+ dr = tcore_sim_decode_ons((unsigned char*)&file_meta->files.data.cphs_net.full_name,
+ (unsigned char *)res, res_len);
+ dbg("file_meta->files.result[%d],file_meta->files.data.cphs_net.full_name[%s]",
+ file_meta->files.result, file_meta->files.data.cphs_net.full_name);
+ break;
+
+ case SIM_EF_CPHS_DYNAMICFLAGS:
+ /*dr = tcore_sim_decode_dynamic_flag(&po->p_cphs->dflagsinfo,
+ p_data->response, p_data->response_len);*/
+ break;
+
+ case SIM_EF_CPHS_DYNAMIC2FLAG:
+ /*dr = tcore_sim_decode_dynamic2_flag(&po->p_cphs->d2flagsinfo, p_data->response,
+ p_data->response_len);*/
+ break;
+
+ case SIM_EF_CPHS_CPHS_INFO:
+ /*dr = tcore_sim_decode_cphs_info(&file_meta->files.data.cphs,
+ (unsigned char *)res, res_len);*/
+ break;
+
+ case SIM_EF_CPHS_OPERATOR_NAME_SHORT_FORM_STRING:
+ dr = tcore_sim_decode_short_ons((unsigned char*)&file_meta->files.data.cphs_net.short_name,
+ (unsigned char *)res, res_len);
+ dbg("file_meta->files.result[%d],file_meta->files.data.cphs_net.short_name[%s]",
+ file_meta->files.result, file_meta->files.data.cphs_net.short_name);
+ break;
+
+ case SIM_EF_CPHS_INFORMATION_NUMBERS:
+ /*dr = tcore_sim_decode_information_number(&po->p_cphs->infn,
+ p_data->response, p_data->response_len);*/
+ break;
+
+ default:
+ dbg("File Decoding Failed - not handled File[0x%x]", file_meta->file_id);
+ dr = 0;
+ break;
+ }
+ } else {
+ sim_result = __sim_decode_status_word(sw1, sw2);
+ file_meta->files.result = sim_result;
+ }
+
+ /* Free memory */
+ g_free(tmp);
+ g_free(res);
+
+ /* Free tokens */
+ tcore_at_tok_free(tokens);
+ } else {
+ err("RESPONSE NOK");
+ dbg("Error - File ID: [0x%x]", file_meta->file_id);
+ sim_result = SIM_ACCESS_FAILED;
+ }
+
+ /* Get File data */
+ __sim_next_from_read_data(tcore_pending_ref_core_object(p), ur,
+ file_meta, sim_result, dr);
+
+ dbg("Exit");
+}
+
+static void __on_response_sim_get_response(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *resp = data;
+ CoreObject *co_sim = NULL;
+ enum tel_sim_access_result sim_result;
+ GSList *tokens = NULL;
+ const char *line = NULL;
+ int sw1 = 0;
+ int sw2 = 0;
+ sim_meta_info_t *file_meta = (sim_meta_info_t *)user_data;
+ UserRequest *ur;
+
+ dbg("SIM Response - SIM File info: [+CRSM]");
+
+ co_sim = tcore_pending_ref_core_object(p);
+ ur = tcore_pending_ref_user_request(p);
+
+ if (resp->success > 0) {
+ dbg("RESPONSE OK");
+ if (resp->lines) {
+ line = (const char *)resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) < 2) {
+ err("Invalid message");
+ tcore_at_tok_free(tokens);
+ return;
+ }
+ }
+ sw1 = atoi(g_slist_nth_data(tokens, 0));
+ sw2 = atoi(g_slist_nth_data(tokens, 1));
+
+ /*1. SIM access success case*/
+ if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
+ unsigned char tag_len = 0;
+ unsigned short record_len = 0;
+ char num_of_records = 0;
+ unsigned char file_id_len = 0;
+ unsigned short file_id = 0;
+ unsigned short file_size = 0;
+ unsigned short file_type = 0;
+ unsigned short arr_file_id = 0;
+ int arr_file_id_rec_num = 0;
+ enum tel_sim_type card_type = SIM_TYPE_UNKNOWN;
+
+ /* handling only last 3 bits */
+ unsigned char file_type_tag = 0x07;
+ unsigned char *ptr_data;
+
+ char *hexData;
+ char *tmp;
+ char *record_data = NULL;
+ guint record_data_len;
+ hexData = g_slist_nth_data(tokens, 2);
+ dbg("hexData: %s", hexData);
+ dbg("hexData: %s", hexData + 1);
+
+ tmp = tcore_at_tok_extract(hexData);
+ __util_hexstring_to_bytes(tmp, &record_data, &record_data_len);
+ tcore_util_hex_dump(" ", record_data_len, record_data);
+ g_free(tmp);
+
+ ptr_data = (unsigned char *)record_data;
+ card_type = tcore_sim_get_type(co_sim);
+ if (SIM_TYPE_USIM == card_type) {
+ /*
+ * ETSI TS 102 221 v7.9.0
+ * - Response Data
+ * '62' FCP template tag
+ *
+ * - Response for an EF
+ * '82' M File Descriptor
+ * '83' M File Identifier
+ * 'A5' O Proprietary information
+ * '8A' M Life Cycle Status Integer
+ * '8B', '8C' or 'AB' C1 Security attributes
+ * '80' M File size
+ * '81' O Total file size
+ * '88' O Short File Identifier (SFI)
+ */
+
+ /* rsim.res_len has complete data length received */
+
+ /* FCP template tag - File Control Parameters tag*/
+ if (*ptr_data == 0x62) {
+ /* parse complete FCP tag*/
+ /* increment to next byte */
+ ptr_data++;
+ tag_len = *ptr_data++;
+ dbg("tag_len: %02x", tag_len);
+ /* FCP file descriptor - file type, accessibility, DF, ADF etc*/
+ if (*ptr_data == 0x82) {
+ /* increment to next byte */
+ ptr_data++;
+ /* 2 or 5 value*/
+ ptr_data++;
+ /* consider only last 3 bits*/
+ dbg("file_type_tag: %02x", file_type_tag);
+ file_type_tag = file_type_tag & (*ptr_data);
+ dbg("file_type_tag: %02x", file_type_tag);
+
+ switch (file_type_tag) {
+ /* increment to next byte */
+ // ptr_data++;
+ case 0x1:
+ dbg("Getting FileType: [Transparent file type]");
+ file_type = SIM_FILE_TYPE_TRANSPARENT;
+
+ /* increment to next byte */
+ ptr_data++;
+ /* increment to next byte */
+ ptr_data++;
+ break;
+
+ case 0x2:
+ dbg("Getting FileType: [Linear fixed file type]");
+ /* increment to next byte */
+ ptr_data++;
+ /* data coding byte - value 21 */
+ ptr_data++;
+ /* 2bytes */
+ memcpy(&record_len, ptr_data, 2);
+ /* swap bytes */
+ SWAP_BYTES_16(record_len);
+ ptr_data = ptr_data + 2;
+ num_of_records = *ptr_data++;
+ /* Data lossy conversation from enum (int) to unsigned char */
+ file_type = SIM_FILE_TYPE_LINEAR_FIXED;
+ break;
+
+ case 0x6:
+ dbg("Cyclic fixed file type");
+ /* increment to next byte */
+ ptr_data++;
+ /* data coding byte - value 21 */
+ ptr_data++;
+ /* 2bytes */
+ memcpy(&record_len, ptr_data, 2);
+ /* swap bytes */
+ SWAP_BYTES_16(record_len);
+ ptr_data = ptr_data + 2;
+ num_of_records = *ptr_data++;
+ file_type = SIM_FILE_TYPE_CYCLIC;
+ break;
+
+ default:
+ dbg("not handled file type [0x%x]", *ptr_data);
+ break;
+ }
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ tcore_at_tok_free(tokens);
+ g_free(record_data);
+ return;
+ }
+
+ /*File identifier - 0x84,0x85,0x86 etc are currently ignored and not handled */
+ if (*ptr_data == 0x83) {
+ /* increment to next byte */
+ ptr_data++;
+ file_id_len = *ptr_data++;
+ dbg("file_id_len: %02x", file_id_len);
+
+ memcpy(&file_id, ptr_data, file_id_len);
+ dbg("file_id: %x", file_id);
+
+ /* swap bytes */
+ SWAP_BYTES_16(file_id);
+ dbg("file_id: %x", file_id);
+
+ ptr_data = ptr_data + 2;
+ dbg("Getting FileID=[0x%x]", file_id);
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ tcore_at_tok_free(tokens);
+ g_free(record_data);
+ return;
+ }
+
+ /* proprietary information */
+ if (*ptr_data == 0xA5) {
+ unsigned short prop_len;
+ /* increment to next byte */
+ ptr_data++;
+
+ /* length */
+ prop_len = *ptr_data;
+ dbg("prop_len: %02x", prop_len);
+
+ /* skip data */
+ ptr_data = ptr_data + prop_len + 1;
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ }
+
+ /* life cycle status integer [8A][length:0x01][status]*/
+ /*
+ status info b8~b1
+ 00000000 : No information given
+ 00000001 : creation state
+ 00000011 : initialization state
+ 000001-1 : operation state -activated
+ 000001-0 : operation state -deactivated
+ 000011-- : Termination state
+ b8~b5 !=0, b4~b1=X : Proprietary
+ Any other value : RFU
+ */
+ if (*ptr_data == 0x8A) {
+ /* increment to next byte */
+ ptr_data++;
+ /* length - value 1 */
+ ptr_data++;
+
+ switch (*ptr_data) {
+ case 0x04:
+ case 0x06:
+ dbg("<RX> operation state -deactivated");
+ ptr_data++;
+ break;
+
+ case 0x05:
+ case 0x07:
+ dbg("<RX> operation state -activated");
+ ptr_data++;
+ break;
+
+ default:
+ dbg("<RX> DEBUG! LIFE CYCLE STATUS =[0x%x]", *ptr_data);
+ ptr_data++;
+ break;
+ }
+ }
+
+ /* related to security attributes : currently not handled*/
+ if (*ptr_data == 0x86 || *ptr_data == 0x8B || *ptr_data == 0x8C || *ptr_data == 0xAB) {
+ /* increment to next byte */
+ ptr_data++;
+ /* if tag length is 3 */
+ if (*ptr_data == 0x03) {
+ /* increment to next byte */
+ ptr_data++;
+ /* EFARR file id */
+ memcpy(&arr_file_id, ptr_data, 2);
+ /* swap byes */
+ SWAP_BYTES_16(arr_file_id);
+ ptr_data = ptr_data + 2;
+ arr_file_id_rec_num = *ptr_data++;
+ dbg("arr_file_id_rec_num:[%d]", arr_file_id_rec_num);
+ } else {
+ /* if tag length is not 3 */
+ /* ignoring bytes */
+ // ptr_data = ptr_data + 4;
+ dbg("Useless security attributes, so jump to next tag");
+ ptr_data = ptr_data + (*ptr_data + 1);
+ }
+ } else {
+ dbg("INVALID FCP received[0x%x] - DEbug!", *ptr_data);
+ tcore_at_tok_free(tokens);
+ g_free(record_data);
+ return;
+ }
+
+ dbg("Current ptr_data value is [%x]", *ptr_data);
+
+ /* file size excluding structural info*/
+ if (*ptr_data == 0x80) {
+ /* for EF file size is body of file and for Linear or cyclic it is
+ * number of recXsizeof(one record)
+ */
+ /* increment to next byte */
+ ptr_data++;
+ /* length is 1 byte - value is 2 bytes or more */
+ ptr_data++;
+ memcpy(&file_size, ptr_data, 2);
+ /* swap bytes */
+ SWAP_BYTES_16(file_size);
+ ptr_data = ptr_data + 2;
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ tcore_at_tok_free(tokens);
+ g_free(record_data);
+ return;
+ }
+
+ /* total file size including structural info*/
+ if (*ptr_data == 0x81) {
+ int len;
+ /* increment to next byte */
+ ptr_data++;
+ /* length */
+ len = *ptr_data;
+ dbg("len:[%d]", len);
+ /* ignored bytes */
+ ptr_data = ptr_data + 3;
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ /* 0x81 is optional tag?? check out! so do not return -1 from here! */
+ }
+ /*short file identifier ignored*/
+ if (*ptr_data == 0x88) {
+ dbg("0x88: Do Nothing");
+ /*DO NOTHING*/
+ }
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ tcore_at_tok_free(tokens);
+ g_free(record_data);
+ return;
+ }
+ } else if (SIM_TYPE_GSM == card_type) {
+ unsigned char gsm_specific_file_data_len = 0;
+ /* ignore RFU byte1 and byte2 */
+ ptr_data++;
+ ptr_data++;
+ /* file size */
+ // file_size = p_info->response_len;
+ memcpy(&file_size, ptr_data, 2);
+ /* swap bytes */
+ SWAP_BYTES_16(file_size);
+ /* parsed file size */
+ ptr_data = ptr_data + 2;
+ /* file id */
+ memcpy(&file_id, ptr_data, 2);
+ SWAP_BYTES_16(file_id);
+ dbg("FILE id --> [%x]", file_id);
+ ptr_data = ptr_data + 2;
+ /* save file type - transparent, linear fixed or cyclic */
+ file_type_tag = (*(ptr_data + 7));
+
+ switch (*ptr_data) {
+ case 0x0:
+ /* RFU file type */
+ dbg("RFU file type- not handled - Debug!");
+ break;
+
+ case 0x1:
+ /* MF file type */
+ dbg("MF file type - not handled - Debug!");
+ break;
+
+ case 0x2:
+ /* DF file type */
+ dbg("DF file type - not handled - Debug!");
+ break;
+
+ case 0x4:
+ /* EF file type */
+ dbg("EF file type [%d] ", file_type_tag);
+ /* increment to next byte */
+ ptr_data++;
+
+ if (file_type_tag == 0x00 || file_type_tag == 0x01) {
+ /* increament to next byte as this byte is RFU */
+ ptr_data++;
+ file_type =
+ (file_type_tag == 0x00) ? SIM_FILE_TYPE_TRANSPARENT : SIM_FILE_TYPE_LINEAR_FIXED;
+ } else {
+ /* increment to next byte */
+ ptr_data++;
+ /* For a cyclic EF all bits except bit 7 are RFU; b7=1 indicates that */
+ /* the INCREASE command is allowed on the selected cyclic file. */
+ file_type = SIM_FILE_TYPE_CYCLIC;
+ }
+ /* bytes 9 to 11 give SIM file access conditions */
+ ptr_data++;
+ /* byte 10 has one nibble that is RF U and another for INCREASE which is not used currently */
+ ptr_data++;
+ /* byte 11 is invalidate and rehabilate nibbles */
+ ptr_data++;
+ /* byte 12 - file status */
+ ptr_data++;
+ /* byte 13 - GSM specific data */
+ gsm_specific_file_data_len = *ptr_data;
+ dbg("gsm_specific_file_data_len:[%d]", gsm_specific_file_data_len);
+ ptr_data++;
+ /* byte 14 - structure of EF - transparent or linear or cyclic , already saved above */
+ ptr_data++;
+ /* byte 15 - length of record for linear and cyclic , for transparent it is set to 0x00. */
+ record_len = *ptr_data;
+ dbg("record length[%d], file size[%d]", record_len, file_size);
+ if (record_len != 0)
+ num_of_records = (file_size / record_len);
+
+ dbg("Number of records [%d]", num_of_records);
+ break;
+
+ default:
+ dbg("not handled file type");
+ break;
+ }
+ } else {
+ err("Unknown Card Type - [%d]", card_type);
+ }
+
+ dbg("req ef[0x%x] resp ef[0x%x] size[%ld] Type[0x%x] "\
+ "NumOfRecords[%ld] RecordLen[%ld]",
+ file_meta->file_id, file_id, file_size,
+ file_type, num_of_records, record_len);
+
+ file_meta->file_type = file_type;
+ file_meta->data_size = file_size;
+ file_meta->rec_length = record_len;
+ file_meta->rec_count = num_of_records;
+ file_meta->current_index = 0; /* reset for new record type EF */
+ sim_result = SIM_ACCESS_SUCCESS;
+ g_free(record_data);
+ } else {
+ /*2. SIM access fail case*/
+ err("Failed to get ef[0x%x] (file_meta->file_id) ", file_meta->file_id);
+ sim_result = __sim_decode_status_word(sw1, sw2);
+ }
+
+ tcore_at_tok_free(tokens);
+ } else {
+ err("RESPONSE NOK");
+ err("Failed to get ef[0x%x] (file_meta->file_id)",
+ file_meta->file_id);
+ sim_result = SIM_ACCESS_FAILED;
+ }
+
+ dbg("Calling __sim_next_from_get_response");
+ __sim_next_from_get_response(co_sim, ur, file_meta, sim_result, FALSE);
+ dbg("Exit");
+}
+
+static void __sim_read_record(CoreObject *co_sim, UserRequest *ur, sim_meta_info_t *file_meta)
+{
+ gchar *at_cmd = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry File-id:[0x%02x]", file_meta->file_id);
+
+ at_cmd = g_strdup_printf("AT+CRSM=%d, %d",
+ SIM_ACCESS_READ_RECORD, file_meta->file_id);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ at_cmd, "+CRSM:",
+ TCORE_AT_SINGLELINE,
+ ur,
+ __on_response_sim_read_data, file_meta,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ dbg("Exit");
+}
+
+static void __sim_read_binary(CoreObject *co_sim, UserRequest *ur, sim_meta_info_t *file_meta)
+{
+ gchar *at_cmd = NULL;
+ int p1 = 0;
+ int p2 = 0;
+ int p3 = 0;
+ int offset = 0;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry File-id:[0x%02x]", file_meta->file_id);
+
+ /*
+ * According to TS 102 221, values of P1, P2, P3 can be as below:
+ * 11.1.3 READ BINARY
+ * P1: See table 11.10
+ * P2: Offset low
+ * Lc: Not present
+ * Data: Not present
+ * Le: Number of bytes to be read (P3)
+ */
+ p1 = (unsigned char) (offset & 0xFF00) >> 8;
+ p2 = (unsigned char) offset & 0x00FF; /* offset low */
+ p3 = (unsigned char) file_meta->data_size;
+
+ if ((file_meta->file_id == SIM_EF_SPN)
+ || (file_meta->file_id == SIM_EF_IMSI)
+ || (file_meta->file_id == SIM_EF_LP)
+ || (file_meta->file_id == SIM_EF_SST))
+ at_cmd = g_strdup_printf("AT+CRSM=%d, %d",
+ SIM_ACCESS_READ_BINARY, file_meta->file_id);
+ else
+ at_cmd = g_strdup_printf("AT+CRSM=%d, %d, %d, %d, %d",
+ SIM_ACCESS_READ_BINARY, file_meta->file_id, p1, p2, p3);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ at_cmd, "+CRSM:",
+ TCORE_AT_SINGLELINE,
+ ur,
+ __on_response_sim_read_data, file_meta,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ dbg("Exit");
+}
+
+static TReturn __sim_get_response(CoreObject *co_sim, UserRequest *ur, sim_meta_info_t *file_meta)
+{
+ gchar *at_cmd = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry File-id:[0x%02x]", file_meta->file_id);
+
+ at_cmd = g_strdup_printf("AT+CRSM=%d, %d",
+ SIM_ACCESS_GET_RESPONSE, file_meta->file_id);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ at_cmd, "+CRSM:",
+ TCORE_AT_SINGLELINE,
+ ur,
+ __on_response_sim_get_response, file_meta,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ return ret;
+}
+
+#if 0 /* To be used later */
+static int __sim_get_lock_type(sim_sec_op_t sec_op)
+{
+ switch(sec_op) {
+ case SIM_CURR_SEC_OP_SIM_DISABLE :
+ case SIM_CURR_SEC_OP_SIM_ENABLE :
+ case SIM_CURR_SEC_OP_SIM_STATUS :
+ return SIM_FACILITY_PS;
+ case SIM_CURR_SEC_OP_PIN1_DISABLE :
+ case SIM_CURR_SEC_OP_PIN1_ENABLE :
+ case SIM_CURR_SEC_OP_PIN1_STATUS :
+ return SIM_FACILITY_SC;
+ case SIM_CURR_SEC_OP_FDN_DISABLE :
+ case SIM_CURR_SEC_OP_FDN_ENABLE :
+ case SIM_CURR_SEC_OP_FDN_STATUS :
+ return SIM_FACILITY_FD;
+ case SIM_CURR_SEC_OP_NET_DISABLE :
+ case SIM_CURR_SEC_OP_NET_ENABLE :
+ case SIM_CURR_SEC_OP_NET_STATUS :
+ return SIM_FACILITY_PN;
+ case SIM_CURR_SEC_OP_NS_DISABLE :
+ case SIM_CURR_SEC_OP_NS_ENABLE :
+ case SIM_CURR_SEC_OP_NS_STATUS :
+ return SIM_FACILITY_PU;
+ case SIM_CURR_SEC_OP_SP_DISABLE :
+ case SIM_CURR_SEC_OP_SP_ENABLE :
+ case SIM_CURR_SEC_OP_SP_STATUS :
+ return SIM_FACILITY_PP;
+ case SIM_CURR_SEC_OP_CP_DISABLE :
+ case SIM_CURR_SEC_OP_CP_ENABLE :
+ case SIM_CURR_SEC_OP_CP_STATUS :
+ return SIM_FACILITY_PC ;
+ default :
+ err("Invalid sec op [%d]", sec_op);
+ return -1;
+ }
+}
+#endif
+
+/* Notifications */
+/*
+ * Notification: +SCSIM: <SIM state>
+ *
+ * Possible values of <SIM state> can be
+ * 0 SIM not present
+ * 1 PIN verification needed
+ * 2 PIN verification not needed - Ready
+ * 3 PIN verified - Ready
+ * 4 PUK verification needed
+ * 5 SIM permanently blocked
+ * 6 SIM Error
+ * 7 ready for attach (+COPS)
+ * 8 SIM Technical Problem
+ * 9 SIM Removed
+ * 10 SIM Reactivating
+ * 11 SIM Reactivated
+ * 12 SIM SMS Caching Completed. (Sent only when SMS caching enabled)
+ * 99 SIM State Unknown
+ */
+static gboolean on_notification_sim_status(CoreObject *co_sim,
+ const void *event_info, void *user_data)
+{
+ GSList *lines = (GSList *)event_info;
+ const gchar *line = (const gchar *)lines->data;
+ enum tel_sim_status sim_status = SIM_STATUS_INITIALIZING;
+ sim_sec_lock_type_t locktype = SEC_LOCK_TYPE_NONE;
+ sim_sec_lock_key_t lockkey = SEC_LOCK_KEY_NONE;
+
+ if (__convert_scpin_str_to_enum((char *)line, &locktype, &lockkey) == FALSE)
+ return TRUE;
+
+ switch (locktype) {
+ case SEC_LOCK_TYPE_READY:
+ if (lockkey == SEC_LOCK_KEY_UNLOCKED)
+ sim_status = SIM_STATUS_INITIALIZING;
+ else
+ sim_status = SIM_STATUS_UNKNOWN;
+ break;
+
+ case SEC_LOCK_TYPE_PS:
+ sim_status = SIM_STATUS_LOCK_REQUIRED;
+ break;
+
+ case SEC_LOCK_TYPE_PF:
+ sim_status = SIM_STATUS_CARD_ERROR;
+ break;
+
+ case SEC_LOCK_TYPE_SC:
+ switch (lockkey) {
+ case SEC_LOCK_KEY_UNLOCKED:
+ break;
+
+ case SEC_LOCK_KEY_PIN:
+ sim_status = SIM_STATUS_PIN_REQUIRED;
+ break;
+
+ case SEC_LOCK_KEY_PUK:
+ sim_status = SIM_STATUS_PUK_REQUIRED;
+ break;
+
+ case SEC_LOCK_KEY_PERM_BLOCKED:
+ sim_status = SIM_STATUS_CARD_BLOCKED;
+ break;
+
+ default:
+ err("Not handled SEC Lock key: [%d]", lockkey);
+ sim_status = SIM_STATUS_UNKNOWN;
+ break;
+ }
+ break;
+
+ case SEC_LOCK_TYPE_FD:
+ break;
+
+ case SEC_LOCK_TYPE_PN:
+ if (SEC_LOCK_KEY_PIN)
+ sim_status = SIM_STATUS_NCK_REQUIRED;
+ else
+ sim_status = SIM_STATUS_UNKNOWN;
+ break;
+
+ case SEC_LOCK_TYPE_PU:
+ if (SEC_LOCK_KEY_PIN)
+ sim_status = SIM_STATUS_NSCK_REQUIRED;
+ else
+ sim_status = SIM_STATUS_UNKNOWN;
+ break;
+
+ case SEC_LOCK_TYPE_PP:
+ if (SEC_LOCK_KEY_PIN)
+ sim_status = SIM_STATUS_SPCK_REQUIRED;
+ else
+ sim_status = SIM_STATUS_UNKNOWN;
+ break;
+
+ case SEC_LOCK_TYPE_PC:
+ if (SEC_LOCK_KEY_PIN)
+ sim_status = SIM_STATUS_CCK_REQUIRED;
+ else
+ sim_status = SIM_STATUS_UNKNOWN;
+ break;
+
+ case SEC_LOCK_TYPE_SC2:
+ case SEC_LOCK_TYPE_PUK2:
+ break;
+
+ case SEC_LOCK_TYPE_NO_SIM:
+ sim_status = SIM_STATUS_CARD_NOT_PRESENT;
+ break;
+
+ case SEC_LOCK_TYPE_UNAVAIL:
+ case SEC_SIM_INIT_CRASH:
+ sim_status = SIM_STATUS_CARD_ERROR;
+ break;
+
+ case SEC_SIM_INIT_COMPLETED:
+ sim_status = SIM_STATUS_INIT_COMPLETED;
+ break;
+
+ case SEC_PB_INIT_COMPLETED:
+ break;
+
+ default:
+ err("Not handled SEC lock type: [%d]", locktype);
+ sim_status = SIM_STATUS_UNKNOWN;
+ break;
+ }
+
+ __sim_process_sim_status(co_sim, sim_status);
+
+ return TRUE;
+}
+
+/* Response Functions */
+static void on_response_sim_verify_pins(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
+ CoreObject *co_sim;
+ UserRequest *ur;
+ struct treq_sim_verify_pins *verify_pin_req;
+ struct tresp_sim_verify_pins verify_pin_resp;
+
+ dbg("Entry");
+
+ memset(&verify_pin_resp, 0x0, sizeof(struct tresp_sim_verify_pins));
+
+ co_sim = tcore_pending_ref_core_object(p);
+ ur = tcore_pending_ref_user_request(p);
+ verify_pin_req = (struct treq_sim_verify_pins *)tcore_user_request_ref_data(ur, NULL);
+
+ if (verify_pin_req->pin_type == SIM_PTYPE_PIN1) {
+ enum tel_sim_status status;
+
+ verify_pin_resp.pin_type = SIM_PTYPE_PIN1;
+
+ status = tcore_sim_get_status(co_sim);
+ if (status != SIM_STATUS_INIT_COMPLETED) {
+ /* Update sim status */
+ __sim_update_sim_status(co_sim, SIM_STATUS_INITIALIZING);
+ dbg("SIM is initializing...");
+ }
+ } else if (verify_pin_req->pin_type == SIM_PTYPE_PIN2) {
+ verify_pin_resp.pin_type = SIM_PTYPE_PIN2;
+ }
+
+ if (at_resp && at_resp->success) {
+ dbg("SIM Verify Pin Response- [OK]");
+ verify_pin_resp.result = SIM_PIN_OPERATION_SUCCESS;
+
+ } else {
+ err("SIM Verify Pin Response- [NOK]");
+
+ /* Update retry count */
+ verify_pin_resp.retry_count = 3;
+ verify_pin_resp.result = SIM_INCORRECT_PASSWORD;
+ }
+
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SIM_VERIFY_PINS,
+ sizeof(struct tresp_sim_verify_pins), &verify_pin_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sim_verify_puks(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
+ struct treq_sim_verify_puks *verify_puk_req;
+ struct tresp_sim_verify_puks verify_puk_resp;
+ UserRequest *ur;
+
+ dbg("Entry");
+
+ ur = tcore_pending_ref_user_request(p);
+ verify_puk_req = (struct treq_sim_verify_puks *)tcore_user_request_ref_data(ur, NULL);
+
+ verify_puk_resp.pin_type = verify_puk_req->puk_type;
+
+ if (at_resp && at_resp->success) {
+ dbg("SIM Verify Puk Response- [OK]");
+ verify_puk_resp.result = SIM_PIN_OPERATION_SUCCESS;
+ } else {
+ err("SIM Verify Puk Response- [NOK]");
+
+ /* Update retry count */
+ verify_puk_resp.retry_count = 3;
+ verify_puk_resp.result = SIM_INCORRECT_PASSWORD;
+ }
+
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SIM_VERIFY_PUKS,
+ sizeof(struct tresp_sim_verify_puks), &verify_puk_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sim_change_pins(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
+ struct treq_sim_change_pins *sim_change_req;
+ struct tresp_sim_change_pins sim_change_resp;
+ UserRequest *ur;
+
+ dbg("Entry");
+
+ ur = tcore_pending_ref_user_request(p);
+ sim_change_req = (struct treq_sim_change_pins *)tcore_user_request_ref_data(ur, NULL);
+
+ sim_change_resp.pin_type = sim_change_req->type;
+
+ if (at_resp && at_resp->success) {
+ dbg("SIM Change Pin Response- [OK]");
+ sim_change_resp.result = SIM_PIN_OPERATION_SUCCESS;
+ } else {
+ err("SIM Change Pin Response- [NOK]");
+
+ /* Update retry count */
+ sim_change_resp.retry_count = 3;
+ sim_change_resp.result = SIM_INCORRECT_PASSWORD;
+ }
+
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SIM_CHANGE_PINS,
+ sizeof(struct tresp_sim_change_pins), &sim_change_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sim_disable_facility(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
+ struct treq_sim_disable_facility *disable_facility_req;
+ struct tresp_sim_disable_facility disable_facility_resp;
+ UserRequest *ur;
+
+ dbg("Entry");
+
+ memset(&disable_facility_resp, 0x0, sizeof(struct tresp_sim_disable_facility));
+
+ ur = tcore_pending_ref_user_request(p);
+ disable_facility_req = (struct treq_sim_disable_facility *)tcore_user_request_ref_data(ur, NULL);
+
+ disable_facility_resp.type = disable_facility_req->type;
+
+ if (at_resp && at_resp->success) {
+ dbg("SIM Disable Facility Response- [OK]");
+ disable_facility_resp.result = SIM_PIN_OPERATION_SUCCESS;
+ } else {
+ err("SIM Disable Facility Response- [NOK]");
+
+ /* Update retry count */
+ disable_facility_resp.retry_count = 3;
+ disable_facility_resp.result = SIM_INCORRECT_PASSWORD;
+ }
+
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SIM_DISABLE_FACILITY,
+ sizeof(struct tresp_sim_disable_facility), &disable_facility_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sim_enable_facility(TcorePending *p,
+ gint data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
+ struct treq_sim_enable_facility *enable_facility_req;
+ struct tresp_sim_enable_facility enable_facility_resp;
+ UserRequest *ur;
+
+ dbg("Entry");
+
+ memset(&enable_facility_resp, 0x0, sizeof(struct tresp_sim_enable_facility));
+
+ ur = tcore_pending_ref_user_request(p);
+ enable_facility_req = (struct treq_sim_enable_facility *)tcore_user_request_ref_data(ur, NULL);
+
+ enable_facility_resp.type = enable_facility_req->type;
+
+ if (at_resp && at_resp->success) {
+ dbg("SIM Disable Facility Response- [OK]");
+ enable_facility_resp.result = SIM_PIN_OPERATION_SUCCESS;
+ } else {
+ err("SIM Disable Facility Response- [NOK]");
+
+ /* Update retry count */
+ enable_facility_resp.retry_count = 3;
+ enable_facility_resp.result = SIM_INCORRECT_PASSWORD;
+ }
+
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SIM_ENABLE_FACILITY,
+ sizeof(struct tresp_sim_enable_facility), &enable_facility_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sim_get_facility(TcorePending *p, gint data_len,
+ const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
+ struct treq_sim_get_facility_status *get_facility_req;
+ struct tresp_sim_get_facility_status get_facility_resp;
+ UserRequest *ur;
+
+ dbg("Entry");
+
+ memset(&get_facility_resp, 0x0, sizeof(struct tresp_sim_get_facility_status));
+
+ ur = tcore_pending_ref_user_request(p);
+ get_facility_req = (struct treq_sim_get_facility_status *)tcore_user_request_ref_data(ur, NULL);
+
+ get_facility_resp.type = get_facility_req->type;
+ get_facility_resp.result = SIM_CARD_ERROR;
+
+ if (at_resp && at_resp->success) {
+ GSList *tokens = NULL;
+ const char *line;
+
+ dbg("SIM Disable Facility Response- [OK]");
+ if (at_resp->lines) {
+ line = (const char *)at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) < 1) {
+ err("Invalid message");
+ }
+ else {
+ char *local_data = g_slist_nth_data(tokens, 0);
+ if (local_data != NULL) {
+ get_facility_resp.b_enable = atoi(local_data);
+ dbg("Facility: [%s] - [%s]",
+ __sim_get_fac_from_lock_type(get_facility_req->type),
+ (get_facility_resp.b_enable ? "Enabled" : "Disabled"));
+
+ get_facility_resp.result = SIM_PIN_OPERATION_SUCCESS;
+ }
+ else {
+ err("Invalid message");
+ }
+ }
+
+ tcore_at_tok_free(tokens);
+ }
+ } else {
+ err("SIM Disable Facility Response- [NOK]");
+ }
+
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SIM_GET_FACILITY_STATUS,
+ sizeof(struct tresp_sim_get_facility_status), &get_facility_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+/* SIM Operations */
+/*
+ * Operation - get_imsi
+ *
+ * Request -
+ * AT-Command: AT+CRSM= <command>[,<fileid>[,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]]
+ * where,
+ * <command>
+ * 176 READ BINARY
+ * 178 READ RECORD
+ * 192 GET RESPONSE
+ * 214 UPDATE BINARY
+ * 220 UPDATE RECORD
+ * 242 STATUS
+ *
+ * <fileid>
+ * 28423 meaning IMSI file (6F07)
+ * 28473 meaning ACM file (6F39)
+ * 28481 meaning PUKT file (6F41)
+ * 28482 meaning SMS file (6F42)
+ *
+ * <P1>, <P2>, <P3>
+ * Integer type defining the request.
+ * These parameters are mandatory for every command, except GET RESPONSE and STATUS.
+ *
+ * <data>
+ * Information which shall be written to the SIM
+ *
+ * <pathid>
+ * String type, contains the path of an elementary file on the SIM/USIM in hexadecimal format
+ *
+ * <status>
+ * 0 not active
+ * 1 active
+ *
+ * Success:
+ * OK
+ * +CRSM: <sw1>,<sw2>[,<response>]
+ *
+ * <sw1>, <sw2>
+ * Integer type containing the SIM information
+ *
+ * <response>
+ * Response of successful completion of the command previously issued
+ *
+ * Failure:
+ * +CME ERROR: <error>
+ */
+#if 0 /* To be used later */
+static TReturn __sim_get_imsi(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_IMSI;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_IMSI;
+
+ return __sim_get_response(co_sim, ur, file_meta);
+}
+#endif
+static TReturn __sim_get_ecc(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+ TReturn ret;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_ECC;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_ECC;
+
+ ret = __sim_get_response(co_sim, ur, file_meta);
+
+ return ret;
+}
+
+static TReturn __sim_get_spdi(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+ TReturn ret;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_SPDI;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_SPDI;
+
+ ret = __sim_get_response(co_sim, ur, file_meta);
+
+ return ret;
+}
+
+static TReturn __sim_get_cfis(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+ TReturn ret;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_USIM_CFIS;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_CALLFORWARDING;
+
+ ret = __sim_get_response(co_sim, ur, file_meta);
+
+ return ret;
+}
+
+static TReturn __sim_get_spn(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+ TReturn ret;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_SPN;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_SPN;
+
+ ret = __sim_get_response(co_sim, ur, file_meta);
+
+ return ret;
+}
+
+static TReturn __sim_get_language(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+ TReturn ret;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_LP;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_LANGUAGE;
+
+ ret = __sim_get_response(co_sim, ur, file_meta);
+
+ return ret;
+}
+
+static TReturn __sim_get_sst(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+ TReturn ret;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_SST;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_SERVICE_TABLE;
+
+ ret = __sim_get_response(co_sim, ur, file_meta);
+
+ return ret;
+}
+
+static TReturn __sim_get_iccid(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+ TReturn ret;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_ICCID;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_ICCID;
+
+ ret = __sim_get_response(co_sim, ur, file_meta);
+
+ return ret;
+}
+
+static TReturn __sim_get_msisdn(CoreObject *co_sim, UserRequest *ur)
+{
+ sim_meta_info_t *file_meta;
+ TReturn ret;
+
+ dbg("Entry");
+
+ ALLOC_METAINFO();
+ file_meta->file_id = SIM_EF_MSISDN;
+ file_meta->file_result = SIM_ACCESS_FAILED;
+ file_meta->req_command = TREQ_SIM_GET_MSISDN;
+
+ ret = __sim_get_response(co_sim, ur, file_meta);
+
+ return ret;
+}
+/*
+ * Operation - verify_pins/verify_puks/change_pins
+ *
+ * Request -
+ * For SIM PIN
+ * AT-Command: AT+CPIN= <pin> [, <newpin>]
+ * where,
+ * <pin>, <newpin>
+ * String type values
+ *
+ * For SIM PIN2
+ * AT-Command: AT+CPIN2= <puk2/oldpin2> [, <newpin2>]andAT+CPIN2=<oldpin2>
+ * where,
+ * <puk2/pin2>, <newpin2>
+ * String type values
+ *
+ * Success:
+ * OK
+ *
+ * Failure:
+ * +CME ERROR: <error>
+ */
+static TReturn s_sim_verify_pins(CoreObject *co_sim, UserRequest *ur)
+{
+ struct treq_sim_verify_pins *verify_pins_req;
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *cmd_str = NULL;
+
+ dbg("Entry");
+
+ verify_pins_req = (struct treq_sim_verify_pins *)tcore_user_request_ref_data(ur, NULL);
+
+ if ((verify_pins_req->pin_type == SIM_PTYPE_PIN1)
+ || (verify_pins_req->pin_type == SIM_PTYPE_PIN2)) {
+ dbg("PUK type: [%d]", verify_pins_req->pin_type);
+ } else {
+ err("Invalid pin type [%d]", verify_pins_req->pin_type);
+ return TCORE_RETURN_EINVAL;
+ }
+
+ cmd_str = g_strdup_printf("AT+CPIN=\"%s\"", verify_pins_req->pin);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ cmd_str, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_sim_verify_pins, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(cmd_str);
+ return ret;
+}
+
+static TReturn s_sim_verify_puks(CoreObject *co_sim, UserRequest *ur)
+{
+ struct treq_sim_verify_puks *verify_puks_req;
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *cmd_str = NULL;
+
+ dbg("Entry");
+
+ verify_puks_req = (struct treq_sim_verify_puks *)tcore_user_request_ref_data(ur, NULL);
+
+ if ((verify_puks_req->puk_type == SIM_PTYPE_PUK1)
+ || (verify_puks_req->puk_type == SIM_PTYPE_PUK2)) {
+ dbg("PUK type: [%d]", verify_puks_req->puk_type);
+ } else {
+ err("Invalid puk type [%d]", verify_puks_req->puk_type);
+ return TCORE_RETURN_EINVAL;
+ }
+
+ cmd_str = g_strdup_printf("AT+CPIN=\"%s\", \"%s\"",
+ verify_puks_req->puk, verify_puks_req->pin);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ cmd_str, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_sim_verify_puks, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(cmd_str);
+ return ret;
+}
+
+static TReturn s_sim_change_pins(CoreObject *co_sim, UserRequest *ur)
+{
+ struct treq_sim_change_pins *sim_change_req;
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *cmd_str = NULL;
+
+ dbg("Entry");
+
+ sim_change_req = (struct treq_sim_change_pins *)tcore_user_request_ref_data(ur, NULL);
+
+ if ((sim_change_req->type == SIM_PTYPE_PIN1)
+ || (sim_change_req->type == SIM_PTYPE_PIN2)) {
+ dbg("PIN type: [%d]", sim_change_req->type);
+ } else {
+ err("Invalid pin type [%d]", sim_change_req->type);
+ return TCORE_RETURN_EINVAL;
+ }
+
+ cmd_str = g_strdup_printf("AT+CPIN=\"%s\", \"%s\"", sim_change_req->old_pin, sim_change_req->new_pin);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ cmd_str, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_sim_change_pins, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(cmd_str);
+ return ret;
+}
+
+/*
+ * Operation - disable_facility/enable_facility/get_facility
+ *
+ * Request -
+ * AT-Command: AT+CLCK = <fac>, <mode> [, <passwd> [, <class>]]
+ * where,
+ * <fac>
+ * SIM facility
+ *
+ * <mode>
+ * 0 unlock
+ * 1 lock
+ * 2 query status
+ *
+ * <passwd>
+ * Password string
+ *
+ * <status>
+ * 0 not active
+ * 1 active
+ *
+ * Success: when <mode>=2:
+ * OK
+ * +CLCK: <status>[,<class1> [<CR><LF>
+ * +CLCK: <status>,<class2> [...]]
+ *
+ * Failure:
+ */
+static TReturn s_sim_disable_facility(CoreObject *co_sim, UserRequest *ur)
+{
+ struct treq_sim_disable_facility *disable_facility_req;
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *cmd_str = NULL;
+ const char *fac = "SC";
+ int mode = 0; /*mode = 0 for disable lock*/
+
+ dbg("Entry");
+
+ disable_facility_req = (struct treq_sim_disable_facility *)tcore_user_request_ref_data(ur, NULL);
+
+ fac = __sim_get_fac_from_lock_type(disable_facility_req->type);
+ if (!fac) {
+ err("Invalid 'fac'");
+ return TCORE_RETURN_EINVAL;
+ }
+
+ cmd_str = g_strdup_printf("AT+CLCK=\"%s\", %d, \"%s\"", fac, mode, disable_facility_req->password);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ cmd_str, "+CLCK:",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sim_disable_facility, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(cmd_str);
+ return ret;
+}
+
+static TReturn s_sim_enable_facility(CoreObject *co_sim, UserRequest *ur)
+{
+ struct treq_sim_enable_facility *enable_facility_req;
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *cmd_str = NULL;
+ const char *fac = "SC";
+ int mode = 1; /*mode = 1 for enable lock*/
+
+ dbg("Entry");
+
+ enable_facility_req = (struct treq_sim_enable_facility *)tcore_user_request_ref_data(ur, NULL);
+
+ fac = __sim_get_fac_from_lock_type(enable_facility_req->type);
+ if (!fac) {
+ err("Invalid 'fac'");
+ return TCORE_RETURN_EINVAL;
+ }
+
+ cmd_str = g_strdup_printf("AT+CLCK=\"%s\", %d, \"%s\"", fac, mode, enable_facility_req->password);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ cmd_str, "+CLCK:",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sim_enable_facility, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(cmd_str);
+ return ret;
+}
+
+TReturn s_sim_read_file(CoreObject *co_sim, UserRequest *ur)
+{
+ TReturn ret = TCORE_RETURN_SUCCESS;
+ enum tcore_request_command command;
+
+ dbg("Entry");
+
+ command = tcore_user_request_get_command(ur);
+
+ switch (command) {
+ case TREQ_SIM_GET_ECC:
+ ret = __sim_get_ecc(co_sim, ur);
+ break;
+
+ case TREQ_SIM_GET_LANGUAGE:
+ ret = __sim_get_language(co_sim, ur);
+ break;
+
+ case TREQ_SIM_GET_CALLFORWARDING:
+ ret = __sim_get_cfis(co_sim, ur);
+ break;
+
+ case TREQ_SIM_GET_SPN:
+ ret = __sim_get_spn(co_sim, ur);
+ break;
+
+ case TREQ_SIM_GET_SPDI:
+ ret = __sim_get_spdi(co_sim, ur);
+ break;
+
+ case TREQ_SIM_GET_SERVICE_TABLE:
+ ret = __sim_get_sst(co_sim, ur);
+ break;
+
+ case TREQ_SIM_GET_ICCID:
+ ret = __sim_get_iccid(co_sim, ur);
+ break;
+
+ case TREQ_SIM_GET_MSISDN:
+ ret = __sim_get_msisdn(co_sim, ur);
+ break;
+
+ case TREQ_SIM_GET_MESSAGEWAITING:
+ case TREQ_SIM_GET_CPHS_INFO:
+ case TREQ_SIM_GET_OPL:
+ case TREQ_SIM_GET_PNN:
+ case TREQ_SIM_GET_CPHS_NETNAME:
+ case TREQ_SIM_GET_OPLMNWACT:
+ case TREQ_SIM_GET_MAILBOX:
+ default:
+ dbg("Unhandled read requests - command: [0x%x]", command);
+ ret = TCORE_RETURN_EINVAL;
+ break;
+ }
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+
+static TReturn s_sim_get_facility(CoreObject *co_sim, UserRequest *ur)
+{
+ struct treq_sim_get_facility_status *get_facility_req;
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *cmd_str = NULL;
+ const char *fac = "SC";
+ int mode = 2; /*mode = 2 for Get Facility*/
+
+ dbg("Entry");
+
+ get_facility_req = (struct treq_sim_get_facility_status *)tcore_user_request_ref_data(ur, NULL);
+
+ fac = __sim_get_fac_from_lock_type(get_facility_req->type);
+ if (!fac) {
+ err("Invalid 'fac'");
+ return TCORE_RETURN_EINVAL;
+ }
+
+ cmd_str = g_strdup_printf("AT+CLCK=\"%s\", %d", fac, mode);
+
+ ret = tcore_prepare_and_send_at_request(co_sim,
+ cmd_str, "+CLCK:",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sim_get_facility, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(cmd_str);
+ return ret;
+}
+
+/* SIM Operations */
+static struct tcore_sim_operations sim_ops = {
+ .verify_pins = s_sim_verify_pins,
+ .verify_puks = s_sim_verify_puks,
+ .change_pins = s_sim_change_pins,
+ .get_facility_status = s_sim_get_facility,
+ .enable_facility = s_sim_enable_facility,
+ .disable_facility = s_sim_disable_facility,
+ .read_file = s_sim_read_file,
+ .update_file = NULL,
+ .transmit_apdu = NULL,
+ .get_atr = NULL,
+ .req_authentication = NULL
+};
+
+gboolean s_sim_init(TcorePlugin *p, TcoreHal *h)
+{
+ CoreObject *co_sim;
+
+ co_sim = tcore_sim_new(p, "sim", &sim_ops, h);
+ if (!co_sim) {
+ err("Core object is NULL");
+ return FALSE;
+ }
+
+ tcore_object_add_callback(co_sim, "+SCSIM:",
+ on_notification_sim_status, NULL);
+
+ return TRUE;
+}
+
+void s_sim_exit(TcorePlugin *p)
+{
+ CoreObject *co_sim;
+
+ co_sim = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SIM);
+ if (!co_sim)
+ return;
+
+ tcore_sim_free(co_sim);
+}
+
+
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <tcore.h>
+#include <hal.h>
+#include <core_object.h>
+#include <plugin.h>
+#include <co_sms.h>
+#include <co_sim.h>
+#include <user_request.h>
+#include <storage.h>
+#include <server.h>
+#include <at.h>
+
+#include "s_common.h"
+#include "s_sms.h"
+
+#define CR '\r'
+#define CTRL_Z '\x1A'
+
+#define AT_MT_UNREAD 0 /* Received and Unread */
+#define AT_MT_READ 1 /* Received and Read */
+#define AT_MO_UNSENT 2 /* Unsent */
+#define AT_MO_SENT 3 /* Sent */
+#define AT_ALL 4 /* Unknown */
+
+#define ATMODEM_NUM_PLAN_ID(sca) (gchar)(sca & 0x0F)
+#define ATMODEM_TYPE_OF_NUM(sca) (gchar)((sca & 0x70) >> 4)
+
+/* SCA 12 bytes long and TDPU is 164 bytes long */
+#define PDU_LEN_MAX 176
+#define HEX_PDU_LEN_MAX ((PDU_LEN_MAX * 2) + 1)
+
+#define SMS_ENCODED_SCA_LEN_MAX 12
+
+#define MAX_GSM_SMS_PARAM_RECORD_SIZE 156
+
+#define ATMODEM_SIM_TON_INTERNATIONAL 1
+#define ATMODEM_SIM_TON_NATIONAL 2
+
+#define TEL_UTIL_ENCODED_SCA_LEN_MAX 12
+
+#define CONVERT_TO_HEX(in, out) (in <= 9) ? \
+ (out = '0' + in) : (out = 'A' + in - 10)
+
+/*SIM CRSM SW1 and Sw2 definitions */
+#define AT_SW1_SUCCESS 0x90
+#define AT_SW2_SUCCESS 0
+
+#define SMS_SWAPBYTES16(x) (((x) & 0xffff0000) | (((x) & 0x0000ff00) >> 8) | (((x) & 0x000000ff) << 8))
+
+/* Local functions */
+static gchar __util_hexchar_to_int(gchar c);
+static gboolean __util_hexstring_to_bytes(gchar *hex_str,
+ gchar **bytes, guint *bytes_len);
+static long __util_encode_hex(const guchar *src,
+ long num_bytes, gchar *buf);
+static guint __util_encode_pdu(const guchar sca[SMS_SMSP_ADDRESS_LEN],
+ const guchar *tpdu, guint tpdu_len, gchar *pdu);
+
+static gchar __util_hexchar_to_int(gchar c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ return (c - 'A' + 10);
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else {
+ err("Invalid charater!!");
+ return -1;
+ }
+}
+
+static gboolean __util_hexstring_to_bytes(gchar *hex_str, gchar **bytes, guint *bytes_len)
+{
+ gchar *byte_str;
+ guint hex_str_len;
+ guint i;
+
+ if (hex_str == NULL)
+ return FALSE;
+
+ hex_str_len = strlen(hex_str);
+
+ byte_str = g_malloc0((hex_str_len / 2) + 1);
+
+ dbg("Convert String to Binary!!!");
+ for (i = 0; i < hex_str_len; i += 2) {
+ byte_str[i / 2] = (gchar)((__util_hexchar_to_int(hex_str[i]) << 4)
+ | __util_hexchar_to_int(hex_str[i + 1]));
+ msg(" [%02x]", byte_str[i / 2]);
+ }
+
+ *bytes_len = (hex_str_len / 2);
+ *bytes = byte_str;
+
+ return TRUE;
+}
+
+static long __util_encode_hex(const guchar *src, long num_bytes, gchar *buf)
+{
+ long i, j;
+
+ if (num_bytes <= 0)
+ return -1;
+
+ for (i = 0, j = 0; i < num_bytes; i++, j++) {
+ CONVERT_TO_HEX(((src[i] >> 4) & 0xf), buf[j++]);
+ CONVERT_TO_HEX((src[i] & 0xf), buf[j]);
+ }
+
+ buf[j] = '\0';
+
+ return j;
+}
+
+static guint __util_encode_pdu(const guchar *sca,
+ const guchar *tpdu, guint tpdu_len, gchar *pdu)
+{
+ guint sca_len = 0;
+ unsigned char converted_sca[SMS_ENCODED_SCA_LEN_MAX];
+
+ if (sca[0] == 0) {
+ converted_sca[0] = 0;
+ sca_len = 0;
+ }
+ else {
+ unsigned int i;
+ /*
+ * For PDU, the SC Address length is the number of packed BCD bytes
+ * + 1 byte for SC Address type whereas the length given in
+ * 3GPP 23.040 Address encoding is the number of digits without 1 byte
+ * for address type.
+ */
+ sca_len = ((sca[0] + 1) / 2) + 1;
+
+ converted_sca[0] = (unsigned char)sca_len;
+
+ for (i = 1; i <= sca_len; i++)
+ converted_sca[i] = sca[i];
+ }
+
+ memcpy(pdu, converted_sca, sca_len + 1);
+ memcpy(pdu + sca_len + 1, tpdu, tpdu_len);
+
+ return sca_len + 1 + tpdu_len;
+
+}
+
+static int util_sms_decode_smsParameters(unsigned char *incoming, unsigned int length, struct telephony_sms_Params *params)
+{
+ int alpha_id_len = 0;
+ int i = 0;
+ int nOffset = 0;
+
+ dbg(" RecordLen = %d", length);
+
+ if(incoming == NULL || params == NULL)
+ return FALSE;
+
+ alpha_id_len = length -SMS_SMSP_PARAMS_MAX_LEN;
+
+ if (alpha_id_len > 0) {
+ if (alpha_id_len > SMS_SMSP_ALPHA_ID_LEN_MAX) {
+ alpha_id_len = SMS_SMSP_ALPHA_ID_LEN_MAX;
+ }
+
+ for (i = 0; i < alpha_id_len; i++) {
+ if (0xff == incoming[i]) {
+ dbg(" found");
+ break;
+ }
+ }
+
+ memcpy(params->szAlphaId, incoming, i);
+
+ params->alphaIdLen = i;
+
+ dbg(" Alpha id length = %d", i);
+ } else {
+ params->alphaIdLen = 0;
+ dbg(" Alpha id length is zero");
+ }
+
+ params->paramIndicator = incoming[alpha_id_len];
+
+ dbg(" Param Indicator = %02x", params->paramIndicator);
+
+ if ((params->paramIndicator & SMSPValidDestAddr) == 0) {
+ nOffset = nDestAddrOffset;
+
+ if (0x00 == incoming[alpha_id_len + nOffset] || 0xff == incoming[alpha_id_len + nOffset]) {
+ params->tpDestAddr.dialNumLen = 0;
+
+ dbg("DestAddr Length is 0");
+ } else {
+ if (0 < (int) incoming[alpha_id_len + nOffset]) {
+ params->tpDestAddr.dialNumLen = (int) (incoming[alpha_id_len + nOffset] - 1);
+
+ if (params->tpDestAddr.dialNumLen > SMS_SMSP_ADDRESS_LEN)
+ params->tpDestAddr.dialNumLen = SMS_SMSP_ADDRESS_LEN;
+ } else {
+ params->tpDestAddr.dialNumLen = 0;
+ }
+
+ params->tpDestAddr.numPlanId = incoming[alpha_id_len + (++nOffset)] & 0x0f;
+ params->tpDestAddr.typeOfNum = (incoming[alpha_id_len + nOffset] & 0x70) >> 4;
+
+ memcpy(params->tpDestAddr.diallingNum, &incoming[alpha_id_len + (++nOffset)], (params->tpDestAddr.dialNumLen));
+
+ dbg("Dest TON is %d", params->tpDestAddr.typeOfNum);
+ dbg("Dest NPI is %d", params->tpDestAddr.numPlanId);
+ dbg("Dest Length = %d", params->tpDestAddr.dialNumLen);
+ dbg("Dest Addr = %s", params->tpDestAddr.diallingNum);
+ }
+ } else {
+ params->tpDestAddr.dialNumLen = 0;
+ }
+
+ if ((params->paramIndicator & SMSPValidSvcAddr) == 0) {
+ nOffset = nSCAAddrOffset;
+
+ if (0x00 == (int) incoming[alpha_id_len + nOffset] || 0xff == (int) incoming[alpha_id_len + nOffset]) {
+ params->tpSvcCntrAddr.dialNumLen = 0;
+ dbg(" SCAddr Length is 0");
+ } else {
+ if (0 < (int) incoming[alpha_id_len + nOffset]) {
+ params->tpSvcCntrAddr.dialNumLen = (int) (incoming[alpha_id_len + nOffset] - 1);
+
+ if (params->tpSvcCntrAddr.dialNumLen > SMS_SMSP_ADDRESS_LEN)
+ params->tpSvcCntrAddr.dialNumLen = SMS_SMSP_ADDRESS_LEN;
+
+ params->tpSvcCntrAddr.numPlanId = incoming[alpha_id_len + (++nOffset)] & 0x0f;
+ params->tpSvcCntrAddr.typeOfNum = (incoming[alpha_id_len + nOffset] & 0x70) >> 4;
+
+ memcpy(params->tpSvcCntrAddr.diallingNum, &incoming[alpha_id_len + (++nOffset)], (params->tpSvcCntrAddr.dialNumLen));
+
+ dbg("SCAddr Length = %d ", params->tpSvcCntrAddr.dialNumLen);
+ dbg("SCAddr TON is %d", params->tpSvcCntrAddr.typeOfNum);
+ dbg("SCAddr NPI is %d", params->tpSvcCntrAddr.numPlanId);
+
+ for (i = 0; i < (int) params->tpSvcCntrAddr.dialNumLen; i++)
+ dbg("SCAddr = %d [%02x]", i, params->tpSvcCntrAddr.diallingNum[i]);
+ } else {
+ params->tpSvcCntrAddr.dialNumLen = 0;
+ }
+ }
+ } else if ((0x00 < (int) incoming[alpha_id_len + nSCAAddrOffset] && (int) incoming[alpha_id_len + nSCAAddrOffset] <= 12)
+ || 0xff != (int) incoming[alpha_id_len + nSCAAddrOffset]) {
+ nOffset = nSCAAddrOffset;
+
+ if (0x00 == (int) incoming[alpha_id_len + nOffset] || 0xff == (int) incoming[alpha_id_len + nOffset]) {
+ params->tpSvcCntrAddr.dialNumLen = 0;
+ dbg("SCAddr Length is 0");
+ } else {
+ if (0 < (int) incoming[alpha_id_len + nOffset]) {
+ params->tpSvcCntrAddr.dialNumLen = (int) (incoming[alpha_id_len + nOffset] - 1);
+
+ params->tpSvcCntrAddr.dialNumLen = incoming[alpha_id_len + nOffset] - 1;
+
+ if (params->tpSvcCntrAddr.dialNumLen > SMS_SMSP_ADDRESS_LEN)
+ params->tpSvcCntrAddr.dialNumLen = SMS_SMSP_ADDRESS_LEN;
+
+ params->tpSvcCntrAddr.numPlanId = incoming[alpha_id_len + (++nOffset)] & 0x0f;
+ params->tpSvcCntrAddr.typeOfNum = (incoming[alpha_id_len + nOffset] & 0x70) >> 4;
+
+ memcpy(params->tpSvcCntrAddr.diallingNum, &incoming[alpha_id_len + (++nOffset)],
+ (params->tpSvcCntrAddr.dialNumLen));
+
+ dbg("SCAddr Length = %d ", params->tpSvcCntrAddr.dialNumLen);
+ dbg("SCAddr TON is %d", params->tpSvcCntrAddr.typeOfNum);
+ dbg("SCAddr NPI is %d", params->tpSvcCntrAddr.numPlanId);
+
+ for (i = 0; i < (int) params->tpSvcCntrAddr.dialNumLen; i++)
+ dbg("SCAddr = %d [%02x]", i, params->tpSvcCntrAddr.diallingNum[i]);
+ } else {
+ params->tpSvcCntrAddr.dialNumLen = 0;
+ }
+ }
+ } else {
+ params->tpSvcCntrAddr.dialNumLen = 0;
+ }
+
+ if ((params->paramIndicator & SMSPValidPID) == 0 && (alpha_id_len + nPIDOffset) < MAX_GSM_SMS_PARAM_RECORD_SIZE) {
+ params->tpProtocolId = incoming[alpha_id_len + nPIDOffset];
+ }
+ if ((params->paramIndicator & SMSPValidDCS) == 0 && (alpha_id_len + nDCSOffset) < MAX_GSM_SMS_PARAM_RECORD_SIZE) {
+ params->tpDataCodingScheme = incoming[alpha_id_len + nDCSOffset];
+ }
+ if ((params->paramIndicator & SMSPValidVP) == 0 && (alpha_id_len + nVPOffset) < MAX_GSM_SMS_PARAM_RECORD_SIZE) {
+ params->tpValidityPeriod = incoming[alpha_id_len + nVPOffset];
+ }
+
+ dbg(" Alpha Id(Len) = %d", (int) params->alphaIdLen);
+
+ for (i = 0; i < (int) params->alphaIdLen; i++) {
+ dbg(" Alpha Id = [%d] [%c]", i, params->szAlphaId[i]);
+ }
+ dbg(" PID = %d",params->tpProtocolId);
+ dbg(" DCS = %d",params->tpDataCodingScheme);
+ dbg(" VP = %d",params->tpValidityPeriod);
+
+ return TRUE;
+}
+
+/*
+ * Notification - SMS-DELIVER
+ * +CMT = [<alpha>],<length><CR><LF><pdu> (PDU mode enabled)
+ *
+ * where,
+ * <alpha> alpha_id
+ * <length> length of the PDU
+ * <pdu> Incomming SMS PDU
+ *
+ * Notification - SMS-STATUS-REPORT
+ * +CDS: <length><CR><LF><pdu> (PDU mode enabled)
+ *
+ * where,
+ * <length> length of the PDU
+ * <pdu> Incomming SMS PDU
+ *
+ */
+static gboolean on_notification_sms_incoming_msg(CoreObject *co,
+ const void *event_info, void *user_data)
+{
+ GSList *tokens = NULL;
+ GSList *lines = NULL;
+ char *line = NULL;
+ int pdu_len = 0, no_of_tokens = 0;
+ gchar *byte_pdu = NULL;
+ guint buf_len = 0;
+
+ struct tnoti_sms_incoming_msg incoming_msg;
+ int sca_length = 0;
+
+ dbg("Enter");
+
+ memset(&incoming_msg, 0x0, sizeof(struct tnoti_sms_incoming_msg));
+
+ lines = (GSList *)event_info;
+ if (2 != g_slist_length(lines)) {
+ err("Invalid number of lines for +CMT. Must be 2");
+ return TRUE;
+ }
+ line = (char *)g_slist_nth_data(lines, 0); /* Fetch Line 1 */
+ if (!line) {
+ err("Line 1 is invalid");
+ return TRUE;
+ }
+ dbg("Line 1: [%s]", line);
+ tokens = tcore_at_tok_new(line); /* Split Line 1 into tokens */
+ no_of_tokens = g_slist_length(tokens);
+
+ /*
+ * Incoming SMS: +CMT
+ * Number of tokens: 2
+ *
+ * Incoming SMS-STATUS-REPORT: +CDS
+ * Number of tokens: 1
+ */
+ if (2 == no_of_tokens) {
+ /* Token 0: Alpha ID */
+ dbg("Alpha ID: [0x%x]", g_slist_nth_data(tokens, 0));
+
+ /* Token 1: PDU Length */
+ pdu_len = atoi((char *)g_slist_nth_data(tokens, 1));
+ dbg("pdu_len: [%d]", pdu_len);
+ } else if (1 == no_of_tokens) {
+ /* 0: PDU Length */
+ pdu_len = atoi((char *)g_slist_nth_data(tokens, 0));
+ dbg("pdu_len: [%d]", pdu_len);
+ }
+
+ /* Fetch Line 2 */
+ line = (char *)g_slist_nth_data(lines, 1);
+ if (!line) {
+ err("Line 2 is invalid");
+ tcore_at_tok_free(tokens);
+ return TRUE;
+ }
+ dbg("Line 2: [%s]", line);
+
+ /* Convert to Bytes */
+ __util_hexstring_to_bytes(line, &byte_pdu, &buf_len);
+
+ sca_length = byte_pdu[0];
+ dbg("SCA length = %d", sca_length);
+
+ incoming_msg.msgInfo.msgLength = pdu_len;
+
+ if (sca_length == 0) {
+ dbg("SCA length = 0");
+ memcpy(incoming_msg.msgInfo.tpduData, &byte_pdu[1], incoming_msg.msgInfo.msgLength);
+ }
+ else {
+ incoming_msg.msgInfo.sca[0] = sca_length;
+ memcpy(&(incoming_msg.msgInfo.sca[1]), &byte_pdu[1], sca_length);
+ memcpy(incoming_msg.msgInfo.tpduData, &byte_pdu[sca_length+1], incoming_msg.msgInfo.msgLength);
+ }
+
+ /* Send notification */
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co)),
+ co, TNOTI_SMS_INCOM_MSG,
+ sizeof(struct tnoti_sms_incoming_msg), &incoming_msg);
+
+ tcore_at_tok_free(tokens);
+ g_free(byte_pdu);
+
+ return TRUE;
+}
+
+#if 0 /* To be used later */
+static int __util_map_sms_err(int err)
+{
+ int sms_error=0;
+
+ switch (err) {
+ case 300: //ME Failure;
+ sms_error = SMS_PHONE_FAILURE;
+ break;
+ case 302: //Operation not allowed;
+ case 303: //Operation not supported;
+ sms_error = SMS_OPERATION_NOT_SUPPORTED;
+ break;
+ case 304: //Invalid PDU mode parameter;
+ case 305: //Invalid text mode parameter;
+ sms_error = SMS_INVALID_PARAMETER_FORMAT;
+ break;
+ case 320: //memory failure;
+ case 321: //invalid memory index;
+ case 322: //memory full;
+ sms_error = SMS_MEMORY_FAILURE;
+ break;
+ case 330: //SCA unknown;
+ case 500: //Unknown error;
+ default:
+ sms_error = SMS_UNKNOWN;
+ break;
+ }
+
+ return sms_error;
+}
+#endif
+
+static gboolean on_notification_sms_device_ready(CoreObject *co,
+ const void *event_info, void *user_data)
+{
+ struct tnoti_sms_ready_status sms_ready_info = {0,};
+
+ dbg("SMS notification - [Device Ready]");
+
+ sms_ready_info.status = TRUE;
+
+ /* Set Device Ready */
+ tcore_sms_set_ready_status(co, sms_ready_info.status);
+
+ /* Send notification: SMS Device ready */
+ tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co)),
+ co, TNOTI_SMS_DEVICE_READY,
+ sizeof(struct tnoti_sms_ready_status), &sms_ready_info);
+
+ return TRUE;
+}
+
+static void on_response_sms_send_more_msg(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+
+ dbg("Enter");
+
+ if (at_resp && at_resp->success) {
+ dbg("Response OK for AT+CMMS: More msgs to send!!");
+ } else {
+ err("Response NOK for AT+CMMS: More msgs to send");
+ }
+
+ /* Need not send any response */
+}
+
+static void on_response_sms_send_sms(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ CoreObject *co = tcore_pending_ref_core_object(p);
+ UserRequest *ur = NULL;
+
+ struct tresp_sms_send_msg send_sms_resp;
+ dbg("Enter");
+
+ CHECK_AND_RETURN(co != NULL);
+
+ send_sms_resp.result = SMS_DEVICE_FAILURE;
+ if (at_resp && at_resp->success) {
+ dbg("Response OK");
+ if (at_resp->lines) {
+ const gchar *line;
+ gchar* line_token;
+ GSList *tokens = NULL;
+ gint msg_ref = 0;
+
+ line = (const gchar *)at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ line_token = g_slist_nth_data(tokens, 0);
+ if (line_token != NULL) {
+ /*
+ * Response from MODEM for send SMS: +CMGS: <mr>[,<ackpdu>]
+ *
+ * Message Reference is not used by MSG_SERVER and application.
+ * So Filling only result
+ */
+ msg_ref = atoi(line_token);
+
+ dbg("Message Reference: [%d]", msg_ref);
+
+ send_sms_resp.result = SMS_SENDSMS_SUCCESS;
+ } else {
+ dbg("No Message Reference received");
+ }
+ tcore_at_tok_free(tokens);
+ }
+ } else {
+ err("Response NOK");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_SEND_UMTS_MSG,
+ sizeof(struct tresp_sms_send_msg), &send_sms_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sms_get_msg_indices(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ UserRequest *ur;
+ struct tresp_sms_get_storedMsgCnt *count_info = NULL;
+
+ const struct tcore_at_response *at_resp = data;
+ GSList *tokens = NULL;
+
+ dbg("Enter");
+
+ count_info = (struct tresp_sms_get_storedMsgCnt *)user_data;
+ count_info->result = TCORE_RETURN_FAILURE;
+
+ if (at_resp && at_resp->success) {
+ dbg("RESPONSE OK");
+ if (at_resp->lines) {
+ char *line = NULL, *line_token = NULL;
+ int line_count = 0, count = 0;
+
+ line_count = g_slist_length(at_resp->lines);
+ dbg("No. of lines: [%d]", line_count);
+
+ for (count = 0; count<line_count; count++) {
+ line = g_slist_nth_data(at_resp->lines, count);
+
+ dbg("gslist_line [%d] is [%s]", count, line);
+
+ if (NULL != line) {
+ tokens = tcore_at_tok_new(line);
+
+ line_token = g_slist_nth_data(tokens, 0);
+ if (NULL != line_token) {
+ count_info->storedMsgCnt.indexList[count] = atoi(line_token);
+ count_info->result = TCORE_RETURN_SUCCESS;
+ } else {
+ dbg("line_token of line [%d] is NULL", count);
+ }
+ tcore_at_tok_free(tokens);
+ } else {
+ dbg("line [%d] is NULL", count);
+ continue;
+ }
+ }
+ }else {
+ err("Invalid Response Received: NO Lines Present");
+ if (count_info->storedMsgCnt.usedCount == 0) { // Check if used count is zero
+ count_info->result = TCORE_RETURN_SUCCESS;
+ }
+ }
+ }
+ else {
+ err("RESPONSE NOK");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_GET_STORED_MSG_COUNT,
+ sizeof(struct tresp_sms_get_storedMsgCnt), count_info);
+ } else {
+ err("ur is NULL");
+ }
+
+ g_free(count_info);
+ tcore_at_tok_free(tokens);
+}
+
+static void on_response_sms_get_msg_count(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ UserRequest *ur;
+ struct tresp_sms_get_storedMsgCnt *count_info;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ const struct tcore_at_response *at_resp = data;
+ GSList *tokens = NULL;
+
+ dbg("Enter");
+
+ ur = tcore_pending_ref_user_request(p);
+
+ count_info = g_try_malloc0(sizeof(struct tresp_sms_get_storedMsgCnt));
+ count_info->result = TCORE_RETURN_FAILURE;
+
+ if (at_resp && at_resp->success) {
+ dbg("RESPONSE OK");
+ if (at_resp->lines) {
+ char *line = NULL, *line_token = NULL;
+
+ line = (char *)at_resp->lines->data;
+ dbg("line: [%s]",line);
+
+ /*
+ * Tokenize
+ *
+ * +CPMS: <used1>, <total1>, <used2>, <total2>, <used3>, <total3>
+ */
+ tokens = tcore_at_tok_new(line);
+
+ /* <used1> */
+ line_token = g_slist_nth_data(tokens, 0);
+ if (line_token == NULL) {
+ err("Line Token for used count is NULL");
+ goto ERROR;
+ }
+ count_info->storedMsgCnt.usedCount = atoi(line_token);
+
+ /* <total1> */
+ line_token = g_slist_nth_data(tokens, 1);
+ if (line_token == NULL) {
+ err("Line Token for Total count is NULL");
+ goto ERROR;
+ }
+ count_info->storedMsgCnt.totalCount = atoi(line_token);
+
+ dbg("Count - used: [%d] total: [%d]",
+ count_info->storedMsgCnt.usedCount, count_info->storedMsgCnt.totalCount);
+ count_info->result = TCORE_RETURN_SUCCESS;
+
+ if (count_info->storedMsgCnt.usedCount > 0) {
+ /* Send Request to modem */
+ ur = tcore_user_request_ref(ur);
+ ret = tcore_prepare_and_send_at_request(tcore_pending_ref_core_object(p),
+ "AT+CMGL=4", "+CMGL",
+ TCORE_AT_MULTILINE,
+ ur,
+ on_response_sms_get_msg_indices, (void *)count_info,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ return;
+
+ }
+ else {
+ dbg("No records...!!!");
+ }
+ }
+ else {
+ err("Invalid Response Received: NO Lines Present");
+ }
+ }
+ else {
+ err("RESPONSE NOK");
+ }
+
+ERROR:
+ if (ur) {
+ dbg("Sending response...");
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_GET_STORED_MSG_COUNT,
+ sizeof(struct tresp_sms_get_storedMsgCnt), count_info);
+ } else {
+ err("ur is NULL");
+ }
+
+ g_free(count_info);
+ tcore_at_tok_free(tokens);
+}
+
+#ifdef EMUL_SUPPORTED
+static void on_response_sms_get_sca(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ UserRequest *ur;
+ struct tresp_sms_get_sca get_sca_resp;
+ const struct tcore_at_response *at_resp = data;
+
+ dbg("Enter");
+
+ get_sca_resp.result = SMS_UNKNOWN;
+ if (at_resp && at_resp->success) {
+ dbg("Response OK");
+ if (at_resp->lines) {
+ GSList *tokens = NULL;
+ const char *sca_tok_addr;
+ gchar *line = NULL, *sca_addr = NULL, *sca_toa = NULL;
+
+ line = (char *)at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ sca_tok_addr = g_slist_nth_data(tokens, 0);
+ sca_toa = g_slist_nth_data(tokens, 1);
+
+ sca_addr = tcore_at_tok_extract(sca_tok_addr);
+ dbg("SCA: [%s] SCA-TOA: [%s]", sca_addr, sca_toa);
+ if ((NULL != sca_addr) && (NULL != sca_toa)) {
+ gchar *sca;
+ guint sca_len = 0;
+
+ __util_hexstring_to_bytes(sca_addr, &sca, &sca_len); /*TODO : Check*/
+ memcpy(get_sca_resp.scaAddress.diallingNum, sca, sca_len);
+ get_sca_resp.scaAddress.dialNumLen = strlen(sca);
+ g_free(sca);
+
+ if (145 == atoi(sca_toa))
+ get_sca_resp.scaAddress.typeOfNum = SIM_TON_INTERNATIONAL;
+ else
+ get_sca_resp.scaAddress.typeOfNum = SIM_TON_NATIONAL;
+ get_sca_resp.scaAddress.numPlanId = 0;
+
+ get_sca_resp.result = SMS_SUCCESS;
+ } else {
+ err("SCA is NULL");
+ }
+ tcore_at_tok_free(tokens);
+ g_free(sca_addr);
+ } else {
+ err("Invalid Response.No Lines Received");
+ }
+ } else {
+ err("Response NOK");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_GET_SCA,
+ sizeof(struct tresp_sms_get_sca), &get_sca_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+#endif
+
+#ifdef EMUL_SUPPORTED
+static void on_response_sms_set_sca(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur;
+ struct tresp_sms_set_sca set_sca_resp = {0, };
+
+ dbg("Enter");
+
+ if (at_resp && at_resp->success) {
+ dbg("Response OK");
+ set_sca_resp.result = SMS_SUCCESS;
+ } else {
+ err("Response NOK");
+ set_sca_resp.result = SMS_UNKNOWN;
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_SET_SCA,
+ sizeof(struct tresp_sms_set_sca), &set_sca_resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+#endif
+
+static void on_response_atmodem_sms_send_deliver_report(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur;
+ struct tresp_sms_set_delivery_report set_deliver_report_rsp = {0,};
+
+ dbg("Enter");
+
+ if (at_resp && at_resp->success) {
+ dbg("Response OK");
+ set_deliver_report_rsp.result = SMS_SUCCESS;
+ } else {
+ err("Response NOK");
+ set_deliver_report_rsp.result = SMS_UNKNOWN;
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_SET_DELIVERY_REPORT,
+ sizeof(struct tresp_sms_set_delivery_report), &set_deliver_report_rsp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sms_get_params(TcorePending *pending, int data_len, const void *data, void *user_data)
+{
+ UserRequest *ur;
+ struct tresp_sms_get_params resp_get_params ;
+ const struct tcore_at_response *at_resp = data;
+ int sw1 = 0, sw2 = 0;
+ const char *line = NULL;
+ char *line_token = NULL;
+ GSList *tokens=NULL;
+ char *hexData = NULL;
+ char *recordData = NULL;
+ int i = 0;
+
+ memset(&resp_get_params, 0, sizeof(struct tresp_sms_get_params));
+ resp_get_params.result = SMS_DEVICE_FAILURE;
+
+ if (at_resp->success > 0) {
+ dbg("RESPONSE OK");
+
+ if (at_resp->lines) {
+ line = (const char *) at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ line_token = g_slist_nth_data(tokens, 0);
+ if (line_token != NULL) {
+ sw1 = atoi(line_token);
+ dbg("sw1 is %d", sw1);
+ } else {
+ dbg("sw1 is NULL");
+ }
+ line_token = g_slist_nth_data(tokens, 1);
+ if (line_token != NULL) {
+ sw2 = atoi(line_token);
+ dbg("sw2 is %d", sw2);
+ if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
+ resp_get_params.result = SMS_SENDSMS_SUCCESS;
+ }
+ } else {
+ dbg("sw2 is NULL");
+ }
+ hexData = g_slist_nth_data(tokens, 2);
+ if (hexData != NULL) {
+
+ recordData = util_hexStringToBytes(hexData);
+ tcore_util_hex_dump(" ", strlen(hexData) / 2, recordData);
+
+ resp_get_params.paramsInfo.recordLen = strlen(hexData) / 2;
+
+ util_sms_decode_smsParameters((unsigned char *) recordData, strlen(hexData) / 2, &(resp_get_params.paramsInfo));
+ resp_get_params.result = SMS_SENDSMS_SUCCESS;
+
+ for (i = 0; i < (int) resp_get_params.paramsInfo.tpSvcCntrAddr.dialNumLen; i++)
+ dbg("SCAddr = %d [%02x]", i, resp_get_params.paramsInfo.tpSvcCntrAddr.diallingNum[i]);
+
+ free(recordData);
+ //free(hexData);
+ } else {
+ dbg("No response");
+
+ }
+ tcore_at_tok_free(tokens);
+ }
+ } else {
+ dbg("RESPONSE NOK");
+ }
+
+ ur = tcore_pending_ref_user_request(pending);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_GET_PARAMS,
+ sizeof(struct tresp_sms_get_params), &resp_get_params);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sms_set_params(TcorePending *pending, int data_len, const void *data, void *user_data)
+{
+ UserRequest *ur;
+ struct tresp_sms_set_params resp_set_sms_params= {0, };
+ const struct tcore_at_response *at_resp = data;
+
+ resp_set_sms_params.result = SMS_DEVICE_FAILURE;
+
+ if (at_resp && at_resp->success) {
+ dbg("RESPONSE OK");
+ if (at_resp->lines) {
+ GSList *tokens=NULL;
+ int sw1 =0 , sw2 = 0;
+ const char *line = NULL;
+ char *line_token = NULL;
+
+ line = (const char *) at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+
+ line_token = g_slist_nth_data(tokens, 0);
+ if (line_token != NULL) {
+ sw1 = atoi(line_token);
+ } else {
+ err("sw1 is NULL");
+ goto EXIT;
+ }
+ line_token = g_slist_nth_data(tokens, 1);
+ if (line_token != NULL) {
+ sw2 = atoi(line_token);
+ } else {
+ err("sw2 is NULL");
+ goto EXIT;
+ }
+ dbg("sw1 - %x sw2 - %x", sw1, sw2);
+ if (((sw1 == AT_SW1_SUCCESS) && (sw2 == AT_SW2_SUCCESS)) || (sw1 == 0x91)) {
+ resp_set_sms_params.result = SMS_SENDSMS_SUCCESS;
+ } else {
+ err("Status Word 1 and Status Word 2 are invalid");
+ }
+EXIT:
+ tcore_at_tok_free(tokens);
+ } else {
+ err("No lines");
+ }
+ } else {
+ err("RESPONSE NOK");
+ }
+
+ ur = tcore_pending_ref_user_request(pending);
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_SET_PARAMS ,
+ sizeof(struct tresp_sms_set_params), &resp_set_sms_params);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_sms_get_param_count(TcorePending *pending, int data_len, const void *data, void *user_data)
+{
+ UserRequest *ur = NULL;
+ struct tresp_sms_get_paramcnt resp_get_param_cnt = {0, };
+ const struct tcore_at_response *at_resp = data;
+ char *line = NULL , *line_token = NULL;
+ int sw1 = 0 , sw2 = 0, *smsp_record_len = NULL;
+ int sim_type = 0;
+ GSList *tokens=NULL;
+ CoreObject *co_sim = NULL; //need this to get the sim type GSM/USIM
+ TcorePlugin *plugin = NULL;
+
+ char *hexData = NULL;
+ char *recordData = NULL;
+
+ dbg("Entry");
+
+ ur = tcore_pending_ref_user_request(pending);
+ resp_get_param_cnt.result = SMS_DEVICE_FAILURE;
+
+ if (at_resp->success > 0) {
+ dbg("RESPONSE OK");
+
+ if (at_resp->lines) {
+ line = (char *) at_resp->lines->data;
+
+ /*+CRSM: <sw1>,<sw2>[,<response>]*/
+ dbg("line is %s", line);
+
+ tokens = tcore_at_tok_new(line);
+ line_token = g_slist_nth_data(tokens, 0);
+ if (line_token != NULL) {
+ sw1 = atoi(line_token);
+ } else {
+ dbg("sw1 is NULL");
+ }
+ line_token = g_slist_nth_data(tokens, 1);
+ if (line_token != NULL) {
+ sw2 = atoi(line_token);
+ if ((sw1 == 144) && (sw2 == 0)) {
+ resp_get_param_cnt.result = SMS_SENDSMS_SUCCESS;
+ }
+ } else {
+ dbg("sw2 is NULL");
+ }
+
+ hexData = g_slist_nth_data(tokens, 2);
+ if (hexData != NULL) {
+
+ /*1. SIM access success case*/
+ if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
+ unsigned char tag_len = 0; /* 1 or 2 bytes ??? */
+ int record_len = 0;
+ char num_of_records = 0;
+ unsigned char file_id_len = 0;
+ unsigned short file_id = 0;
+ unsigned short file_size = 0;
+ unsigned short file_type = 0;
+ unsigned short arr_file_id = 0;
+ int arr_file_id_rec_num = 0;
+
+
+ /* handling only last 3 bits */
+ unsigned char file_type_tag = 0x07;
+ unsigned char *ptr_data;
+
+ dbg("hexData: %s", hexData);
+ dbg("hexData: %s", hexData + 1);
+
+ recordData = util_hexStringToBytes(hexData);
+
+ tcore_util_hex_dump(" ", strlen(hexData) / 2, recordData);
+
+ ptr_data = (unsigned char *)recordData;
+
+ co_sim = tcore_plugin_ref_core_object(tcore_pending_ref_plugin(pending), CORE_OBJECT_TYPE_SIM);
+ sim_type = tcore_sim_get_type(co_sim);
+ dbg("sim type is %d",sim_type);
+
+ if (sim_type == SIM_TYPE_USIM) {
+ /*
+ ETSI TS 102 221 v7.9.0
+ - Response Data
+ '62' FCP template tag
+ - Response for an EF
+ '82' M File Descriptor
+ '83' M File Identifier
+ 'A5' O Proprietary information
+ '8A' M Life Cycle Status Integer
+ '8B', '8C' or 'AB' C1 Security attributes
+ '80' M File size
+ '81' O Total file size
+ '88' O Short File Identifier (SFI)
+ */
+
+ /* rsim.res_len has complete data length received */
+
+ /* FCP template tag - File Control Parameters tag*/
+ if (*ptr_data == 0x62) {
+ /* parse complete FCP tag*/
+ /* increment to next byte */
+ ptr_data++;
+ tag_len = *ptr_data++;
+ dbg("tag_len=[%d]", tag_len);
+ /* FCP file descriptor - file type, accessibility, DF, ADF etc*/
+ if (*ptr_data == 0x82) {
+ /* increment to next byte */
+ ptr_data++;
+ /*2 or 5 value*/
+ ptr_data++;
+ /* unsigned char file_desc_len = *ptr_data++;*/
+ /* s_dbg("file descriptor length: [%d]", file_desc_len);*/
+ /* TBD: currently capture only file type : ignore sharable, non sharable, working, internal etc*/
+ /* consider only last 3 bits*/
+ file_type_tag = file_type_tag & (*ptr_data);
+
+ switch (file_type_tag) {
+ /* increment to next byte */
+ ptr_data++;
+
+ case 0x1:
+ dbg("Getting FileType: [Transparent file type]");
+ /* increment to next byte */
+ ptr_data++;
+ file_type = 0x01; //SIM_FTYPE_TRANSPARENT
+ /* data coding byte - value 21 */
+ ptr_data++;
+ break;
+
+ case 0x2:
+ dbg("Getting FileType: [Linear fixed file type]");
+ /* increment to next byte */
+ ptr_data++;
+ /* data coding byte - value 21 */
+ ptr_data++;
+ /* 2bytes */
+ memcpy(&record_len, ptr_data, 2);
+ /* swap bytes */
+ record_len = SMS_SWAPBYTES16(record_len);
+ ptr_data = ptr_data + 2;
+ num_of_records = *ptr_data++;
+ /* Data lossy conversation from enum (int) to unsigned char */
+ file_type = 0x02; // SIM_FTYPE_LINEAR_FIXED
+ break;
+
+ case 0x6:
+ dbg(" Cyclic fixed file type");
+ /* increment to next byte */
+ ptr_data++;
+ /* data coding byte - value 21 */
+ ptr_data++;
+ /* 2bytes */
+ memcpy(&record_len, ptr_data, 2);
+ /* swap bytes */
+ record_len = SMS_SWAPBYTES16(record_len);
+ ptr_data = ptr_data + 2;
+ num_of_records = *ptr_data++;
+ file_type = 0x04; //SIM_FTYPE_CYCLIC
+ break;
+
+ default:
+ dbg("not handled file type [0x%x]", *ptr_data);
+ break;
+ }
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ //free(hexData);
+ free(recordData);
+ tcore_at_tok_free(tokens);
+ return;
+ }
+
+ /*File identifier - file id?? */ // 0x84,0x85,0x86 etc are currently ignored and not handled
+ if (*ptr_data == 0x83) {
+ /* increment to next byte */
+ ptr_data++;
+ file_id_len = *ptr_data++;
+ memcpy(&file_id, ptr_data, file_id_len);
+ /* swap bytes */
+ file_id = SMS_SWAPBYTES16(file_id);
+ ptr_data = ptr_data + 2;
+ dbg("Getting FileID=[0x%x]", file_id);
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ //free(hexData);
+ free(recordData);
+ tcore_at_tok_free(tokens);
+ return;
+ }
+
+ /* proprietary information */
+ if (*ptr_data == 0xA5) {
+ unsigned short prop_len;
+ /* increment to next byte */
+ ptr_data++;
+ /* length */
+ prop_len = *ptr_data;
+ /* skip data */
+ ptr_data = ptr_data + prop_len + 1;
+ } else {
+ dbg("INVALID FCP received - DEbug!");
+ }
+
+ /* life cycle status integer [8A][length:0x01][status]*/
+ /*
+ status info b8~b1
+ 00000000 : No information given
+ 00000001 : creation state
+ 00000011 : initialization state
+ 000001-1 : operation state -activated
+ 000001-0 : operation state -deactivated
+ 000011-- : Termination state
+ b8~b5 !=0, b4~b1=X : Proprietary
+ Any other value : RFU
+ */
+ if (*ptr_data == 0x8A) {
+ /* increment to next byte */
+ ptr_data++;
+ /* length - value 1 */
+ ptr_data++;
+
+ switch (*ptr_data) {
+ case 0x04:
+ case 0x06:
+ dbg("<IPC_RX> operation state -deactivated");
+ ptr_data++;
+ break;
+
+ case 0x05:
+ case 0x07:
+ dbg("<IPC_RX> operation state -activated");
+ ptr_data++;
+ break;
+
+ default:
+ dbg("<IPC_RX> DEBUG! LIFE CYCLE STATUS =[0x%x]",*ptr_data);
+ ptr_data++;
+ break;
+ }
+ }
+
+ /* related to security attributes : currently not handled*/
+ if (*ptr_data == 0x86 || *ptr_data == 0x8B || *ptr_data == 0x8C || *ptr_data == 0xAB) {
+ /* increment to next byte */
+ ptr_data++;
+ /* if tag length is 3 */
+ if (*ptr_data == 0x03) {
+ /* increment to next byte */
+ ptr_data++;
+ /* EFARR file id */
+ memcpy(&arr_file_id, ptr_data, 2);
+ /* swap byes */
+ arr_file_id = SMS_SWAPBYTES16(arr_file_id);
+ ptr_data = ptr_data + 2;
+ arr_file_id_rec_num = *ptr_data++;
+ dbg("arr_file_id_rec_num=[%d]", arr_file_id_rec_num);
+ } else {
+ /* if tag length is not 3 */
+ /* ignoring bytes */
+ // ptr_data = ptr_data + 4;
+ dbg("Useless security attributes, so jump to next tag");
+ ptr_data = ptr_data + (*ptr_data + 1);
+ }
+ } else {
+ dbg("INVALID FCP received[0x%x] - DEbug!", *ptr_data);
+ //free(hexData);
+ free(recordData);
+ tcore_at_tok_free(tokens);
+ return;
+ }
+
+ dbg("Current ptr_data value is [%x]", *ptr_data);
+
+ /* file size excluding structural info*/
+ if (*ptr_data == 0x80) {
+ /* for EF file size is body of file and for Linear or cyclic it is
+ * number of recXsizeof(one record)
+ */
+ /* increment to next byte */
+ ptr_data++;
+ /* length is 1 byte - value is 2 bytes or more */
+ ptr_data++;
+ memcpy(&file_size, ptr_data, 2);
+ /* swap bytes */
+ file_size = SMS_SWAPBYTES16(file_size);
+ ptr_data = ptr_data + 2;
+ } else {
+ dbg("INVALID FCP received - Debug!");
+ //free(hexData);
+ free(recordData);
+ tcore_at_tok_free(tokens);
+ return;
+ }
+
+ /* total file size including structural info*/
+ if (*ptr_data == 0x81) {
+ int len;
+ /* increment to next byte */
+ ptr_data++;
+ /* length */
+ len = *ptr_data;
+ dbg("len=[%d]", len);
+ /* ignored bytes */
+ ptr_data = ptr_data + 3;
+ } else {
+ dbg("INVALID FCP received - Debug!");
+ /* 0x81 is optional tag?? check out! so do not return -1 from here! */
+ /* return -1; */
+ }
+ /*short file identifier ignored*/
+ if (*ptr_data == 0x88) {
+ dbg("0x88: Do Nothing");
+ /*DO NOTHING*/
+ }
+ } else {
+ dbg("INVALID FCP received - Debug!");
+ //free(hexData);
+ free(recordData);
+ tcore_at_tok_free(tokens);
+ return;
+ }
+ } else if (sim_type == SIM_TYPE_GSM) {
+ /* ignore RFU byte1 and byte2 */
+ ptr_data++;
+ ptr_data++;
+ /* file size */
+ //file_size = p_info->response_len;
+ memcpy(&file_size, ptr_data, 2);
+ /* swap bytes */
+ file_size = SMS_SWAPBYTES16(file_size);
+ /* parsed file size */
+ ptr_data = ptr_data + 2;
+ /* file id */
+ memcpy(&file_id, ptr_data, 2);
+ file_id = SMS_SWAPBYTES16(file_id);
+ dbg(" FILE id --> [%x]", file_id);
+ ptr_data = ptr_data + 2;
+ /* save file type - transparent, linear fixed or cyclic */
+ file_type_tag = (*(ptr_data + 7));
+
+ switch (*ptr_data) {
+ case 0x0:
+ /* RFU file type */
+ dbg(" RFU file type- not handled - Debug!");
+ break;
+
+ case 0x1:
+ /* MF file type */
+ dbg(" MF file type - not handled - Debug!");
+ break;
+
+ case 0x2:
+ /* DF file type */
+ dbg(" DF file type - not handled - Debug!");
+ break;
+
+ case 0x4:
+ /* EF file type */
+ dbg(" EF file type [%d] ", file_type_tag);
+ /* increment to next byte */
+ ptr_data++;
+
+ if (file_type_tag == 0x00 || file_type_tag == 0x01) {
+ /* increament to next byte as this byte is RFU */
+ ptr_data++;
+ file_type =
+ (file_type_tag == 0x00) ? 0x01 : 0x02; // SIM_FTYPE_TRANSPARENT:SIM_FTYPE_LINEAR_FIXED;
+ } else {
+ /* increment to next byte */
+ ptr_data++;
+ /* For a cyclic EF all bits except bit 7 are RFU; b7=1 indicates that */
+ /* the INCREASE command is allowed on the selected cyclic file. */
+ file_type = 0x04; // SIM_FTYPE_CYCLIC;
+ }
+ /* bytes 9 to 11 give SIM file access conditions */
+ ptr_data++;
+ /* byte 10 has one nibble that is RF U and another for INCREASE which is not used currently */
+ ptr_data++;
+ /* byte 11 is invalidate and rehabilate nibbles */
+ ptr_data++;
+ /* byte 12 - file status */
+ ptr_data++;
+ /* byte 13 - GSM specific data */
+ ptr_data++;
+ /* byte 14 - structure of EF - transparent or linear or cyclic , already saved above */
+ ptr_data++;
+ /* byte 15 - length of record for linear and cyclic , for transparent it is set to 0x00. */
+ record_len = *ptr_data;
+ dbg("record length[%d], file size[%d]", record_len, file_size);
+
+ if (record_len != 0)
+ num_of_records = (file_size / record_len);
+
+ dbg("Number of records [%d]", num_of_records);
+ break;
+
+ default:
+ dbg(" not handled file type");
+ break;
+ }
+ } else {
+ dbg(" Card Type - UNKNOWN [%d]", sim_type);
+ }
+
+ dbg("EF[0x%x] size[%ld] Type[0x%x] NumOfRecords[%ld] RecordLen[%ld]", file_id, file_size, file_type, num_of_records, record_len);
+
+ resp_get_param_cnt.recordCount = num_of_records;
+ resp_get_param_cnt.result = SMS_SUCCESS;
+
+ //TO Store smsp record length in the property
+ plugin = tcore_pending_ref_plugin(pending);
+ smsp_record_len = tcore_plugin_ref_property(plugin, "SMSPRECORDLEN");
+ memcpy(smsp_record_len, &record_len, sizeof(int));
+ dbg("Property Updated");
+
+ free(recordData);
+ //free(hexData);
+ } else {
+ /*2. SIM access fail case*/
+ dbg("SIM access fail");
+ resp_get_param_cnt.result = SMS_UNKNOWN;
+ }
+ } else {
+ dbg("presp is NULL");
+ }
+ } else {
+ dbg("line is blank");
+ }
+ } else {
+ dbg("RESPONSE NOK");
+ }
+
+ if (ur) {
+ tcore_user_request_send_response(ur,
+ TRESP_SMS_GET_PARAMCNT,
+ sizeof(struct tresp_sms_get_paramcnt), &resp_get_param_cnt);
+ } else {
+ err("ur is NULL");
+ }
+
+ if(tokens)
+ tcore_at_tok_free(tokens);
+
+}
+
+/* SMS Operations */
+/*
+ * Operation - send_sms
+ *
+ * Request -
+ * AT-Command: AT+CMGS
+ * For PDU mode (+CMGF=0):
+ * +CMGS=<length><CR>
+ * PDU is given<ctrl-Z/ESC>
+ * where,
+ * <length> Length of the pdu.
+ * <PDU> PDU to send.
+ *
+ * Response -
+ *+CMGS: <mr>[,<ackpdu>]
+ * OK
+ * Failure:
+ * +CMS ERROR: <error>
+ */
+static TReturn send_umts_msg(CoreObject *co, UserRequest *ur)
+{
+ const struct treq_sms_send_msg *send_sms_req = NULL;
+ char *at_cmd = NULL;
+ const unsigned char *tpdu_byte_data, *sca_byte_data;
+ guint tpdu_byte_len, pdu_byte_len, pdu_hex_len;
+ char buf[HEX_PDU_LEN_MAX];
+ char pdu[PDU_LEN_MAX];
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Send SMS");
+
+ send_sms_req = tcore_user_request_ref_data(ur, NULL);
+ tpdu_byte_data = send_sms_req->msgDataPackage.tpduData;
+ sca_byte_data = send_sms_req->msgDataPackage.sca;
+
+ /* TPDU length is in byte */
+ tpdu_byte_len = send_sms_req->msgDataPackage.msgLength;
+ dbg("TDPU length: [%d] SCA semi-octet length: [%d]", tpdu_byte_len, sca_byte_data[0]);
+
+ /* Prepare PDU for hex encoding */
+ pdu_byte_len = __util_encode_pdu(sca_byte_data,
+ tpdu_byte_data, tpdu_byte_len, pdu);
+
+ pdu_hex_len = (int) __util_encode_hex((unsigned char *) pdu,
+ pdu_byte_len, buf);
+ dbg("PDU hexadecimal length: [%d]", pdu_hex_len);
+
+ /*
+ * More messages
+ * Use same Radio Resource Channel :More Messages to send
+ */
+ dbg("Send more SMS: [%s]", (send_sms_req->more == 0 ? "NO" : "YES"));
+ if (send_sms_req->more) {
+ /* AT Command: More Msgs to Send */
+ ret = tcore_prepare_and_send_at_request(co,
+ "AT+CMMS=1", "+CMMS:",
+ TCORE_AT_SINGLELINE,
+ NULL,
+ on_response_sms_send_more_msg, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ }
+
+ /* AT-Command : Send SMS */
+ at_cmd = g_strdup_printf("AT+CMGS=%d\r%s%x", tpdu_byte_len, buf, 0x1A);
+
+ ret = tcore_prepare_and_send_at_request(co,
+ at_cmd, "+CMGS",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sms_send_sms, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+/*
+ * Operation - get_sms_count_in_sim
+ *
+ * Request -
+ * AT-Command: AT+CPMS
+ * +CPMS=<mem1>[, <mem2>[,<mem3>]]
+ * where
+ * <mem1> memory storage to read.
+ *
+ * Response -
+ * Success: (Single-line output)
+ * +CPMS: <mem1>,<used1>,<total1>,<mem2>,<used2>,<total2>,
+ * <mem3>,<used3>,<total3>
+ * OK
+ *
+ * Failure:
+ * +CMS ERROR: <error>
+ */
+static TReturn sms_get_msg_count(CoreObject *co, UserRequest *ur)
+{
+ TReturn ret;
+
+ dbg("Enter");
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co,
+ "AT+CPMS=\"SM\"", "+CPMS",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sms_get_msg_count, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+
+/*
+ * Operation - get SCA
+ *
+ * Request -
+ * AT-Command: AT+CSCA?
+ *
+ * Response -
+ * Success: Single-Line
+ * +CSCA: <sca>,<tosca>
+ * OK
+ * where
+ * <sca> Service center number
+ * <tosca> address type of SCA
+ *
+ */
+#ifdef EMUL_SUPPORTED
+static TReturn get_sca(CoreObject *co, UserRequest *ur)
+{
+ TReturn ret;
+
+ dbg("Enter");
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co,
+ "AT+CSCA?", "+CSCA",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sms_get_sca, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ return ret;
+}
+#endif
+
+/*
+ * Operation - set SCA
+ *
+ * Request -
+ * AT-Command: AT+CSCA
+ * AT+CSCA=<sca>[,<tosca>]
+ * where
+ * <sca> Service center number
+ * <tosca> address type of SCA
+ *
+ * Response -
+ * Success: No result
+ * OK
+ *
+ * Failure:
+ * +CMS ERROR: <error>
+ */
+#ifdef EMUL_SUPPORTED
+static TReturn set_sca(CoreObject *co, UserRequest *ur)
+{
+ gchar *at_cmd;
+ const struct treq_sms_set_sca *set_sca_req;
+ gint address_type;
+ TReturn ret;
+
+ dbg("Enter");
+
+ set_sca_req = tcore_user_request_ref_data(ur, NULL);
+ if (set_sca_req->scaInfo.typeOfNum == SIM_TON_INTERNATIONAL)
+ address_type = 145;
+ else
+ address_type = 129;
+
+ /* AT Command */
+ at_cmd = g_strdup_printf("AT+CSCA=\"%s\",%d", set_sca_req->scaInfo.diallingNum, address_type);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co,
+ at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_sms_set_sca, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+#endif
+
+/*
+ * Operation - send_deliver_report
+ *
+ * Request -
+ * Modem Takes care of sending the ACK to the network
+ *
+ * Response -
+ * Success: Default response always SUCCESS posted
+ *
+ */
+static TReturn set_delivery_report(CoreObject *co, UserRequest *ur)
+{
+ const struct treq_sms_set_delivery_report *set_deliver_report_req = NULL;
+ gchar *at_cmd;
+ TReturn ret;
+
+ dbg("Enter");
+
+ set_deliver_report_req = tcore_user_request_ref_data(ur, NULL);
+
+ /*AT Command*/
+ if(set_deliver_report_req->rspType == SMS_SENDSMS_SUCCESS)
+ at_cmd = g_strdup_printf("AT+CNMA=0%s", "\r");
+ else
+ at_cmd = g_strdup_printf("AT+CNMA=2,3%s%x%s", "/n", 0x00ff00, "");
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(co,
+ at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_atmodem_sms_send_deliver_report, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn get_sms_params(CoreObject *co, UserRequest *ur)
+{
+ TReturn ret;
+ char *cmd_str = NULL;
+ const struct treq_sms_get_params *get_sms_params_data = NULL;
+ int record_len = 0 , *smsp_record_len = NULL;
+
+ dbg("Entry");
+
+ get_sms_params_data = tcore_user_request_ref_data(ur, NULL);
+
+ smsp_record_len = (int *)tcore_plugin_ref_property(tcore_object_ref_plugin(co), "SMSPRECORDLEN");
+ record_len = *smsp_record_len;
+ dbg("record len from property %d", record_len);
+
+ //AT+CRSM=command>[,<fileid>[,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]]
+ cmd_str = g_strdup_printf("AT+CRSM=178,28482,%d,4,%d", (get_sms_params_data->index+1), record_len);
+
+ ret = tcore_prepare_and_send_at_request(co,
+ cmd_str, "+CRSM",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sms_get_params, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(cmd_str);
+
+ return ret;
+}
+
+static TReturn set_sms_params(CoreObject *co, UserRequest *ur)
+{
+ TReturn ret;
+ char *cmd_str = NULL;
+
+ unsigned char *encoded_data;
+ char *params_hex_data = NULL;
+
+ int smsp_record_length = 0, *smsp_record_len = NULL;
+ const struct treq_sms_set_params *set_sms_params_data = NULL;
+
+ dbg("Entry");
+
+ /* Updating the SMSP record length from the property*/
+ set_sms_params_data = (struct treq_sms_set_params *)tcore_user_request_ref_data(ur, NULL);
+
+ smsp_record_len = (int *)tcore_plugin_ref_property(tcore_object_ref_plugin(co), "SMSPRECORDLEN");
+ smsp_record_length = *smsp_record_len;
+ dbg("smsp_record_length [%d]", smsp_record_length);
+
+ encoded_data = g_try_malloc0(smsp_record_length);
+ if (NULL == encoded_data) {
+ err("Memory Allocation failed for encoded_data");
+ return TCORE_RETURN_ENOMEM;
+ }
+
+ params_hex_data = g_try_malloc0(smsp_record_length * 2 + 1);
+ if (NULL == params_hex_data) {
+ err("Memory Allocation Failed for Params hex data");
+ g_free(encoded_data);
+ return TCORE_RETURN_ENOMEM;
+ }
+ _tcore_util_sms_encode_smsParameters(&(set_sms_params_data->params),
+ encoded_data, smsp_record_length);
+
+ util_byte_to_hex((const char *)encoded_data, (char *)params_hex_data, smsp_record_length);
+
+ cmd_str = g_strdup_printf("AT+CRSM=220,28482,%d,4,%d,\"%s\"",
+ (set_sms_params_data->params.recordIndex+1),smsp_record_length,params_hex_data);
+
+ ret = tcore_prepare_and_send_at_request(co,
+ cmd_str, "+CRSM:",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sms_set_params, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(cmd_str);
+ g_free(encoded_data);
+ g_free(params_hex_data);
+
+ return ret;
+}
+
+static TReturn get_param_count(CoreObject *co, UserRequest *ur)
+{
+ TReturn ret;
+ char *cmd_str = NULL;
+
+ dbg("Entry");
+
+ //AT+CRSM=command>[,<fileid>[,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]]
+ cmd_str = g_strdup_printf("AT+CRSM=192,28482");
+
+ tcore_util_hex_dump(" ", strlen(cmd_str), (void *)cmd_str);
+
+ ret = tcore_prepare_and_send_at_request(co,
+ cmd_str, "+CRSM",
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_sms_get_param_count, NULL,
+ on_send_at_request, NULL,
+ 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ /* Free resources */
+ g_free(cmd_str);
+
+ return ret;
+}
+
+/* SMS Operations */
+static struct tcore_sms_operations sms_ops = {
+ .send_umts_msg = send_umts_msg,
+ .read_msg = NULL,
+ .save_msg = NULL,
+ .delete_msg = NULL,
+ .get_storedMsgCnt = sms_get_msg_count,
+ .get_sca = NULL,
+ .set_sca = NULL,
+ .get_cb_config = NULL,
+ .set_cb_config = NULL,
+ .set_mem_status = NULL,
+ .get_pref_brearer = NULL,
+ .set_pref_brearer = NULL,
+ .set_delivery_report = set_delivery_report,
+ .set_msg_status = NULL,
+ .get_sms_params = get_sms_params,
+ .set_sms_params = set_sms_params,
+ .get_paramcnt = get_param_count,
+ .send_cdma_msg = NULL,
+};
+
+gboolean s_sms_init(TcorePlugin *p, TcoreHal *hal)
+{
+ CoreObject *co;
+ struct property_sms_info *data = NULL;
+ int *smsp_record_len = NULL;
+
+ co = tcore_sms_new(p, "umts_sms", &sms_ops, hal);
+ if (!co) {
+ err("Failed to create SMS core object");
+ return FALSE;
+ }
+
+ data = g_try_malloc0(sizeof(struct property_sms_info));
+ if (NULL == data) {
+ err("Unable to initialize. Exiting");
+ s_sms_exit(p);
+
+ dbg("Exit");
+ return FALSE;
+ }
+
+ /* Add Callbacks */
+ tcore_object_add_callback(co,
+ "\e+CMT:",
+ on_notification_sms_incoming_msg, NULL);
+ tcore_object_add_callback(co,
+ "+SCDEV",
+ on_notification_sms_device_ready, NULL);
+
+ tcore_plugin_link_property(p, "SMS", data);
+
+ //storing smsp record length
+ smsp_record_len = g_try_malloc0(sizeof(int));
+ tcore_plugin_link_property(p, "SMSPRECORDLEN", smsp_record_len);
+
+ dbg("Exit");
+ return TRUE;
+}
+
+
+void s_sms_exit(TcorePlugin *p)
+{
+ CoreObject *co;
+
+ co = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SMS);
+ if (!co) {
+ err("SMS core object is NULL");
+ return;
+ }
+
+ tcore_sms_free(co);
+}
+
--- /dev/null
+/*
+ * tel-plugin-atmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Hayoon Ko <hayoon.ko@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <tcore.h>
+#include <hal.h>
+#include <core_object.h>
+#include <plugin.h>
+#include <queue.h>
+#include <co_call.h>
+#include <co_ss.h>
+#include <user_request.h>
+#include <server.h>
+#include <at.h>
+
+#include "s_common.h"
+#include "s_ss.h"
+#include "util.h"
+
+enum telephony_ss_opcode {
+ TIZEN_SS_OPCO_DEACTIVATE=0x01,
+ TIZEN_SS_OPCO_ACTIVATE,
+ TIZEN_SS_OPCO_REG,
+ TIZEN_SS_OPCO_DEREG,
+ TIZEN_SS_OPCO_MAX
+} ;
+
+static void _ss_ussd_response(UserRequest *ur, const char* ussd_str,
+ enum telephony_ss_ussd_type type, enum telephony_ss_ussd_status status)
+{
+ struct tresp_ss_ussd resp;
+
+ if (!ur) {
+ err("ur : (NULL)");
+ return ;
+ }
+
+ resp.type = type;
+ resp.status = status;
+ resp.err = SS_ERROR_NONE;
+
+ if (ussd_str) {
+ int len = strlen(ussd_str);
+
+ if (len < MAX_SS_USSD_LEN) {
+ memcpy(resp.str, ussd_str, len);
+ resp.str[ len ] = '\0';
+ }
+ else {
+ memcpy(resp.str, ussd_str, MAX_SS_USSD_LEN);
+ resp.str[ MAX_SS_USSD_LEN - 1 ] = '\0';
+ }
+
+ dbg("resp.str : %s", resp.str);
+ }
+ else {
+ memset(resp.str, '\0', MAX_SS_USSD_LEN);
+ }
+
+ tcore_user_request_send_response(ur,
+ TRESP_SS_SEND_USSD,
+ sizeof(struct tresp_ss_ussd), &resp);
+}
+
+static void _ss_ussd_notification(TcorePlugin *p,
+ const char* ussd_str, enum telephony_ss_ussd_status status)
+{
+ CoreObject *o = 0;
+ struct tnoti_ss_ussd noti;
+
+ if (!p) {
+ err("p : (NULL)");
+ return ;
+ }
+
+ noti.status = status;
+
+ if (ussd_str) {
+ int len = strlen(ussd_str);
+
+ if (len < MAX_SS_USSD_LEN) {
+ memcpy(noti.str, ussd_str, len);
+ noti.str[ len ] = '\0';
+ }
+ else {
+ memcpy(noti.str, ussd_str, MAX_SS_USSD_LEN);
+ noti.str[ MAX_SS_USSD_LEN - 1 ] = '\0';
+ }
+ }
+ else {
+ memset(noti.str, '\0', MAX_SS_USSD_LEN);
+ }
+
+ o = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SS);
+
+ tcore_server_send_notification(tcore_plugin_ref_server(p),
+ o,
+ TNOTI_SS_USSD,
+ sizeof(struct tnoti_ss_ussd),
+ (void*)¬i);
+}
+
+static gboolean on_notification_ss_ussd(CoreObject *o, const void *data, void *user_data)
+{
+ GSList *tokens = NULL;
+ GSList *lines = NULL;
+ gchar *resp_str = NULL;
+ guchar *dcs_str = NULL;
+ const gchar *line;
+
+ gushort len;
+ enum telephony_ss_ussd_status status;
+ UssdSession *ussd_session = 0;
+ char *ussd_str = 0;
+ TcorePlugin *p = 0;
+ int m=0, dcs=0;
+
+ p = tcore_object_ref_plugin(o);
+
+ ussd_session = tcore_ss_ussd_get_session(o);
+
+ lines = (GSList *) data;
+ if (g_slist_length(lines) != 1) {
+ dbg("Unsolicited message but multiple lines");
+ return TRUE;
+ }
+ line = (const gchar *)lines->data;
+ tokens = tcore_at_tok_new(line);
+
+ resp_str = g_slist_nth_data(tokens, 0);
+ if (NULL == resp_str) {
+ err("Status is missing from +CUSD Notification");
+ goto out;
+ }
+ else {
+ m = atoi(resp_str);
+ switch (m) {
+ case 0:
+ status = SS_USSD_NO_ACTION_REQUIRE;
+ break;
+ case 1:
+ status = SS_USSD_ACTION_REQUIRE;
+ break;
+ case 2:
+ status = SS_USSD_TERMINATED_BY_NET;
+ break;
+ case 3:
+ status = SS_USSD_OTHER_CLIENT;
+ break;
+ case 4:
+ status = SS_USSD_NOT_SUPPORT;
+ break;
+ case 5:
+ status = SS_USSD_TIME_OUT;
+ break;
+ default:
+ dbg("unsupported m : %d", m);
+ status = SS_USSD_MAX;
+ break;
+ }
+
+ /* Parse USSD string */
+ resp_str = g_slist_nth_data(tokens, 1);
+ resp_str = tcore_at_tok_extract(resp_str);
+ if (resp_str) {
+ len = strlen((gchar *)resp_str);
+ dbg("USSD String: [%s] Length: [%d]", resp_str, len);
+ } else {
+ dbg("USSD strings is missing from +CUSD Notification");
+ goto out;
+ }
+
+ dcs_str = g_slist_nth_data(tokens, 2);
+ }
+
+ if (dcs_str) {
+ switch (tcore_util_get_cbs_coding_scheme(dcs)) {
+ case TCORE_DCS_TYPE_7_BIT:
+ case TCORE_DCS_TYPE_UNSPECIFIED: {
+ ussd_str = (char *)tcore_util_unpack_gsm7bit((const unsigned char *)resp_str, strlen(resp_str));
+ }
+ break;
+
+ case TCORE_DCS_TYPE_UCS2:
+ case TCORE_DCS_TYPE_8_BIT: {
+ if (strlen(resp_str) > 0) {
+ ussd_str = g_new0(char, strlen(resp_str) + 1);
+ memcpy(ussd_str,resp_str, strlen(resp_str));
+ ussd_str[ strlen(resp_str) ] = '\0';
+ }
+ }
+ break;
+
+ default: {
+ err("unknown dcs type. ussd_session : %x", ussd_session);
+ if (ussd_session) {
+ UserRequest *ur = 0;
+ enum telephony_ss_ussd_type type;
+ tcore_ss_ussd_get_session_data(ussd_session, (void**)&ur);
+
+ if (!ur) {
+ err("ur : (NULL)");
+ goto out;
+ }
+ type = (enum telephony_ss_ussd_type)tcore_ss_ussd_get_session_type(ussd_session);
+
+ _ss_ussd_response(ur, ussd_str, type, status);
+ }
+ g_free(resp_str);
+ return TRUE;
+ }
+ }
+ }
+ else {
+ warn("No DCS string! Using default DCS value");
+ }
+
+ switch (status) {
+ case SS_USSD_NO_ACTION_REQUIRE:
+ case SS_USSD_ACTION_REQUIRE:
+ case SS_USSD_OTHER_CLIENT:
+ case SS_USSD_NOT_SUPPORT:
+ case SS_USSD_TIME_OUT: {
+ if (ussd_session) {
+ UserRequest *ur = 0;
+ enum telephony_ss_ussd_type type;
+
+ tcore_ss_ussd_get_session_data(ussd_session, (void**)&ur);
+ if (!ur) {
+ err("ur : (NULL)");
+ return TRUE;
+ }
+
+ type = (enum telephony_ss_ussd_type)tcore_ss_ussd_get_session_type(ussd_session);
+ _ss_ussd_response(ur, (const char*)ussd_str, type, status);
+
+ g_free(ussd_str);
+ }
+ else {
+ tcore_ss_ussd_create_session(o, TCORE_SS_USSD_TYPE_NETWORK_INITIATED, 0, 0);
+ _ss_ussd_notification(p, (const char*)ussd_str, status);
+
+ g_free(ussd_str);
+ }
+ }
+ break;
+
+ case SS_USSD_TERMINATED_BY_NET: {
+ if (ussd_session) {
+ UserRequest *ur = 0;
+
+ tcore_ss_ussd_get_session_data(ussd_session, (void**)&ur);
+ if (ur) {
+ tcore_user_request_unref(ur);
+ }
+ tcore_ss_ussd_destroy_session(ussd_session);
+ }
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ g_free(resp_str);
+out:
+ tcore_at_tok_free(tokens);
+ return TRUE;
+}
+
+static gboolean __atmodem_ss_convert_forwarding_mode_to_modem_reason(enum telephony_ss_forwarding_mode condition,
+ guint *reason)
+{
+ switch (condition) {
+ case SS_CF_MODE_CFU:
+ *reason = 0;
+ break;
+ case SS_CF_MODE_CFB:
+ *reason = 1;
+ break;
+ case SS_CF_MODE_CFNRy:
+ *reason = 2;
+ break;
+ case SS_CF_MODE_CFNRc:
+ *reason = 3;
+ break;
+ case SS_CF_MODE_CF_ALL:
+ *reason = 4;
+ break;
+ case SS_CF_MODE_CFC:
+ *reason = 5;
+ break;
+ default:
+ dbg("Unsupported condition: [0x%x]", condition);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean __atmodem_ss_convert_forwarding_opcode_to_modem_mode(enum telephony_ss_opcode mode,
+ guint *modex)
+{
+ switch (mode) {
+ case TIZEN_SS_OPCO_DEACTIVATE:
+ *modex = 0;
+ break;
+ case TIZEN_SS_OPCO_ACTIVATE:
+ *modex = 1;
+ break;
+ case TIZEN_SS_OPCO_REG:
+ *modex = 3;
+ break;
+ case TIZEN_SS_OPCO_DEREG:
+ *modex = 4;
+ break;
+ default:
+ err("Unspported mode: [%d]", mode);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean __atmodem_ss_convert_modem_class_to_class(gint classx,
+ enum telephony_ss_class *class)
+{
+ switch (classx) {
+ case 7:
+ *class = SS_CLASS_ALL_TELE;
+ break;
+ case 1:
+ *class = SS_CLASS_VOICE;
+ break;
+ case 2:
+ *class = SS_CLASS_ALL_DATA_TELE;
+ break;
+ case 4:
+ *class = SS_CLASS_FAX;
+ break;
+ case 8:
+ *class = SS_CLASS_SMS;
+ break;
+ case 16:
+ *class = SS_CLASS_ALL_CS_SYNC;
+ break;
+ case 32:
+ *class = SS_CLASS_ALL_CS_ASYNC;
+ break;
+ case 64:
+ *class = SS_CLASS_ALL_DEDI_PS;
+ break;
+ case 128:
+ *class = SS_CLASS_ALL_DEDI_PAD;
+ break;
+ default:
+ err("Invalid modem class: [%d]", classx);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static guint __atmodem_ss_convert_class_to_atmodem_class(enum telephony_ss_class class)
+{
+ switch (class) {
+ case SS_CLASS_ALL_TELE:
+ return 7;
+ case SS_CLASS_VOICE:
+ return 1;
+ case SS_CLASS_ALL_DATA_TELE:
+ return 2;
+ case SS_CLASS_FAX:
+ return 4;
+ case SS_CLASS_SMS:
+ return 8;
+ case SS_CLASS_ALL_CS_SYNC:
+ return 16;
+ case SS_CLASS_ALL_CS_ASYNC:
+ return 32;
+ case SS_CLASS_ALL_DEDI_PS:
+ return 64;
+ case SS_CLASS_ALL_DEDI_PAD:
+ return 128;
+ default:
+ dbg("Unsupported class: [%d], returning default value 7", class);
+ return 7;
+ }
+}
+
+static gboolean __atmodem_ss_convert_barring_type_to_facility(enum telephony_ss_barring_mode mode,
+ const char *facility)
+{
+ switch (mode) {
+ case SS_BARR_MODE_BAOC:
+ facility = "AO";
+ break;
+ case SS_BARR_MODE_BOIC:
+ facility = "OI";
+ break;
+ case SS_BARR_MODE_BOIC_NOT_HC:
+ facility = "OX";
+ break;
+ case SS_BARR_MODE_BAIC:
+ facility = "AI";
+ break;
+ case SS_BARR_MODE_BIC_ROAM:
+ facility = "IR";
+ break;
+ case SS_BARR_MODE_AB:
+ facility = "AB";
+ break;
+ case SS_BARR_MODE_AOB:
+ facility = "AG";
+ break;
+ case SS_BARR_MODE_AIB:
+ facility = "AC";
+ break;
+ case SS_BARR_MODE_BIC_NOT_SIM:
+ facility = "NS";
+ break;
+ default:
+ err("Unspported type: [%d]", mode);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* SS Responses */
+static void on_response_atmodem_ss_set_barring(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_ss_barring resp = {0, };
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ err("Response: [OK]");
+ resp.err = SS_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = SS_ERROR_UNKNOWNERROR;
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ /*TODO :
+ req_buf = (struct treq_ss_barring *) tcore_user_request_ref_data(ur, 0);
+ req_buf = (struct treq_ss_barring *) tcore_user_request_ref_data(ur, 0);
+ resp.record->class = req_buf.class;
+ resp.record->mode = req_buf.mode;
+ Confirm data to be passed up and send accordingly*/
+ tcore_user_request_send_response(ur,
+ TRESP_SS_BARRING_ACTIVATE,
+ sizeof(struct tresp_ss_barring), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_atmodem_ss_get_barring_status(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_ss_barring resp = {0, };
+ struct treq_ss_barring *req_buf = NULL;
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+ int valid_records = 0;
+ GSList *resp_data = NULL;
+ TReturn result = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_ss_barring*) tcore_user_request_ref_data(ur, 0);
+ } else {
+ err("User Request is NULL");
+ }
+
+ if (at_resp) {
+ if (at_resp->lines && at_resp->success) {
+ resp_data = (GSList *) at_resp->lines;
+ resp.record_num= g_slist_length(resp_data);
+ dbg("Total records: [%d]", resp.record_num);
+ }
+ else {
+ err("RESPONSE - [NOK]");
+ }
+ } else {
+ err("No response data");
+ }
+
+ if (req_buf) {
+ if (resp.record_num > 0) {
+ resp.record = g_try_malloc0(
+ (resp.record_num) * sizeof(struct tresp_ss_barring));
+ for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
+ const gchar *line;
+ GSList *tokens = NULL;
+
+ line = (const gchar *) resp_data->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) > 0) {
+ gchar *classx_str;
+ gchar *status = NULL;
+
+ status = g_slist_nth_data(tokens, 0);
+ if (!status) {
+ dbg("Status is missing");
+ tcore_at_tok_free(tokens);
+ continue;
+ }
+
+ if (atoi(status) == 1) {
+ resp.record[valid_records].status = SS_STATUS_REG;
+ } else {
+ resp.record[valid_records].status = SS_STATUS_DEREG;
+ }
+
+ classx_str = g_slist_nth_data(tokens, 1);
+ if (!classx_str) {
+ dbg("Class error. Setting to the requested class: [%d]", req_buf->class);
+ resp.record[valid_records].class = req_buf->class;
+ } else {
+ if (__atmodem_ss_convert_modem_class_to_class(atoi(classx_str),
+ &(resp.record[valid_records].class)) == FALSE) {
+ tcore_at_tok_free(tokens);
+ continue;
+ }
+ }
+
+ resp.record[valid_records].mode= req_buf->mode;
+ result = TCORE_RETURN_SUCCESS;
+ valid_records++;
+ } else {
+ err("Invalid response message");
+ }
+ tcore_at_tok_free(tokens);
+ }
+ }
+ } else {
+ err("req_buf is NULL");
+ }
+
+ dbg("Getting Barring status: [%s]",
+ (result == TCORE_RETURN_FAILURE ? "SUCCESS" : "FAIL"));
+ resp.record_num = valid_records;
+
+ tcore_user_request_send_response(ur,
+ TRESP_SS_BARRING_GET_STATUS,
+ sizeof(struct tresp_ss_barring), &resp);
+
+ if (resp.record) {
+ g_free(resp.record);
+ }
+}
+
+#ifdef EMUL_SUPPORTED
+static void on_response_atmodem_ss_change_barring_password(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_ss_barring resp = {0, };
+/* struct treq_ss_barring *req_buf = NULL; */
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp && at_resp->success) {
+ err("Response: [OK]");
+ resp.err = SS_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = SS_ERROR_UNKNOWNERROR;
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ /*TODO :
+ req_buf = (struct treq_ss_barring *) tcore_user_request_ref_data(ur, 0);
+ resp.record->class = req_buf.class;
+ resp.record->mode = req_buf.mode;
+ Confirm data to be passed up and send accordingly*/
+ tcore_user_request_send_response(ur,
+ TRESP_SS_BARRING_CHANGE_PASSWORD,
+ sizeof(struct tresp_ss_barring), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+#endif
+
+static void on_response_atmodem_ss_set_forwarding(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_ss_forwarding resp = {0, };
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ err("Response: [OK]");
+ resp.err = SS_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = SS_ERROR_UNKNOWNERROR;
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ /*TODO : Confirm data to be passed up and send accordingly*/
+ tcore_user_request_send_response(ur,
+ TRESP_SS_FORWARDING_ACTIVATE,
+ sizeof(struct tresp_ss_barring), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_atmodem_ss_get_forwarding_status(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ struct tresp_ss_forwarding resp = {0, };
+ struct treq_ss_forwarding *req_buf = NULL;
+ int valid_records = 0;
+ GSList *resp_data = NULL;
+ UserRequest *ur = NULL;
+ TReturn result = TCORE_RETURN_FAILURE;
+
+ dbg("Enter");
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_ss_forwarding*) tcore_user_request_ref_data(ur, 0);
+ }
+ if (at_resp) {
+ if (at_resp->lines && at_resp->success) {
+ resp_data = (GSList *) at_resp->lines;
+ resp.record_num= g_slist_length(resp_data);
+ dbg("Total records: [%d]", resp.record_num);
+ }
+ else {
+ err("RESPONSE - [NOK]");
+ resp.err = SS_ERROR_UNKNOWNERROR;
+ }
+ } else {
+ err("No response data");
+ }
+
+ if (req_buf) {
+ if (resp.record_num > 0) {
+ resp.record = g_try_malloc0(
+ (resp.record_num) * sizeof(struct tresp_ss_forwarding));
+ for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
+ const gchar *line;
+ GSList *tokens = NULL;
+
+ line = (const gchar *) resp_data->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) > 0) {
+ gchar *classx_str;
+ gchar *status = NULL;
+ gchar *number = NULL;
+ gchar *time_str = NULL;
+
+ status = g_slist_nth_data(tokens, 0);
+ if (!status) {
+ dbg("Status is missing");
+ tcore_at_tok_free(tokens);
+ continue;
+ }
+
+ if (atoi(status) == 1) {
+ resp.record[valid_records].status = SS_STATUS_ACTIVATE;
+ } else {
+ resp.record[valid_records].status = SS_STATUS_DEACTIVATE;
+ }
+
+ classx_str = g_slist_nth_data(tokens, 1);
+ if (!classx_str) {
+ dbg("Class error. Setting to the requested class: [%d]", req_buf->class);
+ resp.record[valid_records].class = req_buf->class;
+ } else {
+ if (__atmodem_ss_convert_modem_class_to_class(atoi(classx_str),
+ &(resp.record[valid_records].class)) == FALSE) {
+ tcore_at_tok_free(tokens);
+ continue;
+ }
+ }
+
+ number = g_slist_nth_data(tokens, 2);
+ if (number)
+ memcpy((resp.record[valid_records].number),
+ number, strlen(number));
+
+ time_str = g_slist_nth_data(tokens, 6);
+ if (time_str)
+ resp.record[valid_records].time = atoi(time_str);
+
+ resp.record[valid_records].mode = req_buf->mode;
+
+ result = TCORE_RETURN_SUCCESS;
+ valid_records++;
+ } else {
+ err("Invalid response message");
+ }
+ tcore_at_tok_free(tokens);
+ }
+ }
+ } else {
+ err("req_buf is NULL");
+ }
+
+ dbg("Getting Forwarding Status: [%s]",
+ (result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
+ resp.record_num = valid_records;
+
+ tcore_user_request_send_response(ur,
+ TRESP_SS_FORWARDING_DEACTIVATE,
+ sizeof(struct tresp_ss_forwarding), &resp);
+
+ if (resp.record) {
+ g_free(resp.record);
+ }
+}
+
+static void on_response_atmodem_ss_set_waiting(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ struct tresp_ss_waiting resp = {0, };
+ const struct tcore_at_response *at_resp = data;
+ UserRequest *ur = NULL;
+
+ dbg("Entry");
+
+ if (at_resp) {
+ if (at_resp->success) {
+ err("Response: [OK]");
+ resp.err = SS_ERROR_NONE;
+ } else {
+ err("Response: [NOK] - [%s]", at_resp->final_response);
+ resp.err = SS_ERROR_UNKNOWNERROR;
+ }
+ } else {
+ err("No response data");
+ }
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ /*TODO : Confirm data to be passed up and send accordingly*/
+ tcore_user_request_send_response(ur,
+ TRESP_SS_WAITING_ACTIVATE,
+ sizeof(struct tresp_ss_waiting), &resp);
+ } else {
+ err("ur is NULL");
+ }
+}
+
+static void on_response_atmodem_ss_get_waiting_status(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ struct tresp_ss_waiting waiting_resp = {0, };
+ struct treq_ss_waiting *req_buf = NULL;
+ int valid_records = 0;
+ GSList *resp_data = NULL;
+ UserRequest *ur = NULL;
+ TReturn result = TCORE_RETURN_FAILURE;
+
+ dbg("Enter");
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_ss_waiting*) tcore_user_request_ref_data(ur, 0);
+ } else {
+ err("User Request is NULL");
+ }
+
+ if (at_resp) {
+ if (at_resp->lines && at_resp->success) {
+ resp_data = (GSList *) at_resp->lines;
+ waiting_resp.record_num= g_slist_length(resp_data);
+ dbg("Total records: [%d]", waiting_resp.record_num);
+ waiting_resp.err = SS_ERROR_NONE;
+ }
+ else {
+ err("RESPONSE - [NOK]");
+ waiting_resp.err = SS_ERROR_UNKNOWNERROR;
+ }
+ } else {
+ err("No response data");
+ }
+
+ if (req_buf) {
+ if (waiting_resp.record_num > 0) {
+ waiting_resp.record = g_try_malloc0(
+ (waiting_resp.record_num) * sizeof(struct tresp_ss_waiting));
+ for (valid_records = 0; resp_data != NULL; resp_data = resp_data->next) {
+ const gchar *line;
+ GSList *tokens = NULL;
+
+ line = (const gchar *) resp_data->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) > 0) {
+ gchar *classx_str;
+ gchar *status = NULL;
+
+ status = g_slist_nth_data(tokens, 0);
+ if (!status) {
+ dbg("Status is missing");
+ tcore_at_tok_free(tokens);
+ continue;
+ }
+
+ if (atoi(status) == 1) {
+ waiting_resp.record[valid_records].status= SS_STATUS_ACTIVATE;
+ } else {
+ waiting_resp.record[valid_records].status = SS_STATUS_DEACTIVATE;
+ }
+
+ classx_str = g_slist_nth_data(tokens, 1);
+ if (!classx_str) {
+ dbg("Class error. Setting to the requested class: [%d]", req_buf->class);
+ waiting_resp.record[valid_records].class = req_buf->class;
+ } else {
+ if (__atmodem_ss_convert_modem_class_to_class(atoi(classx_str),
+ &(waiting_resp.record[valid_records].class)) == FALSE) {
+ tcore_at_tok_free(tokens);
+ continue;
+ }
+ }
+
+ result = TCORE_RETURN_SUCCESS;
+ valid_records++;
+ } else {
+ err("Invalid response message");
+ }
+ tcore_at_tok_free(tokens);
+ }
+ }
+ }
+
+ dbg("Getting Waiting Status: [%s]",
+ (result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
+ waiting_resp.record_num = valid_records;
+
+ tcore_user_request_send_response(ur,
+ TRESP_SS_WAITING_DEACTIVATE,
+ sizeof(struct tresp_ss_waiting), &waiting_resp);
+
+ if (waiting_resp.record)
+ g_free(waiting_resp.record);
+}
+
+#ifdef EMUL_SUPPORTED
+static void on_response_atmodem_ss_get_cli_status(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ struct tresp_ss_cli cli_resp = {0, };
+ struct treq_ss_cli *req_buf = NULL;
+ UserRequest *ur = NULL;
+ TReturn result = TCORE_RETURN_FAILURE;
+ GSList *tokens = NULL;
+
+ dbg("Enter");
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ req_buf = (struct treq_ss_cli*) tcore_user_request_ref_data(ur, 0);
+ }
+
+ if (req_buf->type == SS_CLI_TYPE_CDIP) {
+ err("Unsupported CLI type: [%d]", req_buf->type);
+ result = TCORE_RETURN_EINVAL;
+ goto out;
+ }
+
+ if (at_resp && at_resp->success) {
+ const gchar *line;
+/* gchar *status = NULL;
+ gint net_status;
+ gint dev_status;
+*/
+ if (!at_resp->lines) {
+ err("Invalid response message");
+ goto out;
+ }
+ line = (const gchar *)at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) < 1) {
+ err("Invalid response message");
+ goto out;
+ }
+ dbg("RESPONSE OK");
+ /*TODO: Confirm Status Mapping and pass accordingly
+ */
+ cli_resp.type = req_buf->type;
+ result = TCORE_RETURN_SUCCESS;
+ } else {
+ err("RESPONSE NOK");
+ }
+
+
+ dbg("Getting CLI Status: [%s]",
+ (result == TCORE_RETURN_SUCCESS ? "SUCCESS" : "FAIL"));
+
+ tcore_user_request_send_response(ur,
+ TRESP_SS_CLI_GET_STATUS,
+ sizeof(struct tresp_ss_cli), &cli_resp);
+
+out:
+ tcore_at_tok_free(tokens);
+}
+#endif
+
+#ifdef EMUL_SUPPORTED
+static void on_response_atmodem_ss_send_ussd_request(TcorePending *p,
+ int data_len, const void *data, void *user_data)
+{
+ const struct tcore_at_response *at_resp = data;
+ struct tresp_ss_ussd ussd_resp = {0, };
+ UssdSession *ussd_s = NULL;
+ UserRequest *ur = NULL;
+ CoreObject *co = NULL;
+
+ dbg("Enter");
+
+ co= tcore_pending_ref_core_object(p);
+
+ ussd_s = tcore_ss_ussd_get_session(co);
+ if (!ussd_s) {
+ err("USSD Session not present");
+ return;
+ }
+
+ if (at_resp && at_resp->success)
+ ussd_resp.err = SS_ERROR_NONE;
+
+ dbg("Send Ussd Request: [%s]",
+ (ussd_resp.err == SS_ERROR_NONE ? "SUCCESS" : "FAIL"));
+
+ ur = tcore_pending_ref_user_request(p);
+ if (ur) {
+ /*TODO : Map response and send accordingly*/
+ tcore_user_request_send_response(ur,
+ TRESP_SS_SEND_USSD,
+ sizeof(struct tresp_ss_ussd), &ussd_resp);
+ } else {
+ err("UR is missing");
+ }
+ tcore_ss_ussd_destroy_session(ussd_s);
+
+}
+#endif
+
+static TReturn _ss_barring_set(CoreObject *o, UserRequest *ur, enum telephony_ss_opcode op)
+{
+ gchar *at_cmd = NULL;
+ struct treq_ss_barring *barring_info = NULL;
+ guint mode;
+ guint classx;
+ const char *facility = NULL;
+ char password[ MAX_SS_BARRING_PASSWORD_LEN + 1];
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ barring_info = (struct treq_ss_barring*)tcore_user_request_ref_data(ur, 0);
+
+ if (op == TIZEN_SS_OPCO_ACTIVATE)
+ mode = 1;
+ else
+ mode = 0;
+
+ if (__atmodem_ss_convert_barring_type_to_facility(
+ barring_info->mode, facility) == FALSE) {
+ err("Invalid arguments");
+ return ret;
+ }
+
+ classx = __atmodem_ss_convert_class_to_atmodem_class(barring_info->class);
+
+ memcpy(password, barring_info->password, MAX_SS_BARRING_PASSWORD_LEN);
+ password[MAX_SS_BARRING_PASSWORD_LEN] = '\0';
+
+ dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
+
+ /* AT-Command */
+ at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,\"%s\",%d",
+ facility, mode, password, classx);
+ dbg("request command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_atmodem_ss_set_barring, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+ return ret;
+}
+
+static TReturn _ss_barring_get(CoreObject *o,
+ UserRequest *ur,
+ enum telephony_ss_class class,
+ enum telephony_ss_barring_mode mode)
+{
+ gchar *at_cmd = NULL;
+ guint classx;
+ const char *facility = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ if (__atmodem_ss_convert_barring_type_to_facility(
+ mode, facility) == FALSE) {
+ err("Invalid arguments");
+ return ret;
+ }
+
+ classx = __atmodem_ss_convert_class_to_atmodem_class(class);
+
+ dbg("facility: [%s], classx:[%d], mode: [%d]", facility, classx, mode);
+
+ /* AT-Command */
+ at_cmd = g_strdup_printf("AT+CLCK=\"%s\",%d,,%d",
+ facility, mode, classx);
+ dbg("request command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_atmodem_ss_get_barring_status, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+ return ret;
+}
+
+static TReturn s_ss_barring_activate(CoreObject *o, UserRequest *ur)
+{
+ return _ss_barring_set(o, ur, TIZEN_SS_OPCO_ACTIVATE);
+}
+
+static TReturn s_ss_barring_deactivate(CoreObject *o, UserRequest *ur)
+{
+ return _ss_barring_set(o, ur, TIZEN_SS_OPCO_DEACTIVATE);
+}
+
+#ifdef EMUL_SUPPORTED
+static TReturn s_ss_barring_change_password(CoreObject *o, UserRequest *ur)
+{
+ gchar *at_cmd = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+ struct treq_ss_barring_change_password *barring_info = 0;
+ char old_password[MAX_SS_BARRING_PASSWORD_LEN + 1];
+ char new_password[MAX_SS_BARRING_PASSWORD_LEN + 1];
+
+ dbg("Entry");
+
+ barring_info = (struct treq_ss_barring_change_password*)tcore_user_request_ref_data(ur, 0);
+
+ memcpy(old_password, barring_info->password_old, MAX_SS_BARRING_PASSWORD_LEN);
+ old_password[MAX_SS_BARRING_PASSWORD_LEN] = '\0';
+ memcpy(new_password, barring_info->password_new, MAX_SS_BARRING_PASSWORD_LEN);
+ new_password[MAX_SS_BARRING_PASSWORD_LEN] = '\0';
+
+ dbg("old passwd - %s new passwd- %s", old_password, new_password);
+ at_cmd = g_strdup_printf("AT+CPWD=\"%s\",\"%s\",\"%s\"", "AB", old_password, new_password);
+ dbg("request command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_atmodem_ss_change_barring_password, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ return ret;
+}
+#endif
+
+static TReturn s_ss_barring_get_status(CoreObject *o, UserRequest *ur)
+{
+ struct treq_ss_barring *barring_info = 0;
+ barring_info = (struct treq_ss_barring*)tcore_user_request_ref_data(ur, 0);
+
+ return _ss_barring_get(o, ur, barring_info->class, SS_BARR_MODE_BOIC);
+}
+
+static TReturn _ss_forwarding_set(CoreObject *o, UserRequest *ur, enum telephony_ss_opcode op)
+{
+ gchar *at_cmd = NULL;
+ struct treq_ss_forwarding *forwarding_info = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+ gchar *tmp_cmd = NULL;
+ guint classx;
+ guint reason;
+ guint mode;
+ guint num_type;
+
+ dbg("Entry");
+
+ forwarding_info = (struct treq_ss_forwarding*) tcore_user_request_ref_data(ur, 0);
+
+ classx = __atmodem_ss_convert_class_to_atmodem_class(forwarding_info->class);
+ if (__atmodem_ss_convert_forwarding_opcode_to_modem_mode(
+ op, &mode) == FALSE) {
+ err("Invalid arguments");
+ return ret;
+ }
+
+ if (__atmodem_ss_convert_forwarding_mode_to_modem_reason(
+ forwarding_info->mode, &reason) == FALSE) {
+ err("Invalid arguments");
+ return ret;
+ }
+
+ if (forwarding_info->number[0] == '+')
+ num_type = 145;
+ else
+ num_type = 129;
+
+ dbg("classx: [%d], reason:[%d], mode: [%d]", classx, reason, mode);
+
+ if (mode == 3) /* TIZEN_SS_OPCO_REGISTER */
+ tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,\"%s\",%d,%d",
+ reason, mode, forwarding_info->number, num_type, classx);
+ else
+ tmp_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d",
+ reason, mode, classx);
+
+ if (reason == 2) /* SS_CF_MODE_CFNRy */
+ at_cmd = g_strdup_printf("%s,,,%d", tmp_cmd, forwarding_info->time);
+ else
+ at_cmd = g_strdup_printf("%s", tmp_cmd);
+ dbg("request command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_atmodem_ss_set_forwarding, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+ g_free(tmp_cmd);
+
+ return ret;
+}
+
+static TReturn _ss_forwarding_get( CoreObject *o,
+ UserRequest *ur,
+ enum telephony_ss_class class,
+ enum telephony_ss_forwarding_mode mode)
+{
+ gchar *at_cmd = NULL;
+ guint classx;
+ guint reason;
+ guint query_mode = 2; /* query status */
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ classx = __atmodem_ss_convert_class_to_atmodem_class(class);
+
+ if (__atmodem_ss_convert_forwarding_mode_to_modem_reason(
+ mode, &reason) == FALSE) {
+ err("Invalid arguments");
+ return ret;
+ }
+
+ dbg("classx: [%d], reason: [%d], mode: [%d]", classx, reason, query_mode);
+
+ at_cmd = g_strdup_printf("AT+CCFC=%d,%d,,,%d", reason, query_mode, classx);
+ dbg("request command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_atmodem_ss_get_forwarding_status, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_ss_forwarding_activate(CoreObject *o, UserRequest *ur)
+{
+ return _ss_forwarding_set(o, ur, TIZEN_SS_OPCO_ACTIVATE);
+}
+
+static TReturn s_ss_forwarding_deactivate(CoreObject *o, UserRequest *ur)
+{
+ return _ss_forwarding_set(o, ur, TIZEN_SS_OPCO_DEACTIVATE);
+}
+
+static TReturn s_ss_forwarding_register(CoreObject *o, UserRequest *ur)
+{
+ return _ss_forwarding_set(o, ur, TIZEN_SS_OPCO_REG);
+}
+
+static TReturn s_ss_forwarding_deregister(CoreObject *o, UserRequest *ur)
+{
+ return _ss_forwarding_set(o, ur, TIZEN_SS_OPCO_DEREG);
+}
+
+static TReturn s_ss_forwarding_get_status(CoreObject *o, UserRequest *ur)
+{
+ struct treq_ss_forwarding *forwarding_info = 0;
+ forwarding_info = (struct treq_ss_forwarding*)tcore_user_request_ref_data(ur, 0);
+
+ return _ss_forwarding_get(o, ur, forwarding_info->class, forwarding_info->mode);
+}
+
+static TReturn _ss_waiting_set(CoreObject *o, UserRequest *ur, enum telephony_ss_opcode opco)
+{
+ gchar *at_cmd = NULL;
+ struct treq_ss_waiting *waiting_info = 0;
+ guint classx;
+ guint mode;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ waiting_info = (struct treq_ss_waiting*) tcore_user_request_ref_data(ur, 0);
+
+ if (opco == TIZEN_SS_OPCO_ACTIVATE) {
+ mode = 1;
+ } else {
+ mode = 0;
+ }
+ classx = __atmodem_ss_convert_class_to_atmodem_class(waiting_info->class);
+ dbg("mode: [%d], class: [%d]", mode, classx);
+
+ at_cmd = g_strdup_printf("AT+CCWA=1,%d,%d", mode, classx);
+ dbg("request command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_atmodem_ss_set_waiting, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn _ss_waiting_get(CoreObject *o,
+ UserRequest *ur,
+ enum telephony_ss_class class)
+{
+ gchar *at_cmd = NULL;
+ guint classx;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ dbg("Entry");
+
+ classx = __atmodem_ss_convert_class_to_atmodem_class(class);
+ dbg("class: [%d]", classx);
+
+ at_cmd = g_strdup_printf("AT+CCWA=1,2,%d", classx);
+ dbg("request command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_atmodem_ss_get_waiting_status, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ return ret;
+}
+
+static TReturn s_ss_waiting_activate(CoreObject *o, UserRequest *ur)
+{
+ return _ss_waiting_set(o, ur, TIZEN_SS_OPCO_ACTIVATE);
+}
+
+static TReturn s_ss_waiting_deactivate(CoreObject *o, UserRequest *ur)
+{
+ return _ss_waiting_set(o, ur, TIZEN_SS_OPCO_DEACTIVATE);
+}
+
+static TReturn s_ss_waiting_get_status(CoreObject *o, UserRequest *ur)
+{
+ struct treq_ss_waiting *waiting = 0;
+ waiting = (struct treq_ss_waiting*)tcore_user_request_ref_data(ur, 0);
+
+ return _ss_waiting_get(o, ur, waiting->class);
+}
+
+#ifdef EMUL_SUPPORTED
+static TReturn s_ss_cli_get_status(CoreObject *o, UserRequest *ur)
+{
+ gchar *at_cmd = NULL;
+ gchar *cmd_prefix = NULL;
+ struct treq_ss_cli *cli_info = NULL;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ cli_info = (struct treq_ss_cli *)tcore_user_request_ref_data(ur, 0);
+
+ switch (cli_info->type) {
+ case SS_CLI_TYPE_CLIR:
+ cmd_prefix = "+CLIR";
+ break;
+ case SS_CLI_TYPE_CLIP:
+ cmd_prefix = "+CLIP";
+ break;
+ case SS_CLI_TYPE_COLP:
+ cmd_prefix = "+COLP";
+ break;
+ case SS_CLI_TYPE_COLR:
+ cmd_prefix = "+COLR";
+ break;
+ case SS_CLI_TYPE_CNAP:
+ cmd_prefix = "+CNAP";
+ break;
+ case SS_CLI_TYPE_CDIP:
+ default:
+ dbg("Unsupported CLI type: [%d]", cli_info->type);
+ return ret;
+ }
+
+ /* AT-Command */
+ at_cmd = g_strdup_printf("AT%s?", cmd_prefix);
+ dbg("request command : %s", at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_SINGLELINE,
+ ur,
+ on_response_atmodem_ss_get_cli_status, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ return ret;
+}
+#endif
+
+#ifdef EMUL_SUPPORTED
+static TReturn s_ss_send_ussd(CoreObject *o, UserRequest *ur)
+{
+ UssdSession *ussd_s = 0;
+ gchar *at_cmd = NULL;
+ struct treq_ss_ussd *ussd = 0;
+ TReturn ret = TCORE_RETURN_FAILURE;
+
+ ussd = (struct treq_ss_ussd*)tcore_user_request_ref_data(ur, 0);
+
+ ussd_s = tcore_ss_ussd_get_session(o);
+ if (!ussd_s) {
+ dbg("USSD session does not exist");
+ tcore_ss_ussd_create_session(o, (enum tcore_ss_ussd_type)ussd->type,
+ (void*)tcore_user_request_ref(ur), 0);
+ } else {
+
+ if (ussd->type == SS_USSD_TYPE_USER_INITIATED) {
+ err("ussd session is already exist");
+
+ g_free(ussd_s);
+ return TCORE_RETURN_FAILURE;
+ }
+
+ tcore_ss_ussd_set_session_type(ussd_s, (enum tcore_ss_ussd_type)ussd->type);
+ }
+
+ at_cmd = g_strdup_printf("AT+CUSD=1,\"%s\",%d", ussd->str, 0x0f);
+ dbg("request command : %s",at_cmd);
+
+ /* Send Request to modem */
+ ret = tcore_prepare_and_send_at_request(o, at_cmd, NULL,
+ TCORE_AT_NO_RESULT,
+ ur,
+ on_response_atmodem_ss_send_ussd_request, NULL,
+ on_send_at_request, NULL, 0, NULL, NULL);
+ dbg("ret: [0x%x]", ret);
+
+ g_free(at_cmd);
+
+ return ret;
+
+}
+#endif
+
+static struct tcore_ss_operations ss_ops = {
+ .barring_activate = s_ss_barring_activate,
+ .barring_deactivate = s_ss_barring_deactivate,
+ .barring_change_password = NULL,
+ .barring_get_status = s_ss_barring_get_status,
+ .forwarding_activate = s_ss_forwarding_activate,
+ .forwarding_deactivate = s_ss_forwarding_deactivate,
+ .forwarding_register = s_ss_forwarding_register,
+ .forwarding_deregister = s_ss_forwarding_deregister,
+ .forwarding_get_status = s_ss_forwarding_get_status,
+ .waiting_activate = s_ss_waiting_activate,
+ .waiting_deactivate = s_ss_waiting_deactivate,
+ .waiting_get_status = s_ss_waiting_get_status,
+ .cli_activate = NULL,
+ .cli_deactivate = NULL,
+ .cli_get_status = NULL,
+ .send_ussd = NULL,
+};
+
+gboolean s_ss_init(TcorePlugin *p, TcoreHal *h)
+{
+ CoreObject *so = 0;
+
+ dbg("s_ss_init()");
+
+ so = tcore_ss_new(p, "ss", &ss_ops, h);
+ if (!so) {
+ err("[ error ] ss_new()");
+ return FALSE;
+ }
+
+/* tcore_object_add_callback(so, EVENT_SS_INFO, on_notification_ss_info, 0); */
+ tcore_object_add_callback(so, "+CUSD:", on_notification_ss_ussd, 0);
+
+ return TRUE;
+}
+
+void s_ss_exit(TcorePlugin *p)
+{
+ CoreObject *o;
+ struct property_network_info *data;
+
+ o = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_SS);
+
+ data = tcore_plugin_ref_property(p, "SS");
+ if (data)
+ g_free(data);
+
+ tcore_ss_free(o);
+}