# Set required packages
INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 tcore tel-headers)
+pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 tcore dlog)
FOREACH(flag ${pkgs_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
ADD_DEFINITIONS("-DFEATURE_TLOG_DEBUG")
ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"IMCMODEM\"")
-ADD_DEFINITIONS("-DEXPORT_API=__attribute__((visibility(\"default\")))")
MESSAGE(${CMAKE_C_FLAGS})
MESSAGE(${CMAKE_EXE_LINKER_FLAGS})
SET(SRCS
- src/desc-imcmodem.c
- src/vnet.c
- src/config.c
+ src/desc-imcmodem.c
+ src/imcmodem.c
+ src/vnet.c
+ src/config.c
)
/*
* tel-plugin-imcmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef __CONFIG_H__
-#define __CONFIG_H__
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
#ifdef __cplusplus
extern "C" {
}
#endif /* __cplusplus */
-#endif /* __CONFIG_H__ */
+#endif /* _CONFIG_H_ */
--- /dev/null
+/*\r
+ * tel-plugin-imcmodem\r
+ *\r
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact: Kyoungyoup Park <gynaru.park@samsung.com>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __IMCMODEM_H__\r
+#define __IMCMODEM_H__\r
+\r
+typedef struct vnet_channel {\r
+ int fd;\r
+ guint watch_id;\r
+ gboolean on;\r
+} ImcmodemVnetChannel;\r
+\r
+typedef struct custom_data {\r
+ TcoreModem *modem;\r
+ ImcmodemVnetChannel ipc0;\r
+} ImcmodemCustomData;\r
+\r
+/* Initialize */\r
+gboolean imcmodem_init(TcorePlugin *plugin);\r
+\r
+/* De-initialize */\r
+void imcmodem_deinit(TcorePlugin *plugin);\r
+\r
+#endif /* __IMCMODEM_H__ */\r
/*
* tel-plugin-imcmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef __VNET_H__
-#define __VNET_H__
+#ifndef _VNET_H_
+#define _VNET_H_
#ifdef __cplusplus
extern "C" {
#endif
/* CP states */
-typedef enum {
+enum vnet_cp_state {
VNET_CP_STATE_UNKNOWN = -1,
VNET_CP_STATE_OFFLINE = 0,
VNET_CP_STATE_CRASH_RESET,
VNET_CP_STATE_ONLINE,
VNET_CP_STATE_NV_REBUILDING,
VNET_CP_STATE_LOADER_DONE,
-} VnetCpState;
+};
-void vnet_start_cp_ramdump(void);
-void vnet_start_cp_reset(void);
+void vnet_start_cp_ramdump( void );
+void vnet_start_cp_reset( void );
-VnetCpState vnet_get_cp_state(int fd);
+enum vnet_cp_state vnet_get_cp_state( int fd );
-int vnet_rfs0_open(void);
-int vnet_ipc0_open(void);
+int vnet_rfs0_open( void );
+int vnet_ipc0_open( void );
#ifdef __cplusplus
}
#endif /* __cplusplus */
-#endif /* __VNET_H__ */
+#endif /* _VNET_H_ */
-%define major 3
-%define minor 0
-%define patchlevel 1
-
-Name: tel-plugin-imcmodem
-Version: %{major}.%{minor}.%{patchlevel}
-Release: 1
-License: Apache-2.0
-Summary: Telephony Plug-in for AT communication with IMC modem (Modem Interface Plug-in)
-Group: System/Libraries
-Source0: tel-plugin-imcmodem-%{version}.tar.gz
-Source1001: tel-plugin-imcmodem.manifest
-BuildRequires: cmake
-BuildRequires: pkgconfig(glib-2.0)
-BuildRequires: pkgconfig(tcore)
-BuildRequires: pkgconfig(tel-headers)
-Requires(post): /sbin/ldconfig
+%define major 0
+%define minor 1
+%define patchlevel 10
+
+Name: tel-plugin-imcmodem
+Version: %{major}.%{minor}.%{patchlevel}
+Release: 1
+License: Apache-2.0
+Summary: telephony plugin library for AT communication with IMC modem
+Group: System/Libraries
+Source0: tel-plugin-imcmodem-%{version}.tar.gz
+BuildRequires: cmake
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(tcore)
+Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig
%description
%prep
%setup -q
-cp %{SOURCE1001} .
%build
%cmake .
-make %{?jobs:-j%jobs}
+make %{?_smp_mflags}
%post
/sbin/ldconfig
cp LICENSE %{buildroot}/usr/share/license/%{name}
%files
-%manifest %{name}.manifest
+%manifest tel-plugin-imcmodem.manifest
%defattr(-,root,root,-)
%{_libdir}/telephony/plugins/*
/usr/share/license/%{name}
/*
* tel-plugin-imcmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <server.h>
#include <plugin.h>
#include <storage.h>
+#include <user_request.h>
#include <core_object.h>
#include <hal.h>
#include <at.h>
#include <mux.h>
+#include "imcmodem.h"
#include "config.h"
#define IMC_MODEM_PLUGIN_NAME "imc-plugin.so"
#define IMC_AT_CPAS_RESULT_ASLEEP 5
/* Maximum Core objects per Logical HAL (indirectly per Channel) */
-#define MAX_CO_PER_CHANNEL 3
+#define MAX_CORE_OBJECTS_PER_CHANNEL 3
+
+#define IMCMODEM_AT_CMD_XTRACE_ENABLE "at+xsystrace=1,\"digrf=1;bb_sw=1;3g_sw=1\",\"digrf=0x84\",\"oct=4\";+xsystrace=11;+trace=1"
/*
* List of supported Core Object types
* Channel 6 - NETWORK & GPS
* Channel 7 - MODEM & PS
*/
-guint supported_modules[IMC_CMUX_MAX_CHANNELS+1][MAX_CO_PER_CHANNEL] =
+unsigned int
+ supported_modules[IMC_CMUX_MAX_CHANNELS+1][MAX_CORE_OBJECTS_PER_CHANNEL] =
{
/*
* Channel 0 - CMUX Control Channel
static gboolean _check_cp_poweron(TcoreHal *hal);
static void _send_enable_logging_command(TcoreHal *hal);
-static void _on_confirmation_send_message(TcorePending *p,
- TelReturn send_status, void *user_data)
+static void _on_confirmation_send_message(TcorePending *pending,
+ gboolean result, void *user_data)
{
- dbg("Message send confirmation - [%s]",
- ((send_status != TEL_RETURN_SUCCESS) ? "FAIL" : "OK"));
-}
+ dbg("Message send confirmation");
-static void _assign_objects_to_hal(guint channel_id, TcoreHal *hal)
+ if (result == FALSE) { /* Fail */
+ dbg("SEND FAIL");
+ } else {
+ dbg("SEND OK");
+ }
+}
+static void _assign_objects_to_hal(int channel_id, TcoreHal *hal, TcoreHal *phy_hal)
{
- TcorePlugin *plugin;
+ ImcmodemCustomData *custom_data;
+ TcoreModem *modem;
gboolean ret;
- guint i;
+ int i;
- plugin = tcore_hal_ref_plugin(hal);
+ if (hal == NULL) {
+ err("HAL is NULL");
+ return;
+ }
+
+ if (phy_hal == NULL) {
+ err("Physical HAL is NULL");
+ return;
+ }
+
+ custom_data = tcore_hal_ref_user_data(phy_hal);
+ if (custom_data == NULL) {
+ err("custom_data is NULL");
+ return;
+ }
- for (i = 0 ; i < MAX_CO_PER_CHANNEL ; i++) {
+ modem = custom_data->modem;
+
+ for (i = 0 ; i < MAX_CORE_OBJECTS_PER_CHANNEL ; i++) {
if (supported_modules[channel_id][i] == 0)
continue;
/* Add Core Object type for specific 'hal' */
- ret = tcore_server_add_cp_mapping_tbl_entry(plugin,
+ ret = tcore_server_add_cp_mapping_tbl_entry(modem,
supported_modules[channel_id][i], hal);
if (ret == TRUE) {
- dbg("Core Object Type: [0x%x] - Success",
- supported_modules[channel_id][i]);
+ dbg("Core Object Type: [0x%x] - Success");
} else {
- err("Core Object Type: [0x%x] - Fail",
- supported_modules[channel_id][i]);
+ err("Core Object Type: [0x%x] - Fail");
}
}
}
static void _on_cmux_setup_complete(gpointer user_data)
{
+ Server *s;
TcoreHal *hal = user_data;
- TcorePlugin *plugin;
+ ImcmodemCustomData *custom_data;
+ unsigned int slot_cnt = 1;
+
dbg("MUX Setup - COMPLETE");
- tcore_check_return(user_data != NULL);
+ if (hal == NULL) {
+ err("HAL is NULL");
+ return;
+ }
- plugin = tcore_hal_ref_plugin(hal);
+ custom_data = tcore_hal_ref_user_data(hal);
+ if (custom_data == NULL) {
+ err("custom_data is NULL");
+ return;
+ }
- /* Print all the HALs and Core Objects for the Plug-in */
- tcore_server_print_modems(plugin);
+ s = tcore_plugin_ref_server(tcore_hal_ref_plugin(hal));
/* Load Modem Plug-in */
- tcore_server_load_modem_plugin(tcore_plugin_ref_server(plugin),
- plugin, IMC_MODEM_PLUGIN_NAME);
+ tcore_server_load_modem_plugin(s,
+ custom_data->modem, IMC_MODEM_PLUGIN_NAME);
+ dbg("Modem plug-in loaded");
+
+ tcore_server_send_notification(s, NULL,
+ TNOTI_SERVER_ADDED_MODEM_PLUGIN_COMPLETED,
+ sizeof(slot_cnt), &slot_cnt);
}
-static void _on_cmux_channel_setup(guint channel_id,
+static void _on_cmux_channel_setup(int channel_id,
TcoreHal *hal, gpointer user_data)
{
+ TcorePlugin *plugin;
TcoreHal *phy_hal;
if ((hal == NULL) || (user_data == NULL))
return;
}
phy_hal = user_data;
+ plugin = tcore_hal_ref_plugin(hal);
- dbg("Channel ID: [%d] Logical HAL: [0x%x] Physical HAL: [0x%x]", channel_id, hal, phy_hal);
+ dbg("Channel ID: [%d] Logical HAL: [0x%x]", channel_id, hal);
/* Assign specifc Core Object types to the Logical HAL (CMUX Channel) */
- _assign_objects_to_hal(channel_id, hal);
+ _assign_objects_to_hal(channel_id, hal, phy_hal);
/* Set HAL state to Power ON (TRUE) */
tcore_hal_set_power_state(hal, TRUE);
dbg("HAL Power State: Power ON");
}
-static void _on_response_cmux_init(TcorePending *p,
- guint data_len, const void *data, void *user_data)
+static void _on_response_cmux_init(TcorePending *p, int data_len,
+ const void *data, void *user_data)
{
- const TcoreAtResponse *resp = data;
+ const TcoreATResponse *resp = data;
TcoreHal *hal = user_data;
- TelReturn ret;
- if (resp && resp->success) {
+ if ((resp != NULL) && resp->success) {
+ TReturn ret;
dbg("Initialize CMUX - [OK]");
/* Setup Internal CMUX */
ret = tcore_cmux_setup_internal_mux(CMUX_MODE_BASIC,
- IMC_CMUX_MAX_CHANNELS, IMC_CMUX_MAX_BUFFER_SIZE, hal,
- _on_cmux_channel_setup, hal, _on_cmux_setup_complete, hal);
+ IMC_CMUX_MAX_CHANNELS,
+ IMC_CMUX_MAX_BUFFER_SIZE, hal,
+ _on_cmux_channel_setup, hal,
+ _on_cmux_setup_complete, hal);
} else {
err("Initialize CMUX - [NOK]");
}
}
static void _on_response_enable_logging(TcorePending *p,
- guint data_len, const void *data, void *user_data)
+ int data_len, const void *data, void *user_data)
{
- const TcoreAtResponse *resp = data;
+ const TcoreATResponse *resp = data;
TcoreHal *hal = user_data;
- TelReturn ret;
+ TReturn ret;
- if (resp && resp->success) {
+ if ((resp != NULL) && resp->success) {
dbg("Enable CP logging - [OK]");
} else {
err("Enable CP logging - [NOK]");
/* Initialize Internal MUX (CMUX) */
ret = tcore_cmux_init(hal, 0, _on_response_cmux_init, hal);
- if (ret != TEL_RETURN_SUCCESS) {
+ if (ret != TCORE_RETURN_SUCCESS) {
err("Failed to initialize CMUX - Error: [0x%x]", ret);
} else {
dbg("Successfully sent CMUX init to CP");
static void _on_timeout_check_cp_poweron(TcorePending *p, void *user_data)
{
TcoreHal *hal = user_data;
- guint data_len = 0;
+ unsigned int data_len = 0;
char *data = "AT+CPAS";
data_len = sizeof(data);
}
static void _on_response_check_cp_poweron(TcorePending *pending,
- guint data_len, const void *data, void *user_data)
+ int data_len, const void *data, void *user_data)
{
- const TcoreAtResponse *resp = data;
+ const TcoreATResponse *resp = data;
TcoreHal *hal = user_data;
GSList *tokens = NULL;
gboolean bpoweron = FALSE;
int response = 0;
- if (resp && resp->success) {
+ if ((resp != NULL)
+ && resp->success) {
dbg("Check CP POWER - [OK]");
/* Parse AT Response */
static void _send_enable_logging_command(TcoreHal *hal)
{
- TcoreAtRequest *at_req = NULL;
+ TcoreATRequest *at_req = NULL;
TcorePending *pending = NULL;
dbg("Sending Trace enabling command for CP logging");
pending = tcore_pending_new(NULL, 0);
/* Create AT Request */
- at_req = tcore_at_request_new("at+xsystrace=1,\"digrf=1;bb_sw=1;3g_sw=1\",\"digrf=0x84\",\"oct=4\";+xsystrace=11;+trace=1",
- NULL, TCORE_AT_COMMAND_TYPE_NO_RESULT);
-
+ at_req = tcore_at_request_new(IMCMODEM_AT_CMD_XTRACE_ENABLE,
+ NULL, TCORE_AT_NO_RESULT);
dbg("AT-Command: [%s] Prefix(if any): [%s] Command length: [%d]",
- at_req->cmd, at_req->prefix, strlen(at_req->cmd));
+ at_req->cmd, at_req->prefix, strlen(at_req->cmd));
/* Set request data and register Response and Send callbacks */
tcore_pending_set_request_data(pending, 0, at_req);
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) {
+ if (tcore_hal_send_request(hal, pending) != TCORE_RETURN_SUCCESS) {
+ tcore_pending_free(pending);
+ tcore_at_free(at_req);
+
err("Failed to send Trace logging command");
} else {
dbg("Successfully sent Trace logging command");
static gboolean _check_cp_poweron(TcoreHal *hal)
{
- TcoreAtRequest *at_req;
+ 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);
+ at_req = tcore_at_request_new("AT+CPAS", "+CPAS:", TCORE_AT_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_send_callback(pending, _on_confirmation_send_message, NULL);
/* Send command to CP */
- if (tcore_hal_send_request(hal, pending) != TEL_RETURN_SUCCESS) {
+ if (tcore_hal_send_request(hal, pending) != TCORE_RETURN_SUCCESS) {
+ tcore_pending_free(pending);
+ tcore_at_free(at_req);
+
err("Failed to send CPAS");
return FALSE;
} else {
gboolean ret;
dbg("Entry");
- tcore_check_return(hal != NULL);
+ if (hal == NULL)
+ return;
ret = _check_cp_poweron(hal);
if (ret == TRUE) {
/*
* tel-plugin-imcmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <stdio.h>
#include <string.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
#include <glib.h>
#include <tcore.h>
-#include <util.h>
#include <server.h>
#include <plugin.h>
-#include <storage.h>
-#include <hal.h>
-#include <mux.h>
-
-#include "vnet.h"
-#include "config.h"
-
-#define IMC_HAL_NAME "imcmodem"
-#define IMC_BUFFER_LEN_MAX 4096
-
-#define IMC_CP_POWER_ON_TIMEOUT 500
-
-#define IMC_MAX_CP_POWER_ON_RETRIES 20
-
-#define IMC_DEVICE_NAME_LEN_MAX 16
-#define IMC_DEVICE_NAME_PREFIX "pdp"
-
-#define VNET_CH_PATH_BOOT0 "/dev/umts_boot0"
-#define IOCTL_CG_DATA_SEND _IO('o', 0x37)
-
-typedef struct {
- int fd;
- guint watch_id;
- gboolean on;
-} VnetChannel;
-
-typedef struct {
- VnetChannel ipc0;
-} CustomData;
-
-typedef gboolean(*cb_func)(GIOChannel *channel, GIOCondition condition, gpointer data);
-
-static gboolean _on_recv_ipc_message(GIOChannel *channel, GIOCondition condition, gpointer data);
-
-static guint _register_gio_watch(TcoreHal *plugin, int fd, void *callback);
-static void _deregister_gio_watch(guint watch_id);
-
-static guint _register_gio_watch(TcoreHal *hal, int fd, void *callback)
-{
- GIOChannel *channel = NULL;
- guint source;
-
- if ((fd < 0) || (callback == NULL))
- return 0;
-
- /* Create Unix Watch channel */
- channel = g_io_channel_unix_new(fd);
-
- /* Add to Watch list for IO and HUP events */
- source = g_io_add_watch(channel,
- G_IO_IN | G_IO_HUP,
- (GIOFunc) callback, hal);
-
- g_io_channel_unref(channel);
- channel = NULL;
-
- return source;
-}
-
-static void _deregister_gio_watch(guint watch_id)
-{
- dbg("[VMODEM] Deregister Watch ID: [%d]", watch_id);
-
- /* Remove source */
- g_source_remove(watch_id);
-}
-
-static gboolean _ipc0_init(TcoreHal *hal, VnetChannel *ch, cb_func recv_message)
-{
- dbg("Entry");
-
- /* Remove and close the Watch ID and 'fd' if they already exist */
- if (ch->fd >= 0) {
- _deregister_gio_watch(ch->watch_id);
- close(ch->fd);
- }
-
- /* Open new 'fd' to communicate to CP */
- ch->fd = vnet_ipc0_open();
- if (ch->fd < 0) {
- err("Failed to Open Communiation Channel to CP: [%d]", ch->fd);
- return FALSE;
- }
- dbg("AP-CP Communication channel opened - fd: [%d]", ch->fd);
-
- /* Register Channel for IO */
- ch->watch_id = _register_gio_watch(hal, ch->fd, recv_message);
-
- /* Channel is ON */
- ch->on = TRUE;
-
- return ch->on;
-}
-
-static void _ipc0_deinit(VnetChannel *ch)
-{
- if (ch->on) {
- dbg("Deinitializing the Channel - Watch ID: [%d] "
- "fd: [%d]", ch->watch_id, ch->fd);
-
- /* Remove and close the Watch ID and 'fd' */
- if (ch->watch_id > 0)
- _deregister_gio_watch(ch->watch_id);
-
- if (ch->fd > 0)
- close(ch->fd);
-
- ch->watch_id = 0;
- ch->fd = 0;
-
- ch->on = FALSE;
- }
-}
-
-static gboolean _silent_reset(TcoreHal *hal)
-{
- dbg("[ERROR] Silent Reset");
-
- /* Set HAL Power State to OFF (FALSE) */
- tcore_hal_set_power_state(hal, FALSE);
-
- /* TODO: Need to handle Silent Reset */
-
- return FALSE;
-}
-
-static gboolean _do_exception_operation(TcoreHal *hal, int fd, GIOCondition cond)
-{
- VnetCpState state = VNET_CP_STATE_UNKNOWN;
- CustomData *user_data = tcore_hal_ref_user_data(hal);
- dbg("Entry");
-
- switch (cond) {
- case G_IO_HUP: {
- state = vnet_get_cp_state(fd);
- if (state == VNET_CP_STATE_UNKNOWN) {
- dbg("[ error ] vnet_get_cp_state()");
- break;
- }
-
- switch (state) {
- case VNET_CP_STATE_CRASH_EXIT: {
- err("CP Crash: Start ramdump");
-
- _ipc0_deinit(&user_data->ipc0);
- vnet_start_cp_ramdump();
-
- state = VNET_CP_STATE_CRASH_RESET;
- }
- break;
-
- case VNET_CP_STATE_CRASH_RESET: {
- err("CP Crash Reset");
-
- _ipc0_deinit(&user_data->ipc0);
-
- if (tcore_hal_get_power_state(hal) == TRUE) {
- state = VNET_CP_STATE_CRASH_RESET;
-
- if (_silent_reset(hal) == FALSE) {
- err("Silent Reset failed!!!");
- break;
- }
- }
-
- /*
- * if current hal power state is FALSE,
- * 'cp_reset' mean normal power off
- * (it's because of kernel concept)
- */
- state = VNET_CP_STATE_OFFLINE;
-
- }
- break;
-
- default:
- err("Unwanted State: [0x%x]", state);
- return TRUE;
- }
- }
- break;
-
- case G_IO_IN:
- case G_IO_OUT:
- case G_IO_PRI:
- case G_IO_ERR:
- case G_IO_NVAL:
- dbg("Unknown/Undefined problem - condition: [0x%x]", cond);
- break;
- }
-
- /* Emit receive callback */
- tcore_hal_emit_recv_callback(hal, sizeof(int), &state);
- return TRUE;
-}
-
-static gboolean _power_on(gpointer data)
-{
- CustomData *user_data;
- TcoreHal *hal;
- gboolean ret;
-
- static int count = 0;
- dbg("Entry");
-
- hal = (TcoreHal*)data;
-
- user_data = tcore_hal_ref_user_data(hal);
- if (user_data == NULL) {
- err("HAL Custom data is NULL");
- return TRUE;
- }
-
- /* Increment the 'count' */
- count++;
-
- /* Create and Open interface to CP */
- ret = _ipc0_init(hal, &user_data->ipc0, _on_recv_ipc_message);
- if (ret == FALSE) {
- err("Failed to Create/Open CP interface - Try count: [%d]", count);
-
- if (count > IMC_MAX_CP_POWER_ON_RETRIES) {
- TcorePlugin *plugin = tcore_hal_ref_plugin(hal);
- Server *server = tcore_plugin_ref_server(plugin);
-
- err("Maximum timeout reached: [%d]", count);
-
- /* Notify server a modem error occured */
- tcore_server_send_server_notification(server,
- TCORE_SERVER_NOTIFICATION_MODEM_ERR, 0, NULL);
-
- tcore_hal_free(hal);
- g_free(user_data);
- return FALSE;
- }
-
- return TRUE;
- }
- dbg("Created AP-CP interface");
-
- /* Set HAL Power State ON (TRUE) */
- tcore_hal_set_power_state(hal, TRUE);
- dbg("HAL Power State: Power ON");
-
- /* CP is ONLINE, send AT+CPAS */
- config_check_cp_power(hal);
-
- /* To stop the cycle need to return FALSE */
- return FALSE;
-}
-
-static void _on_cmux_channel_close(TcoreHal *hal, gpointer user_data)
-{
- TcorePlugin *plugin;
-
- if (hal == NULL) {
- err("HAL is NULL");
- return;
- }
-
- plugin = tcore_hal_ref_plugin(hal);
-
- /* Remove mapping Table */
- tcore_server_remove_cp_mapping_tbl_entry(plugin, hal);
-}
-
-static TcoreHookReturn _on_hal_send(TcoreHal *hal,
- guint data_len, void *data, void *user_data)
-{
- msg("\n====== TX data DUMP ======\n");
- tcore_util_hex_dump(" ", data_len, data);
- msg("\n====== TX data DUMP ======\n");
-
- return TCORE_HOOK_RETURN_CONTINUE;
-}
-
-static void _on_hal_recv(TcoreHal *hal,
- guint data_len, const void *data, void *user_data)
-{
- msg("\n====== RX data DUMP ======\n");
- tcore_util_hex_dump(" ", data_len, data);
- msg("\n====== RX data DUMP ======\n");
-}
-
-static gboolean _on_recv_ipc_message(GIOChannel *channel,
- GIOCondition condition, gpointer data)
-{
- TcoreHal *hal = data;
- CustomData *custom;
- char recv_buffer[IMC_BUFFER_LEN_MAX];
- int recv_len = 0;
- TelReturn ret;
-
- custom = tcore_hal_ref_user_data(hal);
-
- /* If the received input is NOT IO, then we need to handle the exception */
- if (condition != G_IO_IN) {
- err("[ERROR] Not IO input");
- return _do_exception_operation(hal, custom->ipc0.fd, condition);
- }
-
- memset(recv_buffer, 0x0, IMC_BUFFER_LEN_MAX);
-
- /* Receive data from device */
- recv_len = read(custom->ipc0.fd, (guchar *)recv_buffer, IMC_BUFFER_LEN_MAX);
- if (recv_len < 0) {
- err("[READ] recv_len: [%d] Error: [%s]", recv_len, strerror(errno));
- return TRUE;
- }
-
- msg("\n---------- [RECV] Length of received data: [%d] ----------\n", recv_len);
-
- /* Emit response callback */
- tcore_hal_emit_recv_callback(hal, recv_len, recv_buffer);
-
- /* Dispatch received data to response handler */
- ret = tcore_hal_dispatch_response_data(hal, 0, recv_len, recv_buffer);
- msg("\n---------- [RECV FINISH] Receive processing: [%d] ----------\n", ret);
-
- return TRUE;
-}
-
-static TelReturn _hal_send(TcoreHal *hal, guint data_len, void *data)
-{
- int ret;
- CustomData *user_data;
-
- if (tcore_hal_get_power_state(hal) == FALSE)
- return TEL_RETURN_FAILURE;
-
- user_data = tcore_hal_ref_user_data(hal);
- if (!user_data)
- return TEL_RETURN_FAILURE;
-
- dbg("write (fd=%d, len=%d)", user_data->ipc0.fd, data_len);
-
- ret = write(user_data->ipc0.fd, (guchar *) data, data_len);
- if (ret < 0)
- return TEL_RETURN_FAILURE;
-
- return TEL_RETURN_SUCCESS;;
-}
-
-static TelReturn _hal_setup_netif(CoreObject *co,
- TcoreHalSetupNetifCallback func, void *user_data,
- guint cid, gboolean enable)
-{
- if (enable == TRUE) {
- int fd;
- char ifname[IMC_DEVICE_NAME_LEN_MAX];
- int ret = -1;
-
- dbg("ACTIVATE");
-
- /* Open device to send IOCTL command */
- fd = open(VNET_CH_PATH_BOOT0, O_RDWR);
- if (fd < 0) {
- err("Failed to Open [%s] Error: [%s]",
- VNET_CH_PATH_BOOT0, strerror(errno));
- return TEL_RETURN_FAILURE;
- }
-
- /*
- * Send IOCTL to change the Channel to Data mode
- *
- * Presently only 2 Contexts are suported
- */
- switch (cid) {
- case 1: {
- dbg("Send IOCTL: arg 0x05 (0101) HSIC1, cid: [%d]", cid);
- ret = ioctl(fd, IOCTL_CG_DATA_SEND, 0x05);
- }
- break;
-
- case 2: {
- dbg("Send IOCTL: arg 0x0A (1010) HSIC2, cid: [%d]", cid);
- ret = ioctl(fd, IOCTL_CG_DATA_SEND, 0xA);
- }
- break;
-
- default: {
- err("More than 2 Contexts are not supported "
- "right now!!! cid: [%d]", cid);
- }
- }
-
- /* Close 'fd' */
- close(fd);
-
- /* TODO - Need to handle Failure case */
- if (ret < 0) {
- err("[ERROR] IOCTL_CG_DATA_SEND - FAIL [0x%x]",
- IOCTL_CG_DATA_SEND);
-
- /* Invoke callback function */
- if (func)
- func(co, ret, NULL, user_data);
-
- return TEL_RETURN_FAILURE;
- } else {
- dbg("[OK] IOCTL_CG_DATA_SEND - PASS [0x%x]",
- IOCTL_CG_DATA_SEND);
-
- /* Device name */
- snprintf(ifname, IMC_DEVICE_NAME_LEN_MAX, "%s%d",
- IMC_DEVICE_NAME_PREFIX, (cid - 1));
- dbg("Interface Name: [%s]", ifname);
-
- /* Invoke callback function */
- if (func)
- func(co, ret, ifname, user_data);
-
- return TEL_RETURN_SUCCESS;
- }
- } else {
- dbg("DEACTIVATE");
- return TEL_RETURN_SUCCESS;
- }
-}
-
-/* HAL Operations */
-static TcoreHalOperations hal_ops = {
- .power = NULL,
- .send = _hal_send,
- .setup_netif = _hal_setup_netif,
-};
+#include "imcmodem.h"
static gboolean on_load()
{
static gboolean on_init(TcorePlugin *plugin)
{
- TcoreHal *hal;
- CustomData *data;
dbg("Init!!!");
- tcore_check_return_value_assert(plugin != NULL, FALSE);
-
- /* Custom data for Modem Interface Plug-in */
- data = tcore_malloc0(sizeof(CustomData));
- dbg("Created custom data memory");
-
- /* Intialize for fd to -1 */
- data->ipc0.fd = -1;
-
- /* Create Physical HAL */
- hal = tcore_hal_new(plugin, IMC_HAL_NAME,
- &hal_ops, TCORE_HAL_MODE_AT);
- if (hal == NULL) {
- err("Failed to Create Physical HAL");
- tcore_free(data);
+ if (plugin == NULL) {
+ err("'plugin' is NULL");
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);
-
- /* 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");
-
- /* Set HAL state to Power OFF (FALSE) */
- tcore_hal_set_power_state(hal, FALSE);
- dbg("HAL Power State: Power OFF");
-
- /* Resgister to Server */
- tcore_server_register_modem(tcore_plugin_ref_server(plugin), plugin);
-
- /* Check CP Power ON */
- g_timeout_add_full(G_PRIORITY_HIGH,
- IMC_CP_POWER_ON_TIMEOUT, _power_on, hal, NULL);
- return TRUE;
+ return imcmodem_init(plugin);
}
static void on_unload(TcorePlugin *plugin)
{
- TcoreHal *hal;
- CustomData *user_data;
dbg("Unload!!!");
- tcore_check_return_assert(plugin != NULL);
-
- /* 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");
-
- /* HAL cleanup */
- hal = tcore_plugin_ref_user_data(plugin);
- if (hal == NULL) {
- err("HAL is NULL");
+ if (plugin == NULL) {
+ err("Modem Interface Plug-in is NULL");
return;
}
- /* Close CMUX and CMUX channels */
- tcore_cmux_close(hal, _on_cmux_channel_close, NULL);
- dbg("CMUX is closed");
-
- user_data = tcore_hal_ref_user_data(hal);
-
- /* Deinitialize the Physical Channel */
- _ipc0_deinit(&user_data->ipc0);
-
- /* Free custom data */
- tcore_free(user_data);
-
- /* Free HAL */
- tcore_hal_free(hal);
- dbg("Freed HAL");
-
+ imcmodem_deinit(plugin);
dbg("Unloaded MODEM Interface Plug-in");
}
-/* Modem Interface Plug-in descriptor */
-EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = {
+/* Modem Interface Plug-in descriptor - IMC modem */
+struct tcore_plugin_define_desc plugin_define_desc = {
.name = "imcmodem",
.priority = TCORE_PLUGIN_PRIORITY_HIGH,
.version = 1,
--- /dev/null
+/*
+ * tel-plugin-imcmodem
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <glib.h>
+
+#include <tcore.h>
+#include <server.h>
+#include <plugin.h>
+#include <storage.h>
+#include <user_request.h>
+#include <hal.h>
+
+#include "imcmodem.h"
+#include "vnet.h"
+#include "config.h"
+
+#define IMC_HAL_NAME "imcmodem"
+#define IMC_BUFFER_LEN_MAX 4096
+
+#define IMC_CP_POWER_ON_TIMEOUT 500
+
+#define IMC_MAX_CP_POWER_ON_RETRIES 20
+
+#define IMC_DEVICE_NAME_LEN_MAX 16
+#define IMC_DEVICE_NAME_PREFIX "pdp"
+
+#define VNET_CH_PATH_BOOT0 "/dev/umts_boot0"
+#define IOCTL_CG_DATA_SEND _IO('o', 0x37)
+
+static gboolean _on_recv_ipc_message(GIOChannel *channel, GIOCondition condition, gpointer data);
+
+static guint _register_gio_watch(TcoreHal *hal, int fd, GIOFunc callback);
+static void _deregister_gio_watch(guint watch_id);
+
+
+static guint _register_gio_watch(TcoreHal *hal, int fd, GIOFunc callback)
+{
+ GIOChannel *channel = NULL;
+ guint source;
+
+ if ((fd < 0) || (callback == NULL))
+ return 0;
+
+ /* Create Unix Watch channel */
+ channel = g_io_channel_unix_new(fd);
+
+ /* Add to Watch list for IO and HUP events */
+ source = g_io_add_watch(channel, G_IO_IN | G_IO_HUP, (GIOFunc) callback, hal);
+ g_io_channel_unref(channel);
+ channel = NULL;
+
+ return source;
+}
+
+static void _deregister_gio_watch(guint watch_id)
+{
+ dbg("[IMCMODEM] Deregister Watch ID: [%d]", watch_id);
+
+ /* Remove source */
+ g_source_remove(watch_id);
+}
+
+static gboolean _ipc0_init(TcoreHal *hal, ImcmodemVnetChannel *ch, GIOFunc recv_message)
+{
+ dbg("Entry");
+
+ /* Remove and close the Watch ID and 'fd' if they already exist */
+ if (ch->fd >= 0) {
+ _deregister_gio_watch(ch->watch_id);
+ close(ch->fd);
+ }
+
+ /* Open new 'fd' to communicate to CP */
+ ch->fd = vnet_ipc0_open();
+ if (ch->fd < 0) {
+ err("Failed to Open Communiation Channel to CP: [%d]", ch->fd);
+ return FALSE;
+ }
+ dbg("AP-CP Communication channel opened - fd: [%d]", ch->fd);
+
+ /* Register Channel for IO */
+ ch->watch_id = _register_gio_watch(hal, ch->fd, recv_message);
+
+ ch->on = TRUE;
+
+ return ch->on;
+}
+
+static void _ipc0_deinit(ImcmodemVnetChannel *ch)
+{
+ /* Remove and close the Watch ID and 'fd' */
+ dbg("Watch ID: [%d]", ch->watch_id);
+ if (ch->watch_id > 0)
+ _deregister_gio_watch(ch->watch_id);
+
+ dbg("fd: [%d]", ch->fd);
+ if (ch->fd > 0)
+ close(ch->fd);
+
+ ch->watch_id = 0;
+ ch->fd = 0;
+
+ ch->on = FALSE;
+}
+
+static gboolean _silent_reset(TcoreHal *hal)
+{
+ dbg("[ERROR] Silent Reset");
+
+ /* Set HAL Poer State to OFF (FALSE) */
+ tcore_hal_set_power_state(hal, FALSE);
+
+ /* TODO: Need to handle Silent Reset */
+
+ return FALSE;
+}
+
+static gboolean _do_exception_operation(TcoreHal *hal, int fd, GIOCondition cond)
+{
+ enum vnet_cp_state state = VNET_CP_STATE_UNKNOWN;
+ ImcmodemCustomData *custom_data = tcore_hal_ref_user_data(hal);
+ dbg("Entry");
+
+ switch (cond) {
+ case G_IO_HUP: {
+ state = vnet_get_cp_state(fd);
+ if (state == VNET_CP_STATE_UNKNOWN) {
+ dbg("[ error ] vnet_get_cp_state()");
+ break;
+ }
+
+ switch (state) {
+ case VNET_CP_STATE_CRASH_EXIT: {
+ err("CP Crash: Start ramdump");
+
+ _ipc0_deinit(&(custom_data->ipc0));
+ vnet_start_cp_ramdump();
+
+ state = VNET_CP_STATE_CRASH_RESET;
+ }
+ break;
+
+ case VNET_CP_STATE_CRASH_RESET: {
+ err("CP Crash Reset");
+
+ _ipc0_deinit(&(custom_data->ipc0));
+
+ if (tcore_hal_get_power_state(hal) == TRUE) {
+ state = VNET_CP_STATE_CRASH_RESET;
+
+ if (_silent_reset(hal) == FALSE) {
+ err("Silent Reset failed!!!");
+ break;
+ }
+ }
+
+ /*
+ * if current hal power state is FALSE, 'cp_reset' mean normal power off
+ * (it's because of kernel concept)
+ */
+ state = VNET_CP_STATE_OFFLINE;
+
+ }
+ break;
+
+ default:
+ err("Unwanted State: [0x%x]", state);
+ return TRUE;
+ }
+ }
+ break;
+
+ case G_IO_IN:
+ case G_IO_OUT:
+ case G_IO_PRI:
+ case G_IO_ERR:
+ case G_IO_NVAL:
+ dbg("Unknown/Undefined problem - condition: [0x%x]", cond);
+ break;
+ }
+
+ /* Emit receive callback */
+ tcore_hal_emit_recv_callback(hal, sizeof(int), &state);
+ return TRUE;
+}
+
+static gboolean imcmodem_power_on(gpointer data)
+{
+ ImcmodemCustomData *custom_data;
+ TcoreHal *hal;
+ gboolean ret;
+
+ static int count = 0;
+ dbg("Entry");
+
+ hal = (TcoreHal*)data;
+
+ custom_data = tcore_hal_ref_user_data(hal);
+ if (custom_data == NULL) {
+ err("HAL Custom data is NULL");
+ return TRUE;
+ }
+
+ /* Increment the 'count' */
+ count++;
+
+ /* Create and Open interface to CP */
+ ret = _ipc0_init(hal, &custom_data->ipc0, _on_recv_ipc_message);
+ if (ret == FALSE) {
+ err("Failed to Create/Open CP interface - Try count: [%d]", count);
+
+ if (count > IMC_MAX_CP_POWER_ON_RETRIES) {
+ TcorePlugin *plugin = tcore_hal_ref_plugin(hal);
+ Server *server = tcore_plugin_ref_server(plugin);
+ struct tnoti_modem_power modem_power;
+
+ err("Maximum timeout reached: [%d]", count);
+
+ modem_power.state = MODEM_STATE_ERROR;
+
+ /* Notify server a modem error occured */
+ tcore_server_send_notification(server, NULL,
+ TNOTI_MODEM_POWER,
+ sizeof(struct tnoti_modem_power), &modem_power);
+
+ tcore_hal_free(hal);
+ g_free(custom_data);
+
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+ dbg("Created AP-CP interface");
+
+ /* Set HAL Power State ON (TRUE) */
+ tcore_hal_set_power_state(hal, TRUE);
+ dbg("HAL Power State: Power ON");
+
+ /* CP is ONLINE, send AT+CPAS */
+ config_check_cp_power(hal);
+
+ /* To stop the cycle need to return FALSE */
+ return FALSE;
+}
+
+static void _on_cmux_channel_close(TcoreHal *hal, gpointer user_data)
+{
+ ImcmodemCustomData *custom_data;
+
+ if (hal == NULL) {
+ err("HAL is NULL");
+ return;
+ }
+
+ custom_data = tcore_hal_ref_user_data(hal);
+ if (custom_data == NULL) {
+ err("custom_data is NULL");
+ return;
+ }
+
+ /* Remove mapping Table */
+ tcore_server_remove_cp_mapping_tbl_entry(custom_data->modem, hal);
+}
+
+static enum tcore_hook_return imcmodem_on_hal_send(TcoreHal *hal,
+ unsigned int data_len, void *data, void *user_data)
+{
+ msg("\n====== TX data DUMP ======\n");
+ tcore_util_hex_dump(" ", data_len, data);
+ msg("\n====== TX data DUMP ======\n");
+
+ return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+static void imcmodem_on_hal_recv(TcoreHal *hal,
+ unsigned int data_len, const void *data, void *user_data)
+{
+ msg("\n====== RX data DUMP ======\n");
+ tcore_util_hex_dump(" ", data_len, data);
+ msg("\n====== RX data DUMP ======\n");
+}
+
+static gboolean _on_recv_ipc_message(GIOChannel *channel,
+ GIOCondition condition, gpointer data)
+{
+ TcoreHal *hal = data;
+ ImcmodemCustomData *custom_data;
+ char recv_buffer[IMC_BUFFER_LEN_MAX];
+ int recv_len = 0;
+ TReturn ret;
+
+ custom_data = tcore_hal_ref_user_data(hal);
+ if (custom_data == NULL) {
+ err("custom_data is NULL");
+ return TRUE;
+ }
+
+ /* If the received input is NOT IO, then we need to handle the exception */
+ if (condition != G_IO_IN) {
+ err("[ERROR] Not IO input");
+ return _do_exception_operation(hal, custom_data->ipc0.fd, condition);
+ }
+
+ memset(recv_buffer, 0x0, IMC_BUFFER_LEN_MAX);
+
+ /* Receive data from device */
+ recv_len = read(custom_data->ipc0.fd, (guchar *)recv_buffer, IMC_BUFFER_LEN_MAX);
+ if (recv_len < 0) {
+ err("[READ] recv_len: [%d] Error: [%s]", recv_len, strerror(errno));
+ return TRUE;
+ }
+
+ msg("\n---------- [RECV] Length of received data: [%d] ----------\n", recv_len);
+
+ /* Emit response callback */
+ tcore_hal_emit_recv_callback(hal, recv_len, recv_buffer);
+
+ /* Dispatch received data to response handler */
+ ret = tcore_hal_dispatch_response_data(hal, 0, recv_len, recv_buffer);
+ msg("\n---------- [RECV FINISH] Receive processing: [%d] ----------\n", ret);
+
+ return TRUE;
+}
+
+static TReturn imcmodem_hal_send(TcoreHal *hal, unsigned int data_len, void *data)
+{
+ int ret;
+ ImcmodemCustomData *custom_data;
+
+ if (tcore_hal_get_power_state(hal) == FALSE)
+ return TCORE_RETURN_FAILURE;
+
+ custom_data = tcore_hal_ref_user_data(hal);
+ if (custom_data == NULL) {
+ err("custom_data is NULL");
+ return TCORE_RETURN_FAILURE;
+ }
+
+ dbg("write (fd=%d, len=%d)", custom_data->ipc0.fd, data_len);
+
+ ret = write(custom_data->ipc0.fd, (guchar *) data, data_len);
+ if (ret < 0)
+ return TCORE_RETURN_FAILURE;
+
+ return TCORE_RETURN_SUCCESS;;
+}
+
+static TReturn imcmodem_hal_setup_netif(CoreObject *co,
+ TcoreHalSetupNetifCallback func, void *user_data,
+ unsigned int cid, gboolean enable)
+{
+ if (enable == TRUE) {
+ int fd;
+ char ifname[IMC_DEVICE_NAME_LEN_MAX];
+ int ret = -1;
+
+ dbg("ACTIVATE");
+
+ /* Open device to send IOCTL command */
+ fd = open(VNET_CH_PATH_BOOT0, O_RDWR);
+ if (fd < 0) {
+ err("Failed to Open [%s] Error: [%s]", VNET_CH_PATH_BOOT0, strerror(errno));
+ return TCORE_RETURN_FAILURE;
+ }
+
+ /*
+ * Send IOCTL to change the Channel to Data mode
+ *
+ * Presently only 2 Contexts are suported
+ */
+ switch (cid) {
+ case 1: {
+ dbg("Send IOCTL: arg 0x05 (0101) HSIC1, cid: [%d]", cid);
+ ret = ioctl(fd, IOCTL_CG_DATA_SEND, 0x05);
+ }
+ break;
+
+ case 2: {
+ dbg("Send IOCTL: arg 0x0A (1010) HSIC2, cid: [%d]", cid);
+ ret = ioctl(fd, IOCTL_CG_DATA_SEND, 0xA);
+ }
+ break;
+
+ default: {
+ err("More than 2 Contexts are not supported right now!!! cid: [%d]", cid);
+ }
+ }
+
+ /* Close 'fd' */
+ close(fd);
+
+ /* TODO - Need to handle Failure case */
+ if (ret < 0) {
+ err("[ERROR] IOCTL_CG_DATA_SEND - FAIL [0x%x]", IOCTL_CG_DATA_SEND);
+
+ /* Invoke callback function */
+ if (func)
+ func(co, ret, NULL, user_data);
+
+ return TCORE_RETURN_FAILURE;
+ } else {
+ dbg("[OK] IOCTL_CG_DATA_SEND - PASS [0x%x]", IOCTL_CG_DATA_SEND);
+
+ /* Device name */
+ snprintf(ifname, IMC_DEVICE_NAME_LEN_MAX, "%s%d", IMC_DEVICE_NAME_PREFIX, (cid - 1));
+ dbg("Interface Name: [%s]", ifname);
+
+ /* Invoke callback function */
+ if (func)
+ func(co, ret, ifname, user_data);
+
+ return TCORE_RETURN_SUCCESS;
+ }
+ } else {
+ dbg("DEACTIVATE");
+ return TCORE_RETURN_SUCCESS;
+ }
+}
+
+/* HAL Operations */
+static struct tcore_hal_operations hal_ops = {
+ .power = NULL,
+ .send = imcmodem_hal_send,
+ .setup_netif = imcmodem_hal_setup_netif,
+};
+
+/* Initialize */
+gboolean imcmodem_init(TcorePlugin *plugin)
+{
+ TcoreHal *hal;
+ ImcmodemCustomData *custom_data;
+
+ /* Custom data for Modem Interface Plug-in */
+ custom_data = g_try_new0(ImcmodemCustomData, 1);
+ if (custom_data == NULL) {
+ err("Failed to allocate memory for Custom data");
+ return FALSE;
+ }
+ dbg("Created custom data memory");
+
+ /* Register to Server */
+ custom_data->modem = tcore_server_register_modem(tcore_plugin_ref_server(plugin), plugin);
+ if (custom_data->modem == NULL) {
+ err("Failed to Register modem");
+ g_free(custom_data);
+ return FALSE;
+ }
+
+ /* Create Physical HAL */
+ hal = tcore_hal_new(plugin, IMC_HAL_NAME, &hal_ops, TCORE_HAL_MODE_AT);
+ if (hal == NULL) {
+ err("Failed to Create Physical HAL");
+ g_free(custom_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);
+
+ /* Link Custom data to HAL's 'user_data' */
+ tcore_hal_link_user_data(hal, custom_data);
+
+ /* Add callbacks for Send/Receive Hooks */
+ tcore_hal_add_send_hook(hal, imcmodem_on_hal_send, NULL);
+ tcore_hal_add_recv_callback(hal, imcmodem_on_hal_recv, NULL);
+ dbg("Added Send hook and Receive callback");
+
+ /* Set HAL state to Power OFF (FALSE) */
+ tcore_hal_set_power_state(hal, FALSE);
+ dbg("HAL Power State: Power OFF");
+
+ /* Check CP Power ON */
+ g_timeout_add_full(G_PRIORITY_HIGH, IMC_CP_POWER_ON_TIMEOUT, imcmodem_power_on, hal, 0);
+
+ return TRUE;
+}
+
+/* De-initialize */
+void imcmodem_deinit(TcorePlugin *plugin)
+{
+ Server *s;
+ TcoreHal *hal;
+ ImcmodemCustomData *custom_data;
+
+ s = tcore_plugin_ref_server(plugin);
+
+ /* Unload Modem Plug-in */
+ tcore_server_unload_modem_plugin(s, plugin);
+ dbg("Unloaded modem plug-in");
+
+ /* HAL cleanup */
+ hal = tcore_plugin_ref_user_data(plugin);
+ if (hal == NULL) {
+ err("HAL is NULL");
+ return;
+ }
+
+ custom_data = tcore_hal_ref_user_data(hal);
+ if (custom_data != NULL) {
+ /* Unregister Modem Interface Plug-in from Server */
+ tcore_server_unregister_modem(s, custom_data->modem);
+ dbg("Unregistered from Server");
+
+ /* Deinitialize the Physical Channel */
+ _ipc0_deinit(&custom_data->ipc0);
+ dbg("Deinitialized the Channel");
+
+ /* Free custom data */
+ g_free(custom_data);
+ }
+
+ /* Close CMUX and CMUX channels */
+ tcore_cmux_close(hal, _on_cmux_channel_close, NULL);
+ dbg("CMUX is closed");
+
+
+ /* Free HAL */
+ tcore_hal_free(hal);
+ dbg("Freed HAL");
+}
/*
* tel-plugin-imcmodem
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#ifndef __USE_GNU
#define __USE_GNU
#endif
-
-/* Modem image */
-#define MODEM_IMAGE_PATH "/boot/modem.bin"
-
-/* NV Data */
-#define NV_DIR_PATH "/csa/nv"
-#define NV_FILE_PATH NV_DIR_PATH"/nvdata.bin"
+#define MODEM_IMAGE_PATH "/opt/modem/modem.bin"
+#define NV_DIR_PATH "/csa/nv"
+#define NV_FILE_PATH NV_DIR_PATH"/nvdata.bin"
/*
* AP-CP comunication devices
*/
/* To track CP bootup */
-#define VNET_CH_PATH_BOOT0 "/dev/umts_boot0"
+#define VNET_CH_PATH_BOOT0 "/dev/umts_boot0"
/* Control communication channel */
-#define VNET_CH_PATH_IPC0 "/dev/umts_ipc0"
+#define VNET_CH_PATH_IPC0 "/dev/umts_ipc0"
-#define IOCTL_MODEM_STATUS _IO('o', 0x27)
+#define IOCTL_MODEM_STATUS _IO('o', 0x27)
void vnet_start_cp_ramdump()
{
int ret;
-
ret = system("/usr/bin/xmm6262-boot -o u &");
dbg("system(/usr/bin/xmm6262-boot -o u &) ret[%d]", ret);
}
void vnet_start_cp_reset()
{
int ret;
-
ret = system("/usr/bin/xmm6262-boot &");
dbg("system(/usr/bin/xmm6262-boot &) ret[%d]", ret);
}
-VnetCpState vnet_get_cp_state(int fd)
+enum vnet_cp_state vnet_get_cp_state(int fd)
{
- VnetCpState state = VNET_CP_STATE_UNKNOWN;
+ enum vnet_cp_state state = VNET_CP_STATE_UNKNOWN;
dbg("Entry");
/* Get CP state */
state = ioctl(fd, IOCTL_MODEM_STATUS);
+
switch (state) {
case VNET_CP_STATE_OFFLINE:
dbg("CP State: OFFLINE");
- break;
+ break;
case VNET_CP_STATE_CRASH_RESET:
dbg("CP State: CRASH RESET");
- break;
+ break;
case VNET_CP_STATE_CRASH_EXIT:
dbg("CP State: CRASH EXIT");
- break;
+ break;
case VNET_CP_STATE_BOOTING:
dbg("CP State: BOOT");
- break;
+ break;
case VNET_CP_STATE_ONLINE:
dbg("CP State: ONLINE");
- break;
+ break;
case VNET_CP_STATE_NV_REBUILDING:
dbg("CP State: NV REBUILD");
- break;
+ break;
case VNET_CP_STATE_LOADER_DONE:
dbg("CP State: LOADER DONE");
- break;
+ break;
case VNET_CP_STATE_UNKNOWN:
default:
dbg("CP State: UNKNOWN State - [%d]", state);
- break;
+ break;
}
return state;
int vnet_ipc0_open()
{
- VnetCpState state;
+ enum vnet_cp_state state;
int fd;
dbg("Entry");
/* Opening device to track CP state */
fd = open(VNET_CH_PATH_BOOT0, O_RDWR);
if (fd < 0) {
- err("Failed to Open [%s] Error: [%s]",
- VNET_CH_PATH_BOOT0, strerror(errno));
+ err("Failed to Open [%s] Error: [%s]", VNET_CH_PATH_BOOT0, strerror(errno));
return -1;
}
/* Track the state of CP */
state = vnet_get_cp_state(fd);
- dbg("CP State: [%d]", state);
- close(fd);
+ close (fd);
+ dbg("CP State: [%d]", state);
if (state != VNET_CP_STATE_ONLINE) {
err("CP is NOT yet Online!!!");
return -1;
- } else {
- /* Opening AP-CP Control communication device */
- fd = open(VNET_CH_PATH_IPC0, O_RDWR);
- if (fd < 0) {
- err("Failed to Open [%s] Error: [%s]",
- VNET_CH_PATH_IPC0, strerror(errno));
- return -1;
- }
+ }
+
+ /* Opening AP-CP Control communication device */
+ fd = open(VNET_CH_PATH_IPC0, O_RDWR);
+ if (fd < 0) {
+ err("Failed to Open [%s] Error: [%s]", VNET_CH_PATH_IPC0, strerror(errno));
+ return -1;
}
return fd;
<manifest>
<request>
- <domain name="_"/>
+ <domain name="_"/>
</request>
</manifest>