From b25625380264e330d9f716acfae51de3a7c618a7 Mon Sep 17 00:00:00 2001 From: Dongchul Lim Date: Tue, 17 Mar 2015 13:49:11 +0900 Subject: [PATCH] Code Sync up from tizen_2.4 Change-Id: I3c63d18ab520f98f6e0f7c11ed112b7c93fc3866 --- .gitignore | 100 - CMakeLists.txt | 8 +- include/common/imc_tel_err.h | 186 ++ include/imc_call.h | 10 +- include/imc_common.h | 40 +- include/imc_dispatch.h | 26 - include/imc_gps.h | 10 +- include/imc_modem.h | 14 +- include/imc_network.h | 10 +- include/imc_phonebook.h | 8 +- include/imc_ps.h | 8 +- include/imc_sap.h | 8 +- include/imc_sat.h | 9 +- include/imc_sim.h | 14 +- include/imc_sms.h | 10 +- include/imc_ss.h | 10 +- include/nvm/nvm.h | 248 +- packaging/tel-plugin-imc.manifest | 5 - packaging/tel-plugin-imc.spec | 63 +- res/convert_to_sql.c | 4 +- src/desc-imc.c | 295 -- src/desc_imc.c | 294 ++ src/imc_call.c | 4753 +++++++++++++++++----------- src/imc_common.c | 40 +- src/imc_gps.c | 847 ++--- src/imc_modem.c | 1510 ++++----- src/imc_network.c | 3705 +++++++++++++--------- src/imc_phonebook.c | 1892 +++++++---- src/imc_ps.c | 1155 +++---- src/imc_sap.c | 1324 ++++---- src/imc_sat.c | 821 ++--- src/imc_sim.c | 6327 ++++++++++++++++++------------------- src/imc_sms.c | 4785 ++++++++++++++++------------ src/imc_ss.c | 3915 ++++++++++++++--------- src/nvm/nvm.c | 29 +- tel-plugin-imc.manifest | 11 + 36 files changed, 18261 insertions(+), 14233 deletions(-) delete mode 100644 .gitignore create mode 100644 include/common/imc_tel_err.h delete mode 100644 include/imc_dispatch.h mode change 100755 => 100644 include/nvm/nvm.h delete mode 100644 packaging/tel-plugin-imc.manifest mode change 100644 => 100755 packaging/tel-plugin-imc.spec delete mode 100644 src/desc-imc.c create mode 100644 src/desc_imc.c mode change 100644 => 100755 src/imc_sim.c mode change 100644 => 100755 src/imc_ss.c create mode 100644 tel-plugin-imc.manifest diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 63619be..0000000 --- a/.gitignore +++ /dev/null @@ -1,100 +0,0 @@ -#Copyright (c) 2013 GitHub, Inc. -# -#Permission is hereby granted, free of charge, to any person obtaining a -#copy of this software and associated documentation files (the "Software"), -#to deal in the Software without restriction, including without limitation -#the rights to use, copy, modify, merge, publish, distribute, sublicense, -#and/or sell copies of the Software, and to permit persons to whom the -#Software is furnished to do so, subject to the following conditions: -# -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. -# -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -#FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -#DEALINGS IN THE SOFTWARE. -# -# https://github.com/github/gitignore - -# Object files -*.o - -# Libraries -*.lib -*.a - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app - -# CMake -CMakeCache.txt -CMakeFiles -Makefile -cmake_install.cmake -install_manifest.txt - -# Emacs -*~ -\#*\# -/.emacs.desktop -/.emacs.desktop.lock -.elc -auto-save-list -tramp -.\#* - -# Org-mode -.org-id-locations -*_archive - -# Linux -.* -!.gitignore -*~ - -# Vim -*.s[a-w][a-z] -*.un~ -Session.vim -.netrwhist -*~ - -# Eclipse -*.pydevproject -.project -.metadata -bin/** -tmp/** -tmp/**/* -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath diff --git a/CMakeLists.txt b/CMakeLists.txt index 0644560..63190cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ SET(INCLUDEDIR "\${prefix}/include") # Set required packages INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED glib-2.0 tcore tel-headers db-util libxml-2.0 libtzplatform-config vconf) +pkg_check_modules(pkgs REQUIRED glib-2.0 tcore dlog db-util libxml-2.0 vconf) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -20,7 +20,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include /usr/include/libxml2 ) -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} -Werror -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wdeclaration-after-statement -Wmissing-declarations -Wredundant-decls -Wcast-align") ADD_DEFINITIONS("-DFEATURE_TLOG_DEBUG") ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"IMC\"") @@ -29,8 +29,9 @@ MESSAGE(${CMAKE_C_FLAGS}) MESSAGE(${CMAKE_EXE_LINKER_FLAGS}) SET(SRCS - src/desc-imc.c + src/desc_imc.c src/imc_modem.c + src/imc_common.c src/imc_network.c src/imc_sim.c src/imc_sat.c @@ -41,7 +42,6 @@ SET(SRCS src/imc_phonebook.c src/imc_sap.c src/imc_gps.c - src/imc_common.c src/nvm/nvm.c ) diff --git a/include/common/imc_tel_err.h b/include/common/imc_tel_err.h new file mode 100644 index 0000000..4097fc5 --- /dev/null +++ b/include/common/imc_tel_err.h @@ -0,0 +1,186 @@ +/* + * tel-plugin-imc + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hayoon Ko + * + * 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. + */ + +/** + * @open + * @ingroup TelephonyAPI + * @addtogroup COMMON_TAPI COMMON + * @{ + * These error codes are used by Applications. + */ + + +#ifndef _TEL_ERR_H_ +#define _TEL_ERR_H_ +/*================================================================================================== + INCLUDE FILES +==================================================================================================*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*================================================================================================== + CONSTANTS +==================================================================================================*/ + + +/*================================================================================================== + MACROS +==================================================================================================*/ + + +/*================================================================================================== + ENUMS +==================================================================================================*/ + +/************************************************************ +** Errors defined in "+CME ERROR" , +** - see 3GPP TS 27.007 +** - ranges are 0x00 ~ 0x7FFF +************************************************************/ +/** + Error codes sent by the modem in response to the above operations. +*/ +typedef enum { + /* GENERAL ERRORS */ + TAPI_OP_GEN_ERR_PHONE_FAILURE = 0, /* 0 */ + TAPI_OP_GEN_ERR_NO_CONNECTION_TO_PHONE, /* 1 */ + TAPI_OP_GEN_ERR_PHONE_ADAPTOR_LINK_RESERVED, /* 2 */ + TAPI_OP_GEN_ERR_OPER_NOT_ALLOWED, /* 3 */ + TAPI_OP_GEN_ERR_OPER_NOT_SUPPORTED, /* 4 */ + TAPI_OP_GEN_ERR_PH_SIM_PIN_REQU, /* 5 */ + TAPI_OP_GEN_ERR_PH_FSIM_PIN_REQU, /* 6 */ + TAPI_OP_GEN_ERR_PH_FSIM_PUK_REQU, /* 7 */ + TAPI_OP_GEN_ERR_SIM_NOT_INSERTED = 10, /* 10 */ + TAPI_OP_GEN_ERR_SIM_PIN_REQU, /* 11 */ + TAPI_OP_GEN_ERR_SIM_PUK_REQU, /* 12 */ + TAPI_OP_GEN_ERR_SIM_FAILURE, /* 13 */ + TAPI_OP_GEN_ERR_SIM_BUSY, /* 14 */ + TAPI_OP_GEN_ERR_SIM_WRONG, /* 15 */ + TAPI_OP_GEN_ERR_INCORRECT_PW, /* 16 */ + TAPI_OP_GEN_ERR_SIM_PIN2_REQU, /* 17 */ + TAPI_OP_GEN_ERR_SIM_PUK2_REQU, /* 18 */ + TAPI_OP_GEN_ERR_MEM_FULL = 20, /* 20 */ + TAPI_OP_GEN_ERR_INVALID_INDEX, /* 21 */ + TAPI_OP_GEN_ERR_NOT_FOUND, /* 22 */ + TAPI_OP_GEN_ERR_MEM_FAILURE, /* 23 */ + TAPI_OP_GEN_ERR_TEXT_STR_TOO_LONG, /* 24 */ + TAPI_OP_GEN_ERR_INVALID_CHARACTERS_IN_TEXT_STR, /* 25 */ + TAPI_OP_GEN_ERR_DIAL_STR_TOO_LONG, /* 26 */ + TAPI_OP_GEN_ERR_INVALID_CHARACTERS_IN_DIAL_STR, /* 27 */ + TAPI_OP_GEN_ERR_NO_NET_SVC = 30, /* 30 */ + TAPI_OP_GEN_ERR_NET_TIMEOUT, /* 31 */ + TAPI_OP_GEN_ERR_NET_NOT_ALLOWED_EMERGENCY_CALLS_ONLY, /* 32 */ + TAPI_OP_GEN_ERR_NET_PERS_PIN_REQU = 40, /* 40 */ + TAPI_OP_GEN_ERR_NET_PERS_PUK_REQU, /* 41 */ + TAPI_OP_GEN_ERR_NET_SUBSET_PERS_PIN_REQU, /* 42 */ + TAPI_OP_GEN_ERR_NET_SUBSET_PERS_PUK_REQU, /* 43 */ + TAPI_OP_GEN_ERR_SVC_PROVIDER_PERS_PIN_REQU, /* 44 */ + TAPI_OP_GEN_ERR_SVC_PROVIDER_PERS_PUK_REQU, /* 45 */ + TAPI_OP_GEN_ERR_CORPORATE_PERS_PIN_REQU, /* 46 */ + TAPI_OP_GEN_ERR_CORPORATE_PERS_PUK_REQU, /* 47 */ + TAPI_OP_GEN_ERR_HIDDEN_KEY_REQU, /* 48 */ + TAPI_OP_GEN_ERR_UNKNOWN = 100, /* 100 */ + + /* Errors related to a failure to perform an Attach */ + TAPI_OP_GEN_ERR_ILLEGAL_MS = 103, /* 103 */ + TAPI_OP_GEN_ERR_ILLEGAL_ME = 106, /* 106 */ + TAPI_OP_GEN_ERR_GPRS_SVC_NOT_ALLOWED, /* 107 */ + TAPI_OP_GEN_ERR_PLMN_NOT_ALLOWED = 111, /* 111 */ + TAPI_OP_GEN_ERR_LOCATION_AREA_NOT_ALLOWED, /* 112 */ + TAPI_OP_GEN_ERR_ROAMING_NOT_ALLOWED_IN_THIS_LOCATION_AREA, /* 113 */ + + /* Errors related to a failure to Activate a Context */ + TAPI_OP_GEN_ERR_SVC_OPT_NOT_SUPPORTED = 132, /* 132 */ + TAPI_OP_GEN_ERR_REQ_SVC_OPT_NOT_SUBSCRIBED, /* 133 */ + TAPI_OP_GEN_ERR_SVC_OPT_TEMPORARILY_OUT_OF_ORDER, /* 134 */ + TAPI_OP_GEN_ERR_UNSPECIFIED_GPRS_ERR = 148, /* 148 */ + TAPI_OP_GEN_ERR_PDP_AUTHENTICATION_FAILURE, /* 149 */ + TAPI_OP_GEN_ERR_INVALID_MOBILE_CLASS, /* 150 */ + + /* VBS / VGCS and eMLPP -related errors */ + TAPI_OP_GEN_ERR_VBS_VGCS_NOT_SUPPORTED_BY_THE_NET = 151, /* 151 */ + TAPI_OP_GEN_ERR_NO_SVC_SUBSCRIPTION_ON_SIM, /* 152 */ + TAPI_OP_GEN_ERR_NO_SUBSCRIPTION_FOR_GROUP_ID, /* 153 */ + TAPI_OP_GEN_ERR_GROUP_ID_NOT_ACTIVATED_ON_SIM, /* 154 */ + TAPI_OP_GEN_ERR_NO_MATCHING_NOTI = 155, /* 155 */ + TAPI_OP_GEN_ERR_VBS_VGCS_CALL_ALREADY_PRESENT, /* 156 */ + TAPI_OP_GEN_ERR_CONGESTION, /* 157 */ + TAPI_OP_GEN_ERR_NET_FAILURE, /* 158 */ + TAPI_OP_GEN_ERR_UPLINK_BUSY, /* 159 */ + TAPI_OP_GEN_ERR_NO_ACCESS_RIGHTS_FOR_SIM_FILE = 160, /* 160 */ + TAPI_OP_GEN_ERR_NO_SUBSCRIPTION_FOR_PRIORITY, /* 161 */ + TAPI_OP_GEN_ERR_OPER_NOT_APPLICABLE_OR_NOT_POSSIBLE, /* 162 */ + + + /************************************************************ + ** SAMSUNG ADDED ERRORS + ************************************************************/ + TAPI_OP_GEN_ERR_NONE = 0x8000, /* 0x8000 : No Errors */ + + /* General Common Errors : 0x8000 - 0x80FF */ + TAPI_OP_GEN_ERR_INVALID_FORMAT, /* 0x8001 : Invalid Parameter or Format */ + TAPI_OP_GEN_ERR_PHONE_OFFLINE, /* 0x8002 : */ + TAPI_OP_GEN_ERR_CMD_NOT_ALLOWED, /* 0x8003 : */ + TAPI_OP_GEN_ERR_PHONE_IS_INUSE, /* 0x8004 : */ + TAPI_OP_GEN_ERR_INVALID_STATE = 0x8005, /* 0x8005 : */ + + TAPI_OP_GEN_ERR_NO_BUFFER, /* 0x8006 : No internal free buffers */ + TAPI_OP_GEN_ERR_OPER_REJ, /* 0x8007 : Operation Rejected */ + TAPI_OP_GEN_ERR_INSUFFICIENT_RESOURCE, /* 0x8008 : insufficient resource */ + TAPI_OP_GEN_ERR_NET_NOT_RESPOND, /* 0x8009 : Network not responding */ + TAPI_OP_GEN_ERR_SIM_PIN_ENABLE_REQ = 0x800A, /* 0x800A : SIM Pin Enable Required */ + TAPI_OP_GEN_ERR_SIM_PERM_BLOCKED, /* 0x800B : SIM Permanent Blocked */ + TAPI_OP_GEN_ERR_SIM_PHONEBOOK_RESTRICTED, /*0x800C: SIM Phonebook Restricted*/ + TAPI_OP_GEM_ERR_FIXED_DIALING_NUMBER_ONLY, /*0x800D: Restricted By FDN Mode */ + + /* Reserved : 0x800E ~ 0x80FF */ + TAPI_OP_GEN_ERR_800E_RESERVED_START = 0x800E, /* 0x800E */ + + TAPI_OP_GEN_ERR_80FF_RESERVED_END = 0x80ff, /* 0x80FF */ + + /* the other errors */ + TAPI_OP_GEN_ERR_OTHERS = 0xFFFE, /* 0xFFFE */ + + TAPI_OP_GEN_ERR_MAX = 0xFFFF +} tapi_phone_err_t; + + +/*================================================================================================== + STRUCTURES AND OTHER TYPEDEFS +==================================================================================================*/ + + +/*================================================================================================== + FUNCTION PROTOTYPES +==================================================================================================*/ + + +#ifdef __cplusplus +} +#endif + +#endif // _TEL_ERR_H_ + +/** +* @} +*/ diff --git a/include/imc_call.h b/include/imc_call.h index 5e37f0a..82b2bc2 100644 --- a/include/imc_call.h +++ b/include/imc_call.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Sharanayya Mathapati * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +21,7 @@ #ifndef __IMC_CALL_H__ #define __IMC_CALL_H__ -gboolean imc_call_init(TcorePlugin *p, CoreObject *co); -void imc_call_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_call_init(TcorePlugin *cp, CoreObject *co_call); +void imc_call_exit(TcorePlugin *cp, CoreObject *co_call); -#endif /* __IMC_CALL_H__ */ +#endif // __IMC_CALL_H__ \ No newline at end of file diff --git a/include/imc_common.h b/include/imc_common.h index 23e3952..746659c 100644 --- a/include/imc_common.h +++ b/include/imc_common.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hayoon Ko * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,34 +21,12 @@ #ifndef __IMC_COMMON_H__ #define __IMC_COMMON_H__ -#define IMC_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 */ -} ImcRespCbData; - -#define IMC_GET_DATA_FROM_RESP_CB_DATA(ptr) (gpointer)ptr->data -#define IMC_CHECK_REQUEST_RET(ret, resp_cb_data, request) \ -do {\ - if (ret != TEL_RETURN_SUCCESS) { \ - err("Failed to process request - [%s]", request); \ - imc_destroy_resp_cb_data(resp_cb_data); \ - } \ -} while(0) - -ImcRespCbData *imc_create_resp_cb_data(TcoreObjectResponseCallback cb, - void *cb_data, void *data, guint data_len); -void imc_destroy_resp_cb_data(ImcRespCbData *resp_cb_data); +#include -void on_send_imc_request(TcorePending *p, - TelReturn send_status, void *user_data); +void util_hex_dump(char *pad, int size, const void *data); +unsigned char util_hexCharToInt(char c); +char *util_hex_to_string(const char *src, unsigned int src_len); +char* util_hexStringToBytes(char *s); +char* util_removeQuotes(void *data); -#endif /* __IMC_COMMON_H__ */ +#endif // __IMC_COMMON_H__ \ No newline at end of file diff --git a/include/imc_dispatch.h b/include/imc_dispatch.h deleted file mode 100644 index 5e18bc5..0000000 --- a/include/imc_dispatch.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * tel-plugin-imc - * - * 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 __IMC_DISPATCH_H__ -#define __IMC_DISPATCH_H__ - -void do_factory(TcoreHal *h, const ipc_message_type *ipc); -void do_notification_message(TcorePlugin *p, const ipc_message_type *ipc); -void do_notification_sys_message(TcorePlugin *p, const void *data); - -#endif /* __IMC_DISPATCH_H__ */ diff --git a/include/imc_gps.h b/include/imc_gps.h index 0351c96..4b0a74e 100644 --- a/include/imc_gps.h +++ b/include/imc_gps.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Arun Shukla * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +21,7 @@ #ifndef __IMC_GPS_H__ #define __IMC_GPS_H__ -gboolean imc_gps_init(TcorePlugin *p, CoreObject *co); -void imc_gps_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_gps_init(TcorePlugin *cp, CoreObject *co_gps); +void imc_gps_exit(TcorePlugin *cp, CoreObject *co_gps); -#endif /* __IMC_GPS_H__ */ +#endif // __IMC_GPS_H__ \ No newline at end of file diff --git a/include/imc_modem.h b/include/imc_modem.h index 5b48ec3..7793a53 100644 --- a/include/imc_modem.h +++ b/include/imc_modem.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hayoon Ko * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +21,10 @@ #ifndef __IMC_MODEM_H__ #define __IMC_MODEM_H__ -gboolean imc_modem_init(TcorePlugin *p, CoreObject *co); -void imc_modem_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_modem_init(TcorePlugin *cp, CoreObject *co_modem); +void imc_modem_exit(TcorePlugin *cp, CoreObject *co_modem); -void imc_modem_register_nvm(CoreObject *co); -gboolean imc_modem_power_on_modem(TcorePlugin *plugin); +gboolean modem_power_on(TcorePlugin *plugin); +void modem_register_nvm(CoreObject *co_modem); -#endif /* __IMC_MODEM_H__ */ +#endif // __IMC_MODEM_H__ \ No newline at end of file diff --git a/include/imc_network.h b/include/imc_network.h index 3f098b2..4a8bfa7 100644 --- a/include/imc_network.h +++ b/include/imc_network.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Harish Bishnoi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +21,7 @@ #ifndef __IMC_NETWORK_H__ #define __IMC_NETWORK_H__ -gboolean imc_network_init(TcorePlugin *p, CoreObject *co); -void imc_network_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_network_init(TcorePlugin *cp, CoreObject *co_network); +void imc_network_exit(TcorePlugin *cp, CoreObject *co_network); -#endif /* __IMC_NETWORK_H__ */ +#endif // __IMC_NETWORK_H__ \ No newline at end of file diff --git a/include/imc_phonebook.h b/include/imc_phonebook.h index 7e5c468..e26bc40 100644 --- a/include/imc_phonebook.h +++ b/include/imc_phonebook.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +21,7 @@ #ifndef __IMC_PHONEBOOK_H__ #define __IMC_PHONEBOOK_H__ -gboolean imc_phonebook_init(TcorePlugin *p, CoreObject *co); -void imc_phonebook_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_phonebook_init(TcorePlugin *cp, CoreObject *co_phonebook); +void imc_phonebook_exit(TcorePlugin *cp, CoreObject *co_phonebook); #endif /* __IMC_PHONEBOOK_H__ */ diff --git a/include/imc_ps.h b/include/imc_ps.h index 02f5178..b9b60a0 100644 --- a/include/imc_ps.h +++ b/include/imc_ps.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Arun Shukla * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +21,7 @@ #ifndef __IMC_PS_H__ #define __IMC_PS_H__ -gboolean imc_ps_init(TcorePlugin *p, CoreObject *co); -void imc_ps_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_ps_init(TcorePlugin *cp, CoreObject *co_ps); +void imc_ps_exit(TcorePlugin *cp, CoreObject *co_ps); #endif /*__IMC_PS_H__*/ diff --git a/include/imc_sap.h b/include/imc_sap.h index 836efa2..9088e5e 100644 --- a/include/imc_sap.h +++ b/include/imc_sap.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hayoon Ko * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +21,7 @@ #ifndef __IMC_SAP_H__ #define __IMC_SAP_H__ -gboolean imc_sap_init(TcorePlugin *p, CoreObject *co); -void imc_sap_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_sap_init(TcorePlugin *cp, CoreObject *co_sap); +void imc_sap_exit(TcorePlugin *cp, CoreObject *co_sap); #endif /* __IMC_SAP_H__ */ diff --git a/include/imc_sat.h b/include/imc_sat.h index 126f7ff..773e9cb 100644 --- a/include/imc_sat.h +++ b/include/imc_sat.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Harish Bishnoi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +18,11 @@ * limitations under the License. */ + #ifndef __IMC_SAT_H__ #define __IMC_SAT_H__ -gboolean imc_sat_init(TcorePlugin *p, CoreObject *co); -void imc_sat_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_sat_init(TcorePlugin *cp, CoreObject *co_sat); +void imc_sat_exit(TcorePlugin *cp, CoreObject *co_sat); #endif /* __IMC_SAT_H__ */ diff --git a/include/imc_sim.h b/include/imc_sim.h index 8d6d199..2abafe6 100644 --- a/include/imc_sim.h +++ b/include/imc_sim.h @@ -1,7 +1,9 @@ -/* +/** * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Ankit Jogi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +21,7 @@ #ifndef __IMC_SIM_H__ #define __IMC_SIM_H__ -gboolean imc_sim_get_smsp_info(TcorePlugin *plugin, int *rec_count, int *rec_len); - -gboolean imc_sim_init(TcorePlugin *p, CoreObject *co); -void imc_sim_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_sim_init(TcorePlugin *cp, CoreObject *co_sim); +void imc_sim_exit(TcorePlugin *cp, CoreObject *co_sim); -#endif /* __IMC_SIM_H__ */ +#endif // __IMC_SIM_H__ \ No newline at end of file diff --git a/include/imc_sms.h b/include/imc_sms.h index 344de7c..e9b4765 100644 --- a/include/imc_sms.h +++ b/include/imc_sms.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Madhavi Akella * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +21,7 @@ #ifndef __IMC_SMS_H__ #define __IMC_SMS_H__ -gboolean imc_sms_init(TcorePlugin *p, CoreObject *co); -void imc_sms_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_sms_init(TcorePlugin *cp, CoreObject *co_sms); +void imc_sms_exit(TcorePlugin *cp, CoreObject *co_sms); -#endif /* __IMC_SMS_H__ */ +#endif // __IMC_SMS_H__ \ No newline at end of file diff --git a/include/imc_ss.h b/include/imc_ss.h index 0b93897..957837d 100644 --- a/include/imc_ss.h +++ b/include/imc_ss.h @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Sharanayya Mathapati * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +21,7 @@ #ifndef __IMC_SS_H__ #define __IMC_SS_H__ -gboolean imc_ss_init(TcorePlugin *p, CoreObject *co); -void imc_ss_exit(TcorePlugin *p, CoreObject *co); +gboolean imc_ss_init(TcorePlugin *cp, CoreObject *co_ss); +void imc_ss_exit(TcorePlugin *cp, CoreObject *co_ss); -#endif /* __IMC_SS_H__ */ +#endif // __IMC_SS_H__ \ No newline at end of file diff --git a/include/nvm/nvm.h b/include/nvm/nvm.h old mode 100755 new mode 100644 index 0da96fc..4aaefd4 --- a/include/nvm/nvm.h +++ b/include/nvm/nvm.h @@ -1,123 +1,125 @@ -/* - * tel-plugin-imc - * - * 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 __NVM_H__ -#define __NVM_H__ - -/* Priority level for suspension of all updates */ -#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_ALL 4294967295 /* 0xFFFFFFFF */ - -/* Priority level for suspension of High priority updates */ -#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_HIGH 3221225472 /* 0xFFFFFFFF */ - -/* Priority level for suspension of all updates of dynamic data */ -#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_ALL_DYN 1610612735 /* 0x5FFFFFFF */ - -/* Priority level for suspension of Medium all updates */ -#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_MEDIUM 2147483648 /* 0x5FFFFFFF */ - -/* Priority level for suspension of Low updates of Medium */ -#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_LOW 1073741824 /* 0x5FFFFFFF */ - -/* Priority level for unsuspension of all updates */ -#define UTA_FLASH_PLUGIN_PRIO_UNSUSPEND_ALL 0 /* 0x0 */ - -#define NVM_FUNCTION_ID_OFFSET 20 -#define XDRV_INDICATION 0x04 - -#define XDRV_DISABLE "0" -#define XDRV_ENABLE "1" -#define XDRV_UNSUSPEND "0" - -/* Identifies our group with the xdrv AT command set */ -#define IUFP_GROUP "43" -#define IUFP_GROUP_ID 43 - -#define IUFP_REGISTER 0 -#define IUFP_REGISTER_STR "0" - -#define IUFP_SUSPEND 1 -#define IUFP_SUSPEND_STR "1" - -#define IUFP_FLUSH 2 -#define IUFP_FLUSH_STR "2" - -#define IUFP_UPDATE_REQ 3 -#define IUFP_UPDATE_REQ_STR "3" - -#define IUFP_UPDATE_REQ_ACK 3 -#define IUFP_UPDATE_REQ_ACK_STR "3" - -#define IUFP_UPDATE 4 -#define IUFP_UPDATE_STR "4" - -#define IUFP_UPDATE_ACK 4 -#define IUFP_UPDATE_ACK_STR "4" - -#define IUFP_NO_PENDING_UPDATE 5 -#define IUFP_NO_PENDING_UPDATE_STR "5" - -/* XDRV command was executed without any error */ -#define XDRV_RESULT_OK 0 - -typedef enum uta_common_return_codes { - UTA_SUCCESS = 0, - UTA_FAILURE = -1, - UTA_ERROR_OUT_OF_MEMORY = -2, - UTA_ERROR_INVALID_HANDLE = -3, - UTA_ERROR_OUT_OF_RANGE_PARAM = -4, - UTA_ERROR_INVALID_PARAM = -5, - UTA_ERROR_TOO_SMALL_BUF_PARAM = -6, - UTA_ERROR_NOT_SUPPORTED = -7, - UTA_ERROR_TIMEOUT = -8, - UTA_ERROR_WRONG_STATE = -9, - UTA_ERROR_BAD_FORMAT = -10, - UTA_ERROR_INSUFFICIENT_PERMISSIONS = -11, - UTA_ERROR_IO_ERROR = -12, - UTA_ERROR_OUT_OF_HANDLES = -13, - UTA_ERROR_OPERATION_PENDING = -14, - UTA_ERROR_SPECIFIC = -100 -} nvm_return_codes; - -typedef enum nvm_error_numbers { - NVM_NO_ERR = 0, - NVM_CMD_ERR, - NVM_DATA_ERR, - NVM_MEM_FULL_ERR, - NVM_RES_ERR, - NVM_WRITE_ERR, - NVM_READ_ERR, - NVM_RES_LEN_ERR, - NVM_PCKT_ERR, - NVM_REG_FAIL_ERR, - NVM_DATA_LEN_ERR, - NVM_FILE_ERR, - NVM_AT_PORT_ERR, - NVM_READ_AT_ERR, - NVM_DATA_PORT_ERR, - NVM_NO_PENDING_UPDATE, - NVM_UPDATE, - NVM_REGISTER_ERR, - NVM_UNKNOWN_ERR -} nvm_error; - -int nvm_sum_4_bytes(const char *pos); -gboolean nvm_create_nvm_data(); -nvm_error nvm_process_nv_update(const char *data); - -#endif /* __NVM_H__ */ +/* + * tel-plugin-imc + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Paresh Agarwal + * + * 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 __NVM_H__ +#define __NVM_H__ + +/* Priority level for suspension of all updates */ +#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_ALL 4294967295 /* 0xFFFFFFFF */ + +/* Priority level for suspension of High priority updates */ +#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_HIGH 3221225472 /* 0xFFFFFFFF */ + +/* Priority level for suspension of all updates of dynamic data */ +#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_ALL_DYN 1610612735 /* 0x5FFFFFFF */ + +/* Priority level for suspension of Medium all updates */ +#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_MEDIUM 2147483648 /* 0x5FFFFFFF */ + +/* Priority level for suspension of Low updates of Medium */ +#define UTA_FLASH_PLUGIN_PRIO_SUSPEND_LOW 1073741824 /* 0x5FFFFFFF */ + +/* Priority level for unsuspension of all updates */ +#define UTA_FLASH_PLUGIN_PRIO_UNSUSPEND_ALL 0 /* 0x0 */ + +#define NVM_FUNCTION_ID_OFFSET 20 +#define XDRV_INDICATION 0x04 + +#define XDRV_DISABLE "0" +#define XDRV_ENABLE "1" +#define XDRV_UNSUSPEND "0" + +/* Identifies our group with the xdrv AT command set */ +#define IUFP_GROUP "43" +#define IUFP_GROUP_ID 43 + +#define IUFP_REGISTER 0 +#define IUFP_REGISTER_STR "0" + +#define IUFP_SUSPEND 1 +#define IUFP_SUSPEND_STR "1" + +#define IUFP_FLUSH 2 +#define IUFP_FLUSH_STR "2" + +#define IUFP_UPDATE_REQ 3 +#define IUFP_UPDATE_REQ_STR "3" + +#define IUFP_UPDATE_REQ_ACK 3 +#define IUFP_UPDATE_REQ_ACK_STR "3" + +#define IUFP_UPDATE 4 +#define IUFP_UPDATE_STR "4" + +#define IUFP_UPDATE_ACK 4 +#define IUFP_UPDATE_ACK_STR "4" + +#define IUFP_NO_PENDING_UPDATE 5 +#define IUFP_NO_PENDING_UPDATE_STR "5" + +/* XDRV command was executed without any error */ +#define XDRV_RESULT_OK 0 + +typedef enum uta_common_return_codes { + UTA_SUCCESS = 0, + UTA_FAILURE = -1, + UTA_ERROR_OUT_OF_MEMORY = -2, + UTA_ERROR_INVALID_HANDLE = -3, + UTA_ERROR_OUT_OF_RANGE_PARAM = -4, + UTA_ERROR_INVALID_PARAM = -5, + UTA_ERROR_TOO_SMALL_BUF_PARAM = -6, + UTA_ERROR_NOT_SUPPORTED = -7, + UTA_ERROR_TIMEOUT = -8, + UTA_ERROR_WRONG_STATE = -9, + UTA_ERROR_BAD_FORMAT = -10, + UTA_ERROR_INSUFFICIENT_PERMISSIONS = -11, + UTA_ERROR_IO_ERROR = -12, + UTA_ERROR_OUT_OF_HANDLES = -13, + UTA_ERROR_OPERATION_PENDING = -14, + UTA_ERROR_SPECIFIC = -100 +} nvm_return_codes; + +typedef enum nvm_error_numbers { + NVM_NO_ERR = 0, + NVM_CMD_ERR, + NVM_DATA_ERR, + NVM_MEM_FULL_ERR, + NVM_RES_ERR, + NVM_WRITE_ERR, + NVM_READ_ERR, + NVM_RES_LEN_ERR, + NVM_PCKT_ERR, + NVM_REG_FAIL_ERR, + NVM_DATA_LEN_ERR, + NVM_FILE_ERR, + NVM_AT_PORT_ERR, + NVM_READ_AT_ERR, + NVM_DATA_PORT_ERR, + NVM_NO_PENDING_UPDATE, + NVM_UPDATE, + NVM_REGISTER_ERR, + NVM_UNKNOWN_ERR +} nvm_error; + +int nvm_sum_4_bytes(const char *pos); +gboolean nvm_create_nvm_data(); +nvm_error nvm_process_nv_update(const char *data); + +#endif /* __NVM_H__ */ diff --git a/packaging/tel-plugin-imc.manifest b/packaging/tel-plugin-imc.manifest deleted file mode 100644 index 017d22d..0000000 --- a/packaging/tel-plugin-imc.manifest +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packaging/tel-plugin-imc.spec b/packaging/tel-plugin-imc.spec old mode 100644 new mode 100755 index d91d2fa..bd474ba --- a/packaging/tel-plugin-imc.spec +++ b/packaging/tel-plugin-imc.spec @@ -1,70 +1,63 @@ -#sbs-git:slp/pkgs/t/tel-plugin-imc -%define major 3 -%define minor 0 -%define patchlevel 1 +%define major 0 +%define minor 1 +%define patchlevel 69 -Name: tel-plugin-imc -Summary: imc plugin for telephony -Version: %{major}.%{minor}.%{patchlevel} -Release: 1 -Group: Development/Libraries -License: Apache-2.0 -Source0: tel-plugin-imc-%{version}.tar.gz -Source1001: tel-plugin-imc.manifest -Requires(post): /sbin/ldconfig -Requires(postun):/sbin/ldconfig -BuildRequires: cmake -BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(tcore) -BuildRequires: pkgconfig(tel-headers) -BuildRequires: pkgconfig(db-util) -BuildRequires: pkgconfig(libxml-2.0) -BuildRequires: pkgconfig(libtzplatform-config) -BuildRequires: pkgconfig(vconf) + +Name: tel-plugin-imc +Version: %{major}.%{minor}.%{patchlevel} +Release: 1 +License: Apache-2.0 +Summary: imc-plugin for Telephony +Group: Development/Libraries +Source0: tel-plugin-imc-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(tcore) +BuildRequires: pkgconfig(db-util) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(libxml-2.0) +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig %description IMC plugin for telephony %prep %setup -q -cp %{SOURCE1001} . %build %cmake . -make %{?jobs:-j%jobs} +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 - chsmack -a 'System' %{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 - chsmack -a 'System' %{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 %defattr(-,root,root,-) diff --git a/res/convert_to_sql.c b/res/convert_to_sql.c index 72a3bbf..5b1b1ba 100644 --- a/res/convert_to_sql.c +++ b/res/convert_to_sql.c @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hayoon Ko * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/desc-imc.c b/src/desc-imc.c deleted file mode 100644 index 281f1a3..0000000 --- a/src/desc-imc.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * tel-plugin-imc - * - * 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 -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "imc_modem.h" -#include "imc_sim.h" -#include "imc_sat.h" -#include "imc_sap.h" -#include "imc_network.h" -#include "imc_ps.h" -#include "imc_call.h" -#include "imc_ss.h" -#include "imc_sms.h" -#include "imc_phonebook.h" -#include "imc_gps.h" - -#include "imc_common.h" - -/* Initializer Table */ -TcoreObjectInitializer imc_init_table = { - .modem_init = imc_modem_init, - .sim_init = imc_sim_init, - .sat_init = imc_sat_init, - .sap_init = imc_sap_init, - .network_init = imc_network_init, - .ps_init = imc_ps_init, - .call_init = imc_call_init, - .ss_init = imc_ss_init, - .sms_init = imc_sms_init, - .phonebook_init = imc_phonebook_init, - .gps_init = imc_gps_init, -}; - -/* Deinitializer Table */ -TcoreObjectDeinitializer imc_deinit_table = { - .modem_deinit = imc_modem_exit, - .sim_deinit = imc_sim_exit, - .sat_deinit = imc_sat_exit, - .sap_deinit = imc_sap_exit, - .network_deinit = imc_network_exit, - .ps_deinit = imc_ps_exit, - .call_deinit = imc_call_exit, - .ss_deinit = imc_ss_exit, - .sms_deinit = imc_sms_exit, - .phonebook_deinit = imc_phonebook_exit, - .gps_deinit = imc_gps_exit, -}; - -static void __send_request(CoreObject *co, const gchar *at_cmd, - TcorePendingResponseCallback resp_cb, void *resp_cb_data) -{ - (void)tcore_at_prepare_and_send_request(co, at_cmd, NULL, - TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, - resp_cb, resp_cb_data, - on_send_imc_request, NULL); -} - -static void __on_response_subscribe_bootup_notification(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("Subscription for '%s' - [OK]", (gchar *)user_data); - } else { - err("Subscription for '%s' - [NOK]", (gchar *)user_data); - } - - /* Free resource */ - tcore_free(user_data); -} - -static void __on_response_subscribe_bootup_notification_last(TcorePending *p, - guint data_len, const void *data, void *user_data) -{ - const TcoreAtResponse *at_resp = data; - TcorePlugin *plugin = tcore_pending_ref_plugin(p); - gboolean ret; - - if (at_resp && at_resp->success) { - dbg("[Last] Subscription for '%s' - [OK]", (gchar *)user_data); - } else { - err("[Last] Subscription for '%s' - [NOK]", (gchar *)user_data); - } - - /* Free resource */ - tcore_free(user_data); - - dbg("Boot-up configration completed for IMC modem, " - "Bring CP to ONLINE state based on Flight mode status"); - - /* Modem Power */ - ret = imc_modem_power_on_modem(plugin); - dbg("Modem Power ON: [%s]", (ret == TRUE ? "SUCCESS" : "FAIL")); - - /* NVM Registration */ - dbg("Registering modem for NVM manager"); - imc_modem_register_nvm(tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM)); -} - -static void __subscribe_modem_notifications(TcorePlugin *plugin) -{ - CoreObject *call, *sim, *sms, *network, *ps, *gps; - dbg("Entry"); - - /* - * URC Subscriptions - */ - /****** SIM subscriptions ******/ - sim = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SIM); - /* XSIMSTATE */ - __send_request(sim, "AT+XSIMSTATE=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+XSIMSTATE=1")); - - /****** CALL subscriptions ******/ - call = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL); - /* XCALLSTAT */ - __send_request(call, "AT+XCALLSTAT=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+XCALLSTAT=1")); - - /* CSSN */ - __send_request(call, "AT+CSSN=1,1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CSSN=1,1")); - - /* CUSD */ - __send_request(call, "AT+CUSD=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CUSD=1")); - - /* CLIP */ - __send_request(call, "AT+CLIP=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CLIP=1")); - - /****** NETWORK subscriptions ******/ - network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK); - /* CREG */ - __send_request(network, "AT+CREG=2", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CREG=2")); - - /* CGREG */ - __send_request(network, "AT+CGREG=2", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CGREG=2")); - - /* Allow Automatic Time Zone updation via NITZ */ - __send_request(network, "AT+CTZU=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CTZU=1")); - - /* TZ, Time & Daylight changing event reporting Subscription */ - __send_request(network, "AT+CTZR=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CTZR=1")); - - /* XMER */ - __send_request(network, "AT+XMER=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+XMER=1")); - - /****** PS subscriptions ******/ - ps = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_PS); - /* CGEREP */ - __send_request(ps, "AT+CGEREP=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CGEREP=1")); - - /* XDATASTAT */ - __send_request(ps, "AT+XDATASTAT=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+XDATASTAT=1")); - - /* XDNS */ - __send_request(ps, "AT+XDNS=1,1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+XDNS=1,1")); - - /* CMEE */ - __send_request(ps, "AT+CMEE=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CMEE=1")); - - /****** SMS subscriptions ******/ - sms = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SMS); - - /* Incoming SMS, Cell Broadcast, Status Report Subscription */ - __send_request(sms, "AT+CNMI=1,2,2,1,0", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CNMI=1,2,2,1,0")); - - /* Text/PDU mode Subscription */ - __send_request(sms, "AT+CMGF=0", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CMGF=0")); - -#if 0 /* Temporarily Blocking as modem doesn't support */ - /****** SAP subscriptions ******/ - sap = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SAP); - /* XBCSTAT */ - __send_request(sap, "AT+XBCSTAT=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+XBCSTAT=1")); -#endif /* Temporarily Blocking as modem doesn't support */ - - /****** GPS subscriptions ******/ - gps = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_GPS); - /* AGPS- Assist Data and Reset Assist Data Subscription */ - __send_request(gps, "AT+CPOSR=1", - __on_response_subscribe_bootup_notification, - tcore_strdup("AT+CPOSR=1")); - - __send_request(gps, "AT+XCPOSR=1", - __on_response_subscribe_bootup_notification_last, - tcore_strdup("AT+XCPOSR=1")); - - dbg("Exit"); -} - -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, &imc_init_table) - != TEL_RETURN_SUCCESS) { - err("Failed to initialize Core Objects"); - return FALSE; - } - - /* Subscribe for the Events from CP */ - __subscribe_modem_notifications(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, &imc_deinit_table); -} - -/* IMC - Modem Plug-in Descriptor */ -struct tcore_plugin_define_desc plugin_define_desc = { - .name = "imc", - .priority = TCORE_PLUGIN_PRIORITY_MID, - .version = 1, - .load = on_load, - .init = on_init, - .unload = on_unload -}; diff --git a/src/desc_imc.c b/src/desc_imc.c new file mode 100644 index 0000000..90b57d9 --- /dev/null +++ b/src/desc_imc.c @@ -0,0 +1,294 @@ +/* + * tel-plugin-imc + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hayoon Ko + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "imc_network.h" +#include "imc_modem.h" +#include "imc_sim.h" +#include "imc_sap.h" +#include "imc_ps.h" +#include "imc_call.h" +#include "imc_ss.h" +#include "imc_sms.h" +#include "imc_sat.h" +#include "imc_phonebook.h" +#include "imc_gps.h" + +static void on_confirmation_modem_message_send(TcorePending *p, + gboolean result, + void *user_data) +{ + dbg("msg out from queue"); + + dbg("%s", result == FALSE ? "SEND FAIL" : "SEND OK"); +} + +static void on_response_bootup_subscription(TcorePending *p, + int data_len, const void *data, void *user_data) +{ + const TcoreATResponse *resp = data; + dbg("Entry"); + + if (resp->success > 0) { + dbg("RESULT - OK"); + } else { + err("RESULT - ERROR"); + } +} + +static void on_response_last_bootup_subscription(TcorePending *p, + int data_len, const void *data, void *user_data) +{ + const TcoreATResponse *resp = data; + TcorePlugin *plugin = tcore_pending_ref_plugin(p); + gboolean ret; + dbg("Last Subscription - COMPLETED"); + + if (resp->success) { + dbg("RESULT - OK"); + } else { + err("RESULT - FAIL"); + } + + dbg("Boot-up configration completed for IMC modem. %s", + "Bring CP to ONLINE state based on Flightmode status"); + + /* Modem Power */ + ret = modem_power_on(plugin); + dbg("Modem Power ON: [%s]", (ret == TRUE ? "SUCCESS" : "FAIL")); + + /* NVM Registration */ + dbg("Registering modem for NVM manager"); + modem_register_nvm(tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM)); +} + +static void _modem_subscribe_events(TcorePlugin *plugin) +{ + CoreObject *co_call = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL); + CoreObject *co_sim = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SIM); + CoreObject *co_sms = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SMS); + CoreObject *co_network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK); + CoreObject *co_ps = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_PS); + CoreObject *co_sap = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SAP); + CoreObject *co_gps = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_GPS); + + dbg("Entry"); + + /* URC Subscriptions per Module */ + + /****** SIM subscriptions ******/ + /* XSIMSTATE */ + tcore_prepare_and_send_at_request(co_sim, "at+xsimstate=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /****** CALL subscriptions ******/ + /* XCALLSTAT */ + tcore_prepare_and_send_at_request(co_call, "at+xcallstat=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* CSSN */ + tcore_prepare_and_send_at_request(co_call, "at+cssn=1,1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* CUSD */ + tcore_prepare_and_send_at_request(co_call, "at+cusd=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* CLIP */ + tcore_prepare_and_send_at_request(co_call, "at+clip=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /****** NETWORK subscriptions ******/ + /* CREG */ + tcore_prepare_and_send_at_request(co_network, "at+creg=2", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* CGREG */ + tcore_prepare_and_send_at_request(co_network, "at+cgreg=2", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* Allow Automatic Time Zone updation via NITZ */ + tcore_prepare_and_send_at_request(co_network, "at+ctzu=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* TZ, Time & Daylight changing event reporting Subscription */ + tcore_prepare_and_send_at_request(co_network, "at+ctzr=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* XMER */ + tcore_prepare_and_send_at_request(co_network, "at+xmer=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /****** PS subscriptions ******/ + /* CGEREP */ + tcore_prepare_and_send_at_request(co_ps, "at+cgerep=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* XDATASTAT */ + tcore_prepare_and_send_at_request(co_ps, "at+xdatastat=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + + /* XDNS */ + tcore_prepare_and_send_at_request(co_ps, "at+xdns=1,1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* CMEE */ + tcore_prepare_and_send_at_request(co_ps, "at+cmee=2", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /****** SMS subscriptions ******/ + /* CMEE */ + tcore_prepare_and_send_at_request(co_sms, "at+cmee=2", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* Incoming SMS, Cell Broadcast, Status Report Subscription */ + tcore_prepare_and_send_at_request(co_sms, "at+cnmi=1,2,2,1,0", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /* Text/PDU mode Subscription */ + tcore_prepare_and_send_at_request(co_sms, "at+cmgf=0", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /****** GPS subscriptions ******/ + /* AGPS- Assist Data and Reset Assist Data Subscription */ + tcore_prepare_and_send_at_request(co_gps, "at+cposr=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + tcore_prepare_and_send_at_request(co_gps, "at+xcposr=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + /****** SAP subscriptions ******/ + /* XBCSTAT */ + tcore_prepare_and_send_at_request(co_sap, "at+xbcstat=1", NULL, TCORE_AT_NO_RESULT, NULL, + on_response_last_bootup_subscription, NULL, + on_confirmation_modem_message_send, NULL, 0, NULL, NULL); + + dbg("Exit"); +} + +/* Initializer Table */ +struct object_initializer init_table = { + .modem_init = imc_modem_init, + .sim_init = imc_sim_init, + .sat_init = imc_sat_init, + .sap_init = imc_sap_init, + .network_init = imc_network_init, + .ps_init = imc_ps_init, + .call_init = imc_call_init, + .ss_init = imc_ss_init, + .sms_init = imc_sms_init, + .phonebook_init = imc_phonebook_init, + .gps_init = imc_gps_init, +}; + +/* Deinitializer Table */ +struct object_deinitializer deinit_table = { + .modem_deinit = imc_modem_exit, + .sim_deinit = imc_sim_exit, + .sat_deinit = imc_sat_exit, + .sap_deinit = imc_sap_exit, + .network_deinit = imc_network_exit, + .ps_deinit = imc_ps_exit, + .call_deinit = imc_call_exit, + .ss_deinit = imc_ss_exit, + .sms_deinit = imc_sms_exit, + .phonebook_deinit = imc_phonebook_exit, + .gps_deinit = imc_gps_exit, +}; + +static gboolean on_load() +{ + dbg("Load!!!"); + + return TRUE; +} + +static gboolean on_init(TcorePlugin *p) +{ + dbg("Init!!!"); + if (p == NULL) + return FALSE; + + /* Initialize Modules (Core Objects) */ + if (tcore_object_init_objects(p, &init_table) + != TCORE_RETURN_SUCCESS) { + err("Failed to initialize Core Objects"); + return FALSE; + } + + /* Subscribe for the Events from CP */ + _modem_subscribe_events(p); + + dbg("Init - Successful"); + return TRUE; +} + +static void on_unload(TcorePlugin *p) +{ + dbg("Unload!!!"); + + if (p == NULL) + return; + + /* Deinitialize Modules (Core Objects) */ + tcore_object_deinit_objects(p, &deinit_table); +} + +/* IMC - Modem Plug-in Descriptor */ +struct tcore_plugin_define_desc plugin_define_desc = { + .name = "IMC", + .priority = TCORE_PLUGIN_PRIORITY_MID, + .version = 1, + .load = on_load, + .init = on_init, + .unload = on_unload +}; diff --git a/src/imc_call.c b/src/imc_call.c index 64220d0..99666b1 100644 --- a/src/imc_call.c +++ b/src/imc_call.c @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: sharanayya mathapati * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,2214 +18,3413 @@ * limitations under the License. */ + #include #include #include - #include #include -#include -#include -#include #include +#include +#include #include #include +#include +#include +#include #include #include -#include -#include "imc_call.h" #include "imc_common.h" +#include "imc_call.h" + -#define COMMA 0X2c #define STATUS_INCOMING 4 #define STATUS_WAITING 5 #define STATUS_CONNECTED 7 - -#define find_call_object(co, call_id, call_obj) \ - do { \ - call_obj = tcore_call_object_find_by_id(co, call_id); \ - if (!call_obj) { \ - err("unable to find call object"); \ - return; \ - } \ - } while (0) - -struct imc_set_volume_info { - guint next_index; - guint volume; +#define COMMA 0X2c +#define MAX_CALL_DTMF_DIGITS_LEN 32 + +static gboolean setsoundpath = FALSE; +static gboolean soundvolume = FALSE; + +// End Cause field - Call state end cause + +typedef enum { + CALL_END_NO_CAUSE, + + // These definitions are taken from GSM 04.08 Table 10.86 + + CC_CAUSE_UNASSIGNED_NUMBER, + CC_CAUSE_NO_ROUTE_TO_DEST, + CC_CAUSE_CHANNEL_UNACCEPTABLE, + CC_CAUSE_OPERATOR_DETERMINED_BARRING, + CC_CAUSE_NORMAL_CALL_CLEARING, + CC_CAUSE_USER_BUSY, + CC_CAUSE_NO_USER_RESPONDING, + CC_CAUSE_USER_ALERTING_NO_ANSWER, + CC_CAUSE_CALL_REJECTED, + CC_CAUSE_NUMBER_CHANGED, + CC_CAUSE_NON_SELECTED_USER_CLEARING, + CC_CAUSE_DESTINATION_OUT_OF_ORDER, + CC_CAUSE_INVALID_NUMBER_FORMAT, + CC_CAUSE_FACILITY_REJECTED, + CC_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, + CC_CAUSE_NORMAL_UNSPECIFIED, + CC_CAUSE_NO_CIRCUIT_CHANNEL_AVAILABLE, + CC_CAUSE_NETWORK_OUT_OF_ORDER, + CC_CAUSE_TEMPORARY_FAILURE, + CC_CAUSE_SWITCHING_EQUIPMENT_CONGESTION, + CC_CAUSE_ACCESS_INFORMATION_DISCARDED, + CC_CAUSE_REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE, + CC_CAUSE_RESOURCES_UNAVAILABLE_UNSPECIFIED, + CC_CAUSE_QUALITY_OF_SERVICE_UNAVAILABLE, + CC_CAUSE_REQUESTED_FACILITY_NOT_SUBSCRIBED, + CC_CAUSE_INCOMING_CALL_BARRED_WITHIN_CUG, + CC_CAUSE_BEARER_CAPABILITY_NOT_AUTHORISED, + CC_CAUSE_BEARER_CAPABILITY_NOT_PRESENTLY_AVAILABLE, + CC_CAUSE_SERVICE_OR_OPTION_NOT_AVAILABLE, + CC_CAUSE_BEARER_SERVICE_NOT_IMPLEMENTED, + CC_CAUSE_ACM_GEQ_ACMMAX, + CC_CAUSE_REQUESTED_FACILITY_NOT_IMPLEMENTED, + CC_CAUSE_ONLY_RESTRICTED_DIGITAL_INFO_BC_AVAILABLE, + CC_CAUSE_SERVICE_OR_OPTION_NOT_IMPLEMENTED, + CC_CAUSE_INVALID_TRANSACTION_ID_VALUE, + CC_CAUSE_USER_NOT_MEMBER_OF_CUG, + CC_CAUSE_INCOMPATIBLE_DESTINATION, + CC_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION, + CC_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE, + CC_CAUSE_INVALID_MANDATORY_INFORMATION, + CC_CAUSE_MESSAGE_TYPE_NON_EXISTENT, + CC_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROT_STATE, + CC_CAUSE_IE_NON_EXISTENT_OR_NOT_IMPLEMENTED, + CC_CAUSE_CONDITIONAL_IE_ERROR, + CC_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, + CC_CAUSE_RECOVERY_ON_TIMER_EXPIRY, + CC_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, + CC_CAUSE_INTERWORKING_UNSPECIFIED, + CC_CAUSE_END = 128, + + // Reject causes + REJECT_CAUSE_IMSI_UNKNOWN_IN_HLR, + REJECT_CAUSE_ILLEGAL_MS, + REJECT_CAUSE_IMSI_UNKNOWN_IN_VLR, + REJECT_CAUSE_IMEI_NOT_ACCEPTED, + REJECT_CAUSE_ILLEGAL_ME, + REJECT_CAUSE_GPRS_SERVICES_NOT_ALLOWED, + REJECT_CAUSE_GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED, + REJECT_CAUSE_MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK, + REJECT_CAUSE_IMPLICITLY_DETACHED, + REJECT_CAUSE_PLMN_NOT_ALLOWED, + REJECT_CAUSE_LA_NOT_ALLOWED, + REJECT_CAUSE_NATIONAL_ROAMING_NOT_ALLOWED, + REJECT_CAUSE_GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN, + REJECT_CAUSE_NO_SUITABLE_CELLS_IN_LA, + REJECT_CAUSE_MSC_TEMPORARILY_NOT_REACHABLE, + REJECT_CAUSE_NETWORK_FAILURE, + REJECT_CAUSE_MAC_FAILURE, + REJECT_CAUSE_SYNCH_FAILURE, + REJECT_CAUSE_CONGESTTION, + REJECT_CAUSE_GSM_AUTH_UNACCEPTED, + REJECT_CAUSE_SERVICE_OPTION_NOT_SUPPORTED, + REJECT_CAUSE_REQ_SERV_OPT_NOT_SUBSCRIBED, + REJECT_CAUSE_SERVICE_OPT__OUT_OF_ORDER, + REJECT_CAUSE_CALL_CANNOT_BE_IDENTIFIED, + REJECT_CAUSE_NO_PDP_CONTEXT_ACTIVATED, + REJECT_CAUSE_RETRY_UPON_ENTRY_INTO_A_NEW_CELL_MIN_VALUE, + REJECT_CAUSE_RETRY_UPON_ENTRY_INTO_A_NEW_CELL_MAX_VALUE, + REJECT_CAUSE_SEMANTICALLY_INCORRECT_MSG, + REJECT_CAUSE_INVALID_MANDATORY_INFO, + REJECT_CAUSE_MESSAGE_TYPE_NON_EXISTANT, + REJECT_CAUSE_MESSAGE_TYPE_NOT_COMP_PRT_ST, + REJECT_CAUSE_IE_NON_EXISTANT, + REJECT_CAUSE_MSG_NOT_COMPATIBLE_PROTOCOL_STATE, + + + // Connection Management establishment rejection cause + REJECT_CAUSE_REJ_UNSPECIFIED, + + // AS reject causes + REJECT_CAUSE_AS_REJ_RR_REL_IND, + REJECT_CAUSE_AS_REJ_RR_RANDOM_ACCESS_FAILURE, + REJECT_CAUSE_AS_REJ_RRC_REL_IND, + REJECT_CAUSE_AS_REJ_RRC_CLOSE_SESSION_IND, + REJECT_CAUSE_AS_REJ_RRC_OPEN_SESSION_FAILURE, + REJECT_CAUSE_AS_REJ_LOW_LEVEL_FAIL, + REJECT_CAUSE_AS_REJ_LOW_LEVEL_FAIL_REDIAL_NOT_ALLOWED, + REJECT_CAUSE_AS_REJ_LOW_LEVEL_IMMED_RETRY, + + // MM reject causes + REJECT_CAUSE_MM_REJ_INVALID_SIM, + REJECT_CAUSE_MM_REJ_NO_SERVICE, + REJECT_CAUSE_MM_REJ_TIMER_T3230_EXP, + REJECT_CAUSE_MM_REJ_NO_CELL_AVAILABLE, + REJECT_CAUSE_MM_REJ_WRONG_STATE, + REJECT_CAUSE_MM_REJ_ACCESS_CLASS_BLOCKED, + // Definitions for release ind causes between MM and CNM + REJECT_CAUSE_ABORT_MSG_RECEIVED, + REJECT_CAUSE_OTHER_CAUSE, + + // CNM reject causes + REJECT_CAUSE_CNM_REJ_TIMER_T303_EXP, + REJECT_CAUSE_CNM_REJ_NO_RESOURCES, + REJECT_CAUSE_CNM_MM_REL_PENDING, + REJECT_CAUSE_CNM_INVALID_USER_DATA, + CALL_END_CAUSE_MAX = 255 +} call_end_cause_e_type; + + +struct clcc_call_t { + struct call_CLCC_info { + int id; + enum tcore_call_direction direction; + enum tcore_call_status status; + enum tcore_call_type type; + int mpty; + int num_len; + int num_type; + } + info; + char number[90]; }; -static gchar *xdrv_set_volume[] = { - "AT+XDRV=40,7,3,88", - "AT+XDRV=40,7,0,88", - "AT+XDRV=40,8,0,88", - "AT+XDRV=40,8,2,", - NULL +typedef struct { + int network_cause; + int tapi_cause; +} call_end_cause_info; + +/************************************************************************** + * Local Function Prototypes + **************************************************************************/ +/************************* REQUESTS ***************************/ +static void _call_status_idle(TcorePlugin *p, CallObject *co); +static void _call_status_active(TcorePlugin *p, CallObject *co); +static void _call_status_dialing(TcorePlugin *p, CallObject *co); +static void _call_status_alert(TcorePlugin *p, CallObject *co); +static void _call_status_incoming(TcorePlugin *p, CallObject *co); +static void _call_status_waiting(TcorePlugin *p, CallObject *co); +static TReturn _call_list_get(CoreObject *o, gboolean *event_flag); +/* Todo Need to check whether this api is required */ +//static TReturn _set_dtmf_tone_duration(CoreObject *o, UserRequest *ur); + +/************************* CONFIRMATION ***************************/ +static void on_confirmation_call_message_send(TcorePending *p, gboolean result, void *user_data); // from Kernel +static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data); +static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data); +static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data); +static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data); + +static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type); +static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type); +//static void _on_confirmation_dtmf_tone_duration(TcorePending *p, int data_len, const void *data, void *user_data); +static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data); + +/************************* RESPONSES ***************************/ +static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data); + +/************************* NOTIIFICATIONS ***************************/ +static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data); +static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data); +static void on_notification_call_status(CoreObject *o, const void *data, void *user_data); +static gboolean on_notification_call_info(CoreObject *o, const void *data, void *user_data); +static gboolean on_notification_call_clip_info(CoreObject *o, const void *data, void *user_data); + + +/************************************************************************** + * Local Utility Function Prototypes + **************************************************************************/ +static gboolean _call_request_message(TcorePending *pending, CoreObject *o, UserRequest *ur, void *on_resp, void *user_data); +static void _call_branch_by_status(TcorePlugin *p, CallObject *co, unsigned int status); +static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call); + +/************************************************************************** + * Local Function Definitions + **************************************************************************/ + +const call_end_cause_info call_end_cause_table[] = // call end cause table to convert Netwotk cause to TAPI cause +{ + { 1, CC_CAUSE_UNASSIGNED_NUMBER}, { 3, CC_CAUSE_NO_ROUTE_TO_DEST}, + { 6, CC_CAUSE_CHANNEL_UNACCEPTABLE}, { 8, CC_CAUSE_OPERATOR_DETERMINED_BARRING}, + { 16, CC_CAUSE_NORMAL_CALL_CLEARING}, { 17, CC_CAUSE_USER_BUSY}, + { 18, CC_CAUSE_NO_USER_RESPONDING}, { 19, CC_CAUSE_USER_ALERTING_NO_ANSWER}, + { 21, CC_CAUSE_CALL_REJECTED}, { 22, CC_CAUSE_NUMBER_CHANGED}, + { 26, CC_CAUSE_NON_SELECTED_USER_CLEARING}, { 27, CC_CAUSE_DESTINATION_OUT_OF_ORDER}, + { 28, CC_CAUSE_INVALID_NUMBER_FORMAT}, { 29, CC_CAUSE_FACILITY_REJECTED}, + { 30, CC_CAUSE_RESPONSE_TO_STATUS_ENQUIRY}, { 31, CC_CAUSE_NORMAL_UNSPECIFIED}, + { 34, CC_CAUSE_NO_CIRCUIT_CHANNEL_AVAILABLE}, { 38, CC_CAUSE_NETWORK_OUT_OF_ORDER}, + { 41, CC_CAUSE_TEMPORARY_FAILURE}, { 42, CC_CAUSE_SWITCHING_EQUIPMENT_CONGESTION}, + { 43, CC_CAUSE_ACCESS_INFORMATION_DISCARDED}, { 44, CC_CAUSE_REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE}, + { 47, CC_CAUSE_RESOURCES_UNAVAILABLE_UNSPECIFIED}, { 49, CC_CAUSE_QUALITY_OF_SERVICE_UNAVAILABLE}, + { 50, CC_CAUSE_REQUESTED_FACILITY_NOT_SUBSCRIBED}, { 55, CC_CAUSE_INCOMING_CALL_BARRED_WITHIN_CUG}, + { 57, CC_CAUSE_BEARER_CAPABILITY_NOT_AUTHORISED}, { 58, CC_CAUSE_BEARER_CAPABILITY_NOT_PRESENTLY_AVAILABLE}, + { 63, CC_CAUSE_SERVICE_OR_OPTION_NOT_AVAILABLE}, { 65, CC_CAUSE_BEARER_SERVICE_NOT_IMPLEMENTED}, + { 68, CC_CAUSE_ACM_GEQ_ACMMAX}, { 69, CC_CAUSE_REQUESTED_FACILITY_NOT_IMPLEMENTED}, + { 70, CC_CAUSE_ONLY_RESTRICTED_DIGITAL_INFO_BC_AVAILABLE}, { 79, CC_CAUSE_SERVICE_OR_OPTION_NOT_IMPLEMENTED}, + { 81, CC_CAUSE_INVALID_TRANSACTION_ID_VALUE}, { 87, CC_CAUSE_USER_NOT_MEMBER_OF_CUG}, + { 88, CC_CAUSE_INCOMPATIBLE_DESTINATION}, { 91, CC_CAUSE_INVALID_TRANSIT_NETWORK_SELECTION}, + { 95, CC_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE}, { 96, CC_CAUSE_INVALID_MANDATORY_INFORMATION}, + { 97, CC_CAUSE_MESSAGE_TYPE_NON_EXISTENT}, { 98, CC_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROT_STATE}, + { 99, CC_CAUSE_IE_NON_EXISTENT_OR_NOT_IMPLEMENTED}, { 100, CC_CAUSE_CONDITIONAL_IE_ERROR}, + { 101, CC_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE}, { 102, CC_CAUSE_RECOVERY_ON_TIMER_EXPIRY}, + { 111, CC_CAUSE_PROTOCOL_ERROR_UNSPECIFIED}, {127, CC_CAUSE_INTERWORKING_UNSPECIFIED}, }; -/*Forward Declarations*/ -static void on_response_imc_call_default(TcorePending *p, - guint data_len, const void *data, void *user_data); +static enum tcore_call_status _call_status(unsigned int status) +{ + dbg("Entry"); + + 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; -static TelReturn __call_list_get(CoreObject *co, gboolean flag); + case 5: + return TCORE_CALL_STATUS_WAITING; -static void __on_response_imc_call_end_cause(TcorePending *p, - guint data_len, const void *data, void *user_data); + case 6: // DISCONNECTED state // FALL THROUGH + default: + return TCORE_CALL_STATUS_IDLE; + } +} -static TelCallType __call_type(int type) +static gboolean _call_is_in_mpty(int mpty) { dbg("Entry"); - switch (type) { + switch (mpty) { case 0: - return TEL_CALL_TYPE_VOICE; + return FALSE; case 1: - return TEL_CALL_TYPE_VIDEO; + return TRUE; default: - err("invalid call type, returning default call type as voice"); - return TEL_CALL_TYPE_VOICE; + break; } + + return FALSE; } -static TelCallState __call_state(int state) +static enum tcore_call_type call_type(int type) { dbg("Entry"); - switch (state) { + switch (type) { case 0: - return TEL_CALL_STATE_ACTIVE; + return TCORE_CALL_TYPE_VOICE; case 1: - return TEL_CALL_STATE_HELD; + return TCORE_CALL_TYPE_VIDEO; - case 2: - return TEL_CALL_STATE_DIALING; + default: + break; + } - case 3: - return TEL_CALL_STATE_ALERT; + return TCORE_CALL_TYPE_VOICE; +} - case 4: - case 5: - return TEL_CALL_STATE_INCOMING; +static int _compare_call_end_cause(int networkcause) +{ + unsigned int count; - default: - return TEL_CALL_STATE_IDLE; + for (count = 0; count < sizeof(call_end_cause_table) / sizeof(call_end_cause_info); count++) { + if (call_end_cause_table[count].network_cause == networkcause) + return (call_end_cause_table[count].tapi_cause); } + return CC_CAUSE_NORMAL_CALL_CLEARING; + dbg("Exit"); } -static void __call_branch_by_status(CoreObject *co, CallObject *call_obj, - TelCallState call_state) +static gboolean on_notification_call_clip_info(CoreObject *o, const void *data, void *user_data) { - unsigned int call_id; - TelCallType call_type; - TelCallState state; - TcoreNotification command = TCORE_NOTIFICATION_UNKNOWN; - dbg("Call State[%d]", call_state); + dbg("Entry"); - if (tcore_call_object_get_state(call_obj, &state) == FALSE) { - err("unable to get call status"); - return; - } + // TODO - if (call_state == state) { - dbg("current call state and existing call state are same"); - return; - } + return TRUE; +} - if (tcore_call_object_get_call_type(call_obj, &call_type) == FALSE) { - err("unable to get call type"); - return; - } +static gboolean on_notification_call_info(CoreObject *o, const void *data, void *user_data) +{ + GSList *tokens = NULL; + GSList *lines = NULL; + const char *line = NULL; + char *stat; + int status; - if (tcore_call_object_get_id(call_obj, &call_id) == FALSE) { - err("unable to get call id"); - return; + dbg("Entry"); + + lines = (GSList *) data; + if (1 != g_slist_length(lines)) { + err("Unsolicited message, BUT multiple lines present"); + goto OUT; } - /* Set Status */ - tcore_call_object_set_state(call_obj, call_state); + line = (char *) (lines->data); + tokens = tcore_at_tok_new(line); - 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; + stat = g_slist_nth_data(tokens, 1); + if (!stat) { + dbg("Stat is missing from %XCALLSTAT indiaction"); + } else { + status = atoi(stat); - case TEL_CALL_STATE_HELD: - command = TCORE_NOTIFICATION_CALL_STATUS_HELD; - break; + switch (status) { + case STATUS_INCOMING: + dbg("calling on_notification_call_incoming"); + on_notification_call_incoming(o, line, user_data); + break; - case TEL_CALL_STATE_DIALING: - command = TCORE_NOTIFICATION_CALL_STATUS_DIALING; - break; + case STATUS_WAITING: + dbg("calling on_notification_call_waiting"); + on_notification_call_waiting(o, line, user_data); + break; - case TEL_CALL_STATE_ALERT: - command = TCORE_NOTIFICATION_CALL_STATUS_ALERT; - break; + case STATUS_CONNECTED: /*igonre Connected state. */ + dbg("Connected state"); + break; - case TEL_CALL_STATE_INCOMING: - case TEL_CALL_STATE_WAITING: { - TelCallIncomingInfo incoming = {0,}; - - incoming.call_id = call_id; - tcore_call_object_get_cli_validity(call_obj, &incoming.cli_validity); - tcore_call_object_get_number(call_obj, incoming.number); - tcore_call_object_get_cni_validity(call_obj, &incoming.cni_validity); - tcore_call_object_get_name(call_obj, incoming.name); - tcore_call_object_get_mt_forward(call_obj, &incoming.forward); - tcore_call_object_get_active_line(call_obj, &incoming.active_line); - - /* Send notification */ - tcore_object_send_notification(co, - TCORE_NOTIFICATION_CALL_STATUS_INCOMING, - sizeof(TelCallIncomingInfo), &incoming); - return; + default: + dbg("calling on_notification_call_status"); + on_notification_call_status(o, line, user_data); + break; } + } - case TEL_CALL_STATE_IDLE: { - /* Send AT+CEER command*/ - ImcRespCbData *resp_cb_data = NULL; - TelReturn ret; - - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(NULL, NULL, &call_id, sizeof(call_id)); - - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - "AT+CEER", "+CEER:", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - __on_response_imc_call_end_cause, resp_cb_data, - on_send_imc_request, NULL); - if (ret != TEL_RETURN_SUCCESS) { - warn("Failed to send request"); - TelCallStatusIdleNoti idle; - - idle.call_id = call_id; - idle.cause = TEL_CALL_END_CAUSE_NONE; - - /* Send notification */ - tcore_object_send_notification(co, - TCORE_NOTIFICATION_CALL_STATUS_IDLE, - sizeof(TelCallStatusIdleNoti), &idle); - - imc_destroy_resp_cb_data(resp_cb_data); - } + // Free tokens + tcore_at_tok_free(tokens); - /* Free Call object */ - tcore_call_object_free(co, call_obj); - return; - } - } +OUT: + dbg("Exit"); + return TRUE; +} - } - else if (call_type == TEL_CALL_TYPE_VIDEO) { - /* video call notification */ - switch (call_state) { - case TEL_CALL_STATE_ACTIVE: - command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_ACTIVE; - break; +static gboolean _call_request_message(TcorePending *pending, + CoreObject *o, + UserRequest *ur, + void *on_resp, + void *user_data) +{ + TcoreHal *hal = NULL; + TReturn ret; - case TEL_CALL_STATE_HELD: - err("invalid state"); - break; + dbg("Entry"); - case TEL_CALL_STATE_DIALING: - command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_DIALING; - break; + tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT); - case TEL_CALL_STATE_ALERT: - command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_ALERT; - break; + if (on_resp) { + tcore_pending_set_response_callback(pending, on_resp, user_data); + } + tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL); - case TEL_CALL_STATE_INCOMING: - case TEL_CALL_STATE_WAITING: - command = TCORE_NOTIFICATION_VIDEO_CALL_STATUS_INCOMING; - break; + if (ur) { + tcore_pending_link_user_request(pending, ur); + } else { + err("User Request is NULL, is this internal request??"); + } - case TEL_CALL_STATE_IDLE: { - TelCallStatusIdleNoti idle; + // HAL + hal = tcore_object_get_hal(o); + // Send request to HAL + ret = tcore_hal_send_request(hal, pending); + if (TCORE_RETURN_SUCCESS != ret) { + err("Request send failed"); + return FALSE; + } - idle.call_id = call_id; - idle.cause = TEL_CALL_END_CAUSE_NONE; + dbg("Exit"); + return TRUE; +} - /* Send notification */ - tcore_object_send_notification(co, - TCORE_NOTIFICATION_VIDEO_CALL_STATUS_IDLE, - sizeof(TelCallStatusIdleNoti), &idle); +static void _call_status_idle(TcorePlugin *p, CallObject *co) +{ + CoreObject *core_obj = NULL; + char *cmd_str = NULL; + TcorePending *pending = NULL; + TcoreATRequest *req = NULL; + gboolean ret = FALSE; + UserRequest *ur; - /* Free Call object */ - tcore_call_object_free(co, call_obj); + dbg("Entry"); + core_obj = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL); + dbg("Call ID [%d], Call Status [%d]", tcore_call_object_get_id(co), tcore_call_object_get_status(co)); + + if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_IDLE) { + // get call end cause. + cmd_str = g_strdup_printf("%s", "AT+XCEER"); + dbg("Request command string: %s", cmd_str); + + // Create new Pending request + pending = tcore_pending_new(core_obj, 0); + + // Create new AT-Command request + req = tcore_at_request_new(cmd_str, "+XCEER", TCORE_AT_SINGLELINE); + dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd)); + // Free command string + g_free(cmd_str); + + // Set request data (AT command) to Pending request + tcore_pending_set_request_data(pending, 0, req); + + ur = tcore_user_request_new(NULL, NULL); + // Send request + ret = _call_request_message(pending, core_obj, ur, _on_confirmation_call_end_cause, co); + + if (!ret) { + err("Failed to send AT-Command request"); + // free only UserRequest. + if (ur) { + tcore_user_request_free(ur); + ur = NULL; + } return; } - } } else { - err("Unknown Call type: [%d]", call_type); + err("Call object was not free"); + tcore_call_object_free(core_obj, co); } - - if (command != TCORE_NOTIFICATION_UNKNOWN) - tcore_object_send_notification(co, command, sizeof(call_id), &call_id); + dbg("Exit"); + return; } -static void __handle_call_list_get(CoreObject *co, gboolean flag, void *data) +static void _call_status_dialing(TcorePlugin *p, CallObject *co) { - int call_id; - int direction; - int call_type; - int state; - int mpty; - int ton = -1; - GSList *tokens = NULL; - char *resp = NULL; - char *line; - char *num = NULL; - int num_type; - char number[TEL_CALL_CALLING_NUMBER_LEN_MAX +1] = {0,}; - GSList *lines = data; - CallObject *call_obj = NULL; - - while (lines != NULL) { - line = (char *)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_state(atoi(resp)); - - /* */ - resp = g_slist_nth_data(tokens, 3); - if (NULL == resp) { - err("Invalid call_type"); - continue; - } - call_type = __call_type(atoi(resp)); + struct tnoti_call_status_dialing data; - /* */ - resp = g_slist_nth_data(tokens, 4); - if (NULL == resp) { - err("Invalid mpty"); - continue; - } - mpty = atoi(resp); + dbg("Entry"); - /* */ - 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 num type"); - } else { - num_type = atoi(resp); - /* check 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); - } + if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_DIALING) { + data.type = tcore_call_object_get_type(co); + dbg("data.type : [%d]", data.type); - dbg("Call ID: [%d] Direction: [%s] Call Type: [%d] Multi-party: [%s] " - "Number: [%s] TON: [%d] State: [%d]", - call_id, (direction ? "Outgoing" : "Incoming"), call_type, - (mpty ? "YES" : "NO"), number, ton, state); + data.id = tcore_call_object_get_id(co); + dbg("data.id : [%d]", data.id); - 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 Status + tcore_call_object_set_status(co, TCORE_CALL_STATUS_DIALING); - /* Set Call parameters */ - tcore_call_object_set_type(call_obj, call_type); - tcore_call_object_set_direction(call_obj, direction); - tcore_call_object_set_multiparty_state(call_obj, mpty); - tcore_call_object_set_cli_info(call_obj, TEL_CALL_CLI_VALIDITY_VALID, number); - tcore_call_object_set_active_line(call_obj, TEL_CALL_ACTIVE_LINE1); - if (flag == TRUE) - __call_branch_by_status(co, call_obj, state); - else - tcore_call_object_set_state(call_obj, state); + // Send notification to TAPI + tcore_server_send_notification(tcore_plugin_ref_server(p), + tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL), + TNOTI_CALL_STATUS_DIALING, + sizeof(struct tnoti_call_status_dialing), + (void *) &data); } + + dbg("Exit"); + return; } -/* internal notification operation */ -static void __on_notification_imc_call_incoming(CoreObject *co, unsigned int call_id, - void *user_data) +static void _call_status_alert(TcorePlugin *p, CallObject *co) { - GSList *list = NULL; - CallObject *call_obj = NULL; - dbg("entry"); + struct tnoti_call_status_alert data; - /* 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..."); - g_slist_free(list); - return; - } + dbg("Entry"); - call_obj = tcore_call_object_find_by_id(co, call_id); - if (call_obj != NULL) { - err("Call object for Call ID [%d] already exist! Skip...", call_id); - return; - } + // Alerting has just 1 data 'CALL ID' + if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_ALERT) { + data.type = tcore_call_object_get_type(co); + dbg("data.type : [%d]", data.type); - /* Create new Call object */ - call_obj = tcore_call_object_new(co, (unsigned int)call_id); - if (NULL == call_obj) { - err("Failed to create Call object"); - return; + data.id = tcore_call_object_get_id(co); + dbg("data.id : [%d]", data.id); + + // Set Status + tcore_call_object_set_status(co, TCORE_CALL_STATUS_ALERT); + + // Send notification to TAPI + tcore_server_send_notification(tcore_plugin_ref_server(p), + tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL), + TNOTI_CALL_STATUS_ALERT, + sizeof(struct tnoti_call_status_alert), + (void *) &data); } - /* Make request to get current Call list */ - __call_list_get(co, TRUE); + dbg("Exit"); + return; } -static void __on_notification_imc_call_status(CoreObject *co, unsigned int call_id, - unsigned int call_state, void *user_data) +static void _call_status_active(TcorePlugin *p, CallObject *co) { - CallObject *call_obj = NULL; - TelCallState state; - - state = __call_state(call_state); - dbg("state [%d]", state); + struct tnoti_call_status_active data; - switch (state) { - case TEL_CALL_STATE_ACTIVE: { - find_call_object(co, call_id, call_obj); - /* Send notification to application */ - __call_branch_by_status(co, call_obj, state); - } - break; + dbg("Entry"); - case TEL_CALL_STATE_HELD: { - find_call_object(co, call_id, call_obj); - /* Send notification to application */ - __call_branch_by_status(co, call_obj, state); - } - break; + if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_ACTIVE) { + data.type = tcore_call_object_get_type(co); + dbg("data.type : [%d]", data.type); - 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 - * and send notification to application */ - __call_list_get(co, TRUE); - } - break; + data.id = tcore_call_object_get_id(co); + dbg("data.id : [%d]", data.id); - case TEL_CALL_STATE_ALERT: { - find_call_object(co, call_id, call_obj); - /* Send notification to application */ - __call_branch_by_status(co, call_obj, TEL_CALL_STATE_ALERT); - } - break; + // Set Status + tcore_call_object_set_status(co, TCORE_CALL_STATUS_ACTIVE); - case TEL_CALL_STATE_IDLE: { - find_call_object(co, call_id, call_obj); - /* Send notification to application */ - __call_branch_by_status(co, call_obj, state); + // Send notification to TAPI + tcore_server_send_notification(tcore_plugin_ref_server(p), + tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL), + TNOTI_CALL_STATUS_ACTIVE, + sizeof(struct tnoti_call_status_active), + (void *) &data); } - break; - default: - err("invalid call status"); - break; - } + dbg("Exit"); + return; } -/*internal response operation */ -static void __on_response_imc_call_list_get(TcorePending *p, guint data_len, const void *data, - void *user_data) +static void _call_status_held(TcorePlugin *p, CallObject *co) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - GSList *lines = NULL; - TelCallResult result = TEL_CALL_RESULT_FAILURE; - gboolean *flag = IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data); - int count; - dbg("entry"); + struct tnoti_call_status_held data; - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + dbg("Entry"); - if (at_resp && at_resp->success) { - if (NULL == at_resp->lines) { - err("invalid response received"); - return; - } + if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_HELD) { + data.type = tcore_call_object_get_type(co); + dbg("data.type : [%d]", data.type); - lines = (GSList *) at_resp->lines; - count = g_slist_length(lines); - dbg("Total records : %d", count); - if (0 == count) { - err("Call count is zero"); - return; - } - result = TEL_CALL_RESULT_SUCCESS; - dbg("RESPONSE OK"); + data.id = tcore_call_object_get_id(co); + dbg("data.id : [%d]", data.id); - /* parse +CLCC notification parameter */ - __handle_call_list_get(co, *flag, lines); + // Set Status + tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD); - } else { - err("RESPONSE NOK"); + // Send notification to TAPI + tcore_server_send_notification(tcore_plugin_ref_server(p), + tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL), + TNOTI_CALL_STATUS_HELD, + sizeof(struct tnoti_call_status_held), + (void *) &data); } + + dbg("Exit"); + return; } -/*internal request operation */ -static TelReturn __send_call_request(CoreObject *co, TcoreObjectResponseCallback cb, - void *cb_data, gchar *at_cmd, gchar *func_name) +static void _call_status_incoming(TcorePlugin *p, CallObject *co) { - ImcRespCbData *resp_cb_data; - TelReturn ret; + struct tnoti_call_status_incoming data; - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, func_name, - strlen(func_name) + 1); + dbg("Entry"); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - at_cmd, NULL, - TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, - on_response_imc_call_default, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, func_name); + if (tcore_call_object_get_status(co) != TCORE_CALL_STATUS_INCOMING) { + tcore_call_object_set_status(co, TCORE_CALL_STATUS_INCOMING); - /* Free resources */ - g_free(at_cmd); - return ret; -} + data.type = tcore_call_object_get_type(co); + dbg("data.type : [%d]", data.type); - /* - * Operation - Get current call list. - * - * Request - - * AT-Command: AT+CLCC - * - * Response - - * Success: - *[+CLCC: , , , ,[,,[,[,]]] - * - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn __call_list_get(CoreObject *co, gboolean flag) -{ - ImcRespCbData *resp_cb_data; - TelReturn ret = TEL_RETURN_FAILURE; - dbg("Entry"); + data.id = tcore_call_object_get_id(co); + dbg("data.id : [%d]", data.id); - if (NULL == co) { - err("Core Object is NULL"); - return ret; - } + data.cli.mode = tcore_call_object_get_cli_mode(co); + dbg("data.cli.mode : [%d]", data.cli.mode); - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(NULL, NULL, &flag, sizeof(gboolean)); + tcore_call_object_get_number(co, data.cli.number); + dbg("data.cli.number : [%s]", data.cli.number); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - "AT+CLCC","+CLCC", - TCORE_AT_COMMAND_TYPE_MULTILINE, - NULL, - __on_response_imc_call_list_get, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get current call list"); + data.cna.mode = tcore_call_object_get_cna_mode(co); + dbg("data.cna.mode : [%d]", data.cna.mode); - return ret; -} + tcore_call_object_get_name(co, data.cna.name); + dbg("data.cna.name : [%s]", data.cna.name); -static TelCallResult __convert_imc_extended_err_tel_call_result(gint error) -{ - /* - * CEER error codes - * 1 - unassigned (unallocated) number. - * 28 - invalid number format (incomplete number). - * 96 - invalid mandatory information. - * 258 - Invalid parameters. - * 371 - Invalid mandatory info. - * 257 - Out of memory. - * 279 - FDN Failed. - * 42 - switching equipment congestion - * 287 - MM network failure unspecified. - * 380 - Congestion. - */ - dbg("CEER Error: [%d]", error); - - switch (error) { - case 1: - case 28: - case 96: - case 258: - case 371: - return TEL_CALL_RESULT_INVALID_PARAMETER; - case 257: - return TEL_CALL_RESULT_MEMORY_FAILURE; - case 279: - return TEL_CALL_RESULT_FDN_RESTRICTED; - case 42: - case 287: - case 380: - return TEL_CALL_RESULT_NETWORK_BUSY; - default: - return TEL_CALL_RESULT_FAILURE; - } -} - -static TelCallEndCause __convert_imc_extended_err_call_end_cause(gint error) -{ - /* - * CEER error codes - * 1 - unassigned (unallocated) number. - * 3 - No route to destination. - * 16 - operator determined barring. - * 17 - user busy. - * 18 - no user responding. - * 19 - user alerting, no answer. - * 21 - call rejected. - * 22 - number changed - * 27 - destination out of order. - * 28 - invalid number format (incomplete number). - * 29 - facility rejected - * 34 - no circuit / channel available. - * 38 - network out of order - * 41 - temporary failure - * 44 - requested circuit / channel not available. - * 50 - requested facility not subscribed - * 68 - ACM equal to or greater than ACMmax - */ - dbg("Call end-cause: [%d]", error); - switch (error) { - case 1: - return TEL_CALL_END_CAUSE_UNASSIGNED_NUMBER; - case 3: - return TEL_CALL_END_CAUSE_NO_ROUTE_TO_DEST; - case 8: - return TEL_CALL_END_CAUSE_OPERATOR_DETERMINED_BARRING; - case 16: - return TEL_CALL_END_CAUSE_NORMAL_CALL_CLEARING; - case 17: - return TEL_CALL_END_CAUSE_USER_BUSY; - case 18: - return TEL_CALL_END_CAUSE_NO_USER_RESPONDING; - case 19: - return TEL_CALL_END_CAUSE_USER_ALERTING_NO_ANSWER; - case 21: - return TEL_CALL_END_CAUSE_CALL_REJECTED; - case 22: - return TEL_CALL_END_CAUSE_NUMBER_CHANGED; - case 27: - return TEL_CALL_END_CAUSE_DESTINATION_OUT_OF_ORDER; - case 28: - return TEL_CALL_END_CAUSE_INVALID_NUMBER_FORMAT; - case 29: - return TEL_CALL_END_CAUSE_FACILITY_REJECTED; - case 34: - return TEL_CALL_END_CAUSE_NO_CIRCUIT_CHANNEL_AVAILABLE; - case 38: - return TEL_CALL_END_CAUSE_NETWORK_OUT_OF_ORDER; - case 41: - return TEL_CALL_END_CAUSE_TEMPORARY_FAILURE; - case 42: - return TEL_CALL_END_CAUSE_SWITCHING_EQUIPMENT_CONGESTION; - case 44: - return TEL_CALL_END_CAUSE_REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE; - case 50: - return TEL_CALL_END_CAUSE_REQUESTED_FACILITY_NOT_SUBSCRIBED; - case 68: - return TEL_CALL_END_CAUSE_ACM_GEQ_ACMMAX; - case 63: - case 79: - return TEL_CALL_END_CAUSE_SERVICE_OPTION_OUT_OF_ORDER; - default: - return TEL_CALL_END_CAUSE_FAILED; + data.forward = FALSE; // this is tmp code + + data.active_line = tcore_call_object_get_active_line(co); + dbg("data.active_line : [%d]", data.active_line); + + // Send notification to TAPI + tcore_server_send_notification(tcore_plugin_ref_server(p), + tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_CALL), + TNOTI_CALL_STATUS_INCOMING, + sizeof(struct tnoti_call_status_incoming), + (void *) &data); } + + dbg("Exit"); + return; } -static TelCallResult __convert_imc_xdrv_result_tel_call_result(gint xdrv_err) +static void _call_status_waiting(TcorePlugin *p, CallObject *co) { - /* - * 0 - Command was executed without any error. - * 1 - One of the parameters is out of range. - * 2 - The function doesn’t exist for this driver. - * 3 - The group is not supported. - * 4 - The internal state of the driver is not allowing to process the command. - * 5 - The driver interface function for the command is not available. - * 6 - The corresponding driver for the command retuns an error. - * 7 - Timeout occured when expecting response from the corresponding driver. - * 8 - The driver is not supported for this product. - * 12 - No of parameteres passed for the command is mismatch with the rquirements. - * 13 - The given command to xdrv is invalid. - * 14 - Any internal error in xdrv like out of memory. - */ + dbg("Entry"); + _call_status_incoming(p, co); - dbg("XDRV result: [%d]", xdrv_err); - switch (xdrv_err) { - case 1: - case 12: - case 13: - return TEL_CALL_RESULT_INVALID_PARAMETER; - case 14: - return TEL_CALL_RESULT_MEMORY_FAILURE; - default: - return TEL_CALL_RESULT_OPERATION_NOT_SUPPORTED; - } + dbg("Exit"); + return; } -/* Notification */ - -/* - * Operation - call status notification from network. - * notification message format: - * +XCALLSTAT: - * where - * - * indicates the call identification (GSM02.30 4.5.5.1) - * - * 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 disconnected - * 7 connected (indicates the completion of a call setup first time - * for MT and MO calls this is reported in addition to state active) - */ -static gboolean on_notification_imc_call_status(CoreObject *co, const void *data, - void *user_data) +static void _call_branch_by_status(TcorePlugin *p, CallObject *co, unsigned int status) { - GSList *tokens = NULL; - GSList *lines = NULL; - const char *line = NULL; - char *state = NULL, *call_handle = NULL; - unsigned int status, call_id; - dbg("Entry"); - lines = (GSList *) data; - if (lines == NULL) { - err("Invalid response received"); - return TRUE; - } - line = (char *) (lines->data); - tokens = tcore_at_tok_new(line); + dbg("Call Status is %d", status); + switch (status) { + case TCORE_CALL_STATUS_IDLE: + _call_status_idle(p, co); + break; - call_handle = g_slist_nth_data(tokens, 0); - if (NULL == call_handle) { - err("call id missing from %XCALLSTAT indication"); - goto OUT; - } - call_id = atoi(call_handle); - state = g_slist_nth_data(tokens, 1); - if (NULL == state) { - err("call state is missing from %XCALLSTAT indication"); - goto OUT; - } - status = atoi(state); - dbg("call id[%d], status[%d]", call_id, status); + case TCORE_CALL_STATUS_ACTIVE: + _call_status_active(p, co); + break; - switch (status) { - case STATUS_INCOMING: - case STATUS_WAITING: - __on_notification_imc_call_incoming(co, call_id, user_data); + case TCORE_CALL_STATUS_HELD: + _call_status_held(p, co); break; - case STATUS_CONNECTED: /* ignore Connected state. */ - dbg("ignore connected state"); + case TCORE_CALL_STATUS_DIALING: + _call_status_dialing(p, co); break; - default: - __on_notification_imc_call_status(co, call_id, status, user_data); + case TCORE_CALL_STATUS_ALERT: + _call_status_alert(p, co); + break; + + case TCORE_CALL_STATUS_INCOMING: + _call_status_incoming(p, co); + break; + + case TCORE_CALL_STATUS_WAITING: + _call_status_waiting(p, co); break; } -OUT: - // Free tokens - tcore_at_tok_free(tokens); - return TRUE; + + dbg("Exit"); + return; } -/* - * Operation - SS network initiated notification. - * - * notification message format: - * +CSSU: [ [,,]] - * - * (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 ( 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 - * - * refer Closed user group +CCUG - * - * string type phone of format specified by - * - * type of address octet in integer format. - */ -static gboolean on_notification_imc_call_ss_cssu_info(CoreObject *co, const void *event_data, - void *user_data) +static TReturn _call_list_get(CoreObject *o, gboolean *event_flag) { - GSList *tokens = NULL; - TcoreNotification command = TCORE_NOTIFICATION_UNKNOWN; - char *resp = NULL; - char *cmd = 0; - int index = 0; - int code2 = -1; - char *number = NULL; + UserRequest *ur = NULL; + TcorePending *pending = NULL; + char *cmd_str = NULL; + TcoreATRequest *req = NULL; + gboolean ret = FALSE; - dbg("entry"); - - if (1 != g_slist_length((GSList *) event_data)) { - err("unsolicited msg but multiple line"); - return TRUE; + dbg("Entry"); + if (!o) { + err("Core Object is NULL"); + return TCORE_RETURN_FAILURE; } - cmd = (char *) ((GSList *) event_data)->data; - dbg("ss notification message[%s]", cmd); + // Create new User Request + ur = tcore_user_request_new(NULL, NULL); - tokens = tcore_at_tok_new(cmd); + // Command string + cmd_str = g_strdup("AT+CLCC"); - /* parse */ - resp = g_slist_nth_data(tokens, 0); - if (NULL == resp) { - err("Code2 is missing from +CSSU indication"); - tcore_at_tok_free(tokens); - return TRUE; - } + // Create new Pending Request + pending = tcore_pending_new(o, 0); + req = tcore_at_request_new(cmd_str, "+CLCC", TCORE_AT_MULTILINE); - code2 = atoi(resp); + g_free(cmd_str); - /* parse [ , ] */ - if ((resp = g_slist_nth_data(tokens, 1))) - index = atoi(resp); + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); - if ((resp = g_slist_nth_data(tokens, 2))) { - /* Strike off double quotes */ - number = tcore_at_tok_extract(resp); - } + tcore_pending_set_request_data(pending, 0, req); - dbg("+CSSU: = %d = %d = %s ", code2, index, number); + ret = _call_request_message(pending, o, ur, on_response_call_list_get, event_flag); + if (!ret) { + err("AT request (%s) sending failed", req->cmd); + // free only UserRequest. + if (ur) { + tcore_user_request_free(ur); + ur = NULL; + } + return TCORE_RETURN_FAILURE; + } + + dbg("AT request sent success"); + return TCORE_RETURN_SUCCESS; +} + +// CONFIRMATION +static void on_confirmation_call_message_send(TcorePending *p, gboolean result, void *user_data) +{ + dbg("Entry"); + + if (result == FALSE) { // Fail + dbg("SEND FAIL"); + } else { + dbg("SEND OK"); + } + + dbg("Exit"); + return; +} + +static void call_prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback) +{ + TcoreATRequest *req = NULL; + TcoreHal *hal = NULL; + TcorePending *pending = NULL; + TReturn ret; + + hal = tcore_object_get_hal(co); + dbg("hal: %p", hal); + + pending = tcore_pending_new(co, 0); + if (!pending) + dbg("Pending is NULL"); + req = tcore_at_request_new(at_cmd, prefix, at_cmd_type); + + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); + + tcore_pending_set_request_data(pending, 0, req); + tcore_pending_set_response_callback(pending, callback, NULL); + tcore_pending_set_send_callback(pending, on_confirmation_call_message_send, NULL); + ret = tcore_hal_send_request(hal, pending); + if (ret != TCORE_RETURN_SUCCESS) + err("Failed to process request"); +} + +static void on_confirmation_call_outgoing(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = data; + struct tresp_call_dial resp; + enum telephony_call_error error; + dbg("Entry"); + + ur = tcore_pending_ref_user_request(p); + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + resp.err = CALL_ERROR_NONE; + } else { + dbg("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("Unspecified error cause OR string corrupted"); + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + err("Error: [%d]", error); + // TODO: CMEE error mapping is required. + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + // Send Response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_DIAL, sizeof(struct tresp_call_dial), &resp); + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +static void on_confirmation_call_accept(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = data; + struct tresp_call_answer resp; + enum telephony_call_error error; + dbg("Entry"); + + ur = tcore_pending_ref_user_request(p); + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + resp.err = CALL_ERROR_NONE; + } else { + dbg("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("Unspecified error cause OR string corrupted"); + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + err("Error: [%d]", error); + // TODO: CMEE error mapping is required. + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + resp.id = tcore_call_object_get_id((CallObject *) user_data); + + // Send Response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp); + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + + +static void on_confirmation_call_reject(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = data; + struct tresp_call_answer resp; + enum telephony_call_error error; + + dbg("Entry"); + + ur = tcore_pending_ref_user_request(p); + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + resp.err = CALL_ERROR_NONE; + } else { + dbg("RESPONSE NOT OK"); + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("Unspecified error cause OR string corrupted"); + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + err("Error: [%d]", error); + // TODO: CMEE error mapping is required. + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + resp.id = tcore_call_object_get_id((CallObject *) user_data); + + // Send Response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp); + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +static void on_confirmation_call_replace(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = data; + struct tresp_call_answer resp; + enum telephony_call_error error; + + dbg("Entry"); + ur = tcore_pending_ref_user_request(p); + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + resp.err = CALL_ERROR_NONE; + } else { + dbg("RESPONSE NOT OK"); + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("Unspecified error cause OR string corrupted"); + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + err("Error: [%d]", error); + // TODO: CMEE error mapping is required. + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + resp.id = tcore_call_object_get_id((CallObject *) user_data); + + // Send Response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp); + } else { + dbg("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +static void on_confirmation_call_hold_and_accept(TcorePending *p, int data_len, const void *data, void *user_data) +{ + CoreObject *o = NULL; + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = data; + struct tresp_call_answer resp; + enum telephony_call_error error; + + dbg("Entry"); + + o = tcore_pending_ref_core_object(p); + ur = tcore_pending_ref_user_request(p); + resp.id = tcore_call_object_get_id((CallObject *) user_data); + + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + resp.err = CALL_ERROR_NONE; + } else { + err("RESPONSE NOT OK"); + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("Unspecified error cause OR string corrupted"); + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + err("Error: [%d]", error); + // TODO: CMEE error mapping is required. + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + // Send response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_ANSWER, sizeof(struct tresp_call_answer), &resp); + if (!resp.err) { + GSList *list = 0; + CallObject *co = NULL; + + // Active Call + list = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_ACTIVE); + if (!list) { + err("Can't find active Call"); + return; + } + + co = (CallObject *) list->data; + if (!co) { + err("Can't get active Call object"); + return; + } + + // Set Call Status + tcore_call_object_set_status(co, TCORE_CALL_STATUS_HELD); + dbg("Call status is set to HELD"); + } + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +static void _on_confirmation_call_release(TcorePending *p, int data_len, const void *data, void *user_data, int type) +{ + UserRequest *ur = NULL; + struct tresp_call_end resp; + GSList *tokens = NULL; + const char *line = NULL; + enum telephony_call_error error; + const TcoreATResponse *response = data; + + dbg("Entry"); + ur = tcore_pending_ref_user_request(p); + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + resp.err = CALL_ERROR_NONE; + } else { + err("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("Unspecified error cause OR string corrupted"); + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + err("Error: [%d]", error); + // TODO: CMEE error mapping is required. + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } + tcore_at_tok_free(tokens); + } + + resp.type = type; + resp.id = tcore_call_object_get_id((CallObject *) user_data); + dbg("resp.type = %d resp.id= %d", resp.type, resp.id); + + // Send reponse to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp); + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +// RESPONSE +static void on_confirmation_call_endall(TcorePending *p, int data_len, const void *data, void *user_data) +{ + // skip response handling - actual result will be handled in on_confirmation_call_release_all + const TcoreATResponse *response = data; + + dbg("Entry"); + + if (response->success > 0) { + dbg("RESPONSE OK"); + } else { + err("RESPONSE NOT OK"); + } + + dbg("Exit"); + return; +} + + +static void on_confirmation_call_release_all(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ALL); + + return; +} + + +static void on_confirmation_call_release_specific(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_DEFAULT); + + return; +} + +static void on_confirmation_call_release_all_active(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_ACTIVE_ALL); + + return; +} + +static void on_confirmation_call_release_all_held(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call_release(p, data_len, data, user_data, CALL_END_TYPE_HOLD_ALL); + + return; +} + +static void _on_confirmation_call(TcorePending *p, int data_len, const void *data, void *user_data, int type) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = NULL; + enum telephony_call_error error; + + dbg("Entry"); + ur = tcore_pending_ref_user_request(p); + response = (TcoreATResponse *) data; + if (response->success > 0) { + dbg("RESPONSE OK"); + error = CALL_ERROR_NONE; + } else { + err("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("Unspecified error cause OR string corrupted"); + error = CALL_ERROR_SERVICE_UNAVAIL; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + + // TODO: CMEE error mapping is required. + error = CALL_ERROR_SERVICE_UNAVAIL; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + dbg("Response Call type -%d", type); + switch (type) { + case TRESP_CALL_HOLD: + { + struct tresp_call_hold resp; + + resp.err = error; + resp.id = tcore_call_object_get_id((CallObject *) user_data); + dbg("call hold response"); + // Send reponse to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp); + } + break; + + case TRESP_CALL_ACTIVE: + { + struct tresp_call_active resp; + + resp.err = error; + resp.id = tcore_call_object_get_id((CallObject *) user_data); + dbg("call active response"); + // Send reponse to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp); + } + break; + + case TRESP_CALL_JOIN: + { + struct tresp_call_join resp; + + resp.err = error; + resp.id = tcore_call_object_get_id((CallObject *) user_data); + dbg("call join response"); + + // Send reponse to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_JOIN, sizeof(struct tresp_call_join), &resp); + } + break; + + case TRESP_CALL_SPLIT: + { + struct tresp_call_split resp; + + resp.err = error; + resp.id = tcore_call_object_get_id((CallObject *) user_data); + dbg("call split response"); + // Send reponse to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_SPLIT, sizeof(struct tresp_call_split), &resp); + } + break; + + case TRESP_CALL_DEFLECT: + { + struct tresp_call_deflect resp; + + resp.err = error; + resp.id = tcore_call_object_get_id((CallObject *) user_data); + dbg("call deflect response"); + // Send reponse to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_DEFLECT, sizeof(struct tresp_call_deflect), &resp); + } + + break; + + case TRESP_CALL_TRANSFER: + { + struct tresp_call_transfer resp; + + resp.err = error; + resp.id = tcore_call_object_get_id((CallObject *) user_data); + dbg("call transfer response"); + // Send reponse to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_TRANSFER, sizeof(struct tresp_call_transfer), &resp); + } + break; + + case TRESP_CALL_START_CONT_DTMF: + { + struct tresp_call_dtmf resp; + + resp.err = error; + dbg("call dtmf response"); + // Send reponse to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_START_CONT_DTMF, sizeof(struct tresp_call_dtmf), &resp); + } + break; + + default: + { + dbg("type not supported"); + return; + } + } + + if ((type == TRESP_CALL_HOLD) || (type == TRESP_CALL_ACTIVE) || (type == TRESP_CALL_JOIN) + || (type == TRESP_CALL_SPLIT)) { + if (!error) { + CoreObject *core_obj = NULL; + gboolean *eflag = g_new0(gboolean, 1); + + core_obj = tcore_pending_ref_core_object(p); + *eflag = FALSE; + + dbg("Calling _call_list_get"); + _call_list_get(core_obj, eflag); + } + } + + dbg("Exit"); + return; +} + +static void on_confirmation_call_hold(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_HOLD); + + return; +} + +static void on_confirmation_call_active(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_ACTIVE); + + return; +} + +static void on_confirmation_call_join(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_JOIN); + + return; +} + +static void on_confirmation_call_split(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_SPLIT); + + return; +} + +static void on_confirmation_call_deflect(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_DEFLECT); + + return; +} + +static void on_confirmation_call_transfer(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_TRANSFER); + + return; +} + +static void on_confirmation_call_dtmf(TcorePending *p, int data_len, const void *data, void *user_data) +{ + dbg("Entry"); + _on_confirmation_call(p, data_len, data, user_data, TRESP_CALL_START_CONT_DTMF); + + return; +} + +#if 0 +static void _on_confirmation_dtmf_tone_duration(TcorePending *p, int data_len, const void *data, void *user_data) +{ + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = data; + enum telephony_call_error error; + + dbg("Entry"); + + if (response->success > 0) { + dbg("RESPONSE OK"); + error = CALL_ERROR_NONE; + } else { + err("RESPONSE NOT OK"); + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + err("err cause not specified or string corrupted"); + error = CALL_ERROR_SERVICE_UNAVAIL; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + // TODO: CMEE error mapping is required. + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + dbg("Set dtmf tone duration response - %d", error); + return; +} +#endif + +static void on_confirmation_call_swap(TcorePending *p, int data_len, const void *data, void *user_data) +{ + CoreObject *core_obj = NULL; + UserRequest *ur = NULL; + const TcoreATResponse *response = data; + struct tresp_call_swap resp; + GSList *tokens = NULL; + const char *line = NULL; + + dbg("Entry"); + core_obj = tcore_pending_ref_core_object(p); + ur = tcore_pending_ref_user_request(p); + + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + resp.err = CALL_ERROR_NONE; + } else { + err("RESPONSE NOT OK"); + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + err("err cause not specified or string corrupted"); + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } else { + resp.err = atoi(g_slist_nth_data(tokens, 0)); + + // TODO: CMEE error mapping is required. + resp.err = CALL_ERROR_SERVICE_UNAVAIL; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + resp.id = tcore_call_object_get_id((CallObject *) user_data); + dbg("resp.id = %d", resp.id); + + // Send response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_SWAP, sizeof(struct tresp_call_swap), &resp); + + if (!resp.err) { + GSList *active = NULL; + GSList *held = NULL; + CallObject *co = NULL; + gboolean *eflag = NULL; + + held = tcore_call_object_find_by_status(core_obj, TCORE_CALL_STATUS_HELD); + if (!held) { + err("Can't find held Call"); + return; + } + + active = tcore_call_object_find_by_status(core_obj, TCORE_CALL_STATUS_ACTIVE); + if (!active) { + dbg("Can't find active Call"); + return; + } + + while (held) { + co = (CallObject *) held->data; + if (!co) { + err("Can't get held Call object"); + return; + } + + resp.id = tcore_call_object_get_id(co); + + // Send response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_ACTIVE, sizeof(struct tresp_call_active), &resp); + + held = g_slist_next(held); + } + + while (active) { + co = (CallObject *) active->data; + if (!co) { + err("[ error ] can't get active call object"); + return; + } + + resp.id = tcore_call_object_get_id(co); + + // Send response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_HOLD, sizeof(struct tresp_call_hold), &resp); + active = g_slist_next(active); + } + + eflag = g_new0(gboolean, 1); + *eflag = FALSE; + + dbg("calling _call_list_get"); + _call_list_get(core_obj, eflag); + } + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +static void on_confirmation_set_sound_path(TcorePending *p, int data_len, + const void *data, + void *user_data) +{ + const TcoreATResponse *resp = data; + struct tnoti_call_sound_path *snd_path = user_data; + struct tresp_call_set_sound_path resp_set_sound_path; + UserRequest *ur = tcore_pending_ref_user_request(p); + TcorePlugin *plugin = tcore_pending_ref_plugin(p); + CoreObject *co_call; + + if (ur == NULL) { + err("User Request is NULL"); + g_free(user_data); + return; + } + + if (resp->success <= 0) { + + dbg("RESPONSE NOT OK"); + resp_set_sound_path.err = TRUE; + + goto out; + } + + dbg("RESPONSE OK"); + resp_set_sound_path.err = FALSE; + + co_call = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL); + + /* Notify control plugin about sound path */ + tcore_server_send_notification(tcore_plugin_ref_server(plugin), + co_call, TNOTI_CALL_SOUND_PATH, + sizeof(struct tnoti_call_sound_path), + snd_path); + +out: + /* Answer TAPI request */ + tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, + sizeof(resp_set_sound_path), + &resp_set_sound_path); + + g_free(user_data); +} + +static void on_confirmation_call_set_source_sound_path(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = data; + char *resp_str = NULL; + struct tresp_call_set_sound_path resp; + gboolean error; + + dbg("Entry"); + ur = tcore_pending_ref_user_request(p); + + // +XDRV: ,,[,] + if (!response) { + err("Input data is NULL"); + return; + } + + if (response->success > 0) { + dbg("RESPONSE OK"); + + line = (const char *) (((GSList *) response->lines)->data); + tokens = tcore_at_tok_new(line); + + resp_str = g_slist_nth_data(tokens, 0); + if (!g_slist_nth_data(tokens, 0)) { + err("group_id is missing"); + resp.err = TRUE; + goto OUT; + } + + if (!g_slist_nth_data(tokens, 1)) { + err(" function_id is missing"); + resp.err = TRUE; + goto OUT; + } + + resp_str = g_slist_nth_data(tokens, 2); + + if (resp_str) { + error = atoi(resp_str); + if (0 == error) { + dbg("Response is Success"); + resp.err = FALSE; + } else { + resp.err = TRUE; + } + } +OUT: + // Free tokens + tcore_at_tok_free(tokens); + } else { + dbg("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("err cause not specified or string corrupted"); + resp.err = TRUE; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + + // TODO: CMEE error mapping is required. + resp.err = TRUE; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + if (ur) { + if ( resp.err ) { // Send only failed notification . success notification send when destination device is set. + // Send notification to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_set_sound_path), &resp); + setsoundpath = TRUE; + } + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +static void on_confirmation_call_set_destination_sound_path(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + char *resp_str = NULL; + struct tresp_call_set_sound_path resp; + const TcoreATResponse *response = data; + gboolean error; + + dbg("Entry"); + + ur = tcore_pending_ref_user_request(p); + // +XDRV: ,,[,] + + if (!response) { + err("Input data is NULL"); + return; + } + + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + + line = (const char *) (((GSList *) response->lines)->data); + tokens = tcore_at_tok_new(line); + + resp_str = g_slist_nth_data(tokens, 0); + if (!g_slist_nth_data(tokens, 0)) { + dbg("group_id is missing"); + resp.err = TRUE; + goto OUT; + } + + if (!g_slist_nth_data(tokens, 1)) { + dbg("function_id is missing"); + resp.err = TRUE; + goto OUT; + } + + resp_str = g_slist_nth_data(tokens, 2); + if (resp_str) { + error = atoi(resp_str); + if (0 == error) { + dbg("Response is Success"); + resp.err = FALSE; + } else { + resp.err = TRUE; + } + } + +OUT: + // Free tokens + tcore_at_tok_free(tokens); + } else { + dbg("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("err cause not specified or string corrupted"); + resp.err = TRUE; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + // TODO: CMEE error mapping is required. + resp.err = TRUE; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + if (setsoundpath == TRUE) { + setsoundpath = FALSE; + } else { + // Send response to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_PATH, sizeof(struct tresp_call_set_sound_path), &resp); + } + } else { + dbg("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +static void on_confirmation_call_set_source_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + const TcoreATResponse *response = data; + char *resp_str = NULL; + struct tresp_call_set_sound_volume_level resp; + gboolean error; + + ur = tcore_pending_ref_user_request(p); + dbg("Entry"); + // +XDRV: ,,[,] + if (!response) { + err("Input data is NULL"); + return; + } + + if (response->success > 0) { + dbg("RESPONSE OK"); + + line = (const char *) (((GSList *) response->lines)->data); + tokens = tcore_at_tok_new(line); + + resp_str = g_slist_nth_data(tokens, 0); + if (!g_slist_nth_data(tokens, 0)) { + err("group_id is missing"); + resp.err = TRUE; + goto OUT; + } + + if (!g_slist_nth_data(tokens, 1)) { + err("function_id is missing"); + resp.err = TRUE; + goto OUT; + } + + resp_str = g_slist_nth_data(tokens, 2); + if (resp_str) { + error = atoi(resp_str); + + if (0 == error) { + dbg("Response is Success "); + resp.err = FALSE; + } else { + resp.err = TRUE; + } + } + +OUT: + // Free tokens + tcore_at_tok_free(tokens); + } else { + dbg("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("err cause not specified or string corrupted"); + resp.err = TRUE; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + + // TODO: CMEE error mapping is required. + resp.err = TRUE; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + if (ur) { + if (resp.err && soundvolume == FALSE) { // Send only failed notification . success notification send when destination device is set. + // Send reposne to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_set_sound_volume_level), &resp); + soundvolume = TRUE; + } + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + + +static void on_confirmation_call_set_destination_sound_volume_level(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + char *resp_str = NULL; + const TcoreATResponse *response = data; + struct tresp_call_set_sound_volume_level resp; + gboolean error; + + dbg("Entry"); + + ur = tcore_pending_ref_user_request(p); + + // +XDRV: ,,[,] + if (!response) { + err("Input data is NULL"); + return; + } + + if (ur) { + if (response->success > 0) { + dbg("RESPONSE OK"); + line = (const char *) (((GSList *) response->lines)->data); + tokens = tcore_at_tok_new(line); + resp_str = g_slist_nth_data(tokens, 0); + + if (!g_slist_nth_data(tokens, 0)) { + err("group_id is missing"); + resp.err = TRUE; + goto OUT; + } + + if (!g_slist_nth_data(tokens, 1)) { + err("function_id is missing"); + resp.err = TRUE; + goto OUT; + } + + resp_str = g_slist_nth_data(tokens, 2); + + if (resp_str) { + error = atoi(resp_str); + + if (0 == error) { + dbg("Response is Success"); + resp.err = FALSE; + } else { + resp.err = TRUE; + } + } + +OUT: + // Free tokens + tcore_at_tok_free(tokens); + } else { + dbg("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("err cause not specified or string corrupted"); + resp.err = TRUE; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + + // TODO: CMEE error mapping is required. + resp.err = TRUE; + } + + tcore_at_tok_free(tokens); + } + + if (soundvolume == TRUE) { + soundvolume = FALSE; + } else { + // Send reposne to TAPI + tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_VOLUME_LEVEL, sizeof(struct tresp_call_set_sound_volume_level), &resp); + } + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + + +static void on_confirmation_call_set_sound_mute_status(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + char *resp_str = NULL; + struct tresp_call_set_sound_mute_status resp; + const TcoreATResponse *response = data; + gboolean error; + + dbg("Entry"); + + ur = tcore_pending_ref_user_request(p); + + if (!response) { + err("Input data is NULL"); + return; + } + + if (response->success > 0) { + dbg("RESPONSE OK"); + + line = (const char *) (((GSList *) response->lines)->data); + tokens = tcore_at_tok_new(line); + resp_str = g_slist_nth_data(tokens, 0); + + if (!g_slist_nth_data(tokens, 0)) { + err("group_id is missing"); + resp.err = TRUE; + goto OUT; + } + + if (!g_slist_nth_data(tokens, 1)) { + err(" function_id is missing"); + resp.err = TRUE; + goto OUT; + } + + resp_str = g_slist_nth_data(tokens, 2); + + if (resp_str) { + error = atoi(resp_str); + if (0 == error) { + dbg("Response is Success"); + resp.err = FALSE; + } else { + resp.err = TRUE; + } + } +OUT: + // Free tokens + tcore_at_tok_free(tokens); + } else { + dbg("RESPONSE NOT OK"); + + line = (const char *) response->final_response; + tokens = tcore_at_tok_new(line); + + if (g_slist_length(tokens) < 1) { + err("err cause not specified or string corrupted"); + resp.err = TRUE; + } else { + error = atoi(g_slist_nth_data(tokens, 0)); + + // TODO: CMEE error mapping is required. + resp.err = TRUE; + } + + // Free tokens + tcore_at_tok_free(tokens); + } + + if (ur) { + tcore_user_request_send_response(ur, TRESP_CALL_SET_SOUND_MUTE_STATUS, sizeof(struct tresp_call_set_sound_mute_status), &resp); + } else { + err("User Request is NULL"); + } + + dbg("Exit"); + return; +} + +// RESPONSE +static void on_response_call_list_get(TcorePending *p, int data_len, const void *data, void *user_data) +{ + TcorePlugin *plugin = NULL; + CoreObject *core_obj = NULL; + CallObject *co = NULL; + struct clcc_call_t *call_list = NULL; + gboolean *event_flag = (gboolean *) user_data; + const TcoreATResponse *response = data; + GSList *resp_data = NULL; + char *line = NULL; + + int cllc_info = 0, countCalls = 0, countValidCalls = 0; + int error = 0; + + dbg("Entry"); + + plugin = tcore_pending_ref_plugin(p); + core_obj = tcore_pending_ref_core_object(p); + + if (response->success > 0) { + dbg("RESPONCE OK"); + if (response->lines) { + resp_data = (GSList *) response->lines; + countCalls = g_slist_length(resp_data); + dbg("Total records : %d", countCalls); + } + + if (0 == countCalls) { + err("Call count is zero"); + if (event_flag) { + g_free(event_flag); + event_flag = NULL; + } + return; + } - /* - 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; + call_list = g_new0(struct clcc_call_t, countCalls); + + for (countValidCalls = 0; resp_data != NULL; resp_data = resp_data->next, countValidCalls++, cllc_info++) { + line = (char *) (resp_data->data); + + error = _callFromCLCCLine(line, call_list + countValidCalls); + if (0 != error) { + continue; + } + + co = tcore_call_object_find_by_id(core_obj, call_list[cllc_info].info.id); + if (!co) { + co = tcore_call_object_new(core_obj, call_list[cllc_info].info.id); + if (!co) { + err("error : tcore_call_object_new [ id : %d ]", call_list[cllc_info].info.id); + continue; + } + } + + // Call set parameters + tcore_call_object_set_type(co, call_type(call_list[cllc_info].info.type)); + tcore_call_object_set_direction(co, call_list[cllc_info].info.direction); + tcore_call_object_set_multiparty_state(co, _call_is_in_mpty(call_list[cllc_info].info.mpty)); + tcore_call_object_set_cli_info(co, CALL_CLI_MODE_DEFAULT, 0, call_list[cllc_info].number, strlen(call_list[cllc_info].number)); + tcore_call_object_set_active_line(co, 0); + + if (*event_flag) { + dbg("Call status before calling _call_branch_by_status() : (%d)", call_list[cllc_info].info.status); + _call_branch_by_status(plugin, co, call_list[cllc_info].info.status); + } else { + // Set Status + tcore_call_object_set_status(co, call_list[cllc_info].info.status); + + dbg("Call id : (%d)", call_list[cllc_info].info.id); + dbg("Call direction : (%d)", call_list[cllc_info].info.direction); + dbg("Call type : (%d)", call_list[cllc_info].info.type); + dbg("Call mpty : (%d)", call_list[cllc_info].info.mpty); + dbg("Call number : (%s)", call_list[cllc_info].number); + dbg("Call status : (%d)", call_list[cllc_info].info.status); + } + } + + // Free Call list + g_free(call_list); } - if (command != TCORE_NOTIFICATION_UNKNOWN) - tcore_object_send_notification(co, command, 0, NULL); - tcore_at_tok_free(tokens); - g_free(number); + // Free User data + if (event_flag) { + g_free(event_flag); + event_flag = NULL; + } - return TRUE; + dbg("Exit"); + return; } -/* -* Operation - SS network initiated notification. -* notification message format: -* +CSSI : [,] -* where -* -* 0 unconditional call forwarding is active -* 1 some of the conditional call forwarding are active -* 2 call has been forwarded -* 3 call is waiting -* 4 this is a CUG call (also present) -* 5 outgoing calls are barred -* 6 incoming calls are barred -* 7 CLIR suppression rejected -* 8 call has been deflected - -* -* refer Closed user group +CCUG. -*/ -static gboolean on_notification_imc_call_ss_cssi_info(CoreObject *co, const void *event_data, - void *user_data) +static void _on_confirmation_call_end_cause(TcorePending *p, int data_len, const void *data, void *user_data) { + TcorePlugin *plugin = NULL; + CoreObject *core_obj = NULL; + CallObject *co = (CallObject *) user_data; + const TcoreATResponse *response = data; + const char *line = NULL; + struct tnoti_call_status_idle call_status; GSList *tokens = NULL; - TcoreNotification command = TCORE_NOTIFICATION_UNKNOWN; - char *resp = NULL; - char *cmd = 0; - int index = 0; - int code1 = -1; + char *resp_str; + int error; - dbg("entry"); + dbg("Entry"); + plugin = tcore_pending_ref_plugin(p); + core_obj = tcore_pending_ref_core_object(p); - if (1 != g_slist_length((GSList *) event_data)) { - err("unsolicited msg but multiple line"); - return TRUE; - } - cmd = (char *) ((GSList *) event_data)->data; - dbg("ss notification message[%s]", cmd); + if (response->success > 0) { + dbg("RESPONSE OK"); + line = (const char *) (((GSList *) response->lines)->data); + tokens = tcore_at_tok_new(line); + resp_str = g_slist_nth_data(tokens, 0); + if (!resp_str) { + err("call end cause - report value missing"); + } else { + resp_str = g_slist_nth_data(tokens, 1); + if (!resp_str) { + err("call end cause value missing"); + } + error = atoi(resp_str); + dbg("call end cause - %d", error); + call_status.cause = _compare_call_end_cause(error); + dbg("TAPI call end cause - %d", call_status.cause); + } - tokens = tcore_at_tok_new(cmd); - /* parse */ - resp = g_slist_nth_data(tokens, 0); - if (NULL == resp) { - err(" is missing from %CSSI indication"); + // Free tokens + tcore_at_tok_free(tokens); + } else { + err("RESPONSE NOT OK"); + line = (char *) response->final_response; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + err("err cause not specified or string corrupted"); + } else { + err(" err cause value: %d", atoi(g_slist_nth_data(tokens, 0))); + } + call_status.cause = CC_CAUSE_NORMAL_CALL_CLEARING; + // Free tokens tcore_at_tok_free(tokens); - return TRUE; } - code1 = atoi(resp); + call_status.type = tcore_call_object_get_type(co); + dbg("data.type : [%d]", call_status.type); - /* parse [ ] */ - if ((resp = g_slist_nth_data(tokens, 1))) - index = atoi(resp); + call_status.id = tcore_call_object_get_id(co); + dbg("data.id : [%d]", call_status.id); - dbg("+CSSI: = %d = %d ", code1, index); + // Set Status + tcore_call_object_set_status(co, TCORE_CALL_STATUS_IDLE); - /* - other values will be ignored */ - switch (code1) { - case 0: - command = TCORE_NOTIFICATION_CALL_INFO_MO_FORWARD_UNCONDITIONAL; + // Send Notification to TAPI + tcore_server_send_notification(tcore_plugin_ref_server(plugin), + core_obj, + TNOTI_CALL_STATUS_IDLE, + sizeof(struct tnoti_call_status_idle), + (void *) &call_status); + + // Free Call object + tcore_call_object_free(core_obj, co); +} + +static int _callFromCLCCLine(char *line, struct clcc_call_t *p_call) +{ + // +CLCC: 1,0,2,0,0,"18005551212",145 + // [+CLCC: , , , ,[,,[,[,]]] + int state; + int mode; + int isMT; + char *num = NULL; + unsigned int num_type; + GSList *tokens = NULL; + char *resp = NULL; + + dbg("Entry"); + + tokens = tcore_at_tok_new(line); + // parse + resp = g_slist_nth_data(tokens, 0); + if (!resp) { + err("InValid ID"); + goto ERROR; + } + p_call->info.id = atoi(resp); + dbg("id : [%d]\n", p_call->info.id); + + // parse + resp = g_slist_nth_data(tokens, 1); + if (!resp) { + err("InValid Dir"); + goto ERROR; + } + isMT = atoi(resp); + if (0 == isMT) { + p_call->info.direction = TCORE_CALL_DIRECTION_OUTGOING; + } else { + p_call->info.direction = TCORE_CALL_DIRECTION_INCOMING; + } + dbg("Direction : [ %d ]\n", p_call->info.direction); + + // parse + resp = g_slist_nth_data(tokens, 2); + if (!resp) { + err("InValid Stat"); + goto ERROR; + } + state = atoi(resp); + dbg("Call state : %d", state); + switch (state) { + case 0: // active + p_call->info.status = TCORE_CALL_STATUS_ACTIVE; break; + case 1: - command = TCORE_NOTIFICATION_CALL_INFO_MO_FORWARD_CONDITIONAL; + p_call->info.status = TCORE_CALL_STATUS_HELD; break; + case 2: - command = TCORE_NOTIFICATION_CALL_INFO_MO_FORWARDED; + p_call->info.status = TCORE_CALL_STATUS_DIALING; break; + case 3: - command = TCORE_NOTIFICATION_CALL_INFO_MO_WAITING; + p_call->info.status = TCORE_CALL_STATUS_ALERT; break; - case 5: - command = TCORE_NOTIFICATION_CALL_INFO_MO_BARRED_OUTGOING; + + case 4: + p_call->info.status = TCORE_CALL_STATUS_INCOMING; break; - case 6: - command = TCORE_NOTIFICATION_CALL_INFO_MO_BARRED_INCOMING; + + case 5: + p_call->info.status = TCORE_CALL_STATUS_WAITING; break; - case 8: - command = TCORE_NOTIFICATION_CALL_INFO_MO_DEFLECTED; + } + dbg("Status : [%d]\n", p_call->info.status); + + // parse + resp = g_slist_nth_data(tokens, 3); + if (!resp) { + err("InValid Mode"); + goto ERROR; + } + mode = atoi(resp); + switch (mode) { + case 0: + p_call->info.type = TCORE_CALL_TYPE_VOICE; break; - default: - dbg("Unsupported +CSSI notification : %d", code1); + + case 1: + p_call->info.type = TCORE_CALL_TYPE_VIDEO; break; + + default: // only Voice/VT call is supported in CS. treat other unknown calls as error + dbg("invalid type : [%d]\n", mode); + goto ERROR; + } + dbg("Call type : [%d]\n", p_call->info.type); + + // parse + resp = g_slist_nth_data(tokens, 4); + if (!resp) { + err("InValid Mpty"); + goto ERROR; + } + + p_call->info.mpty = atoi(resp); + dbg("Mpty : [ %d ]\n", p_call->info.mpty); + + // parse + resp = g_slist_nth_data(tokens, 5); + dbg("Incoming number - %s and its len - %d", resp, strlen(resp)); + + // tolerate null here + if (!resp) { + err("Number is NULL"); + goto ERROR; + } + // Strike off double quotes + num = util_removeQuotes(resp); + dbg("num after removing quotes - %s", num); + + p_call->info.num_len = strlen(resp); + dbg("num_len : [0x%x]\n", p_call->info.num_len); + + // parse + resp = g_slist_nth_data(tokens, 6); + if (!resp) { + dbg("InValid Num type"); + goto ERROR; } + p_call->info.num_type = atoi(resp); + dbg("BCD num type: [0x%x]\n", p_call->info.num_type); - if (command != TCORE_NOTIFICATION_UNKNOWN) - tcore_object_send_notification(co, command, 0, NULL); + // check number is international or national. + num_type = ((p_call->info.num_type) >> 4) & 0x07; + dbg("called party's type of number : [0x%x]\n", num_type); + + if (num_type == 1 && num[0] != '+') { + // international number + p_call->number[0] = '+'; + memcpy(&(p_call->number[1]), num, strlen(num)); + } else { + memcpy(&(p_call->number), num, strlen(num)); + } + dbg("incoming number - %s", p_call->number); + + g_free(num); + num = NULL; + // Free tokens tcore_at_tok_free(tokens); - return TRUE; + dbg("Exit"); + return 0; + +ERROR: + err("Invalid CLCC line"); + + g_free(num); + + // Free tokens + tcore_at_tok_free(tokens); + err("Exit"); + return -1; } -static gboolean on_notification_imc_call_clip_info(CoreObject *co, const void *data, - void *user_data) +// NOTIFICATION +static void on_notification_call_waiting(CoreObject *o, const void *data, void *user_data) { - dbg("entry"); - /* TODO - handle +CLIP notification*/ - return TRUE; + GSList *tokens = NULL; + const char *line = NULL; + char *pId; + int call_id; + gboolean *eflag; + GSList *pList = NULL; + CallObject *co = NULL, *dupco = NULL; + + dbg("function entrance"); + // check call with waiting status already exist + pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_WAITING); + + if (pList != NULL) { + dbg("[error]Waiting call already exist. skip"); + return; + } + // check call with incoming status already exist + pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING); + + if (pList != NULL) { + dbg("[error]incoming call already exist. skip"); + return; + } + line = (char *) data; + tokens = tcore_at_tok_new(line); + + pId = g_slist_nth_data(tokens, 0); + if (!pId) { + dbg("[error]:Call id is missing from +XCALLSTAT indication"); + tcore_at_tok_free(tokens); + return; + } + + call_id = atoi(pId); + dupco = tcore_call_object_find_by_id(o, call_id); + if (dupco != NULL) { + dbg("co with same id already exist. skip"); + tcore_at_tok_free(tokens); + return; + } + co = tcore_call_object_new(o, call_id); + if (!co) { + dbg("[ error ] co is NULL"); + tcore_at_tok_free(tokens); + return; + } + + tcore_at_tok_free(tokens); + + eflag = g_new0(gboolean, 1); + *eflag = TRUE; + dbg("calling _call_list_get"); + _call_list_get(o, eflag); } -/* Response */ -static void __on_response_imc_call_handle_error_report(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_notification_call_incoming(CoreObject *o, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelCallResult result = TEL_CALL_RESULT_FAILURE; GSList *tokens = NULL; - dbg("entry"); + const char *line = NULL; + char *pId; + int call_id; + gboolean *eflag; + GSList *pList = NULL; + CallObject *co = NULL, *dupco = NULL; - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + dbg("function entrance"); + // check call with incoming status already exist + pList = tcore_call_object_find_by_status(o, TCORE_CALL_STATUS_INCOMING); - if (at_resp && at_resp->success) { - GSList *resp_data = NULL; - gchar *resp_str; - gint error; + if (pList != NULL) { + dbg("incoming call already exist. skip"); + return; + } - resp_data = at_resp->lines; - if (!resp_data) { - err("invalid response data received"); - goto OUT; - } + line = (char *) data; + tokens = tcore_at_tok_new(line); - tokens = tcore_at_tok_new(resp_data->data); - resp_str = g_slist_nth_data(tokens, 0); - if (!resp_str) { - err("In extended error report - missing"); - goto OUT; - } - dbg("category[%s]", resp_str); + pId = g_slist_nth_data(tokens, 0); + if (!pId) { + dbg("Error:Call id is missing from %XCALLSTAT indication"); + tcore_at_tok_free(tokens); + return; + } - resp_str = g_slist_nth_data(tokens, 1); - if (!resp_str) { - err("In extended error report - missing"); - goto OUT; - } - error = atoi(resp_str); - dbg("Cause: [%d] description: [%s]", error, g_slist_nth_data(tokens, 2)); + call_id = atoi(pId); - result = __convert_imc_extended_err_tel_call_result(error); - dbg("result: [%d]", result); - } else { - err("Response - [NOK]"); + dupco = tcore_call_object_find_by_id(o, call_id); + if (dupco != NULL) { + dbg("co with same id already exist. skip"); + tcore_at_tok_free(tokens); + return; } -OUT: - dbg("%s: [%s]", IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data), - (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); + co = tcore_call_object_new(o, call_id); + if (!co) { + dbg("[ error ] co is NULL"); + tcore_at_tok_free(tokens); + return; + } - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); + dbg("freeing at token"); + tcore_at_tok_free(tokens); - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + eflag = g_new0(gboolean, 1); + *eflag = TRUE; - /* Free tokens*/ - tcore_at_tok_free(tokens); + dbg("calling _call_list_get"); + _call_list_get(o, eflag); } -static void __on_response_imc_call_end_cause(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_notification_call_status(CoreObject *o, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelCallStatusIdleNoti idle; - TcoreNotification command; - TelCallEndCause cause = TEL_CALL_END_CAUSE_NONE; - guint *call_id; + char *cmd = NULL; + TcorePlugin *plugin = NULL; + CallObject *co = NULL; + int id = -1; + int status = 0; + int type = 0; + char *stat = NULL; + char *pCallId = NULL; GSList *tokens = NULL; + gboolean *eflag = NULL; + enum tcore_call_status co_status; - dbg("entry"); - - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); - call_id = IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data); - - if (at_resp && at_resp->success) { - GSList *resp_data = NULL; - gchar *resp_str; - gint error; + dbg("function entrance"); + plugin = tcore_object_ref_plugin(o); + cmd = (char *) data; + tokens = tcore_at_tok_new(cmd); - resp_data = at_resp->lines; - if (!resp_data) { - err("invalid response data received"); - goto OUT; + // parse + pCallId = g_slist_nth_data(tokens, 0); + if (!pCallId) { + dbg("CallId is missing from %XCALLSTAT indication"); + tcore_at_tok_free(tokens); + return; + } else { + id = atoi(pCallId); + dbg("call id = %d", id); + // parse + if ((stat = g_slist_nth_data(tokens, 1))) { + status = atoi(stat); } - tokens = tcore_at_tok_new(resp_data->data); - resp_str = g_slist_nth_data(tokens, 0); - if (!resp_str) { - err("In extended error report - missing"); - goto OUT; + dbg("call status = %d", status); + } + + tcore_at_tok_free(tokens); + co_status = _call_status(status); + + dbg("co_status = %d", co_status); + switch (co_status) { + case CALL_STATUS_ACTIVE: + { + dbg("call(%d) status : [ ACTIVE ]", id); + co = tcore_call_object_find_by_id(o, id); + if (!co) { + dbg("co is NULL"); + return; } - dbg("category[%s]", resp_str); - resp_str = g_slist_nth_data(tokens, 1); - if (!resp_str) { - err("In extended error report - missing"); - goto OUT; + _call_status_active(plugin, co); + } + break; + + case CALL_STATUS_HELD: + dbg("call(%d) status : [ held ]", id); + break; + + case CALL_STATUS_DIALING: + { + dbg("call(%d) status : [ dialing ]", id); + co = tcore_call_object_find_by_id(o, id); + if (!co) { + co = tcore_call_object_new(o, id); + if (!co) { + dbg("error : tcore_call_object_new [ id : %d ]", id); + return; + } } - error = atoi(resp_str); - dbg("cause: [%d] description: [%s]", error, g_slist_nth_data(tokens, 2)); - cause = __convert_imc_extended_err_call_end_cause(error); - dbg("cause: [%d]", cause); + tcore_call_object_set_type(co, call_type(type)); + tcore_call_object_set_direction(co, TCORE_CALL_DIRECTION_OUTGOING); + _call_status_dialing(plugin, co); + } + break; - } else { - err("RESPONSE - [NOK]"); + case CALL_STATUS_ALERT: + { + dbg("call(%d) status : [ alert ]", id); + co = tcore_call_object_find_by_id(o, id); + if (!co) { + dbg("co is NULL"); + return; + } + // Store dialed number information into Call object. + eflag = g_new0(gboolean, 1); + *eflag = TRUE; + dbg("calling _call_list_get"); + _call_list_get(o, eflag); } -OUT: - command = TCORE_NOTIFICATION_CALL_STATUS_IDLE; - idle.call_id = *call_id; + break; + + case CALL_STATUS_INCOMING: + case CALL_STATUS_WAITING: + dbg("call(%d) status : [ incoming ]", id); + break; - idle.cause = cause; + case CALL_STATUS_IDLE: + { + dbg("call(%d) status : [ release ]", id); - /* Send notification */ - tcore_object_send_notification(co, command, - sizeof(TelCallStatusIdleNoti), &idle); + co = tcore_call_object_find_by_id(o, id); + if (!co) { + dbg("co is NULL"); + return; + } - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + plugin = tcore_object_ref_plugin(o); + if (!plugin) { + dbg("plugin is NULL"); + return; + } + _call_status_idle(plugin, co); + } + break; - /* Free tokens*/ - tcore_at_tok_free(tokens); + default: + dbg("invalid call status", id); + break; + } } -static void on_response_imc_call_default(TcorePending *p, - guint data_len, const void *data, void *user_data) + +static TReturn imc_call_outgoing(CoreObject *o, UserRequest *ur) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; + struct treq_call_dial *data = 0; + char *cmd_str; + const char *clir, *num; + TcorePending *pending; + TcoreATRequest *req; + gboolean ret; - TelCallResult result = TEL_CALL_RESULT_FAILURE; - dbg("entry"); + dbg("Entry"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + data = (struct treq_call_dial *) tcore_user_request_ref_data(ur, 0); + if (data->type == CALL_TYPE_VIDEO) { + dbg("invalid call type"); + return TCORE_RETURN_FAILURE; + } - if (at_resp && at_resp->success) { - result = TEL_CALL_RESULT_SUCCESS; + if (!strncmp(data->number, "*31#", 4)) { + dbg("clir suppression"); + clir = "i"; + num = data->number + 4; + } else if (!strncmp(data->number, "#31#", 4)) { + dbg("clir invocation"); + clir = "I"; + num = data->number + 4; } else { - TelReturn ret; - if(at_resp){ - err("ERROR[%s]", at_resp->final_response); + int cli = 0; + + dbg("no clir string in number"); + + vconf_get_int("db/ciss/show_my_number", &cli); + + if (cli == 2){ + dbg("clir invocation from setting application"); + clir = "I"; + } else { + dbg("set clir state to default"); + clir = ""; } + num = data->number; + } - /* Send Request to modem to get extended error report*/ - ret = tcore_at_prepare_and_send_request(co, - "AT+CEER", "+CEER:", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - __on_response_imc_call_handle_error_report, resp_cb_data, - on_send_imc_request, NULL); + dbg("data->number = %s", num); + cmd_str = g_strdup_printf("ATD%s%s;", num, clir); - if (ret == TEL_RETURN_SUCCESS) - return; + dbg("request command : %s", cmd_str); + + pending = tcore_pending_new(o, 0); + req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT); + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); + + tcore_pending_set_request_data(pending, 0, req); + ret = _call_request_message(pending, o, ur, on_confirmation_call_outgoing, NULL); + + g_free(cmd_str); + + if (ret == FALSE) { + dbg("AT request(%s) sent failed", req->cmd); + return TCORE_RETURN_FAILURE; } - dbg("%s: [%s]", IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data), - (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); + dbg("AT request(%s) sent success", req->cmd); - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); + dbg("Exit"); - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + return TCORE_RETURN_SUCCESS; } -static void on_response_imc_call_set_volume_info(TcorePending *p, - guint data_len, const void *data, void *user_data) +static TReturn imc_call_answer(CoreObject *o, UserRequest *ur) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - GSList *tokens = NULL; - GSList *line = NULL; - char *resp_str = NULL; - gboolean error; + char *cmd_str = NULL; + CallObject *co = NULL; + struct treq_call_answer *data = 0; + TcorePending *pending = NULL; + TcoreATRequest *req; + gboolean ret = FALSE; + + dbg("function entrance"); + + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; + } - TelCallResult result = TEL_CALL_RESULT_FAILURE; - dbg("Enter"); + data = (struct treq_call_answer *) tcore_user_request_ref_data(ur, 0); + co = tcore_call_object_find_by_id(o, data->id); + if (data->type == CALL_ANSWER_TYPE_ACCEPT) { + dbg(" request type CALL_ANSWER_TYPE_ACCEPT"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + cmd_str = g_strdup_printf("%s", "ATA"); + pending = tcore_pending_new(o, 0); + req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT); + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); - if (at_resp && at_resp->success) { - line = at_resp->lines; - tokens = tcore_at_tok_new(line->data); + tcore_pending_set_request_data(pending, 0, req); + ret = _call_request_message(pending, o, ur, on_confirmation_call_accept, co); + g_free(cmd_str); - if (!g_slist_nth_data(tokens, 0)) { - err("group_id missing"); - goto OUT; + if (!ret) { + dbg("AT request(%s) sent failed", req->cmd); + return TCORE_RETURN_FAILURE; } - - if (!g_slist_nth_data(tokens, 1)) { - err(" function_id missing"); - goto OUT; + } else { + switch (data->type) { + case CALL_ANSWER_TYPE_REJECT: + { + dbg("call answer reject"); + tcore_call_control_answer_reject(o, ur, on_confirmation_call_reject, co); } + break; - resp_str = g_slist_nth_data(tokens, 2); - if (!resp_str) { - err("xdrv result missing"); - goto OUT; - } else { - struct imc_set_volume_info *volume_info; - gchar *vol = ""; - gchar *at_cmd; - TelReturn ret; + case CALL_ANSWER_TYPE_REPLACE: + { + dbg("call answer replace"); + tcore_call_control_answer_replace(o, ur, on_confirmation_call_replace, co); + } + break; - error = atoi(resp_str); - if (error) { - err("RESPONSE NOK"); - result = __convert_imc_xdrv_result_tel_call_result(error); - goto OUT; - } + case CALL_ANSWER_TYPE_HOLD_ACCEPT: + { + dbg("call answer hold and accept"); + tcore_call_control_answer_hold_and_accept(o, ur, on_confirmation_call_hold_and_accept, co); + } + break; - /* Fetch volume_info from resp_cb_data */ - volume_info = (struct imc_set_volume_info *) - IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data); - dbg("volume info index[%d]", volume_info->next_index); + default: + dbg("[ error ] wrong answer type [ %d ]", data->type); + return TCORE_RETURN_FAILURE; + } + } - if (xdrv_set_volume[volume_info->next_index] == NULL) { - /*Processing of xdrv commands completed */ - dbg("RESPONSE OK"); - result = TEL_CALL_RESULT_SUCCESS; - goto OUT; - } else if (volume_info->next_index == 3) { - switch ((volume_info->volume) / 10) { - case 0 : - vol = "0"; - break; - case 1 : - vol = "40"; - break; - case 2 : - vol = "46"; - break; - case 3 : - vol = "52"; - break; - case 4 : - vol = "58"; - break; - case 5 : - vol = "64"; - break; - case 6 : - vol = "70"; - break; - case 7 : - vol = "76"; - break; - case 8 : - vol = "82"; - break; - case 9 : - default : - vol = "88"; - } - } + return TCORE_RETURN_SUCCESS; +} - at_cmd = g_strdup_printf("%s%s", - xdrv_set_volume[volume_info->next_index], vol); +static TReturn imc_call_release(CoreObject *o, UserRequest *ur) +{ + CallObject *co = NULL; + struct treq_call_end *data = 0; + UserRequest *ur_dup = NULL; + char *chld0_cmd = NULL; + char *chld1_cmd = NULL; + TcorePending *pending = NULL, *pending1 = NULL; + TcoreATRequest *req, *req1; + gboolean ret = FALSE; + + dbg("function entrance"); + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; + } + data = (struct treq_call_end *) tcore_user_request_ref_data(ur, 0); + co = tcore_call_object_find_by_id(o, data->id); - /* Increment index to point to next xdrv command */ - volume_info->next_index += 1; + dbg("type of release call = %d", data->type); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - at_cmd, "+XDRV", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - on_response_imc_call_set_volume_info, - resp_cb_data, on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_call_set_volume_info"); - g_free(at_cmd); + if (data->type == CALL_END_TYPE_ALL) { + // releaseAll do not exist on legacy request. send CHLD=0, CHLD=1 in sequence + chld0_cmd = g_strdup("AT+CHLD=0"); + chld1_cmd = g_strdup("AT+CHLD=1"); - return; - } - } + pending = tcore_pending_new(o, 0); + req = tcore_at_request_new(chld0_cmd, NULL, TCORE_AT_NO_RESULT); -OUT : - dbg("Set Volume Info: [%s]", - (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); + dbg("input command is %s", chld0_cmd); + dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); + tcore_pending_set_request_data(pending, 0, req); + ur_dup = tcore_user_request_new(NULL, NULL); + ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_endall, NULL); + g_free(chld0_cmd); - imc_destroy_resp_cb_data(resp_cb_data); - tcore_at_tok_free(tokens); -} + if (!ret) { + dbg("AT request %s has failed ", req->cmd); + if (ur_dup) { + tcore_user_request_free(ur_dup); + ur_dup = NULL; + } + g_free(chld1_cmd); + return TCORE_RETURN_FAILURE; + } -static void on_response_imc_call_set_sound_path(TcorePending *p, - guint data_len, const void *data, void *user_data) -{ - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - GSList *tokens = NULL; - GSList *line = NULL; - char *resp_str = NULL; - gboolean error; - gint xdrv_func_id = -1; + pending1 = tcore_pending_new(o, 0); + req1 = tcore_at_request_new(chld1_cmd, NULL, TCORE_AT_NO_RESULT); - TelCallResult result = TEL_CALL_RESULT_FAILURE; - dbg("Enter"); + dbg("input command is %s", chld1_cmd); + dbg("req-cmd : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd)); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + tcore_pending_set_request_data(pending1, 0, req1); + ret = _call_request_message(pending1, o, ur, on_confirmation_call_release_all, co); + g_free(chld1_cmd); - if (at_resp && at_resp->success) { - line = at_resp->lines; - tokens = tcore_at_tok_new(line->data); - if (!g_slist_nth_data(tokens, 0)) { - err("group_id missing"); - goto OUT; + if (!ret) { + dbg("AT request %s has failed ", req->cmd); + return TCORE_RETURN_FAILURE; } + } else { + switch (data->type) { + case CALL_END_TYPE_DEFAULT: + { + int id = 0; + id = tcore_call_object_get_id(co); + + dbg("call end call id [%d]", id); + tcore_call_control_end_specific(o, ur, id, on_confirmation_call_release_specific, co); + } + break; - if (!(resp_str = g_slist_nth_data(tokens, 1))) { - err("function_id missing"); - goto OUT; + case CALL_END_TYPE_ACTIVE_ALL: + { + dbg("call end all active"); + tcore_call_control_end_all_active(o, ur, on_confirmation_call_release_all_active, co); } - xdrv_func_id = atoi(resp_str); + break; - if (!(resp_str = g_slist_nth_data(tokens, 2))) { - err("RESPONSE NOK"); - goto OUT; + case CALL_END_TYPE_HOLD_ALL: + { + dbg("call end all held"); + tcore_call_control_end_all_held(o, ur, on_confirmation_call_release_all_held, co); } - error = atoi(resp_str); - if (error) { - err("RESPONSE NOK"); - result = __convert_imc_xdrv_result_tel_call_result(error); - goto OUT; + break; + + default: + dbg("[ error ] wrong end type [ %d ]", data->type); + return TCORE_RETURN_FAILURE; } + } - if (xdrv_func_id == 4) { - /* Send next command to configure destination device type */ - gchar *at_cmd; - TelReturn ret; - gint *device_type = IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data); + return TCORE_RETURN_SUCCESS; +} - at_cmd = g_strdup_printf("AT+XDRV=40,5,2,0,0,0,0,0,1,0,1,0,%d", - *device_type); +static TReturn imc_call_hold(CoreObject *o, UserRequest *ur) +{ + struct treq_call_hold *hold = 0; + CallObject *co = NULL; - ret = tcore_at_prepare_and_send_request(co, - at_cmd, "+XDRV", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - on_response_imc_call_set_sound_path, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_call_set_sound_path"); - g_free(at_cmd); + dbg("function entrance"); - return; - } - dbg("RESPONSE OK"); - result = TEL_CALL_RESULT_SUCCESS; + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; } -OUT : - dbg("Set Sound Path: [%s]", - (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); + hold = (struct treq_call_hold *) tcore_user_request_ref_data(ur, 0); + dbg("call id : [ %d ]", hold->id); - tcore_at_tok_free(tokens); - - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); + co = tcore_call_object_find_by_id(o, hold->id); + tcore_call_control_hold(o, ur, on_confirmation_call_hold, co); - imc_destroy_resp_cb_data(resp_cb_data); + return TCORE_RETURN_SUCCESS; } -static void on_response_set_sound_path(TcorePending *p, guint data_len, - const void *data, void *user_data) +static TReturn imc_call_active(CoreObject *o, UserRequest *ur) { - const TcoreAtResponse *at_resp = data; - ImcRespCbData *resp_cb_data = user_data; - TelCallResult result = TEL_CALL_RESULT_FAILURE; - CoreObject *co_call = tcore_pending_ref_core_object(p); + struct treq_call_active *active = 0; + CallObject *co = NULL; + + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; + } - if (at_resp && at_resp->success) - result = TEL_CALL_RESULT_SUCCESS; + active = (struct treq_call_active *) tcore_user_request_ref_data(ur, 0); + dbg("call id : [ %d ]", active->id); - if(resp_cb_data->cb) - resp_cb_data->cb(co_call, (gint)result, NULL, resp_cb_data->cb_data); + co = tcore_call_object_find_by_id(o, active->id); + tcore_call_control_active(o, ur, on_confirmation_call_active, co); - imc_destroy_resp_cb_data(resp_cb_data); + return TCORE_RETURN_SUCCESS; } -static void on_response_imc_call_set_mute(TcorePending *p, guint data_len, - const void *data, void *user_data) +static TReturn imc_call_swap(CoreObject *o, UserRequest *ur) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - GSList *tokens = NULL; - const char *line = NULL; - char *resp_str = NULL; - gboolean error; + struct treq_call_swap *swap = NULL; + CallObject *co = NULL; - TelCallResult result = TEL_CALL_RESULT_FAILURE; - dbg("Enter"); - - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; + } - if (at_resp && at_resp->success) { - line = (((GSList *)at_resp->lines)->data); - tokens = tcore_at_tok_new(line); + swap = (struct treq_call_swap *) tcore_user_request_ref_data(ur, 0); + dbg("call id : [ %d ]", swap->id); - if (!g_slist_nth_data(tokens, 0)) { - err("group_id missing"); - goto OUT; - } + co = tcore_call_object_find_by_id(o, swap->id); + tcore_call_control_swap(o, ur, on_confirmation_call_swap, co); - if (!g_slist_nth_data(tokens, 1)) { - err("function_id missing"); - goto OUT; - } + return TCORE_RETURN_SUCCESS; +} - if (!(resp_str = g_slist_nth_data(tokens, 2))) { - err("xdrv_result missing"); - goto OUT; - } +static TReturn imc_call_join(CoreObject *o, UserRequest *ur) +{ + struct treq_call_join *join = 0; + CallObject *co = NULL; - error = atoi(resp_str); - if (error) { - err(" RESPONSE NOK [%d]", error); - result = __convert_imc_xdrv_result_tel_call_result(error); - goto OUT; - } - result = TEL_CALL_RESULT_SUCCESS; + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; } -OUT : - dbg("Set Mute: [%s]", - (result == TEL_CALL_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); - tcore_at_tok_free(tokens); + join = (struct treq_call_join *) tcore_user_request_ref_data(ur, 0); + dbg("call id : [ %d ]", join->id); - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); + co = tcore_call_object_find_by_id(o, join->id); + tcore_call_control_join(o, ur, on_confirmation_call_join, co); - imc_destroy_resp_cb_data(resp_cb_data); + return TCORE_RETURN_SUCCESS; } - - /* Request */ - /* - * Operation - dial - * - * Request - - * AT-Command: ATD [I] [G] [;] - * - 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: - */ -static TelReturn imc_call_dial(CoreObject *co, const TelCallDial *dial_info, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn imc_call_split(CoreObject *o, UserRequest *ur) { - gchar *at_cmd; - const gchar *clir; - gchar *num; + struct treq_call_split *split = 0; + CallObject *co = NULL; - dbg("entry"); - - if (dial_info->call_type == TEL_CALL_TYPE_VIDEO) { - err("Video call is not supported in imc modem"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; } - 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 { - int cli = 0; - - dbg("no clir string in number"); - - /* it will be removed when setting application use tapi_ss_set_cli() - * instead of his own vconfkey. (0 : By network, 1 : Show, 2 : Hide) - */ - vconf_get_int("db/ciss/show_my_number", &cli); - if (cli == 2){ - dbg("clir invocation from setting application"); - clir = "I"; - } else { - dbg("set clir state to default"); - clir = ""; - } - num = (gchar *)dial_info->number; - } + split = (struct treq_call_split *) tcore_user_request_ref_data(ur, 0); + co = tcore_call_object_find_by_id(o, split->id); + dbg("call id : [ %d ]", split->id); - /* AT-Command */ - at_cmd = g_strdup_printf("ATD%s%s;", num, clir); - dbg(" at command : %s", at_cmd); + tcore_call_control_split(o, ur, split->id, on_confirmation_call_split, co); - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_dial"); + return TCORE_RETURN_SUCCESS; } -/* - * Operation - Answer/Reject/Replace/hold(current call) & accept incoming call. - * - * Request - - * - * 1. AT-Command: ATA - * Response - - * Success: - * OK - * Failure: - * +CME ERROR: - * - * 2. AT-Command: AT+CHLD=[] - * - * 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: - * For more informatiion refer 3GPP TS 27.007. - */ -static TelReturn imc_call_answer(CoreObject *co, TelCallAnswerType ans_type, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn imc_call_deflect(CoreObject *o, UserRequest *ur) { - gchar *at_cmd; - dbg("entry"); + struct treq_call_deflect *deflect = 0; + CallObject *co = NULL; - 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; + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; } - dbg("at command : %s", at_cmd); + deflect = (struct treq_call_deflect *) tcore_user_request_ref_data(ur, 0); + co = tcore_call_object_find_by_number(o, deflect->number); + dbg("deflect number: [ %s ]", deflect->number); - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_answer"); + tcore_call_control_deflect(o, ur, deflect->number, on_confirmation_call_deflect, co); + + return TCORE_RETURN_SUCCESS; } -/* - * Operation - release all calls/release specific call/release all active - * call/release all held calls. - * - * Request - - * 1. AT-Command: AT+CHLD=[] - * - * 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: - */ -static TelReturn imc_call_end(CoreObject *co, const TelCallEnd *end_info, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn imc_call_transfer(CoreObject *o, UserRequest *ur) { - gchar *at_cmd; - dbg("entry"); + struct treq_call_transfer *transfer = 0; + CallObject *co = NULL; - 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; + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; } - dbg("at command : %s", at_cmd); + transfer = (struct treq_call_transfer *) tcore_user_request_ref_data(ur, 0); + dbg("call id : [ %d ]", transfer->id); - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_end"); + co = tcore_call_object_find_by_id(o, transfer->id); + tcore_call_control_transfer(o, ur, on_confirmation_call_transfer, co); + + return TCORE_RETURN_SUCCESS; } -/* - * Operation - send dtmf. - * - * Request - - * 1. AT-Command: AT+VTS=,{,}. - * where - * : - * is a single ASCII character in the set 0-9, #, *, A-D. Even it will support string DTMF. - * : - * integer in range 0-255, meaning 1/10(10 millisec) seconds multiples. The string parameter - * of the command consists of combinations of the following separated by commas: - * NOTE : There is a limit of 50 dtmf tones can be requested through a single VTS command. - * Response - - * Success: - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn imc_call_send_dtmf(CoreObject *co, const char *dtmf_str, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn imc_call_start_cont_dtmf(CoreObject *o, UserRequest *ur) { - gchar *at_cmd; - char *tmp_dtmf = NULL, *dtmf; - unsigned int count; + char *cmd_str = NULL; + gboolean ret = FALSE; + TcoreATRequest *req; + struct treq_call_start_cont_dtmf *dtmf = 0; + char *dtmfstr = NULL, *tmp_dtmf = NULL; + TcorePending *pending = NULL; + //unsigned int dtmf_count; + + dbg("Function enter"); + + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; + } - dbg("entry"); + dtmf = (struct treq_call_start_cont_dtmf *) tcore_user_request_ref_data(ur, 0); + dtmfstr = g_malloc0((MAX_CALL_DTMF_DIGITS_LEN * 2) + 1); // DTMF digits + comma for each dtmf digit. - //(void) _set_dtmf_tone_duration(o, dup); + if (dtmfstr == NULL) { + dbg("Memory allocation failed"); + return TCORE_RETURN_FAILURE; + } - /* DTMF digits + comma for each dtmf digit */ - tmp_dtmf = tcore_malloc0((strlen(dtmf_str) * 2) + 1); - tcore_check_return_value_assert(tmp_dtmf != NULL, TEL_RETURN_FAILURE); - /* Save initial pointer */ - dtmf = tmp_dtmf; + tmp_dtmf = dtmfstr; - for (count = 0; count < strlen(dtmf_str); count++) { - *tmp_dtmf = dtmf_str[count]; +#if 1 + *tmp_dtmf = dtmf->dtmf_digit; +#else + for (dtmf_count = 0; dtmf_count < (unsigned int)strlen((const char *)dtmf->dtmf_digit); dtmf_count++) { + *tmp_dtmf = dtmf->dtmf_digit; tmp_dtmf++; *tmp_dtmf = COMMA; tmp_dtmf++; } - /* last digit is having COMMA , overwrite it with '\0'*/ + // last digit is having COMMA , overwrite it with '\0' . *(--tmp_dtmf) = '\0'; +#endif + dbg("Input DTMF string(%s)", dtmfstr); - /* (AT+VTS = ,,,,,, ..... */ - at_cmd = g_strdup_printf("AT+VTS=%s", dtmf); - dbg("at command : %s", at_cmd); + // AT+VTS = ,,,,,, ..... + cmd_str = g_strdup_printf("AT+VTS=%s", dtmfstr); + dbg("request command : %s", cmd_str); - tcore_free(dtmf); + pending = tcore_pending_new(o, 0); + req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT); + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_send_dtmf"); -} + tcore_pending_set_request_data(pending, 0, req); + ret = _call_request_message(pending, o, ur, on_confirmation_call_dtmf, NULL); + g_free(dtmfstr); + g_free(cmd_str); -/* - * Operation - call hold. - * - * Request - - * 1. AT-Command: AT+CHLD=[] - * Where - * - * 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: - */ -static TelReturn imc_call_hold(CoreObject *co, TcoreObjectResponseCallback cb, - void *cb_data) + if (!ret) { + dbg("AT request sent failed"); + return TCORE_RETURN_FAILURE; + } + return TCORE_RETURN_SUCCESS; +} + +static TReturn imc_call_set_sound_path(CoreObject *o, UserRequest *ur) { - gchar *at_cmd; - dbg("entry"); + UserRequest *ur_dup = NULL; + TcorePending *pending = NULL, *pending1 = NULL; + TcoreATRequest *req, *req1; + char *cmd_str = NULL, *cmd_str1 = NULL; + int device_type = -1; + struct treq_call_set_sound_path *sound_path = 0; + gboolean ret = FALSE; + TcorePlugin *plugin = tcore_object_ref_plugin(o); + const char *cp_name = tcore_server_get_cp_name_by_plugin(plugin); - at_cmd = g_strdup_printf("%s", "AT+CHLD=2"); - dbg("at command : %s", at_cmd); + dbg("function entrance"); - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_hold"); -} + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; + } + sound_path = (struct treq_call_set_sound_path *) tcore_user_request_ref_data(ur, 0); + if (sound_path == NULL) { + dbg("invaling user request"); + return TCORE_RETURN_FAILURE; + } + dbg("audio device type - 0x%x", sound_path->path); + switch (sound_path->path) { + case CALL_SOUND_PATH_HANDSET: + device_type = 1; + break; -/* - * Operation - call active. - * - * Request - - * 1. AT-Command: AT+CHLD=[] - * Where - * - * 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: - */ -static TelReturn imc_call_active(CoreObject *co, TcoreObjectResponseCallback cb, - void *cb_data) -{ - gchar *at_cmd; - dbg("entry"); + case CALL_SOUND_PATH_HEADSET: + device_type = 2; + break; - at_cmd = g_strdup_printf("%s", "AT+CHLD=2"); - dbg("at command : %s", at_cmd); + case CALL_SOUND_PATH_HEADSET_3_5PI: + device_type = 3; + break; - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_active"); -} + case CALL_SOUND_PATH_SPEAKER: + device_type = 4; + break; -/* - * Operation - call swap. - * - * Request - - * 1. AT-Command: AT+CHLD=[] - * Where - * - * 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: - */ -static TelReturn imc_call_swap(CoreObject *co, TcoreObjectResponseCallback cb, - void *cb_data) -{ - gchar *at_cmd; - dbg("entry"); + case CALL_SOUND_PATH_HANDFREE: + device_type = 5; + break; - at_cmd = g_strdup_printf("%s", "AT+CHLD=2"); - dbg("at command : %s", at_cmd); + case CALL_SOUND_PATH_HEADSET_HAC: + device_type = 6; + break; - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_swap"); -} + case CALL_SOUND_PATH_BLUETOOTH: + case CALL_SOUND_PATH_STEREO_BLUETOOTH: + device_type = 7; + break; -/* - * Operation - call join. - * - * Request - - * 1. AT-Command: AT+CHLD=[] - * Where - * - * 3 - adds a held call to the conversation - * Response - - * Success: - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn imc_call_join(CoreObject *co, TcoreObjectResponseCallback cb, - void *cb_data) -{ - gchar *at_cmd; - dbg("entry"); + case CALL_SOUND_PATH_BT_NSEC_OFF: + case CALL_SOUND_PATH_MIC1: + case CALL_SOUND_PATH_MIC2: + default: + dbg("unsupported device type"); + return TCORE_RETURN_FAILURE; + } - at_cmd = g_strdup_printf("%s", "AT+CHLD=3"); - dbg("at command : %s", at_cmd); + if (g_str_has_prefix(cp_name, "mfld_blackbay") == TRUE) { + struct tnoti_call_sound_path *tnoti_snd_path; - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_join"); -} + tnoti_snd_path = g_try_new0(struct tnoti_call_sound_path, 1); + if (!tnoti_snd_path) + return TCORE_RETURN_ENOMEM; -/* - * Operation - call split. - * - * Request - - * 1. AT-Command: AT+CHLD=[] - * Where - * - * 2x - place all active calls on hold except call x with which communication is supported - * Response - - * Success: - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn imc_call_split(CoreObject *co, unsigned int call_id, - TcoreObjectResponseCallback cb, void *cb_data) -{ - gchar *at_cmd; - dbg("entry"); + tnoti_snd_path->path = sound_path->path; - at_cmd = g_strdup_printf("%s%d", "AT+CHLD=2", call_id); - dbg("at command : %s", at_cmd); + /* Configure modem I2S1 to 8khz, mono, PCM if routing to bluetooth */ + if (sound_path->path == CALL_SOUND_PATH_BLUETOOTH || sound_path->path == CALL_SOUND_PATH_STEREO_BLUETOOTH) { + call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,3,0,1,0,0,0,0,0,0,0,21", NULL, TCORE_AT_NO_RESULT, NULL); + call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,2,0,1,0,0,0,0,0,0,0,22", NULL, TCORE_AT_NO_RESULT, NULL); + } + else { + call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,3,0,1,0,8,0,1,0,2,0,21", NULL, TCORE_AT_NO_RESULT, NULL); + call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,2,0,1,0,8,0,1,0,2,0,22", NULL, TCORE_AT_NO_RESULT, NULL); + } - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_split"); -} + /* Configure modem I2S2 and do the modem routing */ + call_prepare_and_send_pending_request(o, "AT+XDRV=40,4,4,0,0,0,8,0,1,0,2,0,21", NULL, TCORE_AT_NO_RESULT, NULL); + call_prepare_and_send_pending_request(o, "AT+XDRV=40,5,3,0,0,0,8,0,1,0,2,0,22", NULL, TCORE_AT_NO_RESULT, NULL); + call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,0,4", NULL, TCORE_AT_NO_RESULT, NULL); + call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,3,0", NULL, TCORE_AT_NO_RESULT, NULL); + call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,4,2", NULL, TCORE_AT_NO_RESULT, NULL); + call_prepare_and_send_pending_request(o, "AT+XDRV=40,6,5,2", NULL, TCORE_AT_NO_RESULT, NULL); -/* - * Operation - call transfer. - * - * Request - - * 1. AT-Command: AT+CHLD=[] - * Where - * - * 4 connects the two calls and disconnects the subscriber from both calls (Explicit Call Transfer) - * Response - - * Success: - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn imc_call_transfer(CoreObject *co, TcoreObjectResponseCallback cb, - void *cb_data) -{ - gchar *at_cmd; - dbg("entry"); + /* amc enable */ + call_prepare_and_send_pending_request(o, "AT+XDRV=40,2,4", NULL, TCORE_AT_NO_RESULT, NULL); //AMC_I2S2_RX + call_prepare_and_send_pending_request(o, "AT+XDRV=40,2,3", NULL, TCORE_AT_NO_RESULT, NULL); //AMC_I2S1_RX + /* amc route: AMC_RADIO_RX => AMC_I2S1_TX */ - at_cmd = g_strdup_printf("%s", "AT+CHLD=4"); - dbg("at command : %s", at_cmd); + pending = tcore_pending_new(o, 0); + req = tcore_at_request_new("AT+XDRV=40,6,0,2", "+XDRV", TCORE_AT_SINGLELINE); + dbg("XDRV req-cmd for source type : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); + tcore_pending_set_request_data(pending, 0, req); + ur_dup = tcore_user_request_ref(ur); + ret = _call_request_message(pending, o, ur_dup, on_confirmation_set_sound_path, tnoti_snd_path); - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_transfer"); -} + } else { -/* - * Operation - call deflect. - * - * Request - - * 1. AT-Command: AT+CTFR= [,] - * Where - * number> - * string type phone number - * - * type of address octet in integer format. It is optional parameter. - * - * Response - - * Success: - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn imc_call_deflect(CoreObject *co, const char *deflect_to, - TcoreObjectResponseCallback cb, void *cb_data) -{ - gchar *at_cmd; - dbg("entry"); + cmd_str = g_strdup_printf("AT+XDRV=40,4,3,0,0,0,0,0,1,0,1,0,%d",device_type); // source type. + pending = tcore_pending_new(o, 0); + req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE); + dbg("XDRV req-cmd for source type : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); + tcore_pending_set_request_data(pending, 0, req); + ur_dup = tcore_user_request_ref(ur); + ret = _call_request_message(pending, o, ur_dup, on_confirmation_call_set_source_sound_path, NULL); + g_free(cmd_str); + + if (!ret) { + dbg("At request(%s) sent failed", req->cmd); + return TCORE_RETURN_FAILURE; + } - at_cmd = g_strdup_printf("AT+CTFR=%s", deflect_to); - dbg("at command : %s", at_cmd); + cmd_str1 = g_strdup_printf("AT+XDRV=40,5,2,0,0,0,0,0,1,0,1,0,%d",device_type); // destination type + pending1 = tcore_pending_new(o, 0); + req1 = tcore_at_request_new(cmd_str1, "+XDRV", TCORE_AT_SINGLELINE); + dbg("XDRV req-cmd for destination type : %s, prefix(if any) :%s, cmd_len : %d", req1->cmd, req1->prefix, strlen(req1->cmd)); + tcore_pending_set_request_data(pending1, 0, req1); + ret = _call_request_message(pending1, o, ur, on_confirmation_call_set_destination_sound_path, NULL); + g_free(cmd_str1); + + if (!ret) { + dbg("AT request %s has failed ", req1->cmd); + return TCORE_RETURN_FAILURE; + } + } - return __send_call_request(co, cb, cb_data, at_cmd, "imc_call_deflect"); + return TCORE_RETURN_SUCCESS; } -static TelReturn imc_call_set_active_line(CoreObject *co, TelCallActiveLine active_line, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn imc_call_set_sound_volume_level(CoreObject *o, UserRequest *ur) { - dbg("entry"); + UserRequest *src_ur = NULL; + UserRequest *dest_ur = NULL; + TcorePending *src_pending = NULL; + TcorePending *dest_pending = NULL; + TcoreATRequest *src_req = NULL; + TcoreATRequest *dest_req = NULL; + char *cmd_str = NULL, *volume_level = NULL; + gboolean ret = FALSE; + struct treq_call_set_sound_volume_level *data = NULL; - dbg("exit"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; -} + dbg("Entry"); -static TelReturn imc_call_get_active_line(CoreObject *co, TcoreObjectResponseCallback cb, - void *cb_data) -{ - dbg("entry"); + if (FALSE == tcore_hal_get_power_state(tcore_object_get_hal(o))) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; + } - dbg("exit"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; -} + data = (struct treq_call_set_sound_volume_level *) tcore_user_request_ref_data(ur, 0); -/* - * Operation - Set voule info. - * - * Request - - * AT-Command: AT+XDRV=,[,] - * The first command parameter defines the involved driver group. - * The second command parameter defines a certain function in the selected driver group. - * Other parameters are dependent on the first two parameters. - * Nearly all parameters are integer values, also if they are represented by literals. - * Only very few are strings or - * hex data strings. - * - * Response - - * +XDRV: ,,[,] - * The first response parameter defines the involved driver group. - * The second response parameter defines the current function in the selected driver group. - * The third response parameter defines the xdrv_result of the operation. - * Additional response parameters dependent on the first two parameters. - */ -static TelReturn imc_call_set_volume_info(CoreObject *co, const TelCallVolumeInfo *volume_info, - TcoreObjectResponseCallback cb, void *cb_data) -{ - ImcRespCbData *resp_cb_data = NULL; - gchar *at_cmd; - TelReturn ret; - struct imc_set_volume_info cb_volume_info; + // Hard-coded values for MIC & Speakers + // Source volume + dbg("Set Source volume"); - dbg("entry"); + cmd_str = g_strdup_printf("%s", "AT+XDRV=40,7,3,88"); // Source type + dbg("Request command string: %s", cmd_str); - cb_volume_info.next_index = 1; - cb_volume_info.volume = volume_info->volume; + // Create new Pending request + src_pending = tcore_pending_new(o, 0); - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, - &cb_volume_info, sizeof(struct imc_set_volume_info)); + // Create new AT-Command request + src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE); + dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd)); - at_cmd = g_strdup_printf("%s", xdrv_set_volume[0]); + // Free Command string + g_free(cmd_str); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - at_cmd, "+XDRV", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - on_response_imc_call_set_volume_info, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_call_set_volume_info"); + tcore_pending_set_request_data(src_pending, 0, src_req); + src_ur = tcore_user_request_ref(ur); - g_free(at_cmd); - return ret; -} + // Send request + ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL); + if (!ret) { + err("Failed to send AT-Command request"); + return TCORE_RETURN_FAILURE; + } + cmd_str = g_strdup_printf("%s", "AT+XDRV=40,7,0,88"); // Destination type + dbg("Request command string: %s", cmd_str); -static TelReturn imc_call_get_volume_info(CoreObject *co, TelCallSoundDevice sound_device, - TcoreObjectResponseCallback cb, void *cb_data) -{ - dbg("Entry"); + // Create new Pending request + src_pending = tcore_pending_new(o, 0); - dbg("Exit"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; -} + // Create new AT-Command request + src_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE); + dbg("Command: %s, prefix(if any): %s, Command length: %d", src_req->cmd, src_req->prefix, strlen(src_req->cmd)); -/* - * Operation - Set sound path. - * - * Request - - * AT-Command: AT+XDRV=,[,] - * The first command parameter defines the involved driver group. - * The second command parameter defines a certain function in the selected driver group. - * Other parameters are dependent on the first two parameters. - * Nearly all parameters are integer values, also if they are represented by literals. - * Only very few are strings or - * hex data strings. - * - * Response - - * +XDRV: ,,[,] - * The first response parameter defines the involved driver group. - * The second response parameter defines the current function in the selected driver group. - * The third response parameter defines the xdrv_result of the operation. - * Additional response parameters dependent on the first two parameters. - */ + // Free Command string + g_free(cmd_str); -static TelReturn imc_call_set_sound_path(CoreObject *co, const TelCallSoundPathInfo *sound_path_info, - TcoreObjectResponseCallback cb, void *cb_data) -{ - ImcRespCbData *resp_cb_data = NULL; - TelReturn ret; - gchar *at_cmd; - gint device_type = -1; - TcorePlugin *plugin = tcore_object_ref_plugin(co); - const char *cp_name = tcore_server_get_cp_name_by_plugin(plugin); + tcore_pending_set_request_data(src_pending, 0, src_req); - dbg("audio device type - 0x%x", sound_path_info->path); + src_ur = tcore_user_request_ref(ur); - switch (sound_path_info->path) { - case TEL_SOUND_PATH_HANDSET: - device_type = 1; - break; - case TEL_SOUND_PATH_HEADSET: - device_type = 2; - break; - case TEL_SOUND_PATH_HEADSET_3_5PI: - device_type = 3; - break; - case TEL_SOUND_PATH_SPK_PHONE: - device_type = 4; - break; - case TEL_SOUND_PATH_HANDSFREE: - device_type = 5; - break; - case TEL_SOUND_PATH_HEADSET_HAC: - device_type = 6; - break; - case TEL_SOUND_PATH_BLUETOOTH: - case TEL_SOUND_PATH_STEREO_BLUETOOTH: - device_type = 7; - break; - case TEL_SOUND_PATH_BT_NSEC_OFF: - case TEL_SOUND_PATH_MIC1: - case TEL_SOUND_PATH_MIC2: - default: - dbg("unsupported device type"); - return TEL_RETURN_INVALID_PARAMETER; + // Send request + ret = _call_request_message(src_pending, o, src_ur, on_confirmation_call_set_source_sound_volume_level, NULL); + if (!ret) { + err("Failed to send AT-Command request"); + return TCORE_RETURN_FAILURE; } - if (g_str_has_prefix(cp_name, "imcmodem")) { - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, &device_type, sizeof(gint)); + // Destination volume + dbg("Set Source volume"); - at_cmd = g_strdup_printf("AT+XDRV=40,4,3,0,0,0,0,0,1,0,1,0,%d", device_type); + cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,88"); // Source type + dbg("Request command string: %s", cmd_str); - ret = tcore_at_prepare_and_send_request(co, - at_cmd, "+XDRV", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - on_response_imc_call_set_sound_path, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, NULL, "imc_call_set_sound_path"); - g_free(at_cmd); - } else { - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0); + // Create new Pending request + dest_pending = tcore_pending_new(o, 0); - /* Configure modem I2S1 to 8khz, mono, PCM if routing to bluetooth */ - if (sound_path_info->path == TEL_SOUND_PATH_BLUETOOTH || - sound_path_info->path == TEL_SOUND_PATH_STEREO_BLUETOOTH) { - tcore_at_prepare_and_send_request(co, - "AT+XDRV=40,4,3,0,1,0,0,0,0,0,0,0,21", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); - - tcore_at_prepare_and_send_request(co, - "AT+XDRV=40,5,2,0,1,0,0,0,0,0,0,0,22", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); - } else { - tcore_at_prepare_and_send_request(co, - "AT+XDRV=40,4,3,0,1,0,8,0,1,0,2,0,21", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); - - tcore_at_prepare_and_send_request(co, - "AT+XDRV=40,5,2,0,1,0,8,0,1,0,2,0,22", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); - } + // Create new AT-Command request + dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE); + dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd)); - /* Configure modem I2S2 and do the modem routing */ - tcore_at_prepare_and_send_request(co, - "AT+XDRV=40,4,4,0,0,0,8,0,1,0,2,0,21", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); + // Free Command string + g_free(cmd_str); + + tcore_pending_set_request_data(dest_pending, 0, dest_req); + dest_ur = tcore_user_request_ref(ur); - tcore_at_prepare_and_send_request(co, - "AT+XDRV=40,5,3,0,0,0,8,0,1,0,2,0,22", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); + // Send request + ret = _call_request_message(dest_pending, o, dest_ur, on_confirmation_call_set_source_sound_volume_level, NULL); + if (!ret) { + err("Failed to send AT-Command request"); + return TCORE_RETURN_FAILURE; + } + + dbg("Input volume level - %d", data->volume); + switch (data->volume) { + case CALL_SOUND_MUTE: + volume_level = "0"; + break; - tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,0,4", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); + case CALL_SOUND_VOLUME_LEVEL_1: + volume_level = "40"; + break; - tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,3,0", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); + case CALL_SOUND_VOLUME_LEVEL_2: + volume_level = "46"; + break; - tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,4,2", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); + case CALL_SOUND_VOLUME_LEVEL_3: + volume_level = "52"; + break; - tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,5,2", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); + case CALL_SOUND_VOLUME_LEVEL_4: + volume_level = "58"; + break; - /* amc enable */ - tcore_at_prepare_and_send_request(co, "AT+XDRV=40,2,4", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); + case CALL_SOUND_VOLUME_LEVEL_5: + volume_level = "64"; + break; - tcore_at_prepare_and_send_request(co, "AT+XDRV=40,2,3", - NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, NULL, NULL, NULL, NULL); + case CALL_SOUND_VOLUME_LEVEL_6: + volume_level = "70"; + break; - /* amc route: AMC_RADIO_RX => AMC_I2S1_TX */ - ret = tcore_at_prepare_and_send_request(co, "AT+XDRV=40,6,0,2", - "+XDRV", TCORE_AT_COMMAND_TYPE_SINGLELINE, NULL, - on_response_set_sound_path, resp_cb_data, NULL, NULL); + case CALL_SOUND_VOLUME_LEVEL_7: + volume_level = "76"; + break; + + case CALL_SOUND_VOLUME_LEVEL_8: + volume_level = "82"; + break; + + case CALL_SOUND_VOLUME_LEVEL_9: + default: + volume_level = "88"; + break; + } + cmd_str = g_strdup_printf("%s%s", "AT+XDRV=40,8,2,", volume_level); // Destination type + dbg("Request command string: %s", cmd_str); + + // Create new Pending request + dest_pending = tcore_pending_new(o, 0); + + // Create new AT-Command request + dest_req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE); + dbg("Command: %s, prefix(if any): %s, Command length: %d", dest_req->cmd, dest_req->prefix, strlen(dest_req->cmd)); - IMC_CHECK_REQUEST_RET(ret, NULL, "imc_call_set_sound_path"); + // Free Command string + g_free(cmd_str); + + tcore_pending_set_request_data(dest_pending, 0, dest_req); + + // Send request + ret = _call_request_message(dest_pending, o, ur, on_confirmation_call_set_destination_sound_volume_level, NULL); + if (!ret) { + err("Failed to send AT-Command request"); + return TCORE_RETURN_FAILURE; } - return ret; + return TCORE_RETURN_SUCCESS; } -/* - * Operation - Set/Unset mute status. - * - * Request - - * AT-Command: AT+XDRV=,[,] - * The first command parameter defines the involved driver group. - * The second command parameter defines a certain function in the selected driver group. - * Other parameters are dependent on the first two parameters. - * Nearly all parameters are integer values, also if they are represented by literals. - * Only very few are strings or - * hex data strings. - * - * Response - - * +XDRV: ,,[,] - * The first response parameter defines the involved driver group. - * The second response parameter defines the current function in the selected driver group. - * The third response parameter defines the xdrv_result of the operation. - * Additional response parameters dependent on the first two parameters. - */ -static TelReturn imc_call_set_mute(CoreObject *co, gboolean mute, TcoreObjectResponseCallback cb, - void *cb_data) +static TReturn imc_call_set_sound_mute_status(CoreObject *o, UserRequest *ur) { - ImcRespCbData *resp_cb_data = NULL; - gchar *at_cmd; - TelReturn ret; + struct treq_call_set_sound_mute_status *data = NULL; + char *cmd_str = NULL; + TReturn ret; + TcorePending *pending = NULL; + TcoreATRequest *req = NULL; - dbg("entry"); + dbg("function entrance"); - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0); + data = (struct treq_call_set_sound_mute_status *) tcore_user_request_ref_data(ur, 0); - /* AT - Command */ - if (mute) - at_cmd = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,0"); /*MUTE*/ - else - at_cmd = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,88"); /*UNMUTE*/ + if (data->status == CALL_SOUND_MUTE_STATUS_ON) + cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,0"); + else if (data->status == CALL_SOUND_MUTE_STATUS_OFF) + cmd_str = g_strdup_printf("%s", "AT+XDRV=40,8,0,0,88"); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - at_cmd, "+XDRV", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - on_response_imc_call_set_mute, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_call_set_mute"); + dbg("Request command : [%s]", cmd_str); - g_free(at_cmd); + pending = tcore_pending_new(o, 0); - return ret; + req = tcore_at_request_new(cmd_str, "+XDRV", TCORE_AT_SINGLELINE); + dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd)); + + g_free(cmd_str); + + // Set request data (AT command) to Pending request + tcore_pending_set_request_data(pending, 0, req); + + // Send request + ret = _call_request_message(pending, o, ur, on_confirmation_call_set_sound_mute_status, NULL); + if (!ret) { + err("Failed to send AT-Command request"); + return TCORE_RETURN_FAILURE; + } + + dbg("Exit"); + return TCORE_RETURN_SUCCESS; } -static TelReturn imc_call_get_mute_status(CoreObject *co, TcoreObjectResponseCallback cb, - void *cb_data) +static TReturn imc_call_set_preferred_voice_subscription(CoreObject *o, UserRequest *ur) { - dbg("entry"); + struct treq_call_set_preferred_voice_subscription *req_data = NULL; + Server *server; + Storage *strg = NULL; + TReturn ret = TCORE_RETURN_FAILURE; - dbg("exit"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; -} + dbg("Entry"); + + server = tcore_plugin_ref_server(tcore_object_ref_plugin(o)); + strg = tcore_server_find_storage(server, "vconf"); + + req_data = (struct treq_call_set_preferred_voice_subscription *) tcore_user_request_ref_data(ur, NULL); + dbg("Preferred Subscription: [%d]", req_data->preferred_subs); + + /* Update VCONF through Storage - req_data->preferred_subs is aligned to VCONFKEY values */ + if (tcore_storage_set_int(strg, STORAGE_KEY_TELEPHONY_PREFERRED_VOICE_SUBSCRIPTION, req_data->preferred_subs)) { + struct tresp_call_set_preferred_voice_subscription resp_data = {0, }; + + /* Send Response */ + resp_data.err = CALL_ERROR_NONE; + ret = tcore_user_request_send_response(ur, + TRESP_CALL_SET_PREFERRED_VOICE_SUBSCRIPTION, + sizeof(struct tresp_call_set_preferred_voice_subscription), &resp_data); + } + dbg("ret: [0x%x]", ret); + return ret; +} -static TelReturn imc_call_set_sound_recording(CoreObject *co, TelCallSoundRecording sound_rec, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn imc_call_get_preferred_voice_subscription(CoreObject *o, UserRequest *ur) { - dbg("entry"); + struct tresp_call_get_preferred_voice_subscription resp_data = {0, }; + TReturn ret = TCORE_RETURN_FAILURE; + Server *server; + Storage *strg = NULL; + + dbg("Entry"); + + server = tcore_plugin_ref_server(tcore_object_ref_plugin(o)); + strg = tcore_server_find_storage(server, "vconf"); + + /* VCONFKEY is aligned to resp_data->preferred_subs type */ + resp_data.preferred_subs = tcore_storage_get_int(strg, STORAGE_KEY_TELEPHONY_PREFERRED_VOICE_SUBSCRIPTION); + dbg("Preferred Subscription: [%d]", resp_data.preferred_subs); + + resp_data.err = CALL_ERROR_NONE; + /* Send Response */ + ret = tcore_user_request_send_response(ur, + TRESP_CALL_GET_PREFERRED_VOICE_SUBSCRIPTION, + sizeof(struct tresp_call_get_preferred_voice_subscription), &resp_data); - dbg("exit"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; + dbg("ret: [0x%x]", ret); + return ret; } -static TelReturn imc_call_set_sound_equalization(CoreObject *co, const TelCallSoundEqualization *sound_eq, - TcoreObjectResponseCallback cb, void *cb_data) +#if 0 +static TReturn _set_dtmf_tone_duration(CoreObject *o, UserRequest *ur) { - dbg("entry"); + char *cmd_str = NULL; + TcorePending *pending = NULL; + TcoreATRequest *req = NULL; + gboolean ret = FALSE; + + dbg("Entry"); + + cmd_str = g_strdup_printf("%s", "AT+VTD=3"); // ~300 mili secs. +VTD= n, where n = (0 - 255) * 1/10 secs. + dbg("Request command string: %s", cmd_str); + + // Create new Pending request + pending = tcore_pending_new(o, 0); + + // Create new AT-Command request + req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT); + dbg("Command: %s, prefix(if any): %s, Command length: %d", req->cmd, req->prefix, strlen(req->cmd)); + + // Free command string */ + g_free(cmd_str); + + // Set request data (AT command) to Pending request + tcore_pending_set_request_data(pending, 0, req); - dbg("exit"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; + // Send request + ret = _call_request_message(pending, o, ur, _on_confirmation_dtmf_tone_duration, NULL); + if (!ret) { + err("Failed to send AT-Command request"); + if (ur) { + tcore_user_request_free(ur); + ur = NULL; + } + return TCORE_RETURN_FAILURE; + } + + dbg("Exit"); + return TCORE_RETURN_SUCCESS; } +#endif -/* Call Operations */ -static TcoreCallOps imc_call_ops = { - .dial = imc_call_dial, +// Call Operations +static struct tcore_call_operations call_ops = { + .dial = imc_call_outgoing, .answer = imc_call_answer, - .end = imc_call_end, - .send_dtmf = imc_call_send_dtmf, + .end = imc_call_release, .hold = imc_call_hold, .active = imc_call_active, .swap = imc_call_swap, .join = imc_call_join, .split = imc_call_split, - .transfer = imc_call_transfer, .deflect = imc_call_deflect, - .set_active_line = imc_call_set_active_line, - .get_active_line = imc_call_get_active_line, - .set_volume_info = imc_call_set_volume_info, - .get_volume_info = imc_call_get_volume_info, + .transfer = imc_call_transfer, + .start_cont_dtmf = imc_call_start_cont_dtmf, + .stop_cont_dtmf = NULL, .set_sound_path = imc_call_set_sound_path, - .set_mute = imc_call_set_mute, - .get_mute_status = imc_call_get_mute_status, - .set_sound_recording = imc_call_set_sound_recording, - .set_sound_equalization = imc_call_set_sound_equalization, + .set_sound_volume_level = imc_call_set_sound_volume_level, + .get_sound_volume_level = NULL, + .set_sound_mute_status = imc_call_set_sound_mute_status, + .get_sound_mute_status = NULL, + .set_sound_equalization = NULL, + .set_sound_noise_reduction = NULL, + .set_preferred_voice_subscription = imc_call_set_preferred_voice_subscription, + .get_preferred_voice_subscription = imc_call_get_preferred_voice_subscription, }; -gboolean imc_call_init(TcorePlugin *p, CoreObject *co) +gboolean imc_call_init(TcorePlugin *cp, CoreObject *co_call) { dbg("Entry"); /* Set operations */ - tcore_call_set_ops(co, &imc_call_ops); + tcore_call_set_ops(co_call, &call_ops); /* Add Callbacks */ - tcore_object_add_callback(co, "+XCALLSTAT", on_notification_imc_call_status, NULL); - tcore_object_add_callback(co, "+CLIP", on_notification_imc_call_clip_info, NULL); - tcore_object_add_callback(co, "+CSSU", on_notification_imc_call_ss_cssu_info, NULL); - tcore_object_add_callback(co, "+CSSI", on_notification_imc_call_ss_cssi_info, NULL); + tcore_object_add_callback(co_call, "+XCALLSTAT", on_notification_call_info, NULL); + tcore_object_add_callback(co_call, "+CLIP", on_notification_call_clip_info, NULL); + + dbg("Exit"); return TRUE; } -void imc_call_exit(TcorePlugin *p, CoreObject *co) +void imc_call_exit(TcorePlugin *cp, CoreObject *co_call) { dbg("Exit"); } diff --git a/src/imc_common.c b/src/imc_common.c index a4b51fb..fb0646a 100644 --- a/src/imc_common.c +++ b/src/imc_common.c @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,44 +19,15 @@ */ #include -#include #include +#include #include - #include -#include -#include "imc_common.h" -void on_send_imc_request(TcorePending *p, - TelReturn send_status, void *user_data) -{ - dbg("Send - [%s]", - (send_status == TEL_RETURN_SUCCESS ? "OK" : "NOK")); -} - -ImcRespCbData *imc_create_resp_cb_data(TcoreObjectResponseCallback cb, - void *cb_data, void *data, guint data_len) -{ - ImcRespCbData *resp_cb_data; - - resp_cb_data = tcore_malloc0(sizeof(ImcRespCbData) + 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 imc_destroy_resp_cb_data(ImcRespCbData *resp_cb_data) -{ - if (resp_cb_data) - tcore_free(resp_cb_data); -} +#include "imc_common.h" -#if 0 #undef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) @@ -129,7 +102,7 @@ unsigned char util_hexCharToInt(char c) char *util_hex_to_string(const char *src, unsigned int src_len) { char *dest; - int i; + unsigned int i; if (src == NULL) return NULL; @@ -237,4 +210,3 @@ char* util_removeQuotes(void *data) return tmp; } -#endif diff --git a/src/imc_gps.c b/src/imc_gps.c index 750b015..964ca69 100644 --- a/src/imc_gps.c +++ b/src/imc_gps.c @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: sharanayya mathapati * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,38 +28,35 @@ #include #include -#include -#include -#include #include +#include +#include #include -#include +#include +#include +#include +#include #include -#include - - #include #include #include -#include -#include - -#include "imc_gps.h" #include "imc_common.h" +#include "imc_gps.h" -#define POSITION_NODE "pos" -#define POSITION_NODE_ATTR_XSI "xsi:noNamespaceSchemaLocation" -#define POSITION_NODE_ATTR_VAL_XSI "pos.xsd" -#define POSITION_NODE_ATTR_XMLNS "xmlns:xsi" -#define POSITION_NODE_ATTR_VAL_XMLNS "http://www.w3.org/2001/XMLSchema-instance" +#define FILE_NAME "/opt/home/root/sample.xml" +#define POSITION_NODE "pos" +#define POSITION_NODE_ATTR_XSI "xsi:noNamespaceSchemaLocation" +#define POSITION_NODE_ATTR_VAL_XSI "pos.xsd" +#define POSITION_NODE_ATTR_XMLNS "xmlns:xsi" +#define POSITION_NODE_ATTR_VAL_XMLNS "http://www.w3.org/2001/XMLSchema-instance" #define MAX_NUM_OF_GPS_REF_TIME_ELEMENT 12 // max number of gps satalite -#define MAX_NUM_OF_GPS_NAV_ELEMENT 16 // max num of navigation gps element. -#define MAX_NUM_OF_GPS_ALMANC_ELEMENTS 64 // Max num of almanc elements. +#define MAX_NUM_OF_GPS_NAV_ELEMENT 16 // max num of navigation gps element. +#define MAX_NUM_OF_GPS_ALMANC_ELEMENTS 64 // Max num of almanc elements. -#define NUM_OF_ELEMENTS(array) (sizeof(array) / sizeof(*(array))) +#define NUM_OF_ELEMENTS(array) (sizeof(array) / sizeof(*(array))) static char node_name[128]; // max len of xml node static char node_value[128]; // max len of xml node value. @@ -122,7 +121,7 @@ typedef struct { unsigned long int gpsTow; unsigned long int gpsWeek; unsigned char nrOfSats; - union { // Not supported. + union { // Not supported. gps_gsm_time_t gsm_time; gps_utran_time_t UtranTime; } networkTimeInfo; @@ -181,35 +180,35 @@ typedef struct { } __attribute__((packed)) gps_navi_subframe_rsv_t; typedef struct { - unsigned char ephemCodeOnL2; // 0~3 - unsigned char ephemUra; // 0~15 - unsigned char ephemSvHealth; // 0~63 - unsigned short ephemIodc; // 0~1023 - unsigned char ephemL2PFlag; // 0~1 + unsigned char ephemCodeOnL2; // 0~3 + unsigned char ephemUra; // 0~15 + unsigned char ephemSvHealth; // 0~63 + unsigned short ephemIodc; // 0~1023 + unsigned char ephemL2PFlag; // 0~1 gps_navi_subframe_rsv_t NavigationSubFrameRsv; - signed char ephemTgd; // -128~127 - unsigned short ephemToc; // 0~37799 - signed char ephemAf2; // -128~12 - signed short ephemAf1; // -32768~32767 - signed long int ephemAf0; // -2097152~2097151 - signed short ephemCrs; // -32768~32767 - signed short ephemDeltaN; // -32768~32767 - signed long int ephemM0; // -2147483648~2147483647 - signed short ephemCuc; // -32768~32767 - unsigned long int ephemE; // 0~4294967295 - signed short ephemCus; // -32768~32767 - unsigned long int ephemAPowrHalf; // 0~4294967295 - unsigned short ephemToe; // 0~37799 - signed char ephemFitFlag; // 0~1 - unsigned char ephemAoda; // 0~31 - signed short ephemCic; // -32768~32767 - signed long int ephemOmegaA0; // -2147483648~2147483647 - signed short ephemCis; // -32768~32767 - signed long int ephemI0; // -2147483648~2147483647 - signed short ephemCrc; // -32768~32767 - signed long int ephemW; // -2147483648~2147483647 - signed long int ephemOmegaADot; // -8388608~8388607 - signed short ephemIDot; // -8192~8191 + signed char ephemTgd; // -128~127 + unsigned short ephemToc; // 0~37799 + signed char ephemAf2; // -128~12 + signed short ephemAf1; // -32768~32767 + signed long int ephemAf0; // -2097152~2097151 + signed short ephemCrs; // -32768~32767 + signed short ephemDeltaN; // -32768~32767 + signed long int ephemM0; // -2147483648~2147483647 + signed short ephemCuc; // -32768~32767 + unsigned long int ephemE; // 0~4294967295 + signed short ephemCus; // -32768~32767 + unsigned long int ephemAPowrHalf; // 0~4294967295 + unsigned short ephemToe; // 0~37799 + signed char ephemFitFlag; // 0~1 + unsigned char ephemAoda; // 0~31 + signed short ephemCic; // -32768~32767 + signed long int ephemOmegaA0; // -2147483648~2147483647 + signed short ephemCis; // -32768~32767 + signed long int ephemI0; // -2147483648~2147483647 + signed short ephemCrc; // -32768~32767 + signed long int ephemW; // -2147483648~2147483647 + signed long int ephemOmegaADot; // -8388608~8388607 + signed short ephemIDot; // -8192~8191 } __attribute__((packed)) gps_navi_ephe_t; typedef enum { @@ -259,16 +258,16 @@ typedef struct { signed char dataId; // only for 3G, 0~3, if this value is -1, it means this value is invalid unsigned char satId; unsigned short almanacE; // 0~65536 - unsigned char almanacToa; // 0~255 - signed short almanacKsii; // -32768~3276 - signed short almanacOmegaDot; // -32768~3276 - unsigned char almanacSvHealth; // 0~255 + unsigned char almanacToa; // 0~255 + signed short almanacKsii; // -32768~3276 + signed short almanacOmegaDot; // -32768~3276 + unsigned char almanacSvHealth; // 0~255 unsigned long int almanacAPowerHalf; // 0~16777215 signed long int almanacOmega0; // -8388608~8388607 signed long int almanacW; // -8388608~8388607 signed long int almanacM0; // -8388608~8388607 - signed short almanacAf0; // -1024~1023 - signed short almanacAf1; // -1024~1023 + signed short almanacAf0; // -1024~1023 + signed short almanacAf1; // -1024~1023 } __attribute__((packed)) gps_almanac_sat_info_t; typedef struct { @@ -298,10 +297,10 @@ typedef struct { typedef struct { unsigned long int gpsTow; - union { + union { gps_gsm_time_t gsm_time; gps_acq_utran_time_t AcqUtranTime; - } acquisitionTimeInfo; // --- not supported. + } acquisitionTimeInfo; // --- not supported. unsigned long int numberOfSat; gps_acq_sat_info_t lcsAcquisitionSatInfo[16]; } __attribute__((packed)) gps_acq_assist_t; @@ -554,12 +553,53 @@ static t_element elements[] = { {"acqu_assist", ACQU_ASSIST}, }; + +/************************************************************************** +* Local Function Prototypes +**************************************************************************/ + +static inline int _modem_sat_status_info_2_tel_sat_info(char *sat_info); + +static inline int _modem_acqa_assit_doppler_2_tel_doppler(char *doppler_info); + +static int _gps_element_compare(char *element[], char *element_str, int nelem); + +static enum gps_assist_element_type _get_element_type(char *element_str); + +static void _parse_ref_time_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist, gboolean GPS_TOW_assist, int count); + +static void _parse_location_parameters(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist); + +static void _parse_dgps_correction_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist); + +static void _parse_ionospheric_model_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist); + +static void _parse_utc_model_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist); + +static void _parse_almanc_model_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist, gboolean alm_elem, int count); + +static void _parse_acqu_assist_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist); + +static void _parse_nav_model_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist, gboolean ephem_and_clock, int element_count); + +static void _set_coordinate(xmlNodePtr node, gps_ellipsoid_po_t *point, int isalt, int altitude); + +static void _set_loc_info_ellipse_elements(xmlNodePtr node, void *elliplse, int is_unc_ellipse); + +static xmlChar* _generate_confirm_measure_pos_xml_text(gps_measure_position_confirm_t *gps_measure_position_confirm); + +static gboolean on_notification_gps_measure_position_from_modem(CoreObject *o, char *file_name, void *user_data); + +/************************************************************************** +* Local Function Definitions + **************************************************************************/ + static inline int _modem_sat_status_info_2_tel_sat_info(char *sat_info) { int count; for (count = 0; count < (int) (sizeof(sat_status_info_table) / sizeof(sat_status_info_t)); count++) { - if (g_strcmp0(sat_status_info_table[count].psat_status, sat_info) == 0) + if (strcmp(sat_status_info_table[count].psat_status, sat_info) == 0) return (sat_status_info_table[count].stat_status); } return (-1); @@ -570,7 +610,7 @@ static inline int _modem_acqa_assit_doppler_2_tel_doppler(char *doppler_info) int count; for (count = 0; count < (int) (sizeof(doppler_status_info_table) / sizeof(doppler_status_info_t)); count++) { - if (g_strcmp0(doppler_status_info_table[count].pdoppler_status, doppler_info) == 0) + if (strcmp(doppler_status_info_table[count].pdoppler_status, doppler_info) == 0) return (doppler_status_info_table[count].doppler_status); } return (-1); @@ -581,23 +621,25 @@ static int _gps_element_compare(char *element[], char *element_str, int nelem) int count; for (count = 0; count < nelem; count++) { - if (g_strcmp0(element[count], element_str) == 0) + if (strcmp(element[count], element_str) == 0) return count; } return -1; } + static enum gps_assist_element_type _get_element_type(char *element_str) { unsigned int index; for (index = 0; index < sizeof(elements) / sizeof(t_element); index++) { - if (g_strcmp0(elements[index].name, element_str) == 0) + if (strcmp(elements[index].name, element_str) == 0) return elements[index].type; } return -1; } + static void _parse_ref_time_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist, gboolean GPS_TOW_assist, int count) { int node_count; @@ -606,7 +648,7 @@ static void _parse_ref_time_gps_elements(char *element_str, char *element_value, dbg("Enter"); if (count < 0 || count >= MAX_NUM_OF_GPS_REF_TIME_ELEMENT) { - err("invalid count"); + dbg("invalid count"); return; } nelem = (int) NUM_OF_ELEMENTS(element); @@ -666,7 +708,7 @@ static void _parse_ref_time_gps_elements(char *element_str, char *element_value, break; default: - err("Invalid gps element"); + dbg("Invalid gps element"); } } } @@ -691,7 +733,7 @@ static void _parse_location_parameters(char *element_str, char *element_value, g case 0: { // gpsdata_assist.ref_loc.latitude_data.north = atoi(element_str_text); - // dbg("gpsdata_assist.ref_loc.latitude_data.north - %d\n",gpsdata_assist.ref_loc.latitude_data.north); + // dbg("gpsdata_assist.ref_loc.latitude_data.north - %d\n",gpsdata_assist.ref_loc.latitude_data.north); } break; @@ -705,13 +747,13 @@ static void _parse_location_parameters(char *element_str, char *element_value, g case 2: { // gpsdata_assist.ref_loc.altitude_data.height_above_surface = atoi(element_str_text); - // dbg("altitude_data.height_above_surface - %d\n",gpsdata_assist.ref_loc.altitude_data.height_above_surface); + // dbg("altitude_data.height_above_surface - %d\n",gpsdata_assist.ref_loc.altitude_data.height_above_surface); } break; case 3: { - gpsdata_assist->ref_loc.altitude = atoi(element_value); // todo- need to confirm + gpsdata_assist->ref_loc.altitude = atoi(element_value); // todo- need to confirm dbg("altitude_data.height - %d\n", gpsdata_assist->ref_loc.altitude); } break; @@ -719,7 +761,7 @@ static void _parse_location_parameters(char *element_str, char *element_value, g case 4: { gpsdata_assist->ref_loc.longitude = atoi(element_value); - dbg("longitude - %d\n", gpsdata_assist->ref_loc.longitude); + dbg("longitude - %d\n", gpsdata_assist->ref_loc.longitude); } break; @@ -759,7 +801,7 @@ static void _parse_location_parameters(char *element_str, char *element_value, g break; default: - err("invalid element"); + dbg("invalid element"); } } @@ -767,19 +809,19 @@ static void _parse_dgps_correction_gps_elements(char *element_str, char *element { dbg("Enter"); - if (g_strcmp0(element_str, "sat_id") == 0) { + if (strcmp(element_str, "sat_id") == 0) { gpsdata_assist->dgps_corrections.seqOfSatElement[0].satId = *element_value; dbg("seqOfSatElement[0].satId - %d\n", gpsdata_assist->dgps_corrections.seqOfSatElement[0].satId); - } else if (g_strcmp0(element_str, "IODE") == 0) { + } else if (strcmp(element_str, "IODE") == 0) { gpsdata_assist->dgps_corrections.seqOfSatElement[0].iode = atoi(element_value); dbg("seqOfSatElement[0].iode - %d\n", gpsdata_assist->dgps_corrections.seqOfSatElement[0].iode); - } else if (g_strcmp0(element_str, "UDRE") == 0) { + } else if (strcmp(element_str, "UDRE") == 0) { gpsdata_assist->dgps_corrections.seqOfSatElement[0].udre = *element_value; dbg("seqOfSatElement[0].udre- %d\n", gpsdata_assist->dgps_corrections.seqOfSatElement[0].udre); - } else if (g_strcmp0(element_str, "PRC") == 0) { + } else if (strcmp(element_str, "PRC") == 0) { gpsdata_assist->dgps_corrections.seqOfSatElement[0].pseudoRangeCor = atoi(element_value); dbg("seqOfSatElement[0].pseudoRangeCor - %d\n", gpsdata_assist->dgps_corrections.seqOfSatElement[0].pseudoRangeCor); - } else if (g_strcmp0(element_str, "RRC") == 0) { + } else if (strcmp(element_str, "RRC") == 0) { gpsdata_assist->dgps_corrections.seqOfSatElement[0].rangeRateCor = atoi(element_value); dbg("seqOfSatElement[0].rangeRateCor - %d\n", gpsdata_assist->dgps_corrections.seqOfSatElement[0].rangeRateCor); } @@ -797,7 +839,7 @@ static void _parse_ionospheric_model_gps_elements(char *element_str, char *eleme case 0: { gpsdata_assist->iono_model.alfa0 = *element_value; - dbg("alfa0 - 0x%X\n", gpsdata_assist->iono_model.alfa0); + dbg("alfa0 - 0x%X\n", gpsdata_assist->iono_model.alfa0); } break; @@ -811,51 +853,51 @@ static void _parse_ionospheric_model_gps_elements(char *element_str, char *eleme case 2: { gpsdata_assist->iono_model.alfa2 = *element_value; - dbg("alfa2 - 0x%X\n", gpsdata_assist->iono_model.alfa2); + dbg("alfa2 - 0x%X\n", gpsdata_assist->iono_model.alfa2); } break; case 3: { gpsdata_assist->iono_model.alfa3 = *element_value; - dbg("alfa3 - 0x%X\n", gpsdata_assist->iono_model.alfa3); + dbg("alfa3 - 0x%X\n", gpsdata_assist->iono_model.alfa3); } break; case 4: { gpsdata_assist->iono_model.beta0 = *element_value; - dbg("beta0 - 0x%X\n", gpsdata_assist->iono_model.beta0); + dbg("beta0 - 0x%X\n", gpsdata_assist->iono_model.beta0); } break; case 5: { gpsdata_assist->iono_model.beta1 = *element_value; - dbg("beta1 -0x%X\n", gpsdata_assist->iono_model.beta1); + dbg("beta1 -0x%X\n", gpsdata_assist->iono_model.beta1); } break; case 6: { gpsdata_assist->iono_model.beta2 = *element_value; - dbg("beta2 - 0x%X\n", gpsdata_assist->iono_model.beta2); + dbg("beta2 - 0x%X\n", gpsdata_assist->iono_model.beta2); } break; case 7: { gpsdata_assist->iono_model.beta3 = *element_value; - dbg("beta3 - 0x%X\n", gpsdata_assist->iono_model.beta3); + dbg("beta3 - 0x%X\n", gpsdata_assist->iono_model.beta3); } break; default: - err("invalid gps element"); + dbg("invalid gps element"); } } -static void _parse_utc_model_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist) +void _parse_utc_model_gps_elements(char *element_str, char *element_value, gps_assist_data_noti_t *gpsdata_assist) { static char *element[] = {"a1", "a0", "tot", "wnt", "dtls", "wnlsf", "dn", "dtlsf"}; int nelem = (int) NUM_OF_ELEMENTS(element); @@ -868,14 +910,14 @@ static void _parse_utc_model_gps_elements(char *element_str, char *element_value case 0: { gpsdata_assist->utc_model.utcA1 = atoi(element_value); - dbg("utcA1 - %d\n", gpsdata_assist->utc_model.utcA1); + dbg("utcA1 - %d\n", gpsdata_assist->utc_model.utcA1); } break; case 1: { gpsdata_assist->utc_model.utcA0 = atoi(element_value); - dbg("utcA0 - %d\n", gpsdata_assist->utc_model.utcA0); + dbg("utcA0 - %d\n", gpsdata_assist->utc_model.utcA0); } break; @@ -910,7 +952,7 @@ static void _parse_utc_model_gps_elements(char *element_str, char *element_value case 6: { gpsdata_assist->utc_model.utcDN = *element_value; - dbg("utcDN - 0x%X\n", gpsdata_assist->utc_model.utcDN); + dbg("utcDN - 0x%X\n", gpsdata_assist->utc_model.utcDN); } break; @@ -922,7 +964,7 @@ static void _parse_utc_model_gps_elements(char *element_str, char *element_value break; default: - err("invalid gps element"); + dbg("invalid gps element"); } } @@ -962,7 +1004,7 @@ static void _parse_almanc_model_gps_elements(char *element_str, char *element_va case 2: { gpsdata_assist->almanac.AlmanacSatInfo[count].satId = *element_value; - dbg("AlmanacSatInfo[%d].sat_id - 0x%X\n", count, gpsdata_assist->almanac.AlmanacSatInfo[count].satId); + dbg("AlmanacSatInfo[%d].sat_id - 0x%X\n", count, gpsdata_assist->almanac.AlmanacSatInfo[count].satId); } break; @@ -976,7 +1018,7 @@ static void _parse_almanc_model_gps_elements(char *element_str, char *element_va case 4: { gpsdata_assist->almanac.AlmanacSatInfo[count].almanacToa = *element_value; - dbg("AlmanacSatInfo[%d].almanacToa - 0x%X\n", count, gpsdata_assist->almanac.AlmanacSatInfo[count].almanacToa); + dbg("AlmanacSatInfo[%d].almanacToa - 0x%X\n", count, gpsdata_assist->almanac.AlmanacSatInfo[count].almanacToa); } break; @@ -1032,19 +1074,19 @@ static void _parse_almanc_model_gps_elements(char *element_str, char *element_va case 12: { gpsdata_assist->almanac.AlmanacSatInfo[count].almanacAf0 = atoi(element_value); - dbg("AlmanacSatInfo[%d].almanacAf0 - %d\n", count, gpsdata_assist->almanac.AlmanacSatInfo[count].almanacAf0); + dbg("AlmanacSatInfo[%d].almanacAf0 - %d\n", count, gpsdata_assist->almanac.AlmanacSatInfo[count].almanacAf0); } break; case 13: { gpsdata_assist->almanac.AlmanacSatInfo[count].almanacAf1 = atoi(element_value); - dbg("AlmanacSatInfo[%d].almanacAf1 - %d\n", count, gpsdata_assist->almanac.AlmanacSatInfo[count].almanacAf1); + dbg("AlmanacSatInfo[%d].almanacAf1 - %d\n", count, gpsdata_assist->almanac.AlmanacSatInfo[count].almanacAf1); } break; default: - err("invalid gps element"); + dbg("invalid gps element"); } } return; @@ -1062,7 +1104,7 @@ static void _parse_acqu_assist_gps_elements(char *element_str, char *element_val switch (count) { case 0: gpsdata_assist->acq_assist.gpsTow = atoi(element_value); - dbg("acq_assist.gpsTow - %d\n", gpsdata_assist->acq_assist.gpsTow); + dbg("acq_assist.gpsTow - %d\n", gpsdata_assist->acq_assist.gpsTow); break; case 1: @@ -1077,7 +1119,7 @@ static void _parse_acqu_assist_gps_elements(char *element_str, char *element_val case 3: gpsdata_assist->acq_assist.lcsAcquisitionSatInfo[0].doppler1 = *element_value; - dbg("lcsAcquisitionSatInfo[0].doppler1 - 0x%X\n", gpsdata_assist->acq_assist.lcsAcquisitionSatInfo[0].doppler1); + dbg("lcsAcquisitionSatInfo[0].doppler1 - 0x%X\n", gpsdata_assist->acq_assist.lcsAcquisitionSatInfo[0].doppler1); break; case 4: @@ -1087,7 +1129,7 @@ static void _parse_acqu_assist_gps_elements(char *element_str, char *element_val case 5: gpsdata_assist->acq_assist.lcsAcquisitionSatInfo[0].intCodePhase = *element_value; - dbg("lcsAcquisitionSatInfo[0].intCodePhase - 0x%X\n", gpsdata_assist->acq_assist.lcsAcquisitionSatInfo[0].intCodePhase); + dbg("lcsAcquisitionSatInfo[0].intCodePhase - 0x%X\n", gpsdata_assist->acq_assist.lcsAcquisitionSatInfo[0].intCodePhase); break; case 6: @@ -1111,7 +1153,7 @@ static void _parse_acqu_assist_gps_elements(char *element_str, char *element_val break; default: - err("invalid gps element"); + dbg("invalid gps element"); } } @@ -1127,7 +1169,7 @@ static void _parse_nav_model_gps_elements(char *element_str, char *element_value int count; if (element_count < 0 || element_count >= MAX_NUM_OF_GPS_NAV_ELEMENT) { - err("invalid count"); + dbg("invalid count"); return; } count = _gps_element_compare(element, element_str, nelem); @@ -1263,12 +1305,13 @@ static void _parse_nav_model_gps_elements(char *element_str, char *element_value break; default: - err("invalid gps element"); + dbg("invalid gps element"); } } } -// Set coordinate elements : + +// Set coordinate elements : static void _set_coordinate(xmlNodePtr node, gps_ellipsoid_po_t *point, int isalt, int altitude) { // .. .. (xmlNodePtr node) @@ -1312,8 +1355,6 @@ static void _set_coordinate(xmlNodePtr node, gps_ellipsoid_po_t *point, int isal return; } - - static void _set_loc_info_ellipse_elements(xmlNodePtr node, void *elliplse, int is_unc_ellipse) { gps_po_unc_ellipse_t *p_unc_ellipse; @@ -1363,81 +1404,81 @@ static xmlChar* _generate_confirm_measure_pos_xml_text(gps_measure_position_conf int count = 0, altitude, size; /* - Creates a new XML document + Creates a new XML document ================================================================================================================================ - - - - - - - - - - - - - < - - - - - - - - - - - <> <\> ... - - - - - <> <\>.. - - - - - - - <> <\>... - - - - - <> <\>.. - - - - - - - - <> <\>.. .. - - - - - - - - - - <> <\> .. - < - - - - - - - - - - - + + + + + + + + + + + + + < + + + + + + + + + + + <> <\> ... + + + + + <> <\>.. + + + + + + + <> <\>... + + + + + <> <\>.. + + + + + + + + <> <\>.. .. + + + + + + + + + + <> <\> .. + < + + + + + + + + + + + ================================================================================================================================ */ @@ -1619,103 +1660,7 @@ static xmlChar* _generate_confirm_measure_pos_xml_text(gps_measure_position_conf return xml; } - -static gboolean on_notification_gps_measure_position_from_modem(CoreObject *o, char *file_name, void *user_data) -{ - char *node = NULL, *node_value = NULL; - char *attribute = NULL; - char *attr_value = NULL; - gps_measure_position_indi_t gps_measure_position_indi; - gboolean rep_quant = FALSE; - xmlTextReaderPtr reader; - - memset(&gps_measure_position_indi, 0x00, sizeof(gps_measure_position_indi)); - reader = xmlReaderForFile(file_name, NULL, 0); - - while (xmlTextReaderRead(reader)) { - switch (xmlTextReaderNodeType(reader)) { - case XML_READER_TYPE_ELEMENT: - { - node = (char *) xmlTextReaderConstName(reader); - dbg("Element: %s", node); - if (node != NULL) { - // Read attribute value. - while (xmlTextReaderMoveToNextAttribute(reader)) { - attribute = (char *) xmlTextReaderConstName(reader); - dbg("Attribute value - %s\n", attribute); - attr_value = (char *) xmlTextReaderConstValue(reader); - dbg("=\"%s\"\n", attr_value); - - if (g_strcmp0(node, "mult_sets") == 0) { - if (g_strcmp0(attribute, "literal") == 0) { - if (g_strcmp0(attr_value, "one") == 0) - gps_measure_position_indi.use_multi_sets = GPS_MULTIPLESETS_ONESET; - else if (g_strcmp0(attr_value, "multiple") == 0) - gps_measure_position_indi.use_multi_sets = GPS_MULTIPLESETS_MULTIPLESETS; - } - dbg("gps_measure_position_indi.use_multi_sets - 0x%x\n", gps_measure_position_indi.use_multi_sets); - } else if (g_strcmp0(node, "rep_quant") == 0) { - rep_quant = TRUE; - if (g_strcmp0(attribute, "addl_assist_data_req") == 0) { - if (g_strcmp0(attr_value, "true") == 0) - gps_measure_position_indi.add_assist_req = GPS_ADDITIONAL_ASSISREQ_REQ; - else - gps_measure_position_indi.add_assist_req = GPS_ADDITIONAL_ASSISREQ_NOT_REQ; - } else if (g_strcmp0(attribute, "gps_timing_of_cell_wanted") == 0) { - if (g_strcmp0(attr_value, "true") == 0) - gps_measure_position_indi.cell_timing_wnt = GPS_CELLTIMING_WANTED; - else - gps_measure_position_indi.cell_timing_wnt = GPS_CELLTIMING_NOT_WANTED; - } - } - } // end of attribute check - - if (g_strcmp0(node, "ms_assisted") == 0) { - gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_ASSISTED; - } else if (g_strcmp0(node, "ms_assisted_no_accuracy") == 0) { - gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_ASSISTED; - } else if (g_strcmp0(node, "ms_based") == 0) { - gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_BASED; - } else if (g_strcmp0(node, "ms_based_pref") == 0) { - gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_BASED_PREF; - } else if (g_strcmp0(node, "ms_assisted_pref") == 0) { - gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_ASSISTED_PREF; - } - } - xmlTextReaderMoveToElement(reader); - } - break; - - case XML_READER_TYPE_TEXT: - { - node_value = (char *) xmlTextReaderConstValue(reader); - dbg("element-value: %s", node_value); - if (node_value != NULL) { - if (g_strcmp0(node, "resp_time_seconds") == 0) { - gps_measure_position_indi.rsp_time = *node_value; - dbg("gps_measure_position_indi.rsp_time - 0x%x", gps_measure_position_indi.rsp_time); - } - if (rep_quant == TRUE) { - if (g_strcmp0(node, "hor_acc") == 0) - gps_measure_position_indi.accuracy.horizontalAccuracy = *node_value; - else if (g_strcmp0(node, "vert_acc") == 0) - gps_measure_position_indi.accuracy.vertcalAccuracy = *node_value; - } - } - } - break; - } - } - xmlFreeTextReader(reader); - xmlCleanupParser(); - - tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),(tcore_object_ref_plugin(o)), - TCORE_NOTIFICATION_GPS_MEASURE_POSITION, sizeof(gps_measure_position_indi), &gps_measure_position_indi); - return TRUE; -} - - -static gboolean on_notification_imc_gps_assist_data(CoreObject *o, const void *event_info, void *user_data) +static gboolean on_notification_gps_assist_data(CoreObject *o, const void *event_info, void *user_data) { int fd; gps_assist_data_noti_t gps_data_assist; @@ -1731,54 +1676,53 @@ static gboolean on_notification_imc_gps_assist_data(CoreObject *o, const void *e xmlTextReaderPtr reader; gboolean _gps_assist_data = FALSE, gps_tow_assist = FALSE; gboolean ephem_and_clock = FALSE, alm_elem = FALSE; - const char *path = NULL; dbg("enter"); /* - Example:GPS assist XML data will be in below format. + Example:GPS assist XML data will be in below format. ================================================================================================================================ - +CPOSR: - - - - - <> <\>..<\GPS_time> <> <\> ..<\GPS_TOW_assist> - - - - <> <\>... <\altitude> - - - - - - - - - - - <> <\> .. .. <\ephem_and_clock> - - - - - - - - - - - 0 <> <\> ...<\alm_elem> - - - - <> <\> ... <\sat_info> - - - - - + +CPOSR: + + + + + <> <\>..<\GPS_time> <> <\> ..<\GPS_TOW_assist> + + + + <> <\>... <\altitude> + + + + + + + + + + + <> <\> .. .. <\ephem_and_clock> + + + + + + + + + + + 0 <> <\> ...<\alm_elem> + + + + <> <\> ... <\sat_info> + + + + + ================================================================================================================================ */ @@ -1792,17 +1736,15 @@ static gboolean on_notification_imc_gps_assist_data(CoreObject *o, const void *e pos = (char *) xml_line; } line = g_strdup((char *) pos); - - path = tzplatform_mkpath(TZ_SYS_ROOT, "sample.xml"); // open file. - if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, S_IRWXU)) == -1) { - err("Cannot open file\n"); + if ((fd = open(FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, S_IRWXU)) == -1) { + dbg("Cannot open file\n"); g_free(line); return FALSE; } // write gps xml data into file. if (write(fd, (const void *) line, strlen(line)) == -1) { - err("Cannot write into file\n"); + dbg("Cannot write into file\n"); close(fd); g_free(line); return FALSE; @@ -1811,7 +1753,7 @@ static gboolean on_notification_imc_gps_assist_data(CoreObject *o, const void *e g_free(line); dbg("read xml file"); - reader = xmlReaderForFile(path, NULL, 0); + reader = xmlReaderForFile(FILE_NAME, NULL, 0); while (xmlTextReaderRead(reader)) { // Get the node type of the current node @@ -1824,23 +1766,23 @@ static gboolean on_notification_imc_gps_assist_data(CoreObject *o, const void *e if (node != NULL) { // check type of sub element of set_element_type = _get_element_type(node); - if ((int) set_element_type != -1) // ignore negative value as excepted element type not set. + if ((int) set_element_type != -1) // ignore negative value as excepted element type not set. node_type = set_element_type; - dbg("xml node type : %d", node_type); + dbg("xml node type : %d", node_type); // Check for position measurement data. - if (g_strcmp0(node, "pos_meas") == 0) { + if (strcmp(node, "pos_meas") == 0) { // Deallocate all the resources associated to the reader xmlFreeTextReader(reader); xmlCleanupParser(); dbg("gps postion measurement notification "); // GPS position measurement notification. - ret = on_notification_gps_measure_position_from_modem(o, path, user_data); + ret = on_notification_gps_measure_position_from_modem(o, FILE_NAME, user_data); // remove file. close(fd); - if (access(path, F_OK) == 0) { - if (remove(path)) + if (access(FILE_NAME, F_OK) == 0) { + if (remove(FILE_NAME)) dbg("file removed"); } return ret; @@ -1858,46 +1800,46 @@ static gboolean on_notification_imc_gps_assist_data(CoreObject *o, const void *e // Read attribute value of if (node_type == NAV_MODEL_ELEM) { - if (g_strcmp0(node, "sat_status") == 0 && g_strcmp0(attribute, "literal") == 0) { + if (strcmp(node, "sat_status") == 0 && strcmp(attribute, "literal") == 0) { gps_data_assist.navi_model.NavigationSatInfo[nav_model_node_count].NavigationSatStatus = _modem_sat_status_info_2_tel_sat_info(attr_value); dbg("navigation sat status of nav model element - %d\n", gps_data_assist.navi_model.NavigationSatInfo[nav_model_node_count].NavigationSatStatus); } } // Read attribute value of else if (node_type == ACQU_ASSIST) { - if (g_strcmp0(node, "dopl1_uncert") == 0 && g_strcmp0(attribute, "literal") == 0) { + if (strcmp(node, "dopl1_uncert") == 0 && strcmp(attribute, "literal") == 0) { gps_data_assist.acq_assist.lcsAcquisitionSatInfo[0].dopplerUncertainty = _modem_acqa_assit_doppler_2_tel_doppler(attr_value); dbg("doppler uncertainty of acqu assist data- %d", gps_data_assist.acq_assist.lcsAcquisitionSatInfo[0].dopplerUncertainty); } } - } // end of attribute check. + } // end of attribute check. // check GPS data is having GPS_assist data. - if (g_strcmp0(node, "GPS_assist") == 0) { + if (strcmp(node, "GPS_assist") == 0) { _gps_assist_data = TRUE; } if (_gps_assist_data == TRUE) { // number of GPS_TOW_assist elements. - if (g_strcmp0(node, "GPS_TOW_assist") == 0) { + if (strcmp(node, "GPS_TOW_assist") == 0) { gps_tow_assist_count++; gps_tow_assist = TRUE; - } else if (g_strcmp0(node, "nav_model_elem") == 0) { + } else if (strcmp(node, "nav_model_elem") == 0) { // number of nav_model_elem. nav_model_node_count++; - } else if (g_strcmp0(node, "alm_elem") == 0) { + } else if (strcmp(node, "alm_elem") == 0) { // number of alm_elem elements. alm_node_count++; dbg("alm_elem_count - %d", alm_node_count); if (node_type == ALMANAC) alm_elem = TRUE; - } else if (g_strcmp0(node, "ephem_and_clock") == 0 && node_type == NAV_MODEL_ELEM) { + } else if (strcmp(node, "ephem_and_clock") == 0 && node_type == NAV_MODEL_ELEM) { ephem_and_clock = TRUE; } } } xmlTextReaderMoveToElement(reader); - } // end of reading node type. + } // end of reading node type. break; case XML_READER_TYPE_TEXT: @@ -1941,10 +1883,10 @@ static gboolean on_notification_imc_gps_assist_data(CoreObject *o, const void *e break; default: - err("invalid element"); + dbg("invalid element"); } } - } // end of reading node value. + } // end of reading node value. break; } } // end of parsing. @@ -1955,126 +1897,219 @@ static gboolean on_notification_imc_gps_assist_data(CoreObject *o, const void *e // remove xml file. close(fd); - if (access(path, F_OK) == 0) { - if (remove(path)) + if (access(FILE_NAME, F_OK) == 0) { + if (remove(FILE_NAME)) dbg("file removed"); } - tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),(tcore_object_ref_plugin(o)), - TCORE_NOTIFICATION_GPS_ASSIST_DATA, sizeof(gps_data_assist), &gps_data_assist); - + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), + o, TNOTI_GPS_ASSIST_DATA, sizeof(gps_data_assist), &gps_data_assist); return TRUE; } -static gboolean on_notification_imc_reset_assist_data(CoreObject *o, const void *event_info, void *user_data) +static gboolean on_notification_gps_measure_position_from_modem(CoreObject *o, char *file_name, void *user_data) { - dbg("enter!\n"); - tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)),(tcore_object_ref_plugin(o)), - TCORE_NOTIFICATION_GPS_RESET_ASSIST_DATA, 0, NULL); + char *node = NULL, *node_value = NULL; + char *attribute = NULL; + char *attr_value = NULL; + gps_measure_position_indi_t gps_measure_position_indi; + gboolean rep_quant = FALSE; + xmlTextReaderPtr reader; + + memset(&gps_measure_position_indi, 0x00, sizeof(gps_measure_position_indi)); + reader = xmlReaderForFile(file_name, NULL, 0); + + while (xmlTextReaderRead(reader)) { + switch (xmlTextReaderNodeType(reader)) { + case XML_READER_TYPE_ELEMENT: + { + node = (char *) xmlTextReaderConstName(reader); + dbg("Element: %s", node); + if (node != NULL) { + // Read attribute value. + while (xmlTextReaderMoveToNextAttribute(reader)) { + attribute = (char *) xmlTextReaderConstName(reader); + dbg("Attribute value - %s\n", attribute); + attr_value = (char *) xmlTextReaderConstValue(reader); + dbg("=\"%s\"\n", attr_value); + + if (strcmp(node, "mult_sets") == 0) { + if (strcmp(attribute, "literal") == 0) { + if (strcmp(attr_value, "one") == 0) + gps_measure_position_indi.use_multi_sets = GPS_MULTIPLESETS_ONESET; + else if (strcmp(attr_value, "multiple") == 0) + gps_measure_position_indi.use_multi_sets = GPS_MULTIPLESETS_MULTIPLESETS; + } + dbg("gps_measure_position_indi.use_multi_sets - 0x%x\n", gps_measure_position_indi.use_multi_sets); + } else if (strcmp(node, "rep_quant") == 0) { + rep_quant = TRUE; + if (strcmp(attribute, "addl_assist_data_req") == 0) { + if (strcmp(attr_value, "true") == 0) + gps_measure_position_indi.add_assist_req = GPS_ADDITIONAL_ASSISREQ_REQ; + else + gps_measure_position_indi.add_assist_req = GPS_ADDITIONAL_ASSISREQ_NOT_REQ; + } else if (strcmp(attribute, "gps_timing_of_cell_wanted") == 0) { + if (strcmp(attr_value, "true") == 0) + gps_measure_position_indi.cell_timing_wnt = GPS_CELLTIMING_WANTED; + else + gps_measure_position_indi.cell_timing_wnt = GPS_CELLTIMING_NOT_WANTED; + } + } + } // end of attribute check + + if (strcmp(node, "ms_assisted") == 0) { + gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_ASSISTED; + } else if (strcmp(node, "ms_assisted_no_accuracy") == 0) { + gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_ASSISTED; + } else if (strcmp(node, "ms_based") == 0) { + gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_BASED; + } else if (strcmp(node, "ms_based_pref") == 0) { + gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_BASED_PREF; + } else if (strcmp(node, "ms_assisted_pref") == 0) { + gps_measure_position_indi.method_type = GPS_METHODTYPE_MS_ASSISTED_PREF; + } + } + xmlTextReaderMoveToElement(reader); + } + break; + case XML_READER_TYPE_TEXT: + { + node_value = (char *) xmlTextReaderConstValue(reader); + dbg("element-value: %s", node_value); + if (node_value != NULL) { + if (strcmp(node, "resp_time_seconds") == 0) { + gps_measure_position_indi.rsp_time = *node_value; + dbg("gps_measure_position_indi.rsp_time - 0x%x", gps_measure_position_indi.rsp_time); + } + if (rep_quant == TRUE) { + if (strcmp(node, "hor_acc") == 0) + gps_measure_position_indi.accuracy.horizontalAccuracy = *node_value; + else if (strcmp(node, "vert_acc") == 0) + gps_measure_position_indi.accuracy.vertcalAccuracy = *node_value; + } + } + } + break; + } + } + xmlFreeTextReader(reader); + xmlCleanupParser(); + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), + o, TNOTI_GPS_MEASURE_POSITION, sizeof(gps_measure_position_indi), &gps_measure_position_indi); return TRUE; } -/* GPS Responses */ -static void on_response_imc_gps_confirm_measure_pos(TcorePending *p, guint data_len, const void *data, void *user_data) -{ - //GPS server does not except confirmation for GPS measure position request. - const TcoreAtResponse *at_resp = data; - ImcRespCbData *resp_cb_data = user_data; +// CONFIRMATION +static void on_confirmation_gps_message_send(TcorePending *p, gboolean result, void *user_data) +{ dbg("Entry"); - if (at_resp && at_resp->success) { - dbg("Confirm measure position - [OK]"); + if (result == FALSE) { // Fail + dbg("SEND FAIL"); } else { - err("Confirm measure position - [NOK]"); + dbg("SEND OK"); } - imc_destroy_resp_cb_data(resp_cb_data); + dbg("Exit"); + return; } -/* GPS Operations */ -/* - * Operation - confirm measure position - * - * Request - - * AT-Command: AT+CPOS= - * text is entered - * - * Success: - * OK - * - * Failure: - * +CME ERROR: - */ +static gboolean on_notification_reset_assist_data(CoreObject *o, const void *event_info, void *user_data) +{ + dbg("enter!\n"); + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), + o, TNOTI_GPS_RESET_ASSIST_DATA, 0, NULL); -static TelReturn imc_gps_confirm_measure_pos (CoreObject *co, const TelGpsDataInfo *gps_data, - TcoreObjectResponseCallback cb, void *cb_data) + return TRUE; +} +static void on_confirmation_gps_measure_position(TcorePending *p, int data_len, const void *data, void *user_data) { - ImcRespCbData *resp_cb_data = NULL; + //GPS server does not except confirmation for GPS measure position request. + dbg("enter"); + + dbg("exit"); +} + +static TReturn gps_confirm_measure_pos(CoreObject *o, UserRequest *ur) +{ + char *raw_str = NULL; char *cmd_str = NULL; + TcorePending *pending = NULL; + TcoreATRequest *req = NULL; + TcoreHal *hal = NULL; + gboolean ret = FALSE; xmlChar *xml = NULL; + unsigned char *data = NULL; + unsigned int data_len; gps_measure_position_confirm_t gps_measure_pos_confirm; - TelReturn ret; - memcpy(&gps_measure_pos_confirm, gps_data->data, gps_data->data_len); + dbg("enter!"); + if (!o || !ur) + return TCORE_RETURN_EINVAL; + + data = (unsigned char *) tcore_user_request_ref_data(ur, &data_len); + memcpy(&gps_measure_pos_confirm, data, data_len); + // make confirm measure postion request in xml format. xml = _generate_confirm_measure_pos_xml_text(&gps_measure_pos_confirm); if (!xml) { err("xml text generation failed"); - return TEL_RETURN_FAILURE; + return TCORE_RETURN_EINVAL; } - /* AT - Command */ - cmd_str = g_strdup_printf("AT+CPOS%s%s\x1A", "\r", xml); - - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0); - - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - cmd_str, NULL, - TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, - on_response_imc_gps_confirm_measure_pos, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Confirm Measure Position"); + // AT+CPOStext is entered + raw_str = g_strdup_printf("AT+CPOS%s", "\r"); + cmd_str = g_strdup_printf("%s%s\x1A", raw_str, xml); + + dbg("command string : %s", cmd_str); + pending = tcore_pending_new(o, 0); + req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT); + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); + tcore_pending_set_request_data(pending, strlen(cmd_str), req); + tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT); + tcore_pending_set_send_callback(pending, on_confirmation_gps_message_send, NULL); + tcore_pending_set_response_callback(pending, on_confirmation_gps_measure_position, NULL); + tcore_pending_link_user_request(pending, ur); + + // HAL + hal = tcore_object_get_hal(o); + // Send request to HAL + ret = tcore_hal_send_request(hal, pending); + if (TCORE_RETURN_SUCCESS != ret) { + err("Request send failed"); + ret = FALSE; + } + dbg("exit"); + g_free(raw_str); g_free(cmd_str); - + xmlFree(xml); return ret; - } - - static TelReturn imc_gps_set_frequency_aiding (CoreObject *co, gboolean state, - TcoreObjectResponseCallback cb, void *cb_data) - { - return TEL_RETURN_OPERATION_NOT_SUPPORTED; - } - - -static TcoreGpsOps imc_gps_ops = { - .confirm_measure_pos = imc_gps_confirm_measure_pos, - .set_frequency_aiding = imc_gps_set_frequency_aiding +static struct tcore_gps_operations gps_ops = { + .confirm_measure_pos = gps_confirm_measure_pos, }; -gboolean imc_gps_init(TcorePlugin *p, CoreObject *co) +gboolean imc_gps_init(TcorePlugin *cp, CoreObject *co_gps) { dbg("Enter"); /* Set operations */ - tcore_gps_set_ops(co, &imc_gps_ops); + tcore_gps_set_ops(co_gps, &gps_ops); - /* Add Callbacks */ - tcore_object_override_callback(co, "+CPOSR", on_notification_imc_gps_assist_data, NULL); - tcore_object_override_callback(co, "+XCPOSR", on_notification_imc_reset_assist_data, NULL); + tcore_object_add_callback(co_gps, "+CPOSR", on_notification_gps_assist_data, NULL); + tcore_object_add_callback(co_gps, "+XCPOSR", on_notification_reset_assist_data, NULL); dbg("Exit"); + return TRUE; } -void imc_gps_exit(TcorePlugin *p, CoreObject *co) +void imc_gps_exit(TcorePlugin *cp, CoreObject *co_gps) { dbg("Exit"); } diff --git a/src/imc_modem.c b/src/imc_modem.c index d18215e..625e555 100644 --- a/src/imc_modem.c +++ b/src/imc_modem.c @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Harish Bishnoi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,851 +21,693 @@ #include #include #include +#include #include #include -#include -#include -#include #include +#include +#include +#include #include +#include #include +#include #include +#include -#include - -#include "imc_modem.h" #include "imc_common.h" +#include "imc_modem.h" #include "nvm/nvm.h" -static gboolean on_event_imc_nvm_update(CoreObject *co, - const void *event_info, void *user_data); - -static TelModemResult -__imc_modem_convert_cme_error_tel_modem_result(const TcoreAtResponse *at_resp) -{ - TelModemResult result = TEL_MODEM_RESULT_FAILURE; - const gchar *line; - GSList *tokens = NULL; - - dbg("Entry"); - if (!at_resp || !at_resp->lines) { - err("Invalid response data"); - return result; - } +#define ID_RESERVED_AT 0x0229 - line = (const gchar *)at_resp->lines->data; - tokens = tcore_at_tok_new(line); - if (g_slist_length(tokens) > 0) { - gchar *resp_str; - gint cme_err; +#define MAX_VERSION_LEN 32 +#define TAPI_MISC_ME_SN_LEN_MAX 32 +#define TAPI_MISC_PRODUCT_CODE_LEN_MAX 32 +#define TAPI_MISC_MODEL_ID_LEN_MAX 17 +#define TAPI_MISC_PRL_ERI_VER_LEN_MAX 17 - resp_str = g_slist_nth_data(tokens, 0); - if (!resp_str) { - err("Invalid CME Error data"); - tcore_at_tok_free(tokens); - return result; - } - cme_err = atoi(resp_str); - dbg("CME error[%d]", cme_err); +#define CPAS_RES_READY 0 +#define CPAS_RES_UNAVAIL 1 +#define CPAS_RES_UNKNOWN 2 +#define CPAS_RES_RINGING 3 +#define CPAS_RES_CALL_PROGRESS 4 +#define CPAS_RES_ASLEEP 5 +#define AT_VER_LEN 20 - switch (cme_err) { - case 3: - result = TEL_MODEM_RESULT_OPERATION_NOT_PERMITTED; - break; - case 4: - result = TEL_MODEM_RESULT_OPERATION_NOT_SUPPORTED; - break; +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, +}; - case 20: - result = TEL_MODEM_RESULT_MEMORY_FAILURE; - break; +typedef enum { + TAPI_MISC_ME_IMEI = 0x00, /**< 0x00: IMEI, GSM/UMTS device */ + TAPI_MISC_ME_ESN = 0x01, /**< 0x01: ESN(Electronic Serial Number), It`s essentially run out. CDMA device */ + TAPI_MISC_ME_MEID = 0x02, /**< 0x02: MEID, This value can have hexa decimal digits. CDMA device */ + TAPI_MISC_ME_MAX = 0xff /**< 0xff: reserved */ +} TelMiscSNIndexType_t; + +typedef struct { + TelMiscSNIndexType_t sn_index; /**< serial number index */ + int sn_len; /**< Length */ + unsigned char szNumber[TAPI_MISC_ME_SN_LEN_MAX]; /**< Number */ +} TelMiscSNInformation; + +/** + * Mobile Equipment Version Information + */ +typedef struct { + unsigned char ver_mask; /**< version mask - 0x01:SW_ver, 0x02:HW_ver, 0x04:RF_CAL_date, 0x08:Product_code, 0x10:Model_ID, 0x20:PRL, 0x04:ERI, 0xff:all */ + unsigned char szSwVersion[MAX_VERSION_LEN]; /**< Software version, null termination */ + unsigned char szHwVersion[MAX_VERSION_LEN]; /**< Hardware version, null termination */ + unsigned char szRfCalDate[MAX_VERSION_LEN]; /**< Calculation Date, null termination */ + unsigned char szProductCode[TAPI_MISC_PRODUCT_CODE_LEN_MAX]; /**< product code, null termination */ + unsigned char szModelId[TAPI_MISC_MODEL_ID_LEN_MAX]; /**< model id (only for CDMA), null termination */ + unsigned char prl_nam_num; /**< number of PRL NAM fields */ + unsigned char szPrlVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3]; /**< prl version (only for CDMA), null termination */ + unsigned char eri_nam_num; /**< number of PRL NAM fields */ + unsigned char szEriVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3]; /**< eri version (only for CDMA), null termination */ +} TelMiscVersionInformation; + + +static void prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback); +static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data); +static void on_response_network_registration(TcorePending *p, int data_len, const void *data, void *user_data); +static void on_response_enable_proactive_command(TcorePending *p, int data_len, const void *data, void *user_data); + +/* NVM */ +static gboolean on_event_nvm_update(CoreObject *o, const void *event_info, void *user_data); +static void modem_unsuspend_nvm_updates(CoreObject *o); +static void modem_send_nvm_update_ack(CoreObject *o); +static void modem_send_nvm_update_request_ack(CoreObject *o); + +static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data) +{ + dbg("on_confirmation_modem_message_send - msg out from queue.\n"); - case 50: - result = TEL_MODEM_RESULT_INVALID_PARAMETER; - break; + if (result == FALSE) { + /* Fail */ + dbg("SEND FAIL"); + } else { + dbg("SEND OK"); + } +} - case 100: - result = TEL_MODEM_RESULT_UNKNOWN_FAILURE; - break; +static void on_response_enable_proactive_command(TcorePending *p, int data_len, const void *data, void *user_data) +{ + const TcoreATResponse *resp = data; - default: - result = TEL_MODEM_RESULT_FAILURE; - } + if (resp->success > 0) { + dbg("RESPONSE OK proactive command enabled"); + } else { + dbg("RESPONSE NOK proactive command disabled"); } - tcore_at_tok_free(tokens); - - return result; } -/* NVM Req/Response */ -static gboolean __imc_modem_check_nvm_response(const void *data, int command) +static void on_response_network_registration(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - const char *line; - char *resp_str; - GSList *tokens = NULL; - gboolean ret = FALSE; - - dbg("Entered"); + const TcoreATResponse *resp = data; - /* +XDRV: ,,[,] */ - if (NULL == at_resp) { - err("Input data is NULL"); - return FALSE; + if (resp->success > 0) { + dbg("registration attempt OK"); + } else { + dbg("registration attempt failed"); } +} - if (at_resp->success > 0) { - dbg("RESPONSE OK"); - line = (const char *) (((GSList *) at_resp->lines)->data); - tokens = tcore_at_tok_new(line); - - /* Group ID */ - resp_str = g_slist_nth_data(tokens, 0); - if (NULL == resp_str) { - err("Group ID is missing "); - goto OUT; - } - else if (IUFP_GROUP_ID != atoi(resp_str)) { - err("Group ID mismatch"); - goto OUT; - } +void prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback) +{ + TcoreATRequest *req = NULL; + TcoreHal *hal = NULL; + TcorePending *pending = NULL; + TReturn ret; - /* Function ID */ - resp_str = g_slist_nth_data(tokens, 1); - if (NULL == resp_str) { - err("Function ID is missing "); - goto OUT; - } - else if (command != atoi(resp_str)) { - err("Function ID mismatch"); - goto OUT; - } + hal = tcore_object_get_hal(co); + dbg("hal: %p", hal); - /* XDRV Result */ - resp_str = g_slist_nth_data(tokens, 2); - if (NULL == resp_str) { - err("XDRV result is missing "); - goto OUT; - } - else if (XDRV_RESULT_OK != atoi(resp_str)) { - err("XDRV result[%d] ", atoi(resp_str)); - goto OUT; - } + pending = tcore_pending_new(co, 0); + if (!pending) + dbg("Pending is NULL"); + req = tcore_at_request_new(at_cmd, prefix, at_cmd_type); - /* Result code */ - resp_str = g_slist_nth_data(tokens, 3); - if (NULL == resp_str) { - err("UTA result is missing "); - goto OUT; - } - else if (UTA_SUCCESS != atoi(resp_str)) { - err("uta result[%d] ", atoi(resp_str)); - goto OUT; - } + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); - ret = TRUE; - } else { - dbg("Response NOK"); - } + tcore_pending_set_request_data(pending, 0, req); + tcore_pending_set_response_callback(pending, callback, NULL); + tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL); + ret = tcore_hal_send_request(hal, pending); -OUT: - tcore_at_tok_free(tokens); + if (ret != TCORE_RETURN_SUCCESS) + err("Failed to send AT request - ret: [0x%x]", ret); - dbg("Exit"); - return ret; } -static void __on_response_modem_unsuspend_nvm_updates(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_power_off(TcorePending *p, int data_len, const void *data, void *user_data) { - /* Check NVM response */ - if (TRUE == __imc_modem_check_nvm_response(data, IUFP_SUSPEND)) { - dbg("Priority level is set to get all updates since Boot-up"); + CoreObject *o = 0; + TcoreHal *h = 0; - /* Create NV data file */ - if (nvm_create_nvm_data() == FALSE) { - err("Failed to Create NV data file"); - } + o = tcore_pending_ref_core_object(p); + h = tcore_object_get_hal(o); - return; - } + dbg("modem power off"); - err("Response NOT OK"); + tcore_hal_set_power_state(h, FALSE); } -static void __imc_modem_unsuspend_nvm_updates(CoreObject *co) +static void on_response_set_flight_mode(TcorePending *p, int data_len, const void *data, void *user_data) { - char *cmd_str; - TelReturn ret; + CoreObject *o = NULL; + UserRequest *ur = NULL; + const TcoreATResponse *ATresp = data; + struct tresp_modem_set_flightmode res = {0}; + int response = 0; + struct tnoti_modem_flight_mode modem_flight_mode = {0}; + + o = tcore_pending_ref_core_object(p); + ur = tcore_pending_ref_user_request(p); + + if (ATresp->success > 0) { + dbg("RESPONSE OK - flight mode operation finished"); + res.result = TCORE_RETURN_SUCCESS; + } else { + GSList *tokens = NULL; + const char *line = NULL; + dbg("RESPONSE NOK"); - /* Prepare AT-Command */ - cmd_str = g_strdup_printf("AT+XDRV=%d, %d, %d, %d", - IUFP_GROUP_ID, IUFP_SUSPEND, - 0, UTA_FLASH_PLUGIN_PRIO_UNSUSPEND_ALL); + line = (const char *) ATresp->final_response; + tokens = tcore_at_tok_new(line); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - cmd_str, "+XDRV:", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - __on_response_modem_unsuspend_nvm_updates, NULL, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, NULL, "Unsuspend Nvm Updates"); + if (g_slist_length(tokens) < 1) { + dbg("err cause not specified or string corrupted"); + } else { + response = atoi(g_slist_nth_data(tokens, 0)); + err("error response: %d", response); + /* TODO: CMEE error mapping is required. */ + } + tcore_at_tok_free(tokens); + res.result = TCORE_RETURN_3GPP_ERROR; + } - g_free(cmd_str); -} + if (NULL == ur) { + dbg("No user request. Internal request created during boot-up sequence"); -static void __on_response_modem_send_nvm_update_ack(TcorePending *p, - guint data_len, const void *data, void *user_data) -{ - /* Check NVM response */ - if (TRUE == __imc_modem_check_nvm_response(data, IUFP_UPDATE_ACK)) { - dbg("[UPDATE ACK] OK"); - return; - } + if (ATresp->success > 0) { + modem_flight_mode.enable = tcore_modem_get_flight_mode_state(o); + dbg("sucess case - Sending Flight Mode Notification (%d) to Telephony Server", modem_flight_mode.enable); - err("[UPDATE ACK] NOT OK"); -} + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_FLIGHT_MODE, + sizeof(struct tnoti_modem_flight_mode), &modem_flight_mode); + } + } else { + const struct treq_modem_set_flightmode *req_data = NULL; -static void __imc_modem_send_nvm_update_ack(CoreObject *co) -{ - char *cmd_str; - TelReturn ret; + dbg("Sending response for Flight mode operation"); - /* Prepare AT-Command */ - cmd_str = g_strdup_printf("AT+XDRV=%s, %s", IUFP_GROUP, IUFP_UPDATE_ACK_STR); + req_data = tcore_user_request_ref_data(ur, NULL); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - cmd_str, "+XDRV:", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - __on_response_modem_send_nvm_update_ack, NULL, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, NULL, "Nvm Update Ack"); + if (TCORE_RETURN_SUCCESS == res.result) { + if (TRUE == req_data->enable){ + tcore_modem_set_flight_mode_state(o, TRUE); + } else { + tcore_modem_set_flight_mode_state(o, FALSE); + } + } + tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE, sizeof(struct tresp_modem_set_flightmode), &res); - g_free(cmd_str); -} + modem_flight_mode.enable = tcore_modem_get_flight_mode_state(o); + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_FLIGHT_MODE, + sizeof(struct tnoti_modem_flight_mode), &modem_flight_mode); -static void __on_response_modem_send_nvm_update_request_ack(TcorePending *p, - guint data_len, const void *data, void *user_data) -{ - /* Check NVM response */ - if (TRUE == __imc_modem_check_nvm_response(data, IUFP_UPDATE_REQ_ACK)) { - dbg("[REQUEST ACK] OK"); - return; + if (req_data->enable == 0) { + dbg("Flight mode is disabled, trigger COPS to register on network"); + /* Trigger Network registration (for the moment automatic) */ + prepare_and_send_pending_request(o, "AT+COPS=0", NULL, TCORE_AT_NO_RESULT, NULL); + } } - - err("[REQUEST ACK] NOT OK"); } -static void __imc_modem_send_nvm_update_request_ack(CoreObject *co) +static void on_response_imei(TcorePending *p, int data_len, const void *data, void *user_data) { - char *cmd_str; - TelReturn ret; + const TcoreATResponse *resp = data; + TcorePlugin *plugin = NULL; + struct tresp_modem_get_imei res; + TelMiscSNInformation *imei_property = NULL; + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line; + int response = 0; - /* Prepare AT-Command */ - cmd_str = g_strdup_printf("AT+XDRV=%s, %s", IUFP_GROUP, IUFP_UPDATE_REQ_ACK_STR); + memset(&res, 0, sizeof(struct tresp_modem_get_imei)); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - cmd_str, "+XDRV:", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - __on_response_modem_send_nvm_update_request_ack, NULL, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, NULL, "Nvm Update Request Ack"); + 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) != 1) { + msg("invalid message"); + goto OUT; + } + } + res.result = TCORE_RETURN_SUCCESS; + strncpy(res.imei, g_slist_nth_data(tokens, 0), 16); - g_free(cmd_str); -} + dbg("imei = [%s]", res.imei); -static void __on_response_modem_register_nvm(TcorePending *p, - guint data_len, const void *data, void *user_data) -{ - /* Check NVM response */ - if (TRUE == __imc_modem_check_nvm_response(data, IUFP_REGISTER)) { - dbg("Registering successful"); + plugin = tcore_pending_ref_plugin(p); + imei_property = tcore_plugin_ref_property(plugin, "IMEI"); + if (imei_property) { + imei_property->sn_index = TAPI_MISC_ME_IMEI; + imei_property->sn_len = strlen(res.imei); + memcpy(imei_property->szNumber, res.imei, imei_property->sn_len); + } + } else { + dbg("RESPONSE NOK"); + if (resp->lines) { + line = (const char *) resp->lines->data; + tokens = tcore_at_tok_new(line); + } - /* Send SUSPEND_UPDATE for all UPDATES */ - __imc_modem_unsuspend_nvm_updates(tcore_pending_ref_core_object(p)); - dbg("Exit"); - return; + if (g_slist_length(tokens) < 1) { + dbg("err cause not specified or string corrupted"); + res.result = TCORE_RETURN_3GPP_ERROR; + } else { + response = atoi(g_slist_nth_data(tokens, 0)); + err("error response: %d", response); + /* TODO: CMEE error mapping is required. */ + res.result = TCORE_RETURN_3GPP_ERROR; + } } - err("Response NOT OK"); -} + ur = tcore_pending_ref_user_request(p); + tcore_user_request_send_response(ur, TRESP_MODEM_GET_IMEI, + sizeof(struct tresp_modem_get_imei), &res); -/* 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"); +OUT: + if (tokens != NULL) + tcore_at_tok_free(tokens); - 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); + return; } -/* System functions */ -gboolean imc_modem_power_on_modem(TcorePlugin *plugin) +static void on_response_version(TcorePending *p, int data_len, const void *data, void *user_data) { - CoreObject *co; - TcoreStorage *strg; - gboolean flight_mode; - TelModemPowerStatus power_status; + const TcoreATResponse *resp = data; + TcorePlugin *plugin = NULL; + struct tresp_modem_get_version res = {0}; + TelMiscVersionInformation *vi_property = NULL; + TelMiscVersionInformation *vi = NULL; + UserRequest *ur = NULL; + GSList *tokens = NULL; + const char *line = NULL; + char *swver = NULL; + char *hwver = NULL; + char *caldate = NULL; + char *pcode = NULL; + char *id = NULL; + int response = 0; + + 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) == 1) { + swver = g_slist_nth_data(tokens, 0); + dbg("version: sw=[%s]", swver); + } else if (g_slist_length(tokens) == 5) { + swver = g_slist_nth_data(tokens, 0); + hwver = g_slist_nth_data(tokens, 1); + caldate = g_slist_nth_data(tokens, 2); + pcode = g_slist_nth_data(tokens, 3); + id = g_slist_nth_data(tokens, 4); + + dbg("version: sw=[%s], hw=[%s], rf_cal=[%s], product_code=[%s], model_id=[%s]", + swver, hwver, caldate, pcode, id); + } else { + msg("invalid message"); + goto OUT; + } + } - co = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM); - tcore_check_return_value_assert(co != NULL, FALSE); + vi = g_try_new0(TelMiscVersionInformation, 1); + if (NULL != swver) + memcpy(vi->szSwVersion, swver, strlen(swver)); + if (NULL != hwver) + memcpy(vi->szHwVersion, hwver, strlen(hwver)); + if (NULL != caldate) + memcpy(vi->szRfCalDate, caldate, strlen(caldate)); + if (NULL != pcode) + memcpy(vi->szProductCode, pcode, strlen(pcode)); + if (NULL != id) + memcpy(vi->szModelId, id, strlen(id)); + + memset(&res, 0, sizeof(struct tresp_modem_get_version)); + + if (NULL != swver) { + snprintf(res.software, + (AT_VER_LEN > strlen(swver) ? strlen(swver) : AT_VER_LEN), + "%s", swver); + } - /* Set Modem Power State to 'ON' */ - tcore_modem_set_powered(co, TRUE); + if (NULL != hwver) { + snprintf(res.hardware, + (AT_VER_LEN > strlen(hwver) ? strlen(hwver) : AT_VER_LEN), + "%s", hwver); + } - /* - * 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); + plugin = tcore_pending_ref_plugin(p); + vi_property = tcore_plugin_ref_property(plugin, "VERSION"); + memcpy(vi_property, vi, sizeof(TelMiscVersionInformation)); + g_free(vi); + } else { + dbg("RESPONSE NOK"); + if (resp->lines) { + line = (const char *) resp->lines->data; + tokens = tcore_at_tok_new(line); + } - return TRUE; -} + memset(&res, 0, sizeof(struct tresp_modem_get_version)); -/* Modem Responses */ -static void on_response_imc_modem_set_power_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); - ImcRespCbData *resp_cb_data = user_data; - TelModemPowerStatus *status; - gboolean powered = FALSE; - TelModemResult result = TEL_MODEM_RESULT_FAILURE; - dbg("Enter"); + if (g_slist_length(tokens) < 1) { + dbg("err cause not specified or string corrupted"); + res.result = TCORE_RETURN_3GPP_ERROR; + } else { + response = atoi(g_slist_nth_data(tokens, 0)); + err("error response: %d", response); + /* TODO: CMEE error mapping is required. */ + res.result = TCORE_RETURN_3GPP_ERROR; + } + } - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + ur = tcore_pending_ref_user_request(p); + tcore_user_request_send_response(ur, TRESP_MODEM_GET_VERSION, + sizeof(struct tresp_modem_get_version), &res); - if (at_resp && at_resp->success){ - dbg("RESPONSE OK"); - result = TEL_MODEM_RESULT_SUCCESS; - } else{ - err("RESPONSE NOK"); - result = __imc_modem_convert_cme_error_tel_modem_result(at_resp); - goto END; - } - - status = (TelModemPowerStatus *) - IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data); - - /* Update Core Object */ - switch (*status) { - case TEL_MODEM_POWER_ON: - dbg("Setting Modem Power status [ON] - [%s]", - (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); - powered = TRUE; - break; - case TEL_MODEM_POWER_OFF: - dbg("Setting Modem Power status [OFF] - [%s]", - (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); - powered = FALSE; - break; - default: - warn("Unexpected - Setting Modem Power status [RESET] - [%s]", - (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); - break; - } - tcore_modem_set_powered(co, powered); - -END: - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); - - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); +OUT: + if (tokens != NULL) + tcore_at_tok_free(tokens); + + return; } -static void on_response_imc_modem_set_flight_mode(TcorePending *p, - guint data_len, const void *data, void *user_data) +static enum tcore_hook_return on_hook_sim_status(Server *s, + CoreObject *source, enum tcore_notification_command command, + unsigned int data_len, void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *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){ - dbg("RESPONSE OK"); - result = TEL_MODEM_RESULT_SUCCESS; - } else{ - err("RESPONSE NOK"); - result = __imc_modem_convert_cme_error_tel_modem_result(at_resp); - goto END; + TcorePlugin *plugin; + const struct tnoti_sim_status *noti_sim_status; + CoreObject *co_sat; + CoreObject *co_network; + + plugin = tcore_object_ref_plugin(source); + co_sat = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SAT); + if (co_sat == NULL) + return TCORE_HOOK_RETURN_CONTINUE; + + co_network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK); + if (co_network == NULL) + return TCORE_HOOK_RETURN_CONTINUE; + + dbg("Get SIM status"); + noti_sim_status = data; + if (noti_sim_status == NULL) + return TCORE_HOOK_RETURN_CONTINUE; + + /* If SIM is initialized, Enable STK and and attach to Network */ + dbg("SIM Status: [%d]", noti_sim_status->sim_status); + if (noti_sim_status->sim_status == SIM_STATUS_INIT_COMPLETED) { + dbg("SIM ready for attach!!! Enable STK and attach to Network"); + + /* Sending AT+CFUN=6 */ + prepare_and_send_pending_request(co_sat, "AT+CFUN=6", NULL, + TCORE_AT_NO_RESULT, on_response_enable_proactive_command); + + /* Sending AT+COPS */ + prepare_and_send_pending_request(co_network, "AT+COPS=0", NULL, + TCORE_AT_NO_RESULT, on_response_network_registration); } - enable = (gboolean *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data); - - dbg("Setting Modem Fiight mode - [%s] - [%s]", - (*enable ? "ON": "OFF"), - (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); + return TCORE_HOOK_RETURN_CONTINUE; +} - /* Update Core Object */ - (void)tcore_modem_set_flight_mode_state(co, *enable); +gboolean modem_power_on(TcorePlugin *plugin) +{ + CoreObject *co_modem = NULL; + struct treq_modem_set_flightmode flight_mode_set = {0}; + struct tnoti_modem_power modem_power = {0}; + Storage *strg = NULL; + + co_modem = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM); + if (co_modem == NULL) { + err("Modem Core object is NULL"); + return FALSE; + } -END: - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); + /* Set Modem Power State to 'ON' */ + tcore_modem_set_powered(co_modem, TRUE); - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + /* Get Flight mode from VCONFKEY */ + strg = tcore_server_find_storage(tcore_plugin_ref_server(plugin), "vconf"); + flight_mode_set.enable = tcore_storage_get_bool(strg, STORAGE_KEY_FLIGHT_MODE_BOOL); - /* - * 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. - */ -} + /* Set Flight mode as per AP settings */ + if (flight_mode_set.enable) { /* Radio OFF */ + prepare_and_send_pending_request(co_modem, "AT+CFUN=4", NULL, + TCORE_AT_NO_RESULT, on_response_set_flight_mode); -/* Current modem does not support this operation */ -#if 0 -static void on_response_imc_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); - ImcRespCbData *resp_cb_data = user_data; - TelModemVersion version = {{0}, {0}, {0}, {0}}; + /* Set Flight mode TRUE */ + tcore_modem_set_flight_mode_state(co_modem, TRUE); + } else { /* Radio ON */ + prepare_and_send_pending_request(co_modem, "AT+CFUN=1", NULL, + TCORE_AT_NO_RESULT, on_response_set_flight_mode); - TelModemResult result = TEL_MODEM_RESULT_FAILURE; - dbg("Enter"); + /* Set Flight mode FALSE */ + tcore_modem_set_flight_mode_state(co_modem, FALSE); + } - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + /* Get IMEI */ + prepare_and_send_pending_request(co_modem, "AT+CGSN", NULL, + TCORE_AT_NUMERIC, on_response_imei); - if (at_resp) { - if (at_resp->lines) { - const gchar *line; - GSList *tokens = NULL; + /* Get Version Number */ + prepare_and_send_pending_request(co_modem, "AT+CGMR", NULL, + TCORE_AT_SINGLELINE, on_response_version); - 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); - if (sw_ver != NULL){ - g_strlcpy(version.software_version, - sw_ver, - TEL_MODEM_VERSION_LENGTH_MAX + 1); - } - if (hw_ver != NULL){ - g_strlcpy(version.hardware_version, - hw_ver, - TEL_MODEM_VERSION_LENGTH_MAX + 1); - } - if (calib_date != NULL){ - g_strlcpy(version.calibration_date, - calib_date, - TEL_MODEM_VERSION_LENGTH_MAX + 1); - } - if (p_code != NULL){ - 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); - } - } + /* Send Notification to TAPI - MODEM_POWER */ + modem_power.state = MODEM_STATE_ONLINE; - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, &version, resp_cb_data->cb_data); + dbg("Sending notification - Modem Power state: [ONLINE]"); + tcore_server_send_notification(tcore_plugin_ref_server(plugin), + co_modem, TNOTI_MODEM_POWER, sizeof(modem_power), &modem_power); - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + return TRUE; } -#endif -static void on_response_imc_modem_get_imei(TcorePending *p, - guint data_len, const void *data, void *user_data) +static TReturn power_off(CoreObject *o, UserRequest *ur) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - gchar imei[TEL_MODEM_IMEI_LENGTH_MAX +1] = {0}; + TcoreHal *hal = NULL; + TcoreATRequest *req = NULL; + TcorePending *pending = NULL; - TelModemResult result = TEL_MODEM_RESULT_FAILURE; - dbg("Enter"); + hal = tcore_object_get_hal(o); + pending = tcore_pending_new(o, 0); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + req = tcore_at_request_new("AT+CFUN=0", NULL, TCORE_AT_NO_RESULT); - if (at_resp) { - if (at_resp->lines) { - const gchar *line; - GSList *tokens = NULL; + dbg("Command: [%s], Prefix(if any): [%s], Command Length: [%d]", + req->cmd, req->prefix, strlen(req->cmd)); - 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)); - result = __imc_modem_convert_cme_error_tel_modem_result(at_resp); - } - } else { - err("Invalid response message"); - result = TEL_MODEM_RESULT_UNKNOWN_FAILURE; - } - tcore_at_tok_free(tokens); - } - } + tcore_pending_set_request_data(pending, 0, req); + tcore_pending_set_response_callback(pending, on_response_power_off, hal); + tcore_pending_link_user_request(pending, ur); + tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL); - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, imei, resp_cb_data->cb_data); + tcore_hal_send_request(hal, pending); - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + return TCORE_RETURN_SUCCESS; } -/* Modem Operations */ -/* - * Operation - set_power_status - * - * Request - - * AT-Command: AT+CFUN= - * where, - * - * 0 Mode to switch off MS - * ... Other modes are available for other oprations - * - * Response - - * Success: (No Result) - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn imc_modem_set_power_status(CoreObject *co, - TelModemPowerStatus status, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn get_imei(CoreObject *o, UserRequest *ur) { - gchar *at_cmd; - guint power_mode; - - ImcRespCbData *resp_cb_data; - TelReturn ret; - - if (status == TEL_MODEM_POWER_ON) { - warn("Modem Power ON - Not supported by CP"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; - } else if (status == TEL_MODEM_POWER_ERROR) { - err("Modem Power ERROR - Invalid mode"); - return TEL_RETURN_INVALID_PARAMETER; - } else { - dbg("Modem Power OFF"); - power_mode = 0; + TcoreHal *hal; + TcoreATRequest *req; + TcorePending *pending = NULL; + + hal = tcore_object_get_hal(o); + if (FALSE == tcore_hal_get_power_state(hal)) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; } + pending = tcore_pending_new(o, 0); - /* AT-Command */ - at_cmd = g_strdup_printf("AT+CFUN=%d", power_mode); - - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, - &status, sizeof(TelModemPowerStatus)); + req = tcore_at_request_new("AT+CGSN", NULL, TCORE_AT_NUMERIC); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - at_cmd, NULL, - TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, - on_response_imc_modem_set_power_status, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Power Status"); + dbg("Command: [%s], Prefix(if any): [%s], Command Length: [%d]", + req->cmd, req->prefix, strlen(req->cmd)); - /* Free resources */ - g_free(at_cmd); + tcore_pending_set_request_data(pending, 0, req); + tcore_pending_set_response_callback(pending, on_response_imei, hal); + tcore_pending_link_user_request(pending, ur); + tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL); - return ret; + return tcore_hal_send_request(hal, pending); } -/* - * Operation - set_flight_mode - * - * Request - - * AT-Command: AT+CFUN= - * where, - * - * 0 Mode to switch off MS - * 1 Full functionality - * 4 Mode to disable phone both transmit and receive - * RF circuits. Airplane mode. - * ... Other modes are available for other oprations - * - * Response - - * Success: (No Result) - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn imc_modem_set_flight_mode(CoreObject *co, gboolean enable, - TcoreObjectResponseCallback cb, void *cb_data) -{ - gchar *at_cmd; - guint power_mode; - - ImcRespCbData *resp_cb_data; - TelReturn ret; - if (enable) { - dbg("Flight mode - [ON]"); - power_mode = 4; - } else { - dbg("Flight mode - [OFF]"); - power_mode = 1; +static TReturn get_version(CoreObject *o, UserRequest *ur) +{ + TcoreHal *hal; + TcoreATRequest *req; + TcorePending *pending = NULL; + + hal = tcore_object_get_hal(o); + if (FALSE == tcore_hal_get_power_state(hal)) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; } + pending = tcore_pending_new(o, 0); - /* AT-Command */ - at_cmd = g_strdup_printf("AT+CFUN=%d", power_mode); - - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, - &enable, sizeof(gboolean)); + req = tcore_at_request_new("AT+CGMR", NULL, TCORE_AT_SINGLELINE); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - at_cmd, NULL, - TCORE_AT_COMMAND_TYPE_NO_RESULT, - NULL, - on_response_imc_modem_set_flight_mode, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Flight mode"); + dbg("Command: [%s], Prefix(if any): [%s], Command Length: [%d]", + req->cmd, req->prefix, strlen(req->cmd)); - /* Free resources */ - g_free(at_cmd); + tcore_pending_set_request_data(pending, 0, req); + tcore_pending_set_response_callback(pending, on_response_version, hal); + tcore_pending_link_user_request(pending, ur); + tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL); - return ret; + return tcore_hal_send_request(hal, pending); } -/* - * Operation - get_flight_mode - * - * Request - - * AT-Command: None - * Fetch information from Core Object - * - * Response - flight_mode (gboolean) - */ -static TelReturn imc_modem_get_flight_mode(CoreObject *co, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn set_flight_mode(CoreObject *o, UserRequest *ur) { - gboolean flight_mode; + TcoreHal *hal = NULL; + TcoreATRequest *req = NULL; + TcorePending *pending = NULL; + const struct treq_modem_set_flightmode *req_data = NULL; + char *cmd_str = NULL; + + hal = tcore_object_get_hal(o); + if (FALSE == tcore_hal_get_power_state(hal)) { + dbg("cp not ready/n"); + return TCORE_RETURN_ENOSYS; + } + pending = tcore_pending_new(o, 0); - /* 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")); + req_data = tcore_user_request_ref_data(ur, NULL); - /* Invoke response callback */ - if (cb) - cb(co, (gint)TEL_MODEM_RESULT_SUCCESS, &flight_mode, cb_data); + if (req_data->enable) { + dbg("Flight mode on/n"); + cmd_str = g_strdup("AT+CFUN=4"); + } else { + dbg("Flight mode off/n"); + cmd_str = g_strdup("AT+CFUN=1"); + } - return TEL_RETURN_SUCCESS; -} + req = tcore_at_request_new((const char *)cmd_str, NULL, TCORE_AT_NO_RESULT); + g_free(cmd_str); -/* - * Operation - get_version - * - * Request - - * AT-Command: AT+CGMR - * - * Response - version (TelModemVersion) - * Success: (Single line) - - * , , , - * OK - * Note: - * Success Response is different from standard 3GPP AT-Command (+CGMR) - * Failure: - * +CME ERROR: - */ -static TelReturn imc_modem_get_version(CoreObject *co, - TcoreObjectResponseCallback cb, void *cb_data) -{ - dbg("entry"); - - /* Current modem does not support this operation */ -#if 0 - ImcRespCbData *resp_cb_data; - TelReturn ret; - - /* Response callback data */ - resp_cb_data = imc_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, - TCORE_PENDING_PRIORITY_DEFAULT, - NULL, - on_response_imc_modem_get_version, resp_cb_data, - on_send_imc_request, NULL, - 0, NULL, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Version"); + dbg("Command: [%s], Prefix(if any): [%s], Command Length: [%d]", + req->cmd, req->prefix, strlen(req->cmd)); - return ret; -#endif + tcore_pending_set_request_data(pending, 0, req); + tcore_pending_set_response_callback(pending, on_response_set_flight_mode, hal); + tcore_pending_link_user_request(pending, ur); + tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL); - dbg("exit"); - return TEL_RETURN_OPERATION_NOT_SUPPORTED; + return tcore_hal_send_request(hal, pending); } -/* - * Operation - get_imei - * - * Request - - * AT-Command: AT+CGSN - * - * Response - imei (gchar array of length 20+'\0' bytes) - * Success: (Single line) - * - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn imc_modem_get_imei(CoreObject *co, - TcoreObjectResponseCallback cb, void *cb_data) +static TReturn get_flight_mode(CoreObject *co_modem, UserRequest *ur) { - ImcRespCbData *resp_cb_data; - TelReturn ret; + struct tresp_modem_get_flightmode resp_data; + TReturn ret; - dbg("Enter"); + memset(&resp_data, 0x0, sizeof(struct tresp_modem_get_flightmode)); - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, - NULL, 0); + 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")); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - "AT+CGSN", NULL, - TCORE_AT_COMMAND_TYPE_NUMERIC, - NULL, - on_response_imc_modem_get_imei, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get IMEI"); + 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 TcoreModemOps imc_modem_ops = { - .set_power_status = imc_modem_set_power_status, - .set_flight_mode = imc_modem_set_flight_mode, - .get_flight_mode = imc_modem_get_flight_mode, - .get_version = imc_modem_get_version, - .get_imei = imc_modem_get_imei +static struct tcore_modem_operations modem_ops = { + .power_on = NULL, + .power_off = power_off, + .power_reset = NULL, + .set_flight_mode = set_flight_mode, + .get_flight_mode = get_flight_mode, + .get_imei = get_imei, + .get_version = get_version, + .get_sn = NULL, + .dun_pin_ctrl = NULL, }; -gboolean imc_modem_init(TcorePlugin *p, CoreObject *co) +gboolean imc_modem_init(TcorePlugin *cp, CoreObject *co_modem) { + TelMiscVersionInformation *vi_property; + TelMiscSNInformation *imei_property; + TelMiscSNInformation *sn_property; + dbg("Enter"); /* Set operations */ - tcore_modem_set_ops(co, &imc_modem_ops); + tcore_modem_set_ops(co_modem, &modem_ops); + + vi_property = g_try_new0(TelMiscVersionInformation, 1); + tcore_plugin_link_property(cp, "VERSION", vi_property); + + imei_property = g_try_new0(TelMiscSNInformation, 1); + tcore_plugin_link_property(cp, "IMEI", imei_property); + + sn_property = g_try_new0(TelMiscSNInformation, 1); + tcore_plugin_link_property(cp, "SN", sn_property); - /* Add Callbacks */ - tcore_object_add_callback(co, "+XDRVI:", on_event_imc_nvm_update, NULL); + tcore_server_add_notification_hook(tcore_plugin_ref_server(cp), + TNOTI_SIM_STATUS, on_hook_sim_status, NULL); + dbg("Registering for +XDRVI event"); + tcore_object_add_callback(co_modem, "+XDRVI", on_event_nvm_update, NULL); dbg("Exit"); return TRUE; } -void imc_modem_exit(TcorePlugin *p, CoreObject *co) +void imc_modem_exit(TcorePlugin *cp, CoreObject *co_modem) { + TelMiscVersionInformation *vi_property; + TelMiscSNInformation *imei_property; + TelMiscSNInformation *sn_property; + TcorePlugin *plugin = tcore_object_ref_plugin(co_modem); + + vi_property = tcore_plugin_ref_property(plugin, "VERSION"); + g_free(vi_property); + + imei_property = tcore_plugin_ref_property(plugin, "IMEI"); + g_free(imei_property); + + sn_property = tcore_plugin_ref_property(plugin, "SN"); + g_free(sn_property); + dbg("Exit"); } @@ -871,7 +715,7 @@ void imc_modem_exit(TcorePlugin *p, CoreObject *co) * NV Manager - Support for Remote File System */ /* NVM Hook */ -static gboolean __imc_nvm_modem_rfs_hook(const char *data) +static gboolean modem_rfs_hook(const char *data) { if (data != NULL) if (data[NVM_FUNCTION_ID_OFFSET] == XDRV_INDICATION) @@ -880,9 +724,8 @@ static gboolean __imc_nvm_modem_rfs_hook(const char *data) return FALSE; } -/* NVM Event */ -gboolean on_event_imc_nvm_update(CoreObject *co, - const void *event_info, void *user_data) +/* NVM event Notification */ +static gboolean on_event_nvm_update(CoreObject *o, const void *event_info, void *user_data) { GSList *tokens = NULL; GSList *lines; @@ -910,7 +753,7 @@ gboolean on_event_imc_nvm_update(CoreObject *co, dbg("NV data processed successfully"); /* Acknowledge NV Update */ - __imc_modem_send_nvm_update_ack(co); + modem_send_nvm_update_ack(o); return ret; } else { @@ -933,7 +776,7 @@ gboolean on_event_imc_nvm_update(CoreObject *co, dbg("NV Update Request"); /* Acknowledge the Update Request */ - __imc_modem_send_nvm_update_request_ack(co); + modem_send_nvm_update_request_ack(o); break; case IUFP_NO_PENDING_UPDATE: @@ -954,30 +797,267 @@ gboolean on_event_imc_nvm_update(CoreObject *co, return ret; } -/* NVM Register */ -void imc_modem_register_nvm(CoreObject *co) +/* NVM Responses */ +static gboolean __modem_check_nvm_response(const void *data, int command) { + const TcoreATResponse *resp = data; + const char *line; + char *resp_str; + GSList *tokens = NULL; + gboolean ret = FALSE; + dbg("Entered"); + + /* +XDRV: ,,[,] */ + if (NULL == resp) { + err("Input data is NULL"); + return FALSE; + } + + if (resp->success > 0) { + dbg("RESPONSE OK"); + line = (const char *) (((GSList *) resp->lines)->data); + tokens = tcore_at_tok_new(line); + + /* Group ID */ + resp_str = g_slist_nth_data(tokens, 0); + if (NULL == resp_str) { + err("Group ID is missing "); + goto OUT; + } + else if (IUFP_GROUP_ID != atoi(resp_str)) { + err("Group ID mismatch"); + goto OUT; + } + + /* Function ID */ + resp_str = g_slist_nth_data(tokens, 1); + if (NULL == resp_str) { + err("Function ID is missing "); + goto OUT; + } + else if (command != atoi(resp_str)) { + err("Function ID mismatch"); + goto OUT; + } + + /* XDRV Result */ + resp_str = g_slist_nth_data(tokens, 2); + if (NULL == resp_str) { + err("XDRV result is missing "); + goto OUT; + } + else if (XDRV_RESULT_OK != atoi(resp_str)) { + err("XDRV result[%d] ", atoi(resp_str)); + goto OUT; + } + + /* Result code */ + resp_str = g_slist_nth_data(tokens, 3); + if (NULL == resp_str) { + err("UTA result is missing "); + goto OUT; + } + else if (UTA_SUCCESS != atoi(resp_str)) { + err("uta result[%d] ", atoi(resp_str)); + goto OUT; + } + + ret = TRUE; + } else { + dbg("Response NOK"); + } + +OUT: + tcore_at_tok_free(tokens); + + dbg("Exit"); + return ret; +} + +static void _on_response_modem_unsuspend_nvm_updates(TcorePending *p, + int data_len, const void *data, void *user_data) +{ + /* Check NVM response */ + if (TRUE == __modem_check_nvm_response(data, IUFP_SUSPEND)) { + dbg("Priority level is set to get all updates since Boot-up"); + + /* Create NV data file */ + if (nvm_create_nvm_data() == FALSE) { + err("Failed to Create NV data file"); + } + + return; + } + + err("Response NOT OK"); +} + +static void _on_response_modem_send_nvm_update_ack(TcorePending *p, + int data_len, const void *data, void *user_data) +{ + /* Check NVM response */ + if (TRUE == __modem_check_nvm_response(data, IUFP_UPDATE_ACK)) { + dbg("[UPDATE ACK] OK"); + return; + } + + err("[UPDATE ACK] NOT OK"); +} + +static void _on_response_modem_send_nvm_update_request_ack(TcorePending *p, + int data_len, const void *data, void *user_data) +{ + /* Check NVM response */ + if (TRUE == __modem_check_nvm_response(data, IUFP_UPDATE_REQ_ACK)) { + dbg("[REQUEST ACK] OK"); + return; + } + + err("[REQUEST ACK] NOT OK"); +} + +static void _on_response_modem_register_nvm(TcorePending *p, + int data_len, const void *data, void *user_data) +{ + /* Check NVM response */ + if (TRUE == __modem_check_nvm_response(data, IUFP_REGISTER)) { + dbg("Registering successful"); + + /* Send SUSPEND_UPDATE for all UPDATES */ + modem_unsuspend_nvm_updates(tcore_pending_ref_core_object(p)); + + dbg("Exit"); + return; + } + + err("Response NOT OK"); +} + +/* NVM Requests */ +static void modem_unsuspend_nvm_updates(CoreObject *o) +{ + TcorePending *pending = NULL; + char *cmd_str; + dbg("Entered"); + + /* Prepare AT-Command */ + cmd_str = g_strdup_printf("AT+XDRV=%d, %d, %d, %d", + IUFP_GROUP_ID, IUFP_SUSPEND, + 0, UTA_FLASH_PLUGIN_PRIO_UNSUSPEND_ALL); + + /* Prepare pending request */ + pending = tcore_at_pending_new(o, + cmd_str, + "+XDRV:", + TCORE_AT_SINGLELINE, + _on_response_modem_unsuspend_nvm_updates, + NULL); + if (pending == NULL) { + err("Failed to form pending request"); + } + else if (tcore_hal_send_request(tcore_object_get_hal(o), pending) + != TCORE_RETURN_SUCCESS) { + err("IUFP_SUSPEND - Unable to send AT-Command"); + } + else { + dbg("IUFP_SUSPEND - Successfully sent AT-Command"); + } + + g_free(cmd_str); +} + +static void modem_send_nvm_update_ack(CoreObject *o) +{ + TcorePending *pending = NULL; + char *cmd_str; + dbg("Entered"); + + /* Prepare AT-Command */ + cmd_str = g_strdup_printf("AT+XDRV=%s, %s", IUFP_GROUP, IUFP_UPDATE_ACK_STR); + + /* Prepare pending request */ + pending = tcore_at_pending_new(o, + cmd_str, + "+XDRV:", + TCORE_AT_SINGLELINE, + _on_response_modem_send_nvm_update_ack, + NULL); + if (pending == NULL) { + err("Failed to form pending request"); + } + else if (tcore_hal_send_request(tcore_object_get_hal(o), pending) + != TCORE_RETURN_SUCCESS) { + err("IUFP_UPDATE_ACK - Unable to send AT-Command"); + } + else { + dbg("IUFP_UPDATE_ACK - Successfully sent AT-Command"); + } + + g_free(cmd_str); +} + +static void modem_send_nvm_update_request_ack(CoreObject *o) +{ + TcorePending *pending = NULL; char *cmd_str; - TelReturn ret; + dbg("Entered"); + + /* Prepare AT-Command */ + cmd_str = g_strdup_printf("AT+XDRV=%s, %s", IUFP_GROUP, IUFP_UPDATE_REQ_ACK_STR); + + /* Prepare pending request */ + pending = tcore_at_pending_new(o, + cmd_str, + "+XDRV:", + TCORE_AT_SINGLELINE, + _on_response_modem_send_nvm_update_request_ack, + NULL); + + + if (pending == NULL) { + err("Failed to form pending request"); + } + else if (tcore_hal_send_request(tcore_object_get_hal(o), pending) + != TCORE_RETURN_SUCCESS) { + err("IUFP_UPDATE_REQ_ACK - Unable to send AT-Ccommand"); + } + else { + dbg("IUFP_UPDATE_REQ_ACK - Successfully sent AT-Command"); + } + + g_free(cmd_str); +} + +void modem_register_nvm(CoreObject *co_modem) +{ + TcorePending *pending = NULL; + char *cmd_str; + dbg("Entered"); /* Prepare AT-Command */ cmd_str = g_strdup_printf("AT+XDRV=%s, %s, %s", IUFP_GROUP, IUFP_REGISTER_STR, XDRV_ENABLE); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - cmd_str, "+XDRV:", - TCORE_AT_COMMAND_TYPE_SINGLELINE, - NULL, - __on_response_modem_register_nvm, NULL, - on_send_imc_request, NULL); - if (ret != TEL_RETURN_SUCCESS) { - err("Failed to process request - [Register NVM]"); + /* Prepare pending request */ + pending = tcore_at_pending_new(co_modem, + cmd_str, + "+XDRV:", + TCORE_AT_SINGLELINE, + _on_response_modem_register_nvm, + NULL); + if (pending == NULL) { + err("Failed to form pending request"); + } + else if (tcore_hal_send_request(tcore_object_get_hal(co_modem), pending) + != TCORE_RETURN_SUCCESS) { + err("IUFP_REGISTER (Enable) -Unable to send AT-Command"); } else { + dbg("IUFP_REGISTER (Enable) -Successfully sent AT-Command"); + /* Add RFS hook */ - dbg("Adding NVM hook"); - tcore_at_add_hook(tcore_object_get_hal(co), __imc_nvm_modem_rfs_hook); + /* Todo unblock this api */ + tcore_at_add_hook(tcore_object_get_hal(co_modem), modem_rfs_hook); } g_free(cmd_str); diff --git a/src/imc_network.c b/src/imc_network.c index e4b9b7c..0e85fdb 100644 --- a/src/imc_network.c +++ b/src/imc_network.c @@ -1,7 +1,9 @@ /* * tel-plugin-imc * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Harish Bishnoi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,21 +25,67 @@ #include #include -#include -#include -#include #include +#include +#include +#include #include +#include +#include +#include #include +#include #include -#include +#include -#include - -#include "imc_network.h" #include "imc_common.h" +#include "imc_network.h" -#define IMC_NETWORK_BASE_16 16 +#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 */ + +#define AT_COPS_MODE_AUTOMATIC 0 /* automatic ( field is ignored) */ +#define AT_COPS_MODE_MANUAL 1 /* manual ( field shall be present, and optionally) */ +#define AT_COPS_MODE_DEREGISTER 2 /* deregister from network */ +#define AT_COPS_MODE_SET_ONLY 3 /* set only */ +#define AT_COPS_MODE_MANUAL_AUTOMATIC 4 /*automatic - manual*/ + +#define AT_COPS_FORMAT_LONG_ALPHANUMERIC 0 /* long format alphanumeric */ +#define AT_COPS_FORMAT_SHORT_ALPHANUMERIC 1 /* short format alphanumeric */ +#define AT_COPS_FORMAT_NUMERIC 2 /* numeric */ + +#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 */ + +#define AT_GSM_XBANDSEL_AUTOMATIC 0 +#define AT_GSM_XBANDSEL_1800 1800 +#define AT_GSM_XBANDSEL_1900 1900 +#define AT_GSM_XBANDSEL_900 900 +#define AT_GSM_XBANDSEL_850 850 +#define AT_GSM_XBANDSEL_450 450 +#define AT_GSM_XBANDSEL_480 480 +#define AT_GSM_XBANDSEL_750 750 +#define AT_GSM_XBANDSEL_380 380 +#define AT_GSM_XBANDSEL_410 410 + +#define AT_XRAT_GSM 0 +#define AT_XRAT_DUAL 1 +#define AT_XRAT_UMTS 2 + +#define MAX_NETWORKS_PREF_PLMN_SUPPORT 150 +#define MAX_NETWORKS_MANUAL_SEARCH_SUPPORT 20 + +#define VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS "db/telephony/dualsim/default_data_service" typedef enum { IMC_NETWORK_SEARCH_STATE_NO_SEARCH, @@ -49,1829 +97,2331 @@ typedef struct { ImcNetworkSearchState search_state; } CustomData; -typedef struct { - CoreObject *co; - TelNetworkResult result; -} ImcNetworkCancelSearch; +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, +}; -static TelNetworkAct __imc_network_map_act(guint act) -{ - /* - * - * 0 GSM - * 2 UTRAN - * 3 GSM w/EGPRS - * 4 UTRAN w/HSDPA - * 5 UTRAN w/HSUPA - * 6 UTRAN w/HSDPA and HSUPA - */ - switch (act) { - case 0: - return TEL_NETWORK_ACT_GSM; - case 2: - return TEL_NETWORK_ACT_UMTS; - case 3: - return TEL_NETWORK_ACT_EGPRS; - case 4: - return TEL_NETWORK_ACT_HSDPA; - case 5: - return TEL_NETWORK_ACT_HSUPA; - case 6: - return TEL_NETWORK_ACT_HSPA; - default: - return TEL_NETWORK_ACT_UNKNOWN; - } -} +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 TelNetworkRegStatus __imc_network_map_stat(guint 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 gboolean get_serving_network(CoreObject *o, UserRequest *ur); -static void __on_response_imc_network_registration(TcorePending *p, - guint data_len, const void *data, void *user_data) + +static void on_confirmation_network_message_send(TcorePending *p, gboolean result, void *user_data) { - const TcoreAtResponse *at_resp = data; - dbg("Entry"); + dbg("on_confirmation_modem_message_send - msg out from queue.\n"); - if (at_resp && at_resp->success) { - dbg("Network Registration - [OK]"); + if (result == FALSE) { + /* Fail */ + dbg("SEND FAIL"); } else { - err("Network Registration - [NOK]"); + dbg("SEND OK"); } } -static void __imc_network_register_to_network(CoreObject *co) +static void nwk_prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, UserRequest *ur, TcorePendingResponseCallback callback) { - TelReturn ret; + TcoreATRequest *req = NULL; + TcoreHal *hal; + TcorePending *pending = NULL; + TReturn 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_imc_network_registration, NULL, - on_send_imc_request, NULL); - dbg("Sending Network Registration request: [%s]", - (ret == TEL_RETURN_SUCCESS ? "SUCCESS" : "FAIL")); + hal = tcore_object_get_hal(co); + + pending = tcore_pending_new(co, 0); + req = tcore_at_request_new(at_cmd, prefix, at_cmd_type); + + dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); + + tcore_pending_set_request_data(pending, 0, req); + tcore_pending_set_response_callback(pending, callback, req->cmd); + tcore_pending_link_user_request(pending, ur); + tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL); + + ret = tcore_hal_send_request(hal, pending); + + if (ret != TCORE_RETURN_SUCCESS) + err("Failed to send AT request - ret: [0x%x]", ret); + + return; } -static TelNetworkResult -__imc_network_convert_cme_error_tel_network_result(const TcoreAtResponse *at_resp) + +static void _insert_mcc_mnc_oper_list(TcorePlugin *p, CoreObject *o) { - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - const gchar *line; - GSList *tokens = NULL; + 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) { + dbg("fail to create database handle"); + return; + } - dbg("Entry"); + 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; - if (!at_resp || !at_resp->lines) { - err("Invalid response data"); - return result; + noi = calloc(sizeof(struct tcore_network_operator_info), 1); + + snprintf(noi->mcc, 4, "%s", (char *) g_hash_table_lookup(row, "1")); + snprintf(noi->mnc, 4, "%s", (char *) g_hash_table_lookup(row, "2")); + snprintf(noi->name, 41, "%s", (char *) g_hash_table_lookup(row, "3")); + snprintf(noi->country, 4, "%s", (char *) g_hash_table_lookup(row, "0")); + + tcore_network_operator_info_add(o, noi); + g_free(noi); + noi = NULL; + + count++; } - line = (const gchar *)at_resp->lines->data; - tokens = tcore_at_tok_new(line); - if (g_slist_length(tokens) > 0) { - gchar *resp_str; - gint cme_err; + dbg("count = %d", count); - resp_str = g_slist_nth_data(tokens, 0); - if (!resp_str) { - err("Invalid CME Error data"); - tcore_at_tok_free(tokens); - return result; - } - cme_err = atoi(resp_str); - dbg("CME error[%d]", cme_err); + g_hash_table_destroy(result); - switch (cme_err) { - case 3: - result = TEL_NETWORK_RESULT_OPERATION_NOT_PERMITTED; - break; + tcore_storage_remove_handle(strg, handle); +} + +static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type, + int domain, int act, int cs_status, int ps_status) +{ + enum telephony_network_service_type ret; + + ret = prev_type; - case 4: - result = TEL_NETWORK_RESULT_OPERATION_NOT_SUPPORTED; + switch (act) { + case NETWORK_ACT_UNKNOWN: + ret = NETWORK_SERVICE_TYPE_UNKNOWN; break; - case 20: - result = TEL_NETWORK_RESULT_MEMORY_FAILURE; + case NETWORK_ACT_GSM: + if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE && domain == NETWORK_SERVICE_DOMAIN_CS) + ret = NETWORK_SERVICE_TYPE_2_5G_EDGE; + else + ret = NETWORK_SERVICE_TYPE_2G; break; - case 30: - case 31: - result = TEL_NETWORK_RESULT_FAILURE; + case NETWORK_ACT_EGPRS: + return NETWORK_SERVICE_TYPE_2_5G_EDGE; break; - case 50: - result = TEL_NETWORK_RESULT_INVALID_PARAMETER; + case NETWORK_ACT_UMTS: + ret = NETWORK_SERVICE_TYPE_3G; break; + } - default: - result = TEL_NETWORK_RESULT_FAILURE; + 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; } } - tcore_at_tok_free(tokens); - return result; + return ret; } -static void __on_response_imc_network_fetch_nw_name_internal(CoreObject *co, - gint result, const void *response, void *user_data) +static void _ps_set(TcorePlugin *p, int status) { - TelNetworkIdentityInfo *identity = (TelNetworkIdentityInfo *)response; + CoreObject *co_ps; + + co_ps = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_PS); + if (co_ps == NULL) { + err("No PS Core Object on plugin"); + return; + } - /* Send notification if result is SUCCESS */ - if (result == TEL_NETWORK_RESULT_SUCCESS) - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_IDENTITY, - sizeof(TelNetworkIdentityInfo), identity); + if (status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) + tcore_ps_set_online(co_ps, TRUE); + else + tcore_ps_set_online(co_ps, FALSE); } -static TcoreHookReturn __on_response_imc_hook_set_flight_mode(CoreObject *co, - gint result, TcoreCommand command, const void *response, const void *user_data) +static void on_timeout_search_network(TcorePending *p, void *user_data) { + UserRequest *ur; + struct tresp_network_search resp; + CustomData *custom_data; - tcore_check_return_value(result == TEL_MODEM_RESULT_SUCCESS, - TCORE_HOOK_RETURN_CONTINUE); + dbg("TIMEOUT !!!!! pending=%p", p); - dbg("Flight mode 'disabled', register to Network"); + memset(&resp, 0, sizeof(struct tresp_network_search)); - /* - * TODO - Check for selection_mode - * Need to check if it is Manual or Automatic and based on - * that need to initiate Network Registratin accordingly. - */ - __imc_network_register_to_network(co); + resp.result = TCORE_RETURN_FAILURE; + resp.list_count = 0; - return TCORE_HOOK_RETURN_CONTINUE; + custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p)); + custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH; + + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &resp); + } } -static void __on_response_imc_network_fetch_nw_name(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_set_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkIdentityInfo identity = {0, }; + UserRequest *ur; + const TcoreATResponse *atResp = data; + // GSList *tokens = NULL; + // char * line = NULL; + struct tresp_network_set_plmn_selection_mode resp = {0}; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; + if (atResp->success > 0) { + dbg("RESPONSE OK"); + resp.result = TCORE_RETURN_SUCCESS; + } else { + dbg("RESPONSE NOK"); + resp.result = TCORE_RETURN_FAILURE; + } - dbg("Enter"); + 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), &resp); + } +} - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); +static void on_response_get_plmn_selection_mode(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur; + struct tresp_network_get_plmn_selection_mode resp = {0}; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + char *line = NULL; + int mode = 0; - if (at_resp && at_resp->success) { - if (at_resp->lines) { - const gchar *line; - GSList *tokens = NULL; - gchar *token_str; - guint i, nol; + resp.result = TCORE_RETURN_FAILURE; - /* Validate that only 3 lines of response is received */ - nol = g_slist_length(at_resp->lines); - if (nol > 3) { - err("Invalid response message"); - imc_destroy_resp_cb_data(resp_cb_data); - return; + if (atResp->success > 0) { + dbg("RESPONSE OK"); + /* Format of output + +COPS: [,,[,< AcT>]] + */ + + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + msg("invalid message"); + goto OUT; } + mode = atoi(tcore_at_tok_nth(tokens, 0)); + dbg("mode = %d", mode); + + switch (mode) { + case AT_COPS_MODE_AUTOMATIC: + resp.mode = NETWORK_SELECT_MODE_AUTOMATIC; + break; + + case AT_COPS_MODE_MANUAL: + case AT_COPS_MODE_MANUAL_AUTOMATIC: + resp.mode = NETWORK_SELECT_MODE_MANUAL; + break; + + case AT_COPS_MODE_DEREGISTER: + case AT_COPS_MODE_SET_ONLY: + resp.result = TCORE_RETURN_FAILURE; + goto OUT; + } + resp.result = TCORE_RETURN_SUCCESS; + } + } else { + dbg("RESPONSE NOK"); + resp.result = TCORE_RETURN_FAILURE; + } - /* Process the Multi-line response */ - for (i = 0; i < nol; i++) { - line = g_slist_nth_data(at_resp->lines, i); +OUT: + 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), &resp); + } - /* - * Tokenize - * - * +XCOPS: [,[,]] - */ - dbg(" : [%s]", line); - tokens = tcore_at_tok_new(line); + if (tokens != NULL) + tcore_at_tok_free(tokens); - if ((token_str = tcore_at_tok_nth(tokens, 0))) { - guint type = atoi(token_str); - dbg(" : [%d]", type); + return; +} - switch (type) { - case 0: /* 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); +static void on_response_search_network(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur; + struct tresp_network_search resp; + int i = 0; + char *line = NULL; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + GSList *network_token = NULL; + int AcT = 0; + char *temp_plmn_info = NULL; + char *alpha_name = NULL; + char *pResp = NULL; + int num_network_avail = 0; + CustomData *custom_data; - /* Update PLMN */ - tcore_network_set_plmn( co, identity.plmn); - } - } - break; + memset(&resp, 0, sizeof(struct tresp_network_search)); + resp.result = TCORE_RETURN_FAILURE; + resp.list_count = 0; - case 1: /* Short Name in ROM (NV-RAM) */ - case 3: /* Short Network Operator Name (CPHS) */ - case 5: /* Short NITZ 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); + custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p)); + if (!custom_data) { + err("Network Search Custom Data is Null"); + return; + } + if (atResp->success > 0) { + dbg("RESPONSE OK"); - /* Update Short name */ - tcore_network_set_short_name(co, identity.short_name); - } - } - break; + /* If Request is Cancelled then return back SUCCESS/SEARCH_CANCELLED */ + if (custom_data->search_state + == IMC_NETWORK_SEARCH_STATE_CANCELLED) { + dbg("Network Search has been Cancelled!!!"); + goto OUT; + } - case 2: /* Long Name in ROM (NV-RAM) */ - case 4: /* Long Network Operator Name (CPHS) */ - case 6: /* Full NITZ 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); + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + num_network_avail = g_slist_length(tokens); + dbg(" length of tokens is %d\n", num_network_avail); + if (num_network_avail < 1) { + msg("invalid message"); + goto OUT; + } + } - /* Update Long name */ - tcore_network_set_long_name(co, identity.long_name); - } - } - break; + resp.result = TCORE_RETURN_SUCCESS; - default: - break; - } - } + /* + * +COPS: [list of supported (,long alphanumeric , + * short alphanumeric ,numeric [,])s] + * [,,(list of supported s),(list of supported s)] + */ + for (i = 0; ((i < num_network_avail) && (i < MAX_NETWORKS_MANUAL_SEARCH_SUPPORT)); i++) { + network_token = tcore_at_tok_new(g_slist_nth_data(tokens, i)); - /* Free resource */ - tcore_at_tok_free(tokens); + pResp = (tcore_at_tok_nth(network_token, 0)); + if (pResp != NULL) { + dbg("status : %s", pResp); + resp.list[i].status = (enum telephony_network_plmn_status) atoi(pResp); + } + + if ((pResp = tcore_at_tok_nth(network_token, 1))) { /* Long Alpha name */ + dbg("Long Alpha name : %s", pResp); + + if (strlen(pResp) > 0) + /* Strip off starting quote & ending quote */ + strncpy(resp.list[i].name, pResp + 1, strlen(pResp) - 2); + } + + if ((pResp = tcore_at_tok_nth(network_token, 2))) { + dbg("Short Aplha name : %s", pResp); + /* Short Aplha name */ + /* Strip off starting quote & ending quote */ + if (strlen(pResp) > 0) + strncpy(resp.list[i].name, pResp + 1, strlen(pResp) - 2); + } + + /* PLMN ID */ + pResp = tcore_at_tok_nth(network_token, 3); + if (pResp != NULL) { + dbg("PLMN ID : %s", pResp); + temp_plmn_info = tcore_at_tok_extract((const char *)pResp); + strncpy(resp.list[i].plmn, temp_plmn_info, 6); + resp.list[i].plmn[6] = '\0'; + } + + /* Parse Access Technology */ + if ((pResp = tcore_at_tok_nth(network_token, 4))) { + if (strlen(pResp) > 0) { + AcT = atoi(pResp); + + if (0 == AcT) + resp.list[i].act = NETWORK_ACT_GSM; + else if (2 == AcT) + resp.list[i].act = NETWORK_ACT_UMTS; + } } - /* Send Notification - Network identity */ - dbg("Network name - Long name: [%s] Short name: [%s] " - "PLMN: [%s]", identity.long_name, - identity.short_name, identity.plmn); + dbg("Operator [%d] :: stat = %d, Name =%s, plmnId = %s, AcT=%d\n", resp.list_count, resp.list[i].status, resp.list[i].name, resp.list[i].plmn, resp.list[i].act); + resp.list_count++; - result = TEL_NETWORK_RESULT_SUCCESS; + tcore_at_tok_free(network_token); + g_free(alpha_name); + g_free(temp_plmn_info); } + } else { + dbg("RESPONSE NOK"); + resp.result = TCORE_RETURN_FAILURE; } - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, &identity, resp_cb_data->cb_data); +OUT: + custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH; - /* Free resource */ - tcore_free(identity.long_name); - tcore_free(identity.short_name); - tcore_free(identity.plmn); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, + TRESP_NETWORK_SEARCH, + sizeof(struct tresp_network_search), &resp); + } - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); + /* Free tokens */ + tcore_at_tok_free(tokens); } -/* - * Operation - fetch_nw_name - * - * Request - - * AT-Command: AT+XCOPS= - * - * may be - * 0 numeric format of network MCC/MNC (three BCD - * digit country code and two/three BCD digit network code) - * 1 Short Name in ROM (NV-RAM) - * 2 Long Name in ROM (NV-RAM) - * 3 Short Network Operator Name (CPHS) - * 4 Long Network Operator Name (CPHS) - * 5 Short NITZ Name - * 6 Full NITZ Name - * 7 Service Provider Name - * 8 EONS short operator name from EF-PNN - * 9 EONS long operator name from EF-PNN - * 11 Short PLMN name (When PS or CS is registered) - * 12 Long PLMN name (When PS or CS is registered) - * 13 numeric format of network MCC/MNC even in limited service - * - * Response - Network name - * Success: (Multiple Single line) - * +XCOPS: [,[,]] - * OK - * Failure: - * +CME ERROR: - */ -static TelReturn __imc_network_fetch_nw_name(CoreObject *co, - TcoreObjectResponseCallback cb, void *cb_data) +static void on_response_set_umts_band(TcorePending *p, int data_len, const void *data, void *user_data) { - ImcRespCbData *resp_cb_data = NULL; - TelReturn ret; + const TcoreATResponse *atResp = data; - /* Response callback data */ - resp_cb_data = imc_create_resp_cb_data(cb, cb_data, NULL, 0); + dbg("On Response Set UMTS Band"); - /* Send Request to modem */ - ret = tcore_at_prepare_and_send_request(co, - "AT+XCOPS=0;+XCOPS=5;+XCOPS=6", "+XCOPS", - TCORE_AT_COMMAND_TYPE_MULTILINE, - NULL, - __on_response_imc_network_fetch_nw_name, resp_cb_data, - on_send_imc_request, NULL); - IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Fetch Network name"); + if (atResp->success > 0) { + dbg("Response OK"); + } else { + dbg("Response NOK"); + } - return ret; + dbg("Wait for response of XRAT before sending final band setting response to AP"); + return; } -/* Hook functions */ -static TcoreHookReturn on_hook_imc_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_imc_hook_set_flight_mode, NULL); +static void on_response_set_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data) +{ + const TcoreATResponse *atResp = data; - return TCORE_HOOK_RETURN_CONTINUE; + dbg("On Response Set GSM Band"); + if (atResp->success > 0) { + dbg("Response OK"); + } else { + dbg("Response NOK"); } - dbg("Flight mode - [Enabled]"); - return TCORE_HOOK_RETURN_CONTINUE; + dbg("Wait for response of XRAT before sending final band setting response to AP"); + return; } -static TcoreHookReturn on_hook_imc_sim_status(TcorePlugin *plugin, - TcoreNotification command, guint data_len, void *data, void *user_data) +static void on_response_get_umts_band(TcorePending *p, int data_len, const void *data, void *user_data) { - const TelSimCardStatus *sim_status = (TelSimCardStatus *)data; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + const char *line = NULL; + int total_umts_bands = 0; + int i = 0; + char *band_token = NULL; + char umts_band[20] = {0}; + char umts_band_1 = 0; + char umts_band_2 = 0; + char umts_band_5 = 0; + UserRequest *ur = NULL; + struct tresp_network_get_band resp = {0}; + + dbg("Entry on_response_get_umts_band"); + + resp.mode = NETWORK_BAND_MODE_PREFERRED; + resp.result = TCORE_RETURN_SUCCESS; + + if (atResp->success > 0) { + dbg("RESPONSE OK"); + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + total_umts_bands = g_slist_length(tokens); + dbg("Total UMTS bands enabled are : %d\n", total_umts_bands); + if (total_umts_bands < 1) { + goto OUT; + } + } + } else { + dbg("RESPONSE NOK"); + goto OUT; + } - tcore_check_return_value(sim_status != NULL, - TCORE_HOOK_RETURN_CONTINUE); + for (i = 0; i < total_umts_bands; i++) { + band_token = tcore_at_tok_nth(tokens, i); - /* - * 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"); + if (band_token == NULL) + continue; - tcore_check_return_value_assert(co != NULL, - TCORE_HOOK_RETURN_CONTINUE); + memset(umts_band, 0x00, sizeof(umts_band)); - /* - * TODO - Check for selection_mode - * Need to check if it is Manual or Automatic and based on - * that need to initiate Network Registratin accordingly. - */ - __imc_network_register_to_network(co); + if (atoi(band_token) == 0) { /* 0 means UMTS automatic */ + umts_band_1 = umts_band_2 = umts_band_5 = TRUE; + break; + } - return TCORE_HOOK_RETURN_CONTINUE; - } + /* Strip off starting quotes & ending quotes */ + strncpy(umts_band, band_token + 1, strlen(band_token) - 2); - dbg("SIM not yet initialized - SIM Status: [%d]", *sim_status); - return TCORE_HOOK_RETURN_CONTINUE; -} + if (!strcmp(umts_band, "UMTS_BAND_I")) { + umts_band_1 = TRUE; + } else if (!strcmp(umts_band, "UMTS_BAND_II")) { + umts_band_2 = TRUE; + } else if (!strcmp(umts_band, "UMTS_BAND_II")) { + umts_band_5 = TRUE; + } else { + /* Telephony is not interest */ + dbg("Telephony is not interested in %s band", umts_band); + } + } -/* Notification callbacks */ -/* - * Notification: +CREG: [,,[,]] - * - * Possible values of 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 - * - * - * string type; two byte location area code in - * hexadecimal format (e.g. 00C3) - * - * - * string type; four byte cell ID in hexadecimal - * format (e.g. 0000A13F) - * - * - * 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_imc_cs_network_info(CoreObject *co, - const void *event_info, void *user_data) -{ - GSList *lines = NULL; - gchar *line = NULL; +OUT: + if ((umts_band_1) && (umts_band_2) && (umts_band_5)) { + resp.band = NETWORK_BAND_TYPE_WCDMA; + } else if (umts_band_1) { + resp.band = NETWORK_BAND_TYPE_WCDMA2100; + } else if (umts_band_2) { + resp.band = NETWORK_BAND_TYPE_WCDMA1900; + } else if (umts_band_5) { + resp.band = NETWORK_BAND_TYPE_WCDMA850; + } else { + resp.result = TCORE_RETURN_FAILURE; + } - dbg("Network notification - CS network info: [+CREG]"); + dbg("Final resp.band sent to TS = %d", resp.band); - 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; + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp); } - 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; + if (tokens != NULL) + tcore_at_tok_free(tokens); - /* - * Tokenize - * - * +CREG: [,,[,]] - */ - tokens = tcore_at_tok_new(line); - if (g_slist_length(tokens) < 1) { - err("Invalid notification message"); - goto out; - } + dbg("Exit on_response_get_umts_band"); + return; +} - /* */ - if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) { - err("No in +CREG"); - goto out; +static void on_response_get_gsm_band(TcorePending *p, int data_len, const void *data, void *user_data) +{ + struct tresp_network_get_band resp = {0}; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + int total_gsm_bands = 0; + const char *line = NULL; + int i = 0; + char *band_token = NULL; + UserRequest *ur = NULL; + int gsm_850 = 0; + int gsm_900 = 0; + int gsm_1800 = 0; + int gsm_1900 = 0; + + dbg("Entry on_response_get_gsm_band"); + + resp.mode = NETWORK_BAND_MODE_PREFERRED; + resp.result = TCORE_RETURN_SUCCESS; + + if (atResp->success > 0) { + dbg("RESPONSE OK"); + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + total_gsm_bands = g_slist_length(tokens); + dbg("Total GSM bands enabled are : %d\n", total_gsm_bands); + if (total_gsm_bands < 1) + goto OUT; } - stat = __imc_network_map_stat(atoi(token_str)); - (void)tcore_network_set_cs_reg_status(co, stat); - - /* */ - 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, IMC_NETWORK_BASE_16); + for (i = 0; i < total_gsm_bands; i++) { + band_token = tcore_at_tok_nth(tokens, i); - /* Update Location Area Code (lac) information */ - (void)tcore_network_set_lac(co, lac); + if (band_token == NULL) + continue; - tcore_free(token_str); - } else { - dbg("No in +CREG"); - (void)tcore_network_get_lac(co, &lac); + if (atoi(band_token) == 0) { /* 0 means GSM automatic */ + gsm_850 = gsm_900 = gsm_1800 = gsm_1900 = TRUE; + break; } - /* */ - if ((token_str = g_slist_nth_data(tokens, 2))) { - token_str = tcore_at_tok_extract((const gchar *)token_str); + switch (atoi(band_token)) { + case AT_GSM_XBANDSEL_850: + gsm_850 = TRUE; + break; - ci = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16); + case AT_GSM_XBANDSEL_900: + gsm_900 = TRUE; + break; - /* Update Cell ID (ci) information */ - (void)tcore_network_set_cell_id(co, ci); + case AT_GSM_XBANDSEL_1800: + gsm_1800 = TRUE; + break; - tcore_free(token_str); - } else { - dbg("No in +CREG"); - (void)tcore_network_get_cell_id(co, &ci); - } + case AT_GSM_XBANDSEL_1900: + gsm_1900 = TRUE; + break; - /* */ - if ((token_str = g_slist_nth_data(tokens, 3))) { - act = __imc_network_map_act(atoi(token_str)); - (void)tcore_network_set_access_technology(co, act); - } else { - dbg("No in +CREG"); - (void)tcore_network_get_access_technology(co, &act); - } - dbg(": %d : 0x%x : 0x%x : %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)__imc_network_fetch_nw_name(co, - __on_response_imc_network_fetch_nw_name_internal, NULL); - break; default: - break; + break; } + } - /* Set Roaming state */ - tcore_network_set_roam_state(co, roam_state); +OUT: + + if (gsm_850 && gsm_900 && gsm_1800 && gsm_1900) { + resp.band = NETWORK_BAND_TYPE_GSM; + } else if (gsm_850 && gsm_1900) { + resp.band = NETWORK_BAND_TYPE_GSM_850_1900; + } else if (gsm_900 && gsm_1800) { + resp.band = NETWORK_BAND_TYPE_GSM_900_1800; + } else if (gsm_1900) { + resp.band = NETWORK_BAND_TYPE_GSM1900; + } else if (gsm_850) { + resp.band = NETWORK_BAND_TYPE_GSM850; + } else if (gsm_1800) { + resp.band = NETWORK_BAND_TYPE_GSM1800; + } else if (gsm_900) { + resp.band = NETWORK_BAND_TYPE_GSM900; + } else { + resp.result = TCORE_RETURN_FAILURE; + } - /* Send Notification - Cell info */ - cell_info.lac = (gint)lac; - cell_info.cell_id = (gint)ci; - (void)tcore_network_get_rac(co, &cell_info.rac); + dbg("Final resp.band sent to TS = %d", resp.band); - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO, - sizeof(TelNetworkCellInfo), &cell_info); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp); + } -out: - /* Free resource */ + if (tokens != NULL) tcore_at_tok_free(tokens); - } - return TRUE; + dbg("Exit on_response_get_gsm_band"); + return; } -/* - * Notification: +CGREG: [,,[,,]] - * - * Possible values of 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 - * - * - * string type; two byte location area code in - * hexadecimal format (e.g. 00C3) - * - * - * string type; four byte cell ID in hexadecimal - * format (e.g. 0000A13F) - * - * - * 0 GSM - * 2 UTRAN - * 3 GSM w/EGPRS - * 4 UTRAN w/HSDPA - * 5 UTRAN w/HSUPA - * 6 UTRAN w/HSDPA and HSUPA - * - * : - * string type; one byte routing area code in hexadecimal format - */ -static gboolean on_notification_imc_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]"); +static void on_response_get_xrat(TcorePending *p, int data_len, const void *data, void *user_data) +{ + TcoreHal *h = NULL; + UserRequest *ur = NULL; + + TcoreATRequest *atreq; + char *cmd_str = NULL; + UserRequest *dup_ur = NULL; + const TcoreATResponse *atResp = data; + const char *line = NULL; + char *pResp = NULL; + GSList *tokens = NULL; + TcorePending *pending = NULL; + CoreObject *o = NULL; + int cp_xrat = 0; + struct tresp_network_get_band resp = {0}; - 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; - } + dbg("Enter on_response_get_xrat !!"); - 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; + resp.mode = NETWORK_BAND_MODE_PREFERRED; - /* - * Tokenize - * - * +CGREG: [,,[,,]] - */ - tokens = tcore_at_tok_new(line); - if (g_slist_length(tokens) < 1) { - err("Invalid notification message"); - goto out; - } + ur = tcore_pending_ref_user_request(p); + h = tcore_object_get_hal(tcore_pending_ref_core_object(p)); + o = tcore_pending_ref_core_object(p); - /* */ - if ((token_str = g_slist_nth_data(tokens, 0)) == NULL) { - err("No in +CGREG"); - goto out; + if (atResp->success > 0) { + dbg("RESPONSE OK"); + if (atResp->lines) { + line = (char *) atResp->lines->data; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + msg("invalid message"); + goto OUT; + } } - stat = __imc_network_map_stat(atoi(token_str)); - (void)tcore_network_set_ps_reg_status(co, stat); - /* */ - if ((token_str = g_slist_nth_data(tokens, 1))) { - token_str = tcore_at_tok_extract((const gchar *)token_str); + if ((pResp = tcore_at_tok_nth(tokens, 0))) { + cp_xrat = atoi(pResp); - lac = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16); + if ((cp_xrat == AT_XRAT_DUAL)) { /* mode is Dual, send reply to Telephony */ + resp.result = TCORE_RETURN_SUCCESS; + resp.band = NETWORK_BAND_TYPE_ANY; - /* Update Location Area Code (lac) information */ - (void)tcore_network_set_lac(co, lac); - - tcore_free(token_str); - } else { - dbg("No in +CGREG"); - (void)tcore_network_get_lac(co, &lac); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp); + } + goto OUT; + } else if ((cp_xrat == AT_XRAT_UMTS)) { + /* Get UMTS Band Information */ + dup_ur = tcore_user_request_ref(ur); /* duplicate user request for AT+XUBANDSEL */ + cmd_str = g_strdup_printf("AT+XUBANDSEL?"); + atreq = tcore_at_request_new(cmd_str, "+XUBANDSEL", TCORE_AT_SINGLELINE); + pending = tcore_pending_new(o, 0); + tcore_pending_set_request_data(pending, 0, atreq); + tcore_pending_set_response_callback(pending, on_response_get_umts_band, NULL); + tcore_pending_link_user_request(pending, ur); + tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL); + tcore_hal_send_request(h, pending); + g_free(cmd_str); + } else if ((cp_xrat == AT_XRAT_UMTS)) { + /* Get GSM Band Information */ + dup_ur = tcore_user_request_ref(ur); /* duplicate user request for AT+XBANDSEL */ + cmd_str = g_strdup_printf("AT+XBANDSEL?"); + atreq = tcore_at_request_new(cmd_str, "+XBANDSEL", TCORE_AT_SINGLELINE); + pending = tcore_pending_new(o, 0); + tcore_pending_set_request_data(pending, 0, atreq); + tcore_pending_set_response_callback(pending, on_response_get_gsm_band, NULL); + tcore_pending_link_user_request(pending, dup_ur); + tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL); + tcore_hal_send_request(h, pending); + g_free(cmd_str); + } } + } else { + dbg("RESPONSE NOK"); - /* */ - if ((token_str = g_slist_nth_data(tokens, 2))) { - token_str = tcore_at_tok_extract((const gchar *)token_str); + resp.result = TCORE_RETURN_FAILURE; + resp.band = NETWORK_BAND_TYPE_ANY; - ci = (guint)strtol(token_str, NULL, IMC_NETWORK_BASE_16); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_BAND, sizeof(struct tresp_network_get_band), &resp); + } + } +OUT: - /* Update Cell ID (ci) information */ - (void)tcore_network_set_cell_id(co, ci); + if (tokens != NULL) + tcore_at_tok_free(tokens); - tcore_free(token_str); - } else { - dbg("No in +CGREG"); - (void)tcore_network_get_cell_id(co, &ci); - } + dbg("Exit on_response_get_xrat !!"); - /* */ - if ((token_str = g_slist_nth_data(tokens, 3))) { - act = __imc_network_map_act(atoi(token_str)); - (void)tcore_network_set_access_technology(co, act); - } else { - dbg("No in +CGREG"); - (void)tcore_network_get_access_technology(co, &act); - } + return; +} - /* */ - 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, IMC_NETWORK_BASE_16); +static void on_response_set_xrat(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + struct tresp_network_set_band resp = {0}; + const TcoreATResponse *atResp = data; - /* Update Routing Area Code (rac) information */ - (void)tcore_network_set_rac(co, rac); + dbg("On Response Set XRAT"); - tcore_free(token_str); - } else { - err("No in +CGREG"); - (void)tcore_network_get_rac(co, &rac); - } - dbg(": %d : 0x%x : 0x%x : %d : 0x%x", stat, lac, ci, act, rac); + if (atResp->success > 0) { + dbg("Response OK"); + resp.result = TCORE_RETURN_SUCCESS; + } else { + dbg("Response NOK"); + resp.result = TCORE_RETURN_FAILURE; + } - /* 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); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_SET_BAND, sizeof(struct tresp_network_set_band), &resp); + } - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_REGISTRATION_STATUS, - sizeof(TelNetworkRegStatusInfo), ®istration_status); + return; +} - /* Set Roaming state */ - if (registration_status.ps_status == TEL_NETWORK_REG_STATUS_ROAMING) - roam_state = TRUE; +static void on_response_set_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur = NULL; + struct tresp_network_set_preferred_plmn resp = {0}; + const TcoreATResponse *atResp = data; - tcore_network_set_roam_state(co, roam_state); + dbg("ENTER on_response_set_preferred_plmn"); - /* Send Notification - Cell info */ - cell_info.lac = lac; - cell_info.cell_id = ci; - cell_info.rac = rac; - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_LOCATION_CELLINFO, - sizeof(TelNetworkCellInfo), &cell_info); + if (atResp->success > 0) { + dbg("Response OK"); + resp.result = TCORE_RETURN_SUCCESS; + } else { + dbg("Response NOK"); + resp.result = TCORE_RETURN_FAILURE; + } -out: - /* Free resource */ - tcore_at_tok_free(tokens); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PREFERRED_PLMN, sizeof(struct tresp_network_set_preferred_plmn), &resp); } - return TRUE; + dbg("Exit on_response_set_preferred_plmn"); + return; } -/* - * Notification: +XNITZINFO: ,,,, - * - * - * string type; Network name in long alphanumeric format. - * - * - * string type; Network name in short alphanumeric format. - * - * - * Local Time Zone; represented as 1 unit = 15 minutes. - * - * - * string type value; Universal Time - * format is "yy/MM/dd,hh:mm:ss", - * wherein characters indicates year, month, day, hour, - * minutes, seconds. - * - * Daylight Saving Time; represented in hours. - */ -static gboolean on_notification_imc_network_time_info(CoreObject *co, - const void *event_info, void *user_data) +static void on_response_get_nitz_name(TcorePending *p, int data_len, const void *data, void *user_data) { - GSList *lines = NULL; - gchar *line = NULL; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + const char *line = NULL; + CoreObject *o = NULL; + struct tnoti_network_identity noti; + int nol = 0; + int count = 0; + int net_name_type = 0; + char *pResp = NULL; + char *net_name = NULL; + + dbg("Entry on_response_get_nitz_name (+XCOPS)"); + o = tcore_pending_ref_core_object(p); + if (atResp->success > 0) { + dbg("RESPONSE OK"); - dbg("Network notification - Time info: [+XNITZINFO]"); + if (atResp->lines) { + nol = g_slist_length(atResp->lines); + if (nol > 3) { + msg("invalid message"); + goto OUT; + } - lines = (GSList *)event_info; - if (g_slist_length(lines) != 1) { - err("+XNITZINFO unsolicited message expected to be Single line " - "but received multiple lines"); - return TRUE; - } - - line = (gchar *)lines->data; - if (line != NULL) { - GSList *tokens = NULL; - TelNetworkNitzInfoNoti nitz_info = {0, }; - gchar *fullname, *shortname; - gchar *ltz, *time; - gchar tmp_time[8] = {0}; - gchar *dstoff; + memset(¬i, 0, sizeof(struct tnoti_network_identity)); - /* - * Tokenize - * - * +XNITZINFO: ,,,, - */ - tokens = tcore_at_tok_new(line); + for (count = 0; count < nol; count++) { + // parse each line + line = g_slist_nth_data(atResp->lines, count); + tokens = tcore_at_tok_new(line); + dbg("line %d start---------------", count); + + if ((pResp = tcore_at_tok_nth(tokens, 0))) { + net_name_type = atoi(pResp); + dbg("Net name type : %d", net_name_type); + + switch (net_name_type) { + case 0: /* plmn_id (mcc, mnc) */ + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + if (strlen(pResp) > 0) { + net_name = tcore_at_tok_extract((const char *)pResp); + strncpy(noti.plmn, net_name, 6); + noti.plmn[6] = '\0'; + } + } + break; + + case 5: /* Short NITZ name*/ + case 3: /* Short Network Name (CPHS) */ + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + if (strlen(pResp) > 0) { + net_name = tcore_at_tok_extract((const char *)pResp); + strncpy(noti.short_name, net_name, 16); + noti.short_name[16] = '\0'; + } + } + break; + + case 6: /* Full NITZ name */ + case 4: /* Long Network Name (CPHS) */ + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + if (strlen(pResp) > 0) { + net_name = tcore_at_tok_extract((const char *)pResp); + strncpy(noti.full_name, net_name, 32); + noti.full_name[32] = '\0'; + } + } + break; - /* */ - if ((fullname = tcore_at_tok_nth(tokens, 1))) { - if (strlen(fullname) > 0) { - fullname = tcore_at_tok_extract((const char *)fullname); + default: + break; + } - /* Update Long name */ - tcore_network_set_long_name(co, fullname); + g_free(net_name); + net_name = NULL; + } - tcore_free(fullname); + tcore_at_tok_free(tokens); } - } - /* */ - if ((shortname = tcore_at_tok_nth(tokens, 1))) { - if (strlen(shortname) > 0) { - shortname = tcore_at_tok_extract((const char *)shortname); + dbg("plmn <%s> short NITZ name<%s> full NITZ name<%s>", + noti.plmn, noti.short_name, noti.full_name); + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_IDENTITY, + sizeof(struct tnoti_network_identity), ¬i); + } + } else { + dbg("RESPONSE NOK"); + } - /* Update Short name */ - tcore_network_set_short_name(co, shortname); +OUT: + dbg("Exit on_response_get_nitz_name"); +} - tcore_free(shortname); - } - } +static void on_response_get_preferred_plmn(TcorePending *p, int data_len, const void *data, void *user_data) +{ + UserRequest *ur; + int i = 0; + char *line = NULL; + const TcoreATResponse *atResp = data; + GSList *tokens = NULL; + char *pResp = NULL; + int plmn_format = 0; - /* */ - if ((ltz = g_slist_nth_data(tokens, 2))) - nitz_info.gmtoff = atoi(ltz) * 15;/* gmtoff in minutes */ + struct tresp_network_get_preferred_plmn resp = {0}; + int total_lines = 0; + int GSM_AcT2 = 0, GSM_Compact_AcT2 = 0, UTRAN_AcT2 = 0; - if ((time = g_slist_nth_data(tokens, 3)) - && (strlen(time) > 18)) { - /* (time + 1) - Skip past initial quote (") */ - g_strlcpy(tmp_time, time + 1, 2+1); - nitz_info.year = atoi(tmp_time); + dbg("Entry"); - /* skip slash (/) after year param */ - g_strlcpy(tmp_time, time + 4, 2+1); - nitz_info.month = atoi(tmp_time); + if (atResp->success > 0) { + dbg("RESPONSE OK"); + if (atResp->lines) { + total_lines = g_slist_length(atResp->lines); + dbg("Total number of network present in Preferred PLMN list is %d\n", total_lines); - /* skip past slash (/) after month param */ - g_strlcpy(tmp_time, time + 7, 2+1); - nitz_info.day = atoi(tmp_time); + if (total_lines < 1) { + msg("invalid message"); + goto OUT; + } - /* skip past comma (,) after day param */ - g_strlcpy(tmp_time, time + 10, 2+1); - nitz_info.hour = atoi(tmp_time); + if (total_lines >= MAX_NETWORKS_PREF_PLMN_SUPPORT) + total_lines = MAX_NETWORKS_PREF_PLMN_SUPPORT; - /* skip past colon (:) after hour param */ - g_strlcpy(tmp_time, time + 13, 2+1); - nitz_info.minute = atoi(tmp_time); +/* ++CPOL: ,,[,,,,] [ ++CPOL: ,,[,,,,] +*/ + resp.result = TCORE_RETURN_SUCCESS; + + for (i = 0; i < total_lines; i++) { + /* Take each line response at a time & parse it */ + line = tcore_at_tok_nth(atResp->lines, i); + tokens = tcore_at_tok_new(line); - /* skip past colon (:) after minute param */ - g_strlcpy(tmp_time, time + 16, 2+1); - nitz_info.second = atoi(tmp_time); - } + /* ,,[,,,,] */ - /* */ - if ((dstoff = g_slist_nth_data(tokens, 4))) { - nitz_info.dstoff = atoi(dstoff); - nitz_info.isdst = TRUE; - } + /* EF Index */ + if ((pResp = tcore_at_tok_nth(tokens, 0))) { + dbg("Index : %s", pResp); + resp.list[i].ef_index = atoi(pResp); + } + /* Format */ + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + dbg("format : %s", pResp); + plmn_format = atoi(pResp); + } - /* Get PLMN */ - tcore_network_get_plmn(co, &nitz_info.plmn); + /* Operator PLMN ID */ + if ((pResp = tcore_at_tok_nth(tokens, 2))) { + dbg("plmn ID : %s", pResp); - /* Send Notification - Network time info */ - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_TIMEINFO, - sizeof(TelNetworkNitzInfoNoti), &nitz_info); + if (strlen(pResp) > 0) { + char *oper; - /* Free resource */ - tcore_free(nitz_info.plmn); - tcore_at_tok_free(tokens); - } + oper = tcore_at_tok_extract((const char *)pResp); + dbg("operator <%s>", oper); - return TRUE; -} + // Get only PLMN ID + if (plmn_format == 2) { + strncpy(resp.list[i].plmn, oper, 6); + resp.list[i].plmn[6] = '\0'; + } -/* - * Notification: - * +XCIEV: , - * or - * +XCIEV:, - * - * 'Radio Signal Strength' can have the values - * 0 -107 dBm or less or unknown - * 1 -99 dBm or less - * 2 -91 dBm or less - * 3 -83 dBm or less - * 4 -75 dBm or less - * 5 -67 dBm or less - * 6 -59 dBm or less - * 7 -51 dBm or less - * - * 'Battery Level' can have the values - * 0 0 % <= level < 5 % - * 1 5 % <= level < 15 % - * 2 15 % <= level < 25 % - * 3 25 % <= level < 40 % - * 4 40 % <= level < 55 % - * 5 55 % <= level < 70 % - * 6 70 % <= level < 85 % - * 7 85 % <= level <= 100 % - * - * NOTE: - * is not consider for - * TCORE_NOTIFICATION_NETWORK_RSSI notification - */ -static gboolean on_notification_imc_network_rssi(CoreObject *co, - const void *event_info, void *user_data) -{ - GSList *lines = NULL; - gchar *line = NULL; + g_free (oper); + } + } - dbg("Network notification - Icon (rssi) info: [+XCIEV]"); + if ((pResp = tcore_at_tok_nth(tokens, 3))) { + dbg("GSM_AcT2 : %s", pResp); + GSM_AcT2 = atoi(pResp); + } - lines = (GSList *)event_info; - if (g_slist_length(lines) != 1) { - err("+XCIEV unsolicited message expected to be Single line " - "but received multiple lines"); - return TRUE; - } + if ((pResp = tcore_at_tok_nth(tokens, 4))) { + dbg("GSM_Compact AcT2 : %s", pResp); + GSM_Compact_AcT2 = atoi(pResp); + } - line = (gchar *)lines->data; - if (line != NULL) { - GSList *tokens = NULL; - gchar *rssi_token; + if ((pResp = tcore_at_tok_nth(tokens, 5))) { + dbg("UTRAN_AcT2 : %s", pResp); + UTRAN_AcT2 = atoi(pResp); + } - /* - * Tokenize - * - * +XCIEV: , - */ - tokens = tcore_at_tok_new(line); + if (UTRAN_AcT2 && (GSM_AcT2 || GSM_Compact_AcT2)) + resp.list[i].act = NETWORK_ACT_GSM_UTRAN; + else if (UTRAN_AcT2) + resp.list[i].act = NETWORK_ACT_UMTS; + else if (GSM_AcT2 || GSM_Compact_AcT2) + resp.list[i].act = NETWORK_ACT_GPRS; - rssi_token = (gchar *)g_slist_nth_data(tokens, 0); - if (rssi_token && strlen(rssi_token)) { - guint rssi_bar = atoi(rssi_token); - dbg("RSSI Level: [%d]", rssi_bar); + (resp.list_count)++; - /* Send Notification - Network Rssi */ - tcore_object_send_notification(co, - TCORE_NOTIFICATION_NETWORK_RSSI, - sizeof(guint), &rssi_bar); + tcore_at_tok_free(tokens); + } } - - /* Free resource */ - tcore_at_tok_free(tokens); + } else { + dbg("RESPONSE NOT OK"); + // TODO: CMEE error mapping is required. + resp.result = TCORE_RETURN_FAILURE; } - return TRUE; +OUT: + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PREFERRED_PLMN, sizeof(struct tresp_network_get_preferred_plmn), &resp); + } + dbg("Exit"); + return; } -/* Network Responses */ - -static void on_response_imc_network_search(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_get_serving_network(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - CustomData *custom_data; - - ImcRespCbData *resp_cb_data = user_data; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - TelNetworkPlmnList plmn_list = {0, }; - guint num_network_avail = 0; - guint count; + const TcoreATResponse *resp = data; + UserRequest *ur; + struct tresp_network_get_serving_network Tresp = {0}; + char *long_plmn_name = NULL; + char *short_plmn_name = NULL; + char *plmn_id = NULL; + CoreObject *o; GSList *tokens = NULL; - - dbg("Enter"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); - - custom_data = tcore_object_ref_user_data(co); - tcore_check_return_assert(custom_data != NULL); - - if (at_resp && at_resp->success) { - const gchar *line; - GSList *net_token = NULL; - gchar *resp; - gint act; - - /* If Request is Cancelled then return back SUCCESS/SEARCH_CANCELLED */ - if (custom_data->search_state - == IMC_NETWORK_SEARCH_STATE_CANCELLED) { - dbg("Network Search has been Cancelled!!!"); - - /* - * TODO: - * - * Need to introduce new Result - - * TEL_NETWORK_RESULT_SEARCH_ABORTED/CANCELLED - * - * Presently sending TEL_NETWORK_RESULT_FAILURE - */ - result = TEL_NETWORK_RESULT_FAILURE; - - goto END; + const char *line; + int network_mode = -1; + int plmn_format = -1; + int AcT = -1; + struct tnoti_network_identity noti; + char *pResp = NULL; + int nol, count = 0; + + o = tcore_pending_ref_core_object(p); + + if (resp->success <= 0) { + dbg("RESPONSE NOK"); + + ur = tcore_pending_ref_user_request(p); + if (ur) { + Tresp.result = TCORE_RETURN_FAILURE; + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp); } - 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); + return; + } else { dbg("RESPONSE OK"); - plmn_list.count = 0; - for (count = 0; count < num_network_avail; count++) { + nol = g_slist_length(resp->lines); + dbg("nol : %d", nol); - 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); + for (count = 0; count < nol; count++) { + // parse each line + line = g_slist_nth_data(resp->lines, count); + tokens = tcore_at_tok_new(line); + dbg("line %d start---------------", count); + // mode + if ((pResp = tcore_at_tok_nth(tokens, 0))) { + dbg("mode : %s", pResp); + network_mode = atoi(pResp); } - 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); + // format (optional) + if ((pResp = tcore_at_tok_nth(tokens, 1))) { + dbg("format : %s", pResp); + if (strlen(pResp) > 0) + plmn_format = atoi(pResp); } - 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 + switch (plmn_format) { + case AT_COPS_FORMAT_LONG_ALPHANUMERIC: + if ((pResp = tcore_at_tok_nth(tokens, 2))) { + dbg("long PLMN : %s", pResp); + if (strlen(pResp) > 0) { + long_plmn_name = tcore_at_tok_extract((const char *)pResp); - /* 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); - } + // set network name into po + tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_FULL, long_plmn_name); + } + } + break; - /* 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; + case AT_COPS_FORMAT_SHORT_ALPHANUMERIC: + if ((pResp = tcore_at_tok_nth(tokens, 2))) { + dbg("short PLMN : %s", pResp); + if (strlen(pResp) > 0) { + short_plmn_name = tcore_at_tok_extract((const char *)pResp); + + // set network name into po + tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SHORT, short_plmn_name); + } } + break; - dbg("Operator [%d] :: status = %d, long_name = %s, short_name = %s plmn = %s, AcT=%d", - plmn_list.count, - 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); + case AT_COPS_FORMAT_NUMERIC: + if ((pResp = tcore_at_tok_nth(tokens, 2))) { + dbg("numeric : %s", pResp); + if (strlen(pResp) > 0) { + plmn_id = tcore_at_tok_extract((const char *)pResp); - plmn_list.count ++; - tcore_at_tok_free(net_token); - } - result = TEL_NETWORK_RESULT_SUCCESS; - } else { - err("RESPONSE NOK"); - result = __imc_network_convert_cme_error_tel_network_result(at_resp); - } + // set plmn id into po + tcore_network_set_plmn(o, plmn_id); + } + } + break; -END: - dbg("Network search : [%s]", - (result == TEL_NETWORK_RESULT_SUCCESS ? "SUCCESS" : "FAIL")); + default: + break; + } - /* Update Search state */ - custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH; + // act + if ((pResp = tcore_at_tok_nth(tokens, 3))) { + dbg("AcT : %s", pResp); + if (strlen(pResp) > 0) { + AcT = atoi(pResp); + tcore_network_set_access_technology(o, lookup_tbl_access_technology[AcT]); + } + } - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, &plmn_list, resp_cb_data->cb_data); + tcore_at_tok_free(tokens); + } - imc_destroy_resp_cb_data(resp_cb_data); + if(plmn_id) + memcpy(Tresp.plmn, plmn_id, strlen(plmn_id)); + tcore_network_get_access_technology(o, &(Tresp.act)); + tcore_network_get_lac(o, &(Tresp.gsm.lac)); - /* 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); - } + ur = tcore_pending_ref_user_request(p); + if (ur) { + Tresp.result = TCORE_RETURN_SUCCESS; + tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &Tresp); + } else { + /* Network change noti */ + struct tnoti_network_change network_change; + + memset(&network_change, 0, sizeof(struct tnoti_network_change)); + if(plmn_id) + memcpy(network_change.plmn, plmn_id, strlen(plmn_id)); + tcore_network_get_access_technology(o, &(network_change.act)); + tcore_network_get_lac(o, &(network_change.gsm.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); + dbg("dbg.. network_change.plmn : %s", network_change.plmn); + dbg("dbg.. network_change.act : %d", network_change.act); + dbg("dbg.. network_change.gsm.lac : %d", network_change.gsm.lac); + + if ((AT_COPS_MODE_DEREGISTER != network_mode) && + (AT_COPS_MODE_SET_ONLY != network_mode)) { + /*Network identity noti*/ + memset(¬i, 0x0, sizeof(struct tnoti_network_identity)); + if (long_plmn_name) + memcpy(noti.full_name, long_plmn_name, MIN(32, strlen(long_plmn_name))); + if (short_plmn_name) + memcpy(noti.short_name, short_plmn_name, MIN(16, strlen(short_plmn_name))); + if (plmn_id) + memcpy(noti.plmn, plmn_id, strlen(plmn_id)); // plmn_id length is necessarily <= 6 + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), + o, TNOTI_NETWORK_IDENTITY, sizeof(struct tnoti_network_identity), ¬i); + dbg("dbg.. noti.short_name : %s", noti.short_name); + dbg("dbg.. noti.full_name : %s", noti.full_name); + dbg("dbg.. noti.plmn : %s", noti.plmn); + } + } - tcore_free(plmn_list.network_list); - tcore_at_tok_free(tokens); + g_free(long_plmn_name); + g_free(short_plmn_name); + g_free(plmn_id); + } + return; } -static gboolean on_response_imc_network_cancel_search(gpointer data) +static void on_response_network_set_mode(TcorePending *p, int data_len, const void *data, void *user_data) { - ImcRespCbData *resp_cb_data = data; - ImcNetworkCancelSearch *cancel_search = - (ImcNetworkCancelSearch *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data); + UserRequest *ur = NULL; + struct tresp_network_set_mode resp = {0}; + const TcoreATResponse *atResp = data; - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(cancel_search->co, (gint)cancel_search->result, - NULL, resp_cb_data->cb_data); + dbg("ENTER on_response_network_set_mode"); - imc_destroy_resp_cb_data(resp_cb_data); + if (atResp && atResp->success) { + dbg("RESPONSE OK"); + resp.result = TCORE_RETURN_SUCCESS; + } else { + err("RESPONSE NOK"); + resp.result = TCORE_RETURN_FAILURE; + } - /* To stop the cycle, need to return FALSE */ - return FALSE; + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, + TRESP_NETWORK_SET_MODE, + sizeof(struct tresp_network_set_mode), &resp); + } } -static void on_response_imc_network_get_selection_mode(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_network_get_mode(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkSelectionMode selection_mode = -1; + UserRequest *ur = NULL; + struct tresp_network_get_mode resp = {0}; + const TcoreATResponse *atResp = data; GSList *tokens = NULL; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - dbg("Enter"); + dbg("ENTER on_response_network_get_mode"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + resp.result = TCORE_RETURN_FAILURE; - if (at_resp && at_resp->success) { + if (atResp && atResp->success) { const gchar *line; - gint mode; + gint net_mode; - if (!at_resp->lines) { + if (!atResp->lines) { err("invalid response received"); goto END; } - line = (char *) at_resp->lines->data; + line = (char *) atResp->lines->data; tokens = tcore_at_tok_new(line); if (g_slist_length(tokens) < 1) { - msg("invalid message"); + err("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; + net_mode = atoi(tcore_at_tok_nth(tokens, 0)); + dbg("mode = %d", net_mode); - result = TEL_NETWORK_RESULT_SUCCESS; - dbg("selection mode[%d]", selection_mode); + switch (net_mode) { + case 0: + resp.mode = NETWORK_MODE_GSM; + break; + case 1: + resp.mode = NETWORK_MODE_AUTO; + break; + case 2: + resp.mode = NETWORK_MODE_WCDMA; + break; + default: + err("Unsupported mode [%d]", net_mode); + goto END; + } + resp.result = TCORE_RETURN_SUCCESS; } else { err("RESPONSE NOK"); - result = __imc_network_convert_cme_error_tel_network_result(at_resp); } 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 */ - imc_destroy_resp_cb_data(resp_cb_data); + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, + TRESP_NETWORK_GET_MODE, + sizeof(struct tresp_network_get_mode), &resp); + } + /* Free resource*/ tcore_at_tok_free(tokens); } -static void on_response_imc_network_default(TcorePending *p, - guint data_len, const void *data, void *user_data) +static void on_response_cancel_manual_search(TcorePending *p, int data_len, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; + UserRequest *ur = NULL; + struct tresp_network_set_cancel_manual_search resp = {0}; + const TcoreATResponse *atResp = data; + CustomData *custom_data; - dbg("Enter"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + dbg("ENTER on_response_cancel_manual_search"); - if (at_resp && at_resp->success) { - dbg("RESPONSE OK"); - result = TEL_NETWORK_RESULT_SUCCESS; + if (atResp->success > 0) { + dbg("Response OK"); + resp.result = TCORE_RETURN_SUCCESS; } else { - err("RESPONSE NOK"); - result = __imc_network_convert_cme_error_tel_network_result(at_resp); + dbg("Response NOK"); + resp.result = TCORE_RETURN_FAILURE; } - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data); + custom_data = tcore_object_ref_user_data(tcore_pending_ref_core_object(p)); + custom_data->search_state = IMC_NETWORK_SEARCH_STATE_NO_SEARCH; - imc_destroy_resp_cb_data(resp_cb_data); -} + ur = tcore_pending_ref_user_request(p); + if (ur) { + tcore_user_request_send_response(ur, + TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH, + sizeof(struct tresp_network_set_cancel_manual_search), &resp); + } + dbg("Exit on_response_cancel_manual_search"); +} -static void on_response_imc_network_get_mode(TcorePending *p, - guint data_len, const void *data, void *user_data) +static gboolean on_event_ps_network_regist(CoreObject *o, const void *data, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - TelNetworkMode mode = -1; + struct tnoti_network_registration_status regist_status; + enum telephony_network_service_domain_status cs_status; + enum telephony_network_service_domain_status ps_status; + enum telephony_network_service_type service_type; + enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN; + struct tnoti_network_location_cellinfo net_lac_cell_info = {0}; + struct tnoti_ps_protocol_status noti = {0}; + unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_PS; + int stat = 0, AcT = 0; + unsigned int lac = 0xffff, ci = 0xffff; + unsigned int rac = 0xffff; GSList *tokens = NULL; + char *pResp; + char *line = NULL; + GSList *lines = NULL; - dbg("Enter"); - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + lines = (GSList *) data; + if (1 != g_slist_length(lines)) { + dbg("unsolicited msg but multiple line"); + goto OUT; + } + line = (char *) (lines->data); + dbg("+CGREG NOTI RECEIVED"); - if (at_resp && at_resp->success) { - const gchar *line; - gint net_mode; +/* ++CREG: [[,,[AcT]] + +Possible values of 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 + + +string type; two byte location area code in hexadecimal format (e.g. 00C3) + + +string type; four byte cell ID in hexadecimal format (e.g. 0000A13F) + + +0 GSM +2 UTRAN +3 GSM w/EGPRS +4 UTRAN w/HSDPA +5 UTRAN w/HSUPA +6 UTRAN w/HSDPA and HSUPA +Note: is supporting from R7 and above Protocol Stack. + +: is R7 and above feature, string type; one byte routing area code in hexadecimal format. +*/ + if (line != NULL) { + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) < 1) { + msg("invalid message"); + goto OUT; + } - if (!at_resp->lines) { - err("invalid response received"); - goto END; + if (!(pResp = g_slist_nth_data(tokens, 0))) { + dbg("No STAT in +CGREG"); + goto OUT; + } else { + stat = atoi(pResp); + if ((pResp = g_slist_nth_data(tokens, 1))) { + pResp = util_removeQuotes(pResp); + lac = strtol(pResp, NULL, 16); + g_free(pResp); + } + + if ((pResp = g_slist_nth_data(tokens, 2))) { + pResp = util_removeQuotes(pResp); + ci = strtol(pResp, NULL, 16); + g_free(pResp); + } else { + dbg("No ci in +CGREG"); + } + + if ((pResp = g_slist_nth_data(tokens, 3))) + AcT = atoi(pResp); + else + dbg("No AcT in +CGREG"); + + if ((pResp = g_slist_nth_data(tokens, 4))) { + pResp = util_removeQuotes(pResp); + rac = strtol(pResp, NULL, 16); + g_free(pResp); + } else { + dbg("No rac in +CGREG"); + } + } + + + dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d, rac = 0x%x", stat, lac, ci, AcT, rac); + + ps_status = lookup_tbl_net_status[stat]; + + tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status); + _ps_set(tcore_object_ref_plugin(o), ps_status); + + tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status); + + act = lookup_tbl_access_technology[AcT]; + tcore_network_set_access_technology(o, act); + + tcore_network_get_service_type(o, &service_type); + dbg("prev_service_type = 0x%x", service_type); + service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status); + dbg("new_service_type = 0x%x", service_type); + tcore_network_set_service_type(o, service_type); + + tcore_network_set_lac(o, lac); + tcore_network_set_cell_id(o, ci); + tcore_network_set_rac(o, rac); + + net_lac_cell_info.lac = lac; + net_lac_cell_info.cell_id = ci; + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO, + sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info); + + regist_status.cs_domain_status = cs_status; + regist_status.ps_domain_status = ps_status; + regist_status.service_type = 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(regist_status), ®ist_status); +#if 0 + if (service_type == NETWORK_SERVICE_TYPE_HSDPA) + noti.status = TELEPHONY_HSDPA_ON; + else + noti.status = TELEPHONY_HSDPA_OFF; +#else + switch(AcT){ + case AT_COPS_ACT_GSM:/*Fall Through*/ + case AT_COPS_ACT_GSM_COMPACT:/*Fall Through*/ + case AT_COPS_ACT_UTRAN:/*Fall Through*/ + case AT_COPS_ACT_GSM_EGPRS:/*Fall Through*/ + case AT_COPS_ACT_E_UTRAN: + { + dbg("Not required for Protocol Status Notification"); + goto OUT; + } + case AT_COPS_ACT_UTRAN_HSDPA: + { + dbg("HSDPA"); + noti.status = TELEPHONY_HSDPA_ON; + break; + } + case AT_COPS_ACT_UTRAN_HSUPA: + { + dbg("HSUPA"); + noti.status = TELEPHONY_HSUPA_ON; + break; + } + case AT_COPS_ACT_UTRAN_HSDPA_HSUPA: + { + dbg("HSPA"); + noti.status = TELEPHONY_HSPA_ON; + break; + } + default: + { + dbg("Ignore"); + goto OUT; + } } +#endif + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_PS_PROTOCOL_STATUS, + sizeof(struct tnoti_ps_protocol_status), ¬i); + + /* Get PLMN ID needed to application */ + // get_serving_network(o, NULL); + } else { + dbg("Response NOK"); + } + +OUT: + if (NULL != tokens) + tcore_at_tok_free(tokens); + return TRUE; +} + +static gboolean on_event_cs_network_regist(CoreObject *o, const void *event_info, void *user_data) +{ + GSList *lines = NULL; + char *line = NULL; + struct tnoti_network_registration_status regist_status; + enum telephony_network_service_domain_status cs_status; + enum telephony_network_service_domain_status ps_status; + enum telephony_network_service_type service_type; + enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN; + struct tnoti_network_location_cellinfo net_lac_cell_info = {0}; + + + unsigned char svc_domain = NETWORK_SERVICE_DOMAIN_CS; + int stat = 0, AcT = 0; + unsigned int lac = 0xffff, ci = 0xffff; + GSList *tokens = NULL; + char *pResp; - line = (char *) at_resp->lines->data; + lines = (GSList *) event_info; + if (1 != g_slist_length(lines)) { + dbg("unsolicited msg but multiple line"); + goto OUT; + } + line = (char *) (lines->data); + + dbg("+CREG NOTI RECEIVED"); + +/* ++CREG: [[,,[AcT]] + +Possible values of 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 + + +string type; two byte location area code in hexadecimal format (e.g. 00C3) + + +string type; four byte cell ID in hexadecimal format (e.g. 0000A13F) + + +0 GSM +2 UTRAN +3 GSM w/EGPRS +4 UTRAN w/HSDPA +5 UTRAN w/HSUPA +6 UTRAN w/HSDPA and HSUPA +Note: is supporting from R7 and above Protocol Stack. +*/ + if (line != NULL) { tokens = tcore_at_tok_new(line); if (g_slist_length(tokens) < 1) { - err("invalid message"); - goto END; + msg("invalid message"); + goto OUT; } - dbg("RESPONSE OK"); - net_mode = atoi(tcore_at_tok_nth(tokens, 0)); - dbg("mode = %d", net_mode); + if (!(pResp = g_slist_nth_data(tokens, 0))) { + dbg("No STAT in +CREG"); + goto OUT; + } else { + stat = atoi(pResp); + if ((pResp = g_slist_nth_data(tokens, 1))) { + pResp = util_removeQuotes(pResp); + lac = strtol(pResp, NULL, 16); + g_free(pResp); + } - switch (net_mode) { - case 0: - mode = TEL_NETWORK_MODE_2G; - break; - case 1: - mode = TEL_NETWORK_MODE_AUTO; - break; - case 2: - mode = TEL_NETWORK_MODE_3G; - break; - default: - err("Unsupported mode [%d]", net_mode); - goto END; + if ((pResp = g_slist_nth_data(tokens, 2))) { + pResp = util_removeQuotes(pResp); + ci = strtol(pResp, NULL, 16); + g_free(pResp); + } else { + dbg("No ci in +CREG"); + } + + if ((pResp = g_slist_nth_data(tokens, 3))) + AcT = atoi(pResp); + else + dbg("No AcT in +CREG"); } - result = TEL_NETWORK_RESULT_SUCCESS; + + + dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d", stat, lac, ci, AcT); + + cs_status = lookup_tbl_net_status[stat]; + tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, cs_status); + + // tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status); + tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status); + + act = lookup_tbl_access_technology[AcT]; + tcore_network_set_access_technology(o, act); + + if (stat == AT_CREG_STAT_REG_ROAM) { + tcore_network_set_roaming_state(o, TRUE); + }else if ((stat == AT_CREG_STAT_REG_DENIED) && (TRUE == tcore_network_get_roaming_state(o))) { + dbg("Ignore roaming set with REG_DENIED when previous state is REG_ROAM"); + }else { + tcore_network_set_roaming_state(o, FALSE); + } + + tcore_network_get_service_type(o, &service_type); + dbg("prev_service_type = 0x%x", service_type); + service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status); + dbg("new_service_type = 0x%x", service_type); + tcore_network_set_service_type(o, service_type); + + tcore_network_set_lac(o, lac); + tcore_network_set_cell_id(o, ci); + + net_lac_cell_info.lac = lac; + net_lac_cell_info.cell_id = ci; + + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO, + sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info); + + regist_status.cs_domain_status = cs_status; + regist_status.ps_domain_status = ps_status; + regist_status.service_type = 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); + + /* Get PLMN ID needed to application */ + if ((NETWORK_SERVICE_DOMAIN_STATUS_FULL == cs_status) || + NETWORK_SERVICE_DOMAIN_STATUS_FULL == ps_status) + get_serving_network(o, NULL); } else { - err("RESPONSE NOK"); - result = __imc_network_convert_cme_error_tel_network_result(at_resp); + dbg("Response NOK"); } -END: - /* Invoke callback */ - if (resp_cb_data->cb) - resp_cb_data->cb(co, (gint)result, &mode, resp_cb_data->cb_data); - /* Free callback data */ - imc_destroy_resp_cb_data(resp_cb_data); - /* Free resource*/ - tcore_at_tok_free(tokens); +OUT: + if (NULL != tokens) + tcore_at_tok_free(tokens); + return TRUE; } -static void on_response_imc_network_get_preferred_plmn(TcorePending *p, - guint data_len, const void *data, void *user_data) +static gboolean on_event_network_icon_info(CoreObject *o, const void *event_info, void *user_data) { - const TcoreAtResponse *at_resp = data; - CoreObject *co = tcore_pending_ref_core_object(p); - ImcRespCbData *resp_cb_data = user_data; - TelNetworkPreferredPlmnList plmn_list = {0,}; - guint count = 0, total_lines = 0; - TelNetworkResult result = TEL_NETWORK_RESULT_FAILURE; - dbg("Enter"); + struct tnoti_network_icon_info net_icon_info = {0}; + char *line = NULL; + char *rssiToken = NULL; + char *batteryToken = NULL; + GSList *tokens = NULL; + GSList *lines = NULL; - tcore_check_return_assert(co != NULL); - tcore_check_return_assert(resp_cb_data != NULL); + lines = (GSList *) event_info; + if (1 != g_slist_length(lines)) { + dbg("unsolicited msg but multiple line"); + goto OUT; + } + line = (char *) (lines->data); + dbg("+XCIEV Network Icon Info Noti Recieve"); + memset(&net_icon_info, 0, sizeof(struct tnoti_network_icon_info)); - if (at_resp && at_resp->success) { - GSList *tokens; - gchar *resp; - gchar *line; - gboolean gsm_act2 = FALSE, gsm_compact_act2 = FALSE; - gboolean utran_act2 = FALSE; + if (line != NULL) { + dbg("Response OK"); - if (!at_resp->lines) { - err("invalid response received"); - goto END; + tokens = tcore_at_tok_new(line); + if (g_slist_length(tokens) != 2) { + msg("invalid message"); + goto OUT; } - total_lines = g_slist_length(at_resp->lines); - if (total_lines < 1) { - msg("invalid message"); - goto END; + rssiToken = (char *) g_slist_nth_data(tokens, 0); + + if (strlen(rssiToken) > 0) { + net_icon_info.type = NETWORK_ICON_INFO_RSSI; + net_icon_info.rssi = atoi(g_slist_nth_data(tokens, 0)); + dbg("rssi level : %d", net_icon_info.rssi); } - dbg("RESPONSE OK"); - result = TEL_NETWORK_RESULT_SUCCESS; + batteryToken = (char *) g_slist_nth_data(tokens, 1); + if (strlen(batteryToken) > 0) { + net_icon_info.type = NETWORK_ICON_INFO_BATTERY; + net_icon_info.battery = atoi(g_slist_nth_data(tokens, 1)); + dbg("battery level : %d", net_icon_info.battery); + } - plmn_list.list = tcore_malloc0(sizeof(TelNetworkPreferredPlmnInfo) * total_lines); - plmn_list.count = 0; + tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_ICON_INFO, + sizeof(struct tnoti_network_icon_info), &net_icon_info); + } else { + dbg("Response NOK"); + } - for (count = 0; count < total_lines; count++) { - /* Take each line response at a time & parse it */ - line = tcore_at_tok_nth(at_resp->lines, count); - tokens = tcore_at_tok_new(line); - /*Index */ - if ((resp = tcore_at_tok_nth(tokens, 0))) { - plmn_list.list[count].index = atoi(resp); - } +OUT: + if (NULL != tokens) + tcore_at_tok_free(tokens); - /* PLMN ID */ - if ((resp = tcore_at_tok_nth(tokens, 2))) { - plmn_list.list[count].plmn = tcore_at_tok_extract(resp); - } + return TRUE; +} - /*GSM_AcT1 */ - if ((resp = tcore_at_tok_nth(tokens, 3))) { - gsm_act2 = atoi(resp); - } +static gboolean on_event_network_ctzv_time_info(CoreObject *o, const void *event_info, void *user_data) +{ + struct tnoti_network_timeinfo net_time_info = {0}; + char *line = NULL; + GSList *tokens = NULL; + char *time = NULL; + char *time_zone = NULL; + GSList *lines = NULL; + char ptime_param[20] = {0}; + UserRequest *ur = NULL; + dbg("Enter : on_event_network_ctzv_time_info"); + + lines = (GSList *) event_info; + if (1 != g_slist_length(lines)) { + dbg("unsolicited msg but multiple line"); + goto OUT; + } + line = (char *) (lines->data); - /*GSM_Compact_AcT2 */ - if ((resp = tcore_at_tok_nth(tokens, 4))) { - gsm_compact_act2 = atoi(resp); - } +/* ++CTZV: ,