From 7746ae5070326c96905ab2594c2548ece91c0cb9 Mon Sep 17 00:00:00 2001 From: Dongchul Lim Date: Tue, 17 Mar 2015 13:54:05 +0900 Subject: [PATCH] Code Sync up from tizen_2.4 Change-Id: I83dfd645cf6179dddbedec9562e267ca1a037415 --- CMakeLists.txt | 25 +- README | 1 + include/config.h | 38 - include/legacy/TelUtility.h | 165 ++++ include/vdpram.h | 20 +- include/vdpram_dump.h | 12 +- packaging/tel-plugin-vmodem.spec | 33 +- src/config.c | 303 ------ src/desc-vmodem.c | 607 ++++++++---- src/vdpram.c | 1025 ++++++++++---------- src/vdpram_dump.c | 128 ++- ...n-vmodem.manifest => tel-plugin-vmodem.manifest | 2 +- 12 files changed, 1204 insertions(+), 1155 deletions(-) create mode 100644 README delete mode 100644 include/config.h create mode 100644 include/legacy/TelUtility.h mode change 100644 => 100755 packaging/tel-plugin-vmodem.spec delete mode 100644 src/config.c mode change 100644 => 100755 src/desc-vmodem.c rename packaging/tel-plugin-vmodem.manifest => tel-plugin-vmodem.manifest (66%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae6fd11..67a4dbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,12 +6,12 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(EXEC_PREFIX "\${prefix}") SET(LIBDIR "\${prefix}/lib") SET(INCLUDEDIR "\${prefix}/include") -SET(PKGCONFIGDIR "${PREFIX}/${LIB_INSTALL_DIR}/pkgconfig" CACHE PATH PKGCONFIGDIR) +SET(PKGCONFIGDIR "${PREFIX}/lib/pkgconfig" CACHE PATH PKGCONFIGDIR) SET(CMAKE_INSTALL_PREFIX "${PREFIX}") # Set required packages INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED glib-2.0 tcore tel-headers) +pkg_check_modules(pkgs REQUIRED glib-2.0 tcore dlog) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -19,24 +19,28 @@ ENDFOREACH(flag) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wdeclaration-after-statement -Wmissing-declarations -Wredundant-decls -Wcast-align") - +SET(ADDITIONAL_CFLAGS "-Wall -Wno-array-bounds -Wno-empty-body -Wno-ignored-qualifiers -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wcast-qual") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wextra -fvisibility=hidden -fPIC") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter -Wno-missing-field-initializers -Wdeclaration-after-statement -Wmissing-declarations -Wredundant-decls -Wcast-align") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ADDITIONAL_CFLAGS}") ADD_DEFINITIONS("-DFEATURE_TLOG_DEBUG") ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"VMODEM\"") +ADD_DEFINITIONS("-DPLUGIN_VERSION=${VERSION}") ADD_DEFINITIONS("-DEXPORT_API=__attribute__((visibility(\"default\")))") MESSAGE(${CMAKE_C_FLAGS}) -MESSAGE(${CMAKE_EXE_LINKER_FLAGS}) +MESSAGE(${pkgs_LDFLAGS}) SET(SRCS - src/desc-vmodem.c - src/vdpram.c - src/config.c - src/vdpram_dump.c + src/desc-vmodem.c + src/vdpram.c + src/vdpram_dump.c ) + # library build ADD_LIBRARY(vmodem-plugin SHARED ${SRCS}) TARGET_LINK_LIBRARIES(vmodem-plugin ${pkgs_LDFLAGS}) @@ -44,5 +48,6 @@ SET_TARGET_PROPERTIES(vmodem-plugin PROPERTIES PREFIX "" OUTPUT_NAME vmodem-plug # install -INSTALL(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${LIB_INSTALL_DIR}/telephony/plugins) +INSTALL(TARGETS vmodem-plugin + LIBRARY DESTINATION lib/telephony/plugins) INSTALL(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION /usr/share/license RENAME tel-plugin-vmodem) diff --git a/README b/README new file mode 100644 index 0000000..74c53d9 --- /dev/null +++ b/README @@ -0,0 +1 @@ +AT based modem plugin diff --git a/include/config.h b/include/config.h deleted file mode 100644 index d7d27f0..0000000 --- a/include/config.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * tel-plugin-vmodem - * - * 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 __CONFIG_H__ -#define __CONFIG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - gint vdpram_fd; - gint vdpram_watch_id; -} CustomData; - -void vmodem_config_check_cp_power(TcoreHal *hal); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CONFIG_H__ */ diff --git a/include/legacy/TelUtility.h b/include/legacy/TelUtility.h new file mode 100644 index 0000000..60e2205 --- /dev/null +++ b/include/legacy/TelUtility.h @@ -0,0 +1,165 @@ +/* + * tel-plugin-vmodem + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Kyeongchul Kim + * + * 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 +* @{ +* +* @file TelUtility.h + + @brief This file serves as a "C" header file defines structures for Utility Services. \n + It contains a sample set of constants, enums, structs that would be required by applications. + */ + +#ifndef _TEL_UTILITY_H_ +#define _TEL_UTILITY_H_ +/*================================================================================================== + INCLUDE FILES +==================================================================================================*/ +#ifdef __cplusplus +extern "C" +{ +#endif + +/*================================================================================================== + CONSTANTS +==================================================================================================*/ + + +/*================================================================================================== + MACROS +==================================================================================================*/ +#define INVALID_REQUEST_ID -1 /**< Invalid RequestId Value */ + + +/*================================================================================================== + ENUMS +==================================================================================================*/ +/** +* @enum TapiResult_t +* Below enumerations are the return codes of TAPI API's +*/ +typedef enum +{ + TAPI_API_SUCCESS = 0, /** * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,13 +21,13 @@ #ifndef __VDPRAM_H__ #define __VDPRAM_H__ -gint vdpram_open (void); -gboolean vdpram_close(gint fd); - -gboolean vdpram_poweron(gint fd); -gboolean vdpram_poweroff(gint fd); +int vdpram_close(int fd); +int vdpram_open (void); +int vdpramerr_open(void); +int vdpram_poweron(int fd); +int vdpram_poweroff(int fd); -gint vdpram_tty_read(gint fd, void *buf, size_t buf_len); -gint vdpram_tty_write(gint fd, void *buf, size_t buf_len); +int vdpram_tty_read(int nFd, void* buf, size_t nbytes); +int vdpram_tty_write(int nFd, void* buf, size_t nbytes); -#endif /* __VDPRAM_H__ */ +#endif diff --git a/include/vdpram_dump.h b/include/vdpram_dump.h index b75c261..e98a275 100644 --- a/include/vdpram_dump.h +++ b/include/vdpram_dump.h @@ -1,7 +1,9 @@ /* * tel-plugin-vmodem * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Junhwan An * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +21,10 @@ #ifndef __VDPRAM_DUMP_H__ #define __VDPRAM_DUMP_H__ -void vdpram_hex_dump(gboolean tx, gushort data_len, void *data); +#define IPC_TX 0 +#define IPC_RX 1 + +void vdpram_hex_dump(int dir, unsigned short data_len, void *data); + +#endif -#endif /* __VDPRAM_DUMP_H__ */ diff --git a/packaging/tel-plugin-vmodem.spec b/packaging/tel-plugin-vmodem.spec old mode 100644 new mode 100755 index 0ddb068..026712e --- a/packaging/tel-plugin-vmodem.spec +++ b/packaging/tel-plugin-vmodem.spec @@ -1,32 +1,31 @@ -%define major 3 -%define minor 0 -%define patchlevel 1 +%define major 0 +%define minor 1 +%define patchlevel 18 -Name: tel-plugin-vmodem +Name: tel-plugin-vmodem Version: %{major}.%{minor}.%{patchlevel} Release: 1 -License: Apache-2.0 -Summary: Telephony Plug-in for AT communication with AT Virtual Modem (emulator) +License: Apache +Summary: Telephony AT Virtual Modem library Group: System/Libraries -Source0: tel-plugin-vmodem-%{version}.tar.gz -Source1001: tel-plugin-vmodem.manifest -Requires(post): /sbin/ldconfig -Requires(postun): /sbin/ldconfig +Source0: tel-plugin-vmodem-%{version}.tar.gz BuildRequires: cmake BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(tcore) -BuildRequires: pkgconfig(tel-headers) +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig %description Telephony AT Modem library %prep %setup -q -cp %{SOURCE1001} . %build -%cmake . -make %{?jobs:-j%jobs} +versionint=$[%{major} * 1000000 + %{minor} * 1000 + %{patchlevel}] +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DVERSION=$versionint +make %{?_smp_mflags} %post /sbin/ldconfig @@ -36,10 +35,10 @@ make %{?jobs:-j%jobs} %install %make_install mkdir -p %{buildroot}/usr/share/license -cp LICENSE %{buildroot}/usr/share/license/%{name} %files -%manifest %{name}.manifest +%manifest tel-plugin-vmodem.manifest %defattr(-,root,root,-) +#%doc COPYING %{_libdir}/telephony/plugins/vmodem-plugin* -/usr/share/license/%{name} +/usr/share/license/tel-plugin-vmodem diff --git a/src/config.c b/src/config.c deleted file mode 100644 index 7774474..0000000 --- a/src/config.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * tel-plugin-vmodem - * - * 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 -#include -#include -#include -#include - -#include "config.h" - -#define AT_MODEM_PLUGIN_NAME "atmodem-plugin.so" - -/* Maximum Core objects per Logical HAL (indirectly per Channel) */ -#define MAX_CO_PER_CHANNEL 2 - -/* CP States */ -#define AT_CPAS_RESULT_READY 0 -#define AT_CPAS_RESULT_UNAVAIL 1 -#define AT_CPAS_RESULT_UNKNOWN 2 -#define AT_CPAS_RESULT_RINGING 3 -#define AT_CPAS_RESULT_CALL_PROGRESS 4 -#define AT_CPAS_RESULT_ASLEEP 5 - -typedef struct { - guint type; - gchar *name; -} VmodemSupportedCo; - -/* - * List of supported Core Object types - */ -static VmodemSupportedCo supported_modules[] = { - {CORE_OBJECT_TYPE_MODEM, "Modem"}, - {CORE_OBJECT_TYPE_NETWORK, "Network"}, - {CORE_OBJECT_TYPE_CALL, "Call"}, - {CORE_OBJECT_TYPE_SIM, "Sim"}, - {CORE_OBJECT_TYPE_SMS, "Sms"}, - {CORE_OBJECT_TYPE_SS, "SS"}, - {CORE_OBJECT_TYPE_PS, "PS"}, - {0, ""}, -}; - -static gboolean __check_cp_poweron(TcoreHal *hal); - -static void __assign_objects_to_hal(TcoreHal *hal) -{ - TcorePlugin *plugin; - gboolean ret; - guint i = 0; - - plugin = tcore_hal_ref_plugin(hal); - - while (supported_modules[i].type != 0) { - /* Add Core Object type for specific 'hal' */ - ret = tcore_server_add_cp_mapping_tbl_entry(plugin, - supported_modules[i].type, hal); - if (ret == TRUE) { - dbg("Core Object Type: [0x%x] - Success", - supported_modules[i].name); - } else { - err("Core Object Type: [0x%x] - Fail", - supported_modules[i].name); - } - - i++; - }; -} - -static void __deassign_objects_from_hal(TcoreHal *hal) -{ - TcorePlugin *plugin; - - plugin = tcore_hal_ref_plugin(hal); - - /* Remove mapping table entry */ - tcore_server_remove_cp_mapping_tbl_entry(plugin, hal); -} - -static gboolean __load_modem_plugin(gpointer data) -{ - TcoreHal *hal = (TcoreHal *)data; - TcorePlugin *plugin; - - dbg("Entry"); - - if (hal == NULL) { - err("hal is NULL"); - return FALSE; - } - - plugin = tcore_hal_ref_plugin(hal); - - /* Load Modem Plug-in */ - if (tcore_server_load_modem_plugin(tcore_plugin_ref_server(plugin), - plugin, AT_MODEM_PLUGIN_NAME) != TEL_RETURN_SUCCESS) { - err("Load Modem Plug-in - [FAIL]"); - - /* Clean-up */ - __deassign_objects_from_hal(hal); - - goto EXIT; - } else { - dbg("Load Modem Plug-in - [SUCCESS]"); - } - - return TRUE; - -EXIT: - /* TODO: Handle Deregister */ - - return FALSE; -} - -static void __on_confirmation_send_message(TcorePending *p, - TelReturn send_status, void *user_data) -{ - dbg("Message send confirmation - [%s]", - ((send_status != TEL_RETURN_SUCCESS) ? "FAIL" : "OK")); -} - -static void __on_timeout_check_cp_poweron(TcorePending *p, void *user_data) -{ - TcoreHal *hal = user_data; - guint data_len = 0; - char *data = "AT+CPAS"; - - data_len = sizeof(data); - - dbg("Resending Command: [%s] Command Length: [%d]", data, data_len); - - /* - * Retransmit 1st AT command (AT+CPAS) directly via HAL without disturbing - * pending queue. - * HAL was passed as user_data, re-using it - */ - tcore_hal_send_data(hal, data_len, (void *)data); -} - -static void __on_response_check_cp_poweron(TcorePending *pending, - guint data_len, const void *data, void *user_data) -{ - const TcoreAtResponse *resp = data; - TcoreHal *hal = user_data; - - GSList *tokens = NULL; - const char *line; - gboolean bpoweron = FALSE; - int response = 0; - - if (resp && resp->success) { - dbg("Check CP POWER - [OK]"); - - /* Parse AT Response */ - if (resp->lines) { - dbg("Check CP POWER - [OK]"); - line = (const char *) resp->lines->data; - dbg("line: %s", line); - tokens = tcore_at_tok_new(line); - dbg("tokens: %p", tokens); - if (g_slist_length(tokens) != 1) { - err("Invalid message"); - goto ERROR; - } - - dbg("Check CP POWER - [OK]"); - - response = atoi(g_slist_nth_data(tokens, 0)); - dbg("CPAS State: [%d]", response); - - switch (response) { - case AT_CPAS_RESULT_READY: - case AT_CPAS_RESULT_RINGING: - case AT_CPAS_RESULT_CALL_PROGRESS: - case AT_CPAS_RESULT_ASLEEP: - dbg("CP Power ON!!!"); - bpoweron = TRUE; - break; - - case AT_CPAS_RESULT_UNAVAIL: - case AT_CPAS_RESULT_UNKNOWN: - default: - err("Value is Unvailable/Unknown - but CP responded - proceed with Power ON!!!"); - bpoweron = TRUE; - break; - } - } - else { - err("Check CP POWER - [NOK] - lines NULL"); - } - } else { - err("Check CP POWER - [NOK]"); - } - -ERROR: - /* Free tokens */ - tcore_at_tok_free(tokens); - - if (bpoweron == TRUE) { - dbg("CP Power ON received"); - - /* Load Modem Plug-in */ - if(__load_modem_plugin(hal) == FALSE) { - /* TODO: Handle Deregistration */ - } - else { - dbg("Modem Plug-in loaded successfully"); - } - } else { - err("CP is not ready, send CPAS again"); - __check_cp_poweron(hal); - } -} - -static gboolean __check_cp_poweron(TcoreHal *hal) -{ - TcoreAtRequest *at_req; - TcorePending *pending = NULL; - - /* Create Pending request */ - pending = tcore_pending_new(NULL, 0); - - /* Create AT Request */ - at_req = tcore_at_request_new("AT+CPAS", - "+CPAS:", TCORE_AT_COMMAND_TYPE_SINGLELINE); - - dbg("AT-Command: [%s] Prefix(if any): [%s] Command length: [%d]", - at_req->cmd, at_req->prefix, strlen(at_req->cmd)); - - tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT); - - /* Set timeout value and timeout callback */ - tcore_pending_set_timeout(pending, 10); - tcore_pending_set_timeout_callback(pending, - __on_timeout_check_cp_poweron, hal); - - /* Set request data and register Response and Send callbacks */ - tcore_pending_set_request_data(pending, 0, at_req); - tcore_pending_set_response_callback(pending, - __on_response_check_cp_poweron, hal); - tcore_pending_set_send_callback(pending, - __on_confirmation_send_message, NULL); - - /* Send command to CP */ - if (tcore_hal_send_request(hal, pending) != TEL_RETURN_SUCCESS) { - err("Failed to send CPAS"); - - /* Free resource */ - tcore_at_request_free(at_req); - tcore_pending_free(pending); - - return FALSE; - } - - dbg("Successfully sent CPAS"); - return TRUE; -} - -void vmodem_config_check_cp_power(TcoreHal *hal) -{ - gboolean ret; - dbg("Entry"); - - tcore_check_return(hal != NULL); - - ret = __check_cp_poweron(hal); - if (ret == TRUE) { - dbg("Successfully sent check CP Power ON command"); - - /* Add Core Objects list to HAL */ - __assign_objects_to_hal(hal); - } else { - err("Failed to send check CP Power ON command"); - /* TODO: Handle Deregister */ - } -} diff --git a/src/desc-vmodem.c b/src/desc-vmodem.c old mode 100644 new mode 100755 index 35ef200..76fc9b6 --- a/src/desc-vmodem.c +++ b/src/desc-vmodem.c @@ -1,7 +1,9 @@ /* * tel-plugin-vmodem * - * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Junhwan An * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,32 +19,131 @@ */ #include -#include #include #include #include +#include #include #include #include #include -#include #include +#include +#include #include +#include -#include "config.h" #include "vdpram.h" -#include "vdpram_dump.h" -#define VMODEM_HAL_NAME "vmodem" +#define SERVER_INIT_WAIT_TIMEOUT 500 + +#define DEVICE_NAME_LEN_MAX 16 +#define DEVICE_NAME_PREFIX "pdp" + +#define BUF_LEN_MAX 512 -#define DEVICE_NAME_LEN_MAX 16 -#define DEVICE_NAME_PREFIX "pdp" +#define CORE_OBJECT_NAME_MAX 16 -#define BUF_LEN_MAX 512 +#define MODEM_PLUGIN_NAME "atmodem-plugin.so" -#define AT_CP_POWER_ON_TIMEOUT 500 +#define BIT_SIZE(type) (sizeof(type) * 8) + +#define COPY_MASK(type) ((0xffffffff) >> (32 - BIT_SIZE(type))) + +#define MASK(width, offset, data) \ + (((width) == BIT_SIZE(data)) ? (data) : \ + ((((COPY_MASK(data) << (BIT_SIZE(data) - ((width) % BIT_SIZE(data)))) & COPY_MASK(data)) >> (offset)) & (data))) \ + + +#define MASK_AND_SHIFT(width, offset, shift, data) \ + ((((signed) (shift)) < 0) ? \ + MASK((width), (offset), (data)) << -(shift) : \ + MASK((width), (offset), (data)) >> (((signed) (shift)))) \ + +struct custom_data { + int vdpram_fd; + guint watch_id_vdpram; +}; + +typedef struct { + TcoreHal *hal; + TcoreModem *modem; +} PluginData; + +struct v_modules { + unsigned int co_type; + char co_name[CORE_OBJECT_NAME_MAX]; +}; + +static char __util_unpackb(const char *src, int pos, int len) +{ + char result = 0; + int rshift = 0; + + src += pos / 8; + pos %= 8; + + rshift = MAX(8 - (pos + len), 0); + + if (rshift > 0) { + result = MASK_AND_SHIFT(len, pos, rshift, (unsigned char)*src); + } else { + result = MASK(8 - pos, pos, (unsigned char)*src); + src++; + len -= 8 - pos; + + if (len > 0) result = (result << len) | (*src >> (8 - len)); // if any bits left + } + + return result; +} + +static char __util_convert_byte_hexchar(char val) +{ + char hex_char; + + if (val <= 9) { + hex_char = (char) (val + '0'); + } else if (val >= 10 && val <= 15) { + hex_char = (char) (val - 10 + 'A'); + } else { + hex_char = '0'; + } + + return (hex_char); +} + +static gboolean __util_byte_to_hex(const char *byte_pdu, char *hex_pdu, int num_bytes) +{ + int i; + char nibble; + int buf_pos = 0; + + for (i = 0; i < num_bytes * 2; i++) { + nibble = __util_unpackb(byte_pdu, buf_pos, 4); + buf_pos += 4; + hex_pdu[i] = __util_convert_byte_hexchar(nibble); + } + + return TRUE; +} + +static TcoreModem *__get_modem(TcorePlugin *modem_iface_plugin) +{ + PluginData *user_data; + + if (modem_iface_plugin == NULL) + return NULL; + + user_data = tcore_plugin_ref_user_data(modem_iface_plugin); + if (user_data == NULL) + return NULL; + + /* 'modem' corresponding to Modem Interface plug-in */ + return user_data->modem; +} static guint __vmodem_reencode_mt_sms(gchar *mt_sms, guint mt_sms_len) { @@ -52,9 +153,12 @@ static guint __vmodem_reencode_mt_sms(gchar *mt_sms, guint mt_sms_len) gchar sms_buf[BUF_LEN_MAX] = {0, }; guint sca_len, pdu_len, tpdu_len; - gushort tpdu_len_ptr; - gchar data; - guint i; + gushort tpdu_len_ptr = 0; + gchar tpdu_len_str[8] = {0}; + guint i, local_index = 0; + + if (mt_sms_len > BUF_LEN_MAX) + mt_sms_len = BUF_LEN_MAX-2; for (i = 0; i < mt_sms_len; i++) { if ((mt_sms[i] == VMODEM_CR) @@ -78,23 +182,67 @@ static guint __vmodem_reencode_mt_sms(gchar *mt_sms, guint mt_sms_len) tpdu_len = pdu_len - (sca_len+1); dbg("PDU length: [%d] Actual TPDU Length: [%d]", pdu_len, tpdu_len); - tcore_util_byte_to_hex(&mt_sms[i], &sms_buf[i], pdu_len); - dbg("MT SMS: [%s]", sms_buf); + if (pdu_len >= 100 && tpdu_len < 100) { + /* + * Move back complete buffer by a Byte (to fill up the + * void created by hundreds place). + */ + if (i > 3) { + sms_buf[i-3] = VMODEM_CR; + sms_buf[i-2] = VMODEM_LF; + + __util_byte_to_hex(&mt_sms[i], &sms_buf[i-1], pdu_len); + i += (2*pdu_len - 1); + } + } else { + __util_byte_to_hex(&mt_sms[i], &sms_buf[i], pdu_len); + i += 2*pdu_len; + } + + /* Update actual TPDU length */ + snprintf(tpdu_len_str, 8, "%d", tpdu_len); + switch (strlen(tpdu_len_str)) { + case 4: /* 100s place */ + dbg("1000s : [%d]", tpdu_len_str[local_index]); + + sms_buf[tpdu_len_ptr] = tpdu_len_str[local_index]; + tpdu_len_ptr++; + + local_index++; + case 3: /* 100s place */ + dbg("100s : [%d]", tpdu_len_str[local_index]); + + sms_buf[tpdu_len_ptr] = tpdu_len_str[local_index]; + tpdu_len_ptr++; + + local_index++; + case 2: /* 10s place */ + dbg("10s : [%d]", tpdu_len_str[local_index]); + + sms_buf[tpdu_len_ptr] = tpdu_len_str[local_index]; + tpdu_len_ptr++; + + local_index++; + case 1: /* 1s place */ + dbg("1s : [%d]", tpdu_len_str[local_index]); + + sms_buf[tpdu_len_ptr] = tpdu_len_str[local_index]; + tpdu_len_ptr++; + break; + default: + dbg("Unsupported length: [%d]", strlen(tpdu_len_str)); + break; + } /* Append & */ - i += 2*pdu_len; + if (i > BUF_LEN_MAX) + i = BUF_LEN_MAX-2; + sms_buf[i++] = VMODEM_CR; sms_buf[i++] = VMODEM_LF; + dbg("MT SMS: [%s]", sms_buf); - /* Update actual TPDU length */ - data = (tpdu_len/10) + '0'; - sms_buf[tpdu_len_ptr] = data; - tpdu_len_ptr++; - - data = (tpdu_len%10) + '0'; - sms_buf[tpdu_len_ptr] = data; - - tcore_util_hex_dump(" ", (gint)i, sms_buf); + tcore_util_hex_dump(" ", (int)i, sms_buf); /* * Copy back @@ -133,61 +281,101 @@ static void __deregister_gio_watch(guint watch_id) g_source_remove(watch_id); } -static TcoreHookReturn __on_hal_send(TcoreHal *hal, - guint data_len, void *data, void *user_data) +static gboolean __load_modem_plugin(gpointer data) { - /* Dumping Send (Write) data */ - vdpram_hex_dump(TRUE, data_len, data); + TcoreHal *hal; + TcorePlugin *plugin; + struct custom_data *user_data; + TcoreModem *modem; + unsigned int slot_count = 1; - return TCORE_HOOK_RETURN_CONTINUE; -} + dbg("Entry"); -static void __on_hal_recv(TcoreHal *hal, - guint data_len, const void *data, void *user_data) -{ - /* Dumping Receive (Read) data */ - vdpram_hex_dump(FALSE, data_len, (void *)data); + if (data == NULL) { + err("data is NULL"); + return FALSE; + } + + hal = data; + plugin = tcore_hal_ref_plugin(hal); + modem = __get_modem(plugin); + + /* Load Modem Plug-in */ + if (tcore_server_load_modem_plugin(tcore_plugin_ref_server(plugin), + modem, MODEM_PLUGIN_NAME) == TCORE_RETURN_FAILURE) { + err("Load Modem Plug-in - [FAIL]"); + + goto EXIT; + } else { + dbg("Load Modem Plug-in - [SUCCESS]"); + } + + tcore_server_send_notification(tcore_plugin_ref_server(plugin), + NULL, TNOTI_SERVER_ADDED_MODEM_PLUGIN_COMPLETED, + sizeof(slot_count), &slot_count); + + /* To stop the cycle need to return FALSE */ + return FALSE; + +EXIT: + user_data = tcore_hal_ref_user_data(hal); + if (user_data == NULL) + return FALSE; + + /* Deregister from Watch list */ + __deregister_gio_watch(user_data->watch_id_vdpram); + + /* Free HAL */ + tcore_hal_free(hal); + + /* Close VDPRAM device */ + vdpram_close(user_data->vdpram_fd); + + /* Free custom data */ + g_free(user_data); + + return FALSE; } -static gboolean __modem_power(TcoreHal *hal, gboolean enable) +static TReturn _modem_power(TcoreHal *hal, gboolean enable) { - CustomData *user_data; + struct custom_data *user_data; user_data = tcore_hal_ref_user_data(hal); if (user_data == NULL) { - err("User data is NULL"); - return FALSE; + err(" User data is NULL"); + return TCORE_RETURN_FAILURE; } - if (enable == TRUE) { /* POWER ON */ + if (enable == TRUE) { /* POWER ON */ if (FALSE == vdpram_poweron(user_data->vdpram_fd)) { - err("Power ON - [FAIL]"); - return FALSE; + err(" Power ON - [FAIL]"); + return TCORE_RETURN_FAILURE; } /* Set Power State - ON */ tcore_hal_set_power_state(hal, TRUE); - } else { /* POWER OFF */ + } else { /* POWER OFF */ if (vdpram_poweroff(user_data->vdpram_fd) == FALSE) { - err("Power OFF - [FAIL]"); - return FALSE; + err(" Power OFF - [FAIL]"); + return TCORE_RETURN_FAILURE; } /* Set Power state - OFF */ tcore_hal_set_power_state(hal, FALSE); } - return TRUE; + return TCORE_RETURN_SUCCESS; } -static gboolean __on_recv_vdpram_message(GIOChannel *channel, +static gboolean on_recv_vdpram_message(GIOChannel *channel, GIOCondition condition, gpointer data) { TcoreHal *hal = data; - CustomData *custom; - char buf[BUF_LEN_MAX] = {0, }; + struct custom_data *custom; + char buf[BUF_LEN_MAX]; int n = 0; - TelReturn ret; + TReturn ret; custom = tcore_hal_ref_user_data(hal); memset(buf, 0x0, BUF_LEN_MAX); @@ -195,17 +383,14 @@ static gboolean __on_recv_vdpram_message(GIOChannel *channel, /* Read from Device */ n = vdpram_tty_read(custom->vdpram_fd, buf, BUF_LEN_MAX); if (n < 0) { - err("Read error - Data received: [%d]", n); + err(" Read error - Data received: [%d]", n); return TRUE; } - dbg("DPRAM Receive - Data length: [%d]", n); - - /* Emit receive callback */ - + dbg(" DPRAM Receive - Data length: [%d]", n); msg("\n---------- [RECV] Length of received data: [%d] ----------\n", n); - /* Emit response callback */ + /* Emit receive callback */ tcore_hal_emit_recv_callback(hal, n, buf); /* @@ -217,164 +402,115 @@ static gboolean __on_recv_vdpram_message(GIOChannel *channel, dbg("Received - [MT SMS]"); n = __vmodem_reencode_mt_sms((gchar *)buf, n); } + else if (buf[0] == 0x25) { + dbg("Replaced % --> +"); + buf[0] = 0x2B; + } /* Dispatch received data to response handler */ + dbg("Invoking tcore_hal_dispatch_response_data()"); ret = tcore_hal_dispatch_response_data(hal, 0, n, buf); msg("\n---------- [RECV FINISH] Receive processing: [%d] ----------\n", ret); return TRUE; } -static gboolean __power_on(gpointer data) +static TReturn hal_power(TcoreHal *hal, gboolean flag) { - CustomData *user_data; - TcoreHal *hal = (TcoreHal*)data; - - dbg("Entry"); - - user_data = tcore_hal_ref_user_data(hal); - tcore_check_return_value_assert(user_data != NULL, TRUE); - - /* - * Open DPRAM device: Create and Open interface to CP - */ - user_data->vdpram_fd = vdpram_open(); - if (user_data->vdpram_fd < 1) { - TcorePlugin *plugin = tcore_hal_ref_plugin(hal); - Server *server = tcore_plugin_ref_server(plugin); - - err("Failed to Create/Open CP interface"); - - /* Notify server a modem error occured */ - tcore_server_send_server_notification(server, - TCORE_SERVER_NOTIFICATION_MODEM_ERR, 0, NULL); - - goto EXIT; - } - dbg("Created AP-CP interface"); - - /* Register to Watch llist */ - user_data->vdpram_watch_id = __register_gio_watch(hal, - user_data->vdpram_fd, __on_recv_vdpram_message); - dbg("fd: [%d] Watch ID: [%d]", user_data->vdpram_fd, user_data->vdpram_watch_id); - - /* Power ON VDPRAM device */ - if (__modem_power(hal, TRUE)) { - dbg("Power ON - [SUCCESS]"); - } else { - err("Power ON - [FAIL]"); - goto EXIT; - } - - /* CP is ONLINE, send AT+CPAS */ - vmodem_config_check_cp_power(hal); - - /* To stop the cycle need to return FALSE */ - return FALSE; - -EXIT: - /* TODO: Handle Deregister */ - - /* To stop the cycle need to return FALSE */ - return FALSE; -} - -/* HAL Operations */ -static TelReturn _hal_power(TcoreHal *hal, gboolean flag) -{ - return __modem_power(hal, flag); + return _modem_power(hal, flag); } -static TelReturn _hal_send(TcoreHal *hal, - guint data_len, void *data) +static TReturn hal_send(TcoreHal *hal, unsigned int data_len, void *data) { - CustomData *user_data; - gint ret; + int ret; + struct custom_data *user_data; if (tcore_hal_get_power_state(hal) == FALSE) { - err("HAL Power state - OFF"); - return TEL_RETURN_FAILURE; + err(" HAL Power state - OFF"); + return TCORE_RETURN_FAILURE; } user_data = tcore_hal_ref_user_data(hal); if (user_data == NULL) { - err("User data is NULL"); - return TEL_RETURN_FAILURE; + err(" User data is NULL"); + return TCORE_RETURN_FAILURE; } ret = vdpram_tty_write(user_data->vdpram_fd, data, data_len); - if(ret < 0) { - err("Write failed"); - return TEL_RETURN_FAILURE; + if(ret < 0) { + err(" Write failed"); + return TCORE_RETURN_FAILURE; + } + else { + dbg("vdpram_tty_write success ret=%d (fd=%d, len=%d)", + ret, user_data->vdpram_fd, data_len); + return TCORE_RETURN_SUCCESS; } - dbg("vdpram_tty_write success ret=%d (fd=%d, len=%d)", - ret, user_data->vdpram_fd, data_len); - - return TEL_RETURN_SUCCESS; } -static TelReturn _hal_setup_netif(CoreObject *co, +static TReturn hal_setup_netif(CoreObject *co, TcoreHalSetupNetifCallback func, void *user_data, - guint cid, gboolean enable) + unsigned int cid, gboolean enable) { char ifname[DEVICE_NAME_LEN_MAX]; int size = 0; int fd = 0; char buf[32]; - char *control = NULL; + const char *control = NULL; if (cid > 3) { - err("Context ID: [%d]", cid); - return TEL_RETURN_INVALID_PARAMETER; + err(" Context ID: [%d]", cid); + return TCORE_RETURN_EINVAL; } if (enable == TRUE) { - dbg("ACTIVATE - Context ID: [%d]", cid); + dbg(" ACTIVATE - Context ID: [%d]", cid); control = "/sys/class/net/svnet0/pdp/activate"; } else { - dbg("DEACTIVATE - Context ID: [%d]", cid); + dbg(" DEACTIVATE - Context ID: [%d]", cid); control = "/sys/class/net/svnet0/pdp/deactivate"; } fd = open(control, O_WRONLY); if (fd < 0) { - err("Failed to Open interface: [%s]", control); + err(" Failed to Open interface: [%s]", control); /* Invoke callback function */ if (func) func(co, -1, NULL, user_data); - return TEL_RETURN_FAILURE; + return TCORE_RETURN_FAILURE; } /* Context ID needs to be written to the Device */ snprintf(buf, sizeof(buf), "%d", cid); size = write(fd, buf, strlen(buf)); + dbg(" SIZE [%d]", size); /* Close 'fd' */ close(fd); /* Device name */ snprintf(ifname, DEVICE_NAME_LEN_MAX, "%s%d", DEVICE_NAME_PREFIX, (cid - 1)); - dbg("Interface Name: [%s]", ifname); + dbg(" Interface Name: [%s]", ifname); /* Invoke callback function */ if (func) func(co, 0, ifname, user_data); - return TEL_RETURN_SUCCESS; + return TCORE_RETURN_SUCCESS; } /* HAL Operations */ -static TcoreHalOperations hal_ops = { - .power = _hal_power, - .send = _hal_send, - .setup_netif = _hal_setup_netif, +static struct tcore_hal_operations hal_ops = { + .power = hal_power, + .send = hal_send, + .setup_netif = hal_setup_netif, }; static gboolean on_load() { - dbg("Load!!!"); + dbg(" Load!!!"); return TRUE; } @@ -382,105 +518,166 @@ static gboolean on_load() static gboolean on_init(TcorePlugin *plugin) { TcoreHal *hal; - CustomData *data; - dbg("Init!!!"); + PluginData *user_data; + struct custom_data *data; - tcore_check_return_value_assert(plugin != NULL, FALSE); + dbg(" Init!!!"); - /* Custom data for Modem Interface Plug-in */ - data = tcore_malloc0(sizeof(CustomData)); - dbg("Created custom data memory"); + if (plugin == NULL) { + err(" PLug-in is NULL"); + return FALSE; + } - /* Create Physical HAL */ - hal = tcore_hal_new(plugin, VMODEM_HAL_NAME, - &hal_ops, TCORE_HAL_MODE_AT); - if (hal == NULL) { - err("Failed to Create Physical HAL"); - tcore_free(data); + /* User Data for Modem Interface Plug-in */ + user_data = g_try_new0(PluginData, 1); + if (user_data == NULL) { + err(" Failed to allocate memory for Plugin data"); return FALSE; } - dbg("HAL [0x%x] created", hal); - /* Set HAL as Modem Interface Plug-in's User data */ - tcore_plugin_link_user_data(plugin, hal); + /* Register to Server */ + user_data->modem = tcore_server_register_modem(tcore_plugin_ref_server(plugin), plugin); + if (user_data->modem == NULL){ + err(" Registration Failed"); + g_free(user_data); + return FALSE; + } + dbg(" Registered from Server"); - /* Link Custom data to HAL's 'user_data' */ - tcore_hal_link_user_data(hal, data); - /* Add callbacks for Send/Receive Hooks */ - tcore_hal_add_send_hook(hal, __on_hal_send, NULL); - tcore_hal_add_recv_callback(hal, __on_hal_recv, NULL); - dbg("Added Send hook and Receive callback"); + data = g_try_new0(struct custom_data, 1); + if (data == NULL) { + err(" Failed to allocate memory for Custom data"); + g_free(user_data); + /* Unregister from Server */ + tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), user_data->modem); + return FALSE; + } - /* Set HAL state to Power OFF (FALSE) */ - (void)tcore_hal_set_power_state(hal, FALSE); - dbg("HAL Power State: Power OFF"); + /* + * Open DPRAM device + */ + data->vdpram_fd = vdpram_open(); - /* Resgister to Server */ - if (tcore_server_register_modem(tcore_plugin_ref_server(plugin), - plugin) == FALSE) { - err("Registration Failed"); + /* + * Create and initialize HAL + */ + hal = tcore_hal_new(plugin, "vmodem", &hal_ops, TCORE_HAL_MODE_AT); + if (hal == NULL) { + /* Close VDPRAM device */ + vdpram_close(data->vdpram_fd); + + /* Fre custom data */ + g_free(data); + + /* Fre Plugin data */ + g_free(user_data); + + /* Unregister from Server */ + tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), user_data->modem); - tcore_hal_free(hal); - tcore_free(data); return FALSE; } - dbg("Registered from Server"); + user_data->hal = hal; + + /* Link custom data to HAL user data */ + tcore_hal_link_user_data(hal, data); + + /* Set HAL as Modem Interface Plug-in's User data */ + tcore_plugin_link_user_data(plugin, user_data); + + /* Register to Watch list */ + data->watch_id_vdpram = __register_gio_watch(hal, + data->vdpram_fd, on_recv_vdpram_message); + dbg(" fd: [%d] Watch ID: [%d]", + data->vdpram_fd, data->watch_id_vdpram); + + /* Power ON VDPRAM device */ + if (_modem_power(hal, TRUE) == TCORE_RETURN_SUCCESS) { + dbg(" Power ON - [SUCCESS]"); + } else { + err(" Power ON - [FAIL]"); + goto EXIT; + } /* Check CP Power ON */ - g_timeout_add_full(G_PRIORITY_HIGH, - AT_CP_POWER_ON_TIMEOUT, __power_on, hal, NULL); + g_timeout_add_full(G_PRIORITY_HIGH, SERVER_INIT_WAIT_TIMEOUT, __load_modem_plugin, hal, 0); + dbg("[VMMODEM] Exit"); return TRUE; + +EXIT: + /* Deregister from Watch list */ + __deregister_gio_watch(data->watch_id_vdpram); + + /* Free HAL */ + tcore_hal_free(hal); + + /* Close VDPRAM device */ + vdpram_close(data->vdpram_fd); + + /* Free custom data */ + g_free(data); + + /*Free Plugin Data*/ + g_free(user_data); + + /* Unregister from Server */ + tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), user_data->modem); + + return FALSE; } static void on_unload(TcorePlugin *plugin) { TcoreHal *hal; - CustomData *user_data; - dbg("Unload!!!"); - - tcore_check_return_assert(plugin != NULL); + struct custom_data *data; + PluginData *user_data; - /* Unload Modem Plug-in */ - tcore_server_unload_modem_plugin(tcore_plugin_ref_server(plugin), plugin); - - /* Unregister Modem Interface Plug-in from Server */ - tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), plugin); - dbg("Unregistered from Server"); + dbg(" Unload!!!"); - /* HAL cleanup */ - hal = tcore_plugin_ref_user_data(plugin); - if (hal == NULL) { - err("HAL is NULL"); + if (plugin == NULL) return; - } - user_data = tcore_hal_ref_user_data(hal); + user_data = tcore_plugin_ref_user_data(plugin); if (user_data == NULL) return; + hal = user_data->hal; + + /* Unload Modem Plug-in */ +#if 0 /* TODO - Open the code below */ + tcore_server_unload_modem_plugin(tcore_plugin_ref_server(plugin), plugin); +#endif + data = tcore_hal_ref_user_data(hal); + if (data == NULL) + return; + /* Deregister from Watch list */ - __deregister_gio_watch(user_data->vdpram_watch_id); - dbg("Deregistered Watch ID"); + __deregister_gio_watch(data->watch_id_vdpram); + dbg(" Deregistered Watch ID"); + + /* Free HAL */ + tcore_hal_free(hal); + dbg(" Freed HAL"); /* Close VDPRAM device */ - (void)vdpram_close(user_data->vdpram_fd); - dbg("Closed VDPRAM device"); + vdpram_close(data->vdpram_fd); + dbg(" Closed VDPRAM device"); /* Free custom data */ - g_free(user_data); + g_free(data); - /* Free HAL */ - tcore_hal_free(hal); - dbg("Freed HAL"); + tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), user_data->modem); + dbg(" Unregistered from Server"); - dbg("Unloaded MODEM Interface Plug-in"); + dbg(" Unloaded MODEM"); + g_free(user_data); } -/* VMODEM (Modem Interface Plug-in) descriptor */ +/* VMODEM Descriptor Structure */ EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = { - .name = "vmodem", + .name = "VMODEM", .priority = TCORE_PLUGIN_PRIORITY_HIGH, .version = 1, .load = on_load, diff --git a/src/vdpram.c b/src/vdpram.c index 07eca2a..f585850 100644 --- a/src/vdpram.c +++ b/src/vdpram.c @@ -1,538 +1,523 @@ -/* - * tel-plugin-vmodem - * - * 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 - -#include - -#include "vdpram.h" - -#ifndef TIOCMODG -# ifdef TIOCMGET -# define TIOCMODG TIOCMGET -# else -# ifdef MCGETA -# define TIOCMODG MCGETA -# endif -# endif -#endif - -#ifndef TIOCMODS -# ifdef TIOCMSET -# define TIOCMODS TIOCMSET -# else -# ifdef MCSETA -# define TIOCMODS MCSETA -# endif -# endif -#endif - -#define VDPRAM_OPEN_PATH "/dev/vdpram0" - -/* DPRAM ioctls for DPRAM tty devices */ -#define IOC_MZ_MAGIC ('h') -#define HN_DPRAM_PHONE_ON _IO (IOC_MZ_MAGIC, 0xd0) -#define HN_DPRAM_PHONE_OFF _IO (IOC_MZ_MAGIC, 0xd1) -#define HN_DPRAM_PHONE_GETSTATUS _IOR(IOC_MZ_MAGIC, 0xd2, guint) - -/* Retry parameters */ -#define SLEEP_TIME_IN_SEC 0 -#define SLEEP_TIME_IN_MSEC 50 - -#define MAX_RETRY_COUNT 10 - -typedef struct tty_old_setting TtyOldSetting; - -struct tty_old_setting { - gint fd; - struct termios termiosVal; - TtyOldSetting *next; - TtyOldSetting *prev; -}; - -static TtyOldSetting *ttyold_head = NULL; - /* - * Insert TTY old settings + * tel-plugin-vmodem + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Junhwan An + * + * 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. */ -static void __insert_tty_oldsetting(TtyOldSetting *me) -{ - dbg("Enter"); - - if (me == NULL) - return; - - if (ttyold_head) - ttyold_head->prev = me; - - me->next = ttyold_head; - me->prev = 0; - ttyold_head = me; -} - + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "legacy/TelUtility.h" +#include "vdpram.h" +#include "vdpram_dump.h" + +#ifndef TIOCMODG +# ifdef TIOCMGET +# define TIOCMODG TIOCMGET +# else +# ifdef MCGETA +# define TIOCMODG MCGETA +# endif +# endif +#endif + +#ifndef TIOCMODS +# ifdef TIOCMSET +# define TIOCMODS TIOCMSET +# else +# ifdef MCSETA +# define TIOCMODS MCSETA +# endif +# endif +#endif + +typedef struct _tty_old_setting_t{ + int fd; + struct termios termiosVal; + struct _tty_old_setting_t *next; + struct _tty_old_setting_t *prev; +} tty_old_setting_t; + +#define VDPRAM_OPEN_PATH "/dev/vdpram0" + +/* DPRAM ioctls for DPRAM tty devices */ +#define IOC_MZ_MAGIC ('h') +#define HN_DPRAM_PHONE_ON _IO (IOC_MZ_MAGIC, 0xd0) +#define HN_DPRAM_PHONE_OFF _IO (IOC_MZ_MAGIC, 0xd1) +#define HN_DPRAM_PHONE_GETSTATUS _IOR(IOC_MZ_MAGIC, 0xd2, unsigned int) + +static tty_old_setting_t *ttyold_head = NULL; + +/* static functions */ +static void __insert_tty_oldsetting(tty_old_setting_t *me) +{ + dbg("Function Enterence."); + + if (me == NULL) + return; + + if (ttyold_head) + ttyold_head->prev = me; + + me->next = ttyold_head; + me->prev = 0; + ttyold_head = me; +} + +static tty_old_setting_t *__search_tty_oldsetting(int fd) +{ + tty_old_setting_t *tty = NULL; + + dbg("Function Enterence."); + + if (ttyold_head == NULL) + return NULL; + + tty = ttyold_head; + + do{ + if (tty->fd == fd) { + dbg("oldsetting for inputted fd is found"); + break; + } + else { + if (tty->next == NULL) { + dbg("No oldsetting is found"); + tty = NULL; + break; + } + tty = tty->next; + } + }while(1); + + return tty; +} + +static void __remove_tty_oldsetting(tty_old_setting_t *me) +{ + dbg( "Function Enterence."); + + if (me == NULL) + return; + + if (me->prev) + me->prev->next = me->next; + else + ttyold_head = me->next; + + if (me->next) + me->next->prev = me->prev; +} + +/* Set hardware flow control. +*/ +static void __tty_sethwf(int fd, int on) +{ + struct termios tty; + + dbg("Function Enterence."); + + if (tcgetattr(fd, &tty)) + err("__tty_sethwf: tcgetattr:"); + + if (on) + tty.c_cflag |= CRTSCTS; + else + tty.c_cflag &= ~CRTSCTS; + + if (tcsetattr(fd, TCSANOW, &tty)) + err("__tty_sethwf: tcsetattr:"); +} + /* - * Search TTY old settings - */ -static TtyOldSetting *__search_tty_oldsetting(gint fd) -{ - TtyOldSetting *tty = ttyold_head; - - dbg("Enter"); - - while (tty) { - if (tty->fd == fd) { - dbg("tty for fd [%d] found!!!", fd); - break; - } - tty = tty->next; - }; - - return tty; -} - +* Set RTS line. Sometimes dropped. Linux specific? +*/ +static int __tty_setrts(int fd) +{ + int mcs; + + dbg("Function Enterence."); + + if (-1 == ioctl(fd, TIOCMODG, &mcs)) + err("icotl: TIOCMODG"); + + mcs |= TIOCM_RTS; + + if (-1 == ioctl(fd, TIOCMODS, &mcs)) + err("icotl: TIOCMODS"); + + return 0; +} + /* - * Remove TTY old settings + * Set baudrate, parity and number of bits. */ -static void __remove_tty_oldsetting(TtyOldSetting *me) -{ - dbg("Enter"); - - if (me == NULL) - return; - - if (me->prev) - me->prev->next = me->next; - else - ttyold_head = me->next; - - if (me->next) - me->next->prev = me->prev; -} - +static int __tty_setparms(int fd, + const char* baudr, const char* par, + const char* bits, const char* stop, + int hwf, int swf) +{ + int spd = -1; + int newbaud; + int bit = bits[0]; + int stop_bit = stop[0]; + + struct termios tty; + tty_old_setting_t *old_setting = NULL; + + dbg("Function Enterence."); + + old_setting = calloc(sizeof(tty_old_setting_t), 1); + + if (old_setting == NULL) + return TAPI_API_SYSTEM_OUT_OF_MEM; + + old_setting->fd = fd; + + if (tcgetattr(fd, &tty) < 0) { + free(old_setting); + return TAPI_API_TRANSPORT_LAYER_FAILURE; + } + + if (tcgetattr(fd, &old_setting->termiosVal) < 0) { + free(old_setting); + return TAPI_API_TRANSPORT_LAYER_FAILURE; + } + + __insert_tty_oldsetting(old_setting); + + fflush(stdout); + + /* We generate mark and space parity ourself. */ + if (bit == '7' && (par[0] == 'M' || par[0] == 'S')) + bit = '8'; + + /* Check if 'baudr' is really a number */ + if ((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0') + newbaud = -1; + + switch(newbaud) + { + case 0: + spd = 0; + break; + + case 3: + spd = B300; + break; + + case 6: + spd = B600; + break; + + case 12: + spd = B1200; + break; + + case 24: + spd = B2400; + break; + + case 48: + spd = B4800; + break; + + case 96: + spd = B9600; + break; + + case 192: + spd = B19200; + break; + + case 384: + spd = B38400; + break; + + case 576: + spd = B57600; + break; + + case 1152: + spd = B115200; + break; + + default: + err("invaid baud rate"); + break; + } + + if (spd != -1) { + cfsetospeed(&tty, (speed_t) spd); + cfsetispeed(&tty, (speed_t) spd); + } + + switch(bit) + { + case '5': + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5; + break; + + case '6': + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6; + break; + + case '7': + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7; + break; + + case '8': + default: + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; + break; + } + + switch(stop_bit) + { + case '1': + tty.c_cflag &= ~CSTOPB; + break; + + case '2': + default: + tty.c_cflag |= CSTOPB; + break; + } + + /* Set into raw, no echo mode */ + tty.c_iflag = IGNBRK; + tty.c_lflag = 0; + tty.c_oflag = 0; + tty.c_cflag |= CLOCAL | CREAD; + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 1; + + if (swf) + tty.c_iflag |= IXON | IXOFF; + else + tty.c_iflag &= ~(IXON | IXOFF | IXANY); + + tty.c_cflag &= ~(PARENB | PARODD); + + if (par[0] == 'E') + tty.c_cflag |= PARENB; + else if (par[0] == 'O') + tty.c_cflag |= (PARENB | PARODD); + + if (tcsetattr(fd, TCSANOW, &tty) < 0) { + free(old_setting); + return TAPI_API_TRANSPORT_LAYER_FAILURE; + } + + __tty_setrts(fd); + __tty_sethwf(fd, hwf); + + return TAPI_API_SUCCESS; + +} + +static int __tty_close(int fd) +{ + tty_old_setting_t *old_setting = NULL; + + dbg("Function Enterence."); + + old_setting = __search_tty_oldsetting(fd); + if (old_setting == NULL) + return TAPI_API_SUCCESS; + + if (tcsetattr(fd, TCSAFLUSH, &old_setting->termiosVal) < 0) { + err("close failed"); + return TAPI_API_TRANSPORT_LAYER_FAILURE; + } + + __remove_tty_oldsetting(old_setting); + + free(old_setting); + + close(fd); + + return TAPI_API_SUCCESS; +} + /* - * Set hardware flow control - */ -static void __tty_sethwf(gint fd, gint on) -{ - struct termios tty; - - dbg("Enter"); - - if (tcgetattr(fd, &tty)) - err("__tty_sethwf: tcgetattr:"); - - if (on == 1) - tty.c_cflag |= CRTSCTS; - else - tty.c_cflag &= ~CRTSCTS; - - if (tcsetattr(fd, TCSANOW, &tty)) - err("__tty_sethwf: tcsetattr:"); -} - -/* - * Set RTS line. Sometimes dropped. Linux specific? - */ -static gint __tty_setrts(gint fd) -{ - gint mcs; - - dbg("Enter"); - - if (-1 == ioctl(fd, TIOCMODG, &mcs)) - err("icotl: TIOCMODG"); - - mcs |= TIOCM_RTS; - - if (-1 == ioctl(fd, TIOCMODS, &mcs)) - err("icotl: TIOCMODS"); - - return 0; -} - -/* - * Set baudrate, parity and number of bits - */ -static gboolean __tty_setparms(gint fd, - gchar *baudr, gchar *par, gchar *bits, gchar *stop, gint hwf, gint swf) -{ - gint spd = -1; - gint newbaud; - gint bit = bits[0]; - gint stop_bit = stop[0]; - - struct termios tty; - TtyOldSetting *old_setting = NULL; - - dbg("Enter"); - - old_setting = g_try_new0(TtyOldSetting, 1); - - if (old_setting == NULL) - return FALSE; - - old_setting->fd = fd; - - if (tcgetattr(fd, &tty) < 0) { - g_free(old_setting); - return FALSE; - } - - if (tcgetattr(fd, &old_setting->termiosVal) < 0) { - g_free(old_setting); - return FALSE; - } - - __insert_tty_oldsetting(old_setting); - - fflush(stdout); - - /* We generate mark and space parity ourself. */ - if (bit == '7' && (par[0] == 'M' || par[0] == 'S')) - bit = '8'; - - /* Check if 'baudr' is really a number */ - if ((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0') - newbaud = -1; - - switch (newbaud) { - case 0: - spd = 0; - break; - - case 3: - spd = B300; - break; - - case 6: - spd = B600; - break; - - case 12: - spd = B1200; - break; - - case 24: - spd = B2400; - break; - - case 48: - spd = B4800; - break; - - case 96: - spd = B9600; - break; - - case 192: - spd = B19200; - break; - - case 384: - spd = B38400; - break; - - case 576: - spd = B57600; - break; - - case 1152: - spd = B115200; - break; - - default: - err("invaid baud rate"); - break; - } - - if (spd != -1) { - cfsetospeed(&tty, (speed_t) spd); - cfsetispeed(&tty, (speed_t) spd); - } - - switch (bit) { - case '5': - tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5; - break; - - case '6': - tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6; - break; - - case '7': - tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7; - break; - - case '8': - default: - tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; - break; - } - - switch (stop_bit) { - case '1': - tty.c_cflag &= ~CSTOPB; - break; - - case '2': - default: - tty.c_cflag |= CSTOPB; - break; - } - - /* Set into raw, no echo mode */ - tty.c_iflag = IGNBRK; - tty.c_lflag = 0; - tty.c_oflag = 0; - tty.c_cflag |= CLOCAL | CREAD; - tty.c_cc[VMIN] = 1; - tty.c_cc[VTIME] = 1; - - if (swf) - tty.c_iflag |= IXON | IXOFF; - else - tty.c_iflag &= ~(IXON | IXOFF | IXANY); - - tty.c_cflag &= ~(PARENB | PARODD); - - if (par[0] == 'E') - tty.c_cflag |= PARENB; - else if (par[0] == 'O') - tty.c_cflag |= (PARENB | PARODD); - - if (tcsetattr(fd, TCSANOW, &tty) < 0) { - g_free(old_setting); - return FALSE; - } - - __tty_setrts(fd); - __tty_sethwf(fd, hwf); - - return TRUE; -} - +* restore the old settings before close. +*/ +int vdpram_close(int fd) +{ + int ret = TAPI_API_SUCCESS; + + dbg("Function Enterence."); + + ret = __tty_close(fd); + + return ret; +} + /* - * Close TTY Device - */ -static gboolean __tty_close(gint fd) -{ - TtyOldSetting *old_setting = NULL; - - dbg("Enter"); - - /* Get previous settings */ - old_setting = __search_tty_oldsetting(fd); - if (old_setting == NULL) { - dbg("No previous settings found!!!"); - return TRUE; - } - - if (tcsetattr(fd, TCSAFLUSH, &old_setting->termiosVal) < 0) { - err("Close failed"); - return FALSE; - } - - /* Remove the previous setting configured */ - __remove_tty_oldsetting(old_setting); - - /* Free memory */ - g_free(old_setting); - - /* Close fd */ - close(fd); - - return TRUE; -} - -/* - * Wait on select - */ -static void __sleep(gint sec, gint msec) +* Open the vdpram fd. +*/ +int vdpram_open (void) { - struct timeval tv; + int rv = -1; + int fd = -1; + int val = 0; + unsigned int cmd =0; + + fd = open(VDPRAM_OPEN_PATH, O_RDWR); + + if (fd < 0) { + err("#### Failed to open vdpram file: error no hex %x", errno); + return rv; + } + else + dbg("#### Success to open vdpram file. fd:%d, path:%s", fd, VDPRAM_OPEN_PATH); + + + if (__tty_setparms(fd, "115200", "N", "8", "1", 0, 0) != TAPI_API_SUCCESS) { + vdpram_close(fd); + return rv; + } + else + dbg("#### Success set tty vdpram params. fd:%d", fd); + + /*TODO: No need to check Status. Delete*/ + cmd = HN_DPRAM_PHONE_GETSTATUS; + + if (ioctl(fd, cmd, &val) < 0) { + err("#### ioctl failed fd:%d, cmd:%lu, val:%d", fd,cmd,val); + vdpram_close(fd); + return rv; + } + else + dbg("#### ioctl Success fd:%d, cmd:%lu, val:%d", fd,cmd,val); - tv.tv_sec = sec; - tv.tv_usec = msec; + return fd; - select(0, NULL, NULL, NULL, &tv); } /* - * Close the VDPRAM device - */ -gboolean vdpram_close(gint fd) -{ - gint ret; - - dbg("Enter"); - - /* Close VDPRAM Device */ - ret = __tty_close(fd); - - return ret; -} - -/* - * Open the VDPRAM device - */ -gint vdpram_open (void) -{ - gint rv = -1; - gint fd = -1; - gint val = 0; - guint cmd =0; - - dbg("Enter"); - - /* Open DPRAM device */ - fd = open(VDPRAM_OPEN_PATH, O_RDWR); - if (fd < 0) { - err("Open VDPRAM file - [FAIL] Error: [%s]", strerror(errno)); - return rv; - } else { - dbg("Open VDPRAM file - [SUCCESS] fd: [%d] path: [%s]", - fd, VDPRAM_OPEN_PATH); - } - - /* Set device parameters */ - if (__tty_setparms(fd, "115200", "N", "8", "1", 0, 0) != TRUE) { - err("Set TTY device parameters - [FAIL]"); - - /* Close VDPRAM Device */ - (void)vdpram_close(fd); - return rv; - } +* power on the phone. +*/ +int vdpram_poweron(int fd) +{ + int rv = -1; + + if (ioctl(fd, HN_DPRAM_PHONE_ON, NULL) < 0) { + err("Phone Power On failed (fd:%d)", fd); + rv = 0; + } else { - dbg("Set TTY device parameters - [SUCCESS]"); + dbg("Phone Power On success (fd:%d)", fd); + rv = 1; } - - /* TODO: No need to check Status. Delete */ - cmd = HN_DPRAM_PHONE_GETSTATUS; - if (ioctl(fd, cmd, &val) < 0) { - err("Get Phone status - [FAIL] fd: [d] cmd: [%d] val: [%d]", - fd, cmd, val); - - /* Close Device */ - (void)vdpram_close(fd); - - return rv; - } else { - dbg("Get Phone status - [SUCCESS]"); - } - - return fd; -} - -/* - * Power ON the Phone + return rv; +} + + /* + * Power Off the Phone. */ -gboolean vdpram_poweron(gint fd) -{ - if (ioctl(fd, HN_DPRAM_PHONE_ON, NULL) < 0) { - err("Phone Power ON [FAIL] - fd: [%d] Error: [%s]", fd, strerror(errno)); - return FALSE; - } - else { - dbg("Phone Power ON [SUCCESS] - fd: [%d]", fd); - return TRUE; - } -} - +int vdpram_poweroff(int fd) +{ + int rv; + + if (ioctl(fd, HN_DPRAM_PHONE_OFF, NULL) < 0) { + err("Phone Power Off failed."); + rv = -1; + } + else { + dbg("Phone Power Off success."); + rv = 1; + } + + return rv; +} + /* - * Power OFF the Phone - */ -gboolean vdpram_poweroff(gint fd) -{ - if (ioctl(fd, HN_DPRAM_PHONE_OFF, NULL) < 0) { - err("Phone Power OFF [FAIL] - fd: [%d] Error: [%s]", fd, strerror(errno)); - return FALSE; - } - else { - dbg("Phone Power OFF [SUCCESS] - fd: [%d]", fd); - return TRUE; - } -} - -/* - * Read data from VDPRAM - */ -gint vdpram_tty_read(gint fd, void *buf, size_t buf_len) -{ - gint actual = 0; - - if ((actual = read(fd, buf, buf_len)) < 0) { - err("Read [FAIL] - fd: [%d] Error: [%s]", fd, strerror(errno)); - } - - return actual; -} - -/* - * Write data to VDPRAM - */ -gint vdpram_tty_write(gint fd, void *buf, size_t buf_len) -{ - size_t actual = 0; - guint retry = 0; - gint ret; - - while(actual < buf_len) { - /* Write to Device */ - ret = write(fd, (guchar *)buf, buf_len - actual); +* Read data from vdpram. +*/ + +int vdpram_tty_read(int nFd, void* buf, size_t nbytes) +{ + int actual = 0; + + if ((actual = read(nFd, buf, nbytes)) < 0) { + dbg("[TRANSPORT DPRAM]read failed."); + } + vdpram_hex_dump(IPC_RX, actual, buf); + + return actual; +} + +static void __selectsleep(int sec,int msec) +{ + struct timeval tv; + tv.tv_sec=sec; + tv.tv_usec=msec; + select(0,NULL,NULL,NULL,&tv); + return; +} + +/* +* Write data to vdpram. +*/ +int vdpram_tty_write(int nFd, void* buf, size_t nbytes) +{ + int ret; + size_t actual = 0; + int retry = 0; + + do { + vdpram_hex_dump(IPC_TX, nbytes, buf); + ret = write(nFd, (unsigned char* )buf, nbytes - actual); + + if ((ret < 0 && errno == EAGAIN) || (ret < 0 && errno == EBUSY)) { + err("write failed. retry.. ret[%d] with errno[%d] ",ret, errno); + __selectsleep(0,50); + + if (retry == 10) + return 0; + + retry = retry + 1; + continue; + } + if (ret < 0) { - err("Write [FAIL] - fd: [%d] Error: [%s]", - fd, strerror(errno)); - - if ((errno == EAGAIN) || (errno == EBUSY)) { - /* Sleep for 50 msecs */ - __sleep(SLEEP_TIME_IN_SEC, SLEEP_TIME_IN_MSEC); - - if (retry == MAX_RETRY_COUNT) { - err("Maximum retries completed!!!"); - return 0; - } - - retry = retry + 1; - continue; - } - - if (actual != buf_len) - err("Write [FAIL] - fd: [%d]", fd); - - err("Write [FAIL] - Error: [%s]", strerror(errno)); - return actual; - } - - actual += ret; - buf += ret; - dbg("Write Actual bytes: [%d] Written bytes: [%d]", actual, ret); - }; - - return actual; -} + if (actual != nbytes) + err("write failed.ret[%d]",ret); + + err("errno [%d]",errno); + return actual; + } + + actual += ret; + buf += ret; + + } while(actual < nbytes); + + return actual; +} +/* EOF */ diff --git a/src/vdpram_dump.c b/src/vdpram_dump.c index d44836e..adc8d6f 100644 --- a/src/vdpram_dump.c +++ b/src/vdpram_dump.c @@ -1,49 +1,79 @@ -/* - * tel-plugin-vmodem - * - * 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 "vdpram_dump.h" - -void vdpram_hex_dump(gboolean tx, gushort data_len, void *data) -{ - char *d; - - if(!data) - return; - - if (tx == TRUE) - d = "[TX]"; - else - d = "[RX]"; - - msg("\n====== Data DUMP ======\n"); - - msg(" %s\tData length: [%d] -", d, data_len); - tcore_util_hex_dump(" ", (gint)data_len, data); - - msg("\n====== Data DUMP ======\n"); -} +/* + * tel-plugin-vmodem + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Junhwan An + * + * 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 "vdpram_dump.h" + +static void hex_dump(const char *pad, int size, const void *data) +{ + char buf[255] = {0, }; + char hex[4] = {0, }; + int i; + unsigned const char *p; + + if (size <= 0) { + msg("%sno data", pad); + return; + } + + p = (unsigned const char *)data; + + snprintf(buf, 255, "%s%04X: ", pad, 0); + for (i = 0; i - + -- 2.7.4