/*
* tel-plugin-imc
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Harish Bishnoi <hbishnoi@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 <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <glib.h>
#include <tcore.h>
-#include <server.h>
-#include <plugin.h>
-#include <core_object.h>
#include <hal.h>
+#include <core_object.h>
+#include <plugin.h>
+#include <user_request.h>
#include <queue.h>
+#include <co_modem.h>
#include <storage.h>
+#include <server.h>
#include <at.h>
-#include <co_modem.h>
-
-#include "imc_modem.h"
#include "imc_common.h"
+#include "imc_modem.h"
#include "nvm/nvm.h"
-static gboolean on_event_imc_nvm_update(CoreObject *co,
+/*
+ * Modem Private data
+ */
+typedef struct {
+ /* IMEI */
+ gboolean imei_valid; /**< IMEI validatity flag */
+ char imei[MODEM_DEVICE_IMEI_LEN_MAX];
+
+ /* Version information */
+ gboolean version_valid; /**< Version validatity flag */
+ char software[33];
+ char hardware[33];
+ char calibration[33];
+ char product_code[33];
+} PrivateData;
+
+static void on_confirmation_modem_message_send(TcorePending *pending,
+ gboolean result, void *user_data);
+static void on_response_network_registration(TcorePending *pending,
+ int data_len, const void *data, void *user_data);
+static void on_response_enable_proactive_command(TcorePending *pending,
+ int data_len, const void *data, void *user_data);
+
+/* NVM */
+static gboolean on_event_modem_nvm_update(CoreObject *co_modem,
const void *event_info, void *user_data);
+static void modem_unsuspend_nvm_updates(CoreObject *co_modem);
+static void modem_send_nvm_update_ack(CoreObject *co_modem);
+static void modem_send_nvm_update_request_ack(CoreObject *co_modem);
-/* NVM Req/Response */
-static gboolean __imc_modem_check_nvm_response(const void *data, int command)
+static void on_confirmation_modem_message_send(TcorePending *pending,
+ gboolean result, void *user_data)
{
- const TcoreAtResponse *at_resp = data;
- const char *line;
- char *resp_str;
- GSList *tokens = NULL;
- gboolean ret = FALSE;
-
- dbg("Entered");
-
- /* +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>] */
- if (NULL == at_resp) {
- err("Input data is NULL");
- return FALSE;
- }
-
- if (at_resp->success > 0) {
- dbg("RESPONSE OK");
- line = (const char *) (((GSList *) at_resp->lines)->data);
- tokens = tcore_at_tok_new(line);
-
- /* Group ID */
- resp_str = g_slist_nth_data(tokens, 0);
- if (NULL == resp_str) {
- err("Group ID is missing ");
- goto OUT;
- }
- else if (IUFP_GROUP_ID != atoi(resp_str)) {
- err("Group ID mismatch");
- goto OUT;
- }
-
- /* Function ID */
- resp_str = g_slist_nth_data(tokens, 1);
- if (NULL == resp_str) {
- err("Function ID is missing ");
- goto OUT;
- }
- else if (command != atoi(resp_str)) {
- err("Function ID mismatch");
- goto OUT;
- }
-
- /* XDRV Result */
- resp_str = g_slist_nth_data(tokens, 2);
- if (NULL == resp_str) {
- err("XDRV result is missing ");
- goto OUT;
- }
- else if (XDRV_RESULT_OK != atoi(resp_str)) {
- err("XDRV result[%d] ", atoi(resp_str));
- goto OUT;
- }
-
- /* Result code */
- resp_str = g_slist_nth_data(tokens, 3);
- if (NULL == resp_str) {
- err("UTA result is missing ");
- goto OUT;
- }
- else if (UTA_SUCCESS != atoi(resp_str)) {
- err("uta result[%d] ", atoi(resp_str));
- goto OUT;
- }
-
- ret = TRUE;
- } else {
- dbg("Response NOK");
- }
-
-OUT:
- tcore_at_tok_free(tokens);
-
- dbg("Exit");
- return ret;
+ dbg("Request send: [%s]", (result == TRUE ? "Success" : "Fail"));
}
-static void __on_response_modem_unsuspend_nvm_updates(TcorePending *p,
- guint data_len, const void *data, void *user_data)
+static void on_response_enable_proactive_command(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
{
- /* Check NVM response */
- if (TRUE == __imc_modem_check_nvm_response(data, IUFP_SUSPEND)) {
- dbg("Priority level is set to get all updates since Boot-up");
+ const TcoreATResponse *at_resp = data;
- /* Create NV data file */
- if (nvm_create_nvm_data() == FALSE) {
- err("Failed to Create NV data file");
- }
+ dbg("[Response] Pro-active command enabling - RESPONSE '%s'",
+ (at_resp->success > 0 ? "OK" : "NOK"));
+}
- return;
- }
+static void on_response_network_registration(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
+{
+ const TcoreATResponse *at_resp = data;
- err("Response NOT OK");
+ dbg("[Response] Network Registration enable - RESPONSE '%s'",
+ (at_resp->success > 0 ? "OK" : "NOK"));
}
-static void __imc_modem_unsuspend_nvm_updates(CoreObject *co)
+static void on_response_modem_power_off(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
{
- char *cmd_str;
- TelReturn ret;
+ const TcoreATResponse *at_resp = data;
+ struct tresp_modem_power_off modem_power_off_resp;
+ CoreObject *co_modem = 0;
+ UserRequest *ur;
+ TcoreHal *h = 0;
- /* Prepare AT-Command */
- cmd_str = g_strdup_printf("AT+XDRV=%d, %d, %d, %d",
- IUFP_GROUP_ID, IUFP_SUSPEND,
- 0, UTA_FLASH_PLUGIN_PRIO_UNSUSPEND_ALL);
+ dbg("[Response] Modem Power OFF - RESPONSE '%s'",
+ (at_resp->success > 0 ? "OK" : "NOK"));
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, "+XDRV:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_modem_unsuspend_nvm_updates, NULL,
- on_send_imc_request, NULL);
- IMC_CHECK_REQUEST_RET(ret, NULL, "Unsuspend Nvm Updates");
+ co_modem = tcore_pending_ref_core_object(pending);
+ h = tcore_object_get_hal(co_modem);
- g_free(cmd_str);
-}
+ if (at_resp->success > 0) {
+ modem_power_off_resp.result = TCORE_RETURN_SUCCESS;
-static void __on_response_modem_send_nvm_update_ack(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- /* Check NVM response */
- if (TRUE == __imc_modem_check_nvm_response(data, IUFP_UPDATE_ACK)) {
- dbg("[UPDATE ACK] OK");
- return;
+ /* Update HAL state */
+ tcore_hal_set_power_state(h, FALSE);
+ } else {
+ modem_power_off_resp.result = TCORE_RETURN_FAILURE;
}
- err("[UPDATE ACK] NOT OK");
+ /* Send Response */
+ ur = tcore_pending_ref_user_request(pending);
+ tcore_user_request_send_response(ur,
+ TRESP_MODEM_POWER_OFF,
+ sizeof(struct tresp_modem_power_off), &modem_power_off_resp);
}
-static void __imc_modem_send_nvm_update_ack(CoreObject *co)
+static void on_response_modem_set_flight_mode(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
{
- char *cmd_str;
- TelReturn ret;
+ CoreObject *co_modem = NULL;
+ UserRequest *ur = NULL;
+ const TcoreATResponse *at_resp = data;
+ struct tresp_modem_set_flightmode modem_set_flightmode_resp = {0};
+ int response = 0;
+ struct tnoti_modem_flight_mode modem_flight_mode = {0};
- /* Prepare AT-Command */
- cmd_str = g_strdup_printf("AT+XDRV=%s, %s", IUFP_GROUP, IUFP_UPDATE_ACK_STR);
+ co_modem = tcore_pending_ref_core_object(pending);
+ ur = tcore_pending_ref_user_request(pending);
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, "+XDRV:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_modem_send_nvm_update_ack, NULL,
- on_send_imc_request, NULL);
- IMC_CHECK_REQUEST_RET(ret, NULL, "Nvm Update Ack");
+ dbg("[Response] Modem Set Flight mode - RESPONSE '%s'",
+ (at_resp->success > 0 ? "OK" : "NOK"));
- g_free(cmd_str);
-}
+ if (at_resp->success > 0) {
+ modem_set_flightmode_resp.result = TCORE_RETURN_SUCCESS;
+ } else {
+ GSList *tokens = NULL;
+ const char *line = NULL;
-static void __on_response_modem_send_nvm_update_request_ack(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- /* Check NVM response */
- if (TRUE == __imc_modem_check_nvm_response(data, IUFP_UPDATE_REQ_ACK)) {
- dbg("[REQUEST ACK] OK");
- return;
+ line = (const char *) at_resp->final_response;
+ tokens = tcore_at_tok_new(line);
+
+ if (g_slist_length(tokens) < 1) {
+ dbg("err cause not specified or string corrupted");
+ } else {
+ response = atoi(g_slist_nth_data(tokens, 0));
+ err("error response: %d", response);
+ /* TODO: CMEE error mapping is required. */
+ }
+ tcore_at_tok_free(tokens);
+ modem_set_flightmode_resp.result = TCORE_RETURN_3GPP_ERROR;
}
- err("[REQUEST ACK] NOT OK");
-}
+ if (NULL == ur) {
+ dbg("Internal request created during boot-up sequence");
-static void __imc_modem_send_nvm_update_request_ack(CoreObject *co)
-{
- char *cmd_str;
- TelReturn ret;
+ if (at_resp->success > 0) {
+ Server *server;
- /* Prepare AT-Command */
- cmd_str = g_strdup_printf("AT+XDRV=%s, %s", IUFP_GROUP, IUFP_UPDATE_REQ_ACK_STR);
+ modem_flight_mode.enable =
+ tcore_modem_get_flight_mode_state(co_modem);
+ dbg("Sending Flight Mode Notification (%d) to Telephony Server",
+ modem_flight_mode.enable);
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- cmd_str, "+XDRV:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_modem_send_nvm_update_request_ack, NULL,
- on_send_imc_request, NULL);
- IMC_CHECK_REQUEST_RET(ret, NULL, "Nvm Update Request Ack");
+ server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_modem));
- g_free(cmd_str);
-}
+ /* Send Notification */
+ tcore_server_send_notification(server,
+ co_modem, TNOTI_MODEM_FLIGHT_MODE,
+ sizeof(struct tnoti_modem_flight_mode), &modem_flight_mode);
+ }
+ } else {
+ Server *server;
+ const struct treq_modem_set_flightmode *req_data = NULL;
-static void __on_response_modem_register_nvm(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- /* Check NVM response */
- if (TRUE == __imc_modem_check_nvm_response(data, IUFP_REGISTER)) {
- dbg("Registering successful");
+ dbg("Sending response for Flight mode operation");
- /* Send SUSPEND_UPDATE for all UPDATES */
- __imc_modem_unsuspend_nvm_updates(tcore_pending_ref_core_object(p));
+ req_data = tcore_user_request_ref_data(ur, NULL);
- dbg("Exit");
- return;
- }
+ if (TCORE_RETURN_SUCCESS == modem_set_flightmode_resp.result) {
+ if (TRUE == req_data->enable)
+ tcore_modem_set_flight_mode_state(co_modem, TRUE);
+ else
+ tcore_modem_set_flight_mode_state(co_modem, FALSE);
+ }
- err("Response NOT OK");
-}
+ /* Send Response */
+ tcore_user_request_send_response(ur,
+ TRESP_MODEM_SET_FLIGHTMODE,
+ sizeof(struct tresp_modem_set_flightmode), &modem_set_flightmode_resp);
-/* System function responses */
-static void on_response_modem_set_flight_mode_internal(TcorePlugin *plugin,
- gint result, const void *response, void *user_data)
-{
- CoreObject *co;
- gboolean flight_mode;
- dbg("Enter");
+ modem_flight_mode.enable = tcore_modem_get_flight_mode_state(co_modem);
- co = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
- tcore_check_return_assert(co != NULL);
- tcore_check_return(result == TEL_MODEM_RESULT_SUCCESS);
+ server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_modem));
- /* Get Flight mode state */
- (void)tcore_modem_get_flight_mode_state(co, &flight_mode);
+ /* Send Notification */
+ tcore_server_send_notification(server,
+ co_modem, TNOTI_MODEM_FLIGHT_MODE,
+ sizeof(struct tnoti_modem_flight_mode), &modem_flight_mode);
- dbg("Setting Modem Fiight mode (internal) - [%s] - [SUCCESS]",
- (flight_mode ? "ON": "OFF"));
+ if (req_data->enable == 0) {
+ dbg("Flight mode is disabled, trigger COPS to register on network");
- /*
- * Send notification
- *
- * This is an internal request to set Flight mode, which is sent during
- * boot-up based on AP-side configuration (VCONF).
- *
- * Need to notify TAPI through Notiifcation -
- * TCORE_NOTIFICATION_MODEM_FLIGHT_MODE
- */
- (void)tcore_object_send_notification(co,
- TCORE_NOTIFICATION_MODEM_FLIGHT_MODE,
- sizeof(gboolean), &flight_mode);
+ /* Trigger Network registration (for the moment automatic) */
+ tcore_prepare_and_send_at_request(co_modem,
+ "AT+COPS=0", NULL,
+ TCORE_AT_NO_RESULT, NULL,
+ NULL, NULL,
+ NULL, NULL, 0, NULL, NULL);
+ }
+ }
}
-/* System functions */
-gboolean imc_modem_power_on_modem(TcorePlugin *plugin)
+static void on_response_modem_get_imei(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
{
- CoreObject *co;
- TcoreStorage *strg;
- gboolean flight_mode;
- TelModemPowerStatus power_status;
+ const TcoreATResponse *at_resp = data;
+ struct tresp_modem_get_imei modem_get_imei_resp;
+ UserRequest *ur = NULL;
+ GSList *tokens = NULL;
+ const char *line;
- co = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
- tcore_check_return_value_assert(co != NULL, FALSE);
+ memset(&modem_get_imei_resp, 0x0, sizeof(struct tresp_modem_get_imei));
- /* Set Modem Power State to 'ON' */
- tcore_modem_set_powered(co, TRUE);
+ if (at_resp->success > 0) {
+ CoreObject *co = NULL;
+ PrivateData *priv_data = NULL;
- /*
- * Set Flight mode (as per AP settings -VCONF)
- */
- /* Get Flight mode from VCONFKEY */
- strg = tcore_server_find_storage(tcore_plugin_ref_server(plugin), "vconf");
- tcore_check_return_value_assert(strg != NULL, FALSE);
+ dbg("RESPONSE OK");
- flight_mode = tcore_storage_get_bool(strg, STORAGE_KEY_FLIGHT_MODE);
+ if (at_resp->lines) {
+ line = (const char *) at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) != 1) {
+ msg("invalid message");
+ goto OUT;
+ }
+ }
- /*
- * Set Flight mode request is dispatched to Core Object (Modem)
- * to ensure that 'Request Hooks' get executed.
- */
- (void)tcore_object_dispatch_request(co, TRUE,
- TCORE_COMMAND_MODEM_SET_FLIGHTMODE,
- &flight_mode, sizeof(gboolean),
- on_response_modem_set_flight_mode_internal, NULL);
+ modem_get_imei_resp.result = TCORE_RETURN_SUCCESS;
+ strncpy(modem_get_imei_resp.imei, g_slist_nth_data(tokens, 0), MODEM_DEVICE_IMEI_LEN_MAX - 1);
+ dbg("IMEI: [%s]", modem_get_imei_resp.imei);
- /*
- * Send notification
- *
- * Need to notify Modem is Powered UP through Notiifcation -
- * TCORE_NOTIFICATION_MODEM_POWER
- */
- power_status = TEL_MODEM_POWER_ON;
- (void)tcore_object_send_notification(co,
- TCORE_NOTIFICATION_MODEM_POWER,
- sizeof(TelModemPowerStatus), &power_status);
+ /* Cache IMEI */
+ co = tcore_pending_ref_core_object(pending);
+ priv_data = tcore_object_ref_user_data(co);
+ priv_data->imei_valid = TRUE;
+ strncpy(priv_data->imei, modem_get_imei_resp.imei, MODEM_DEVICE_IMEI_LEN_MAX - 1);
+ } else {
+ dbg("RESPONSE NOK");
- return TRUE;
-}
+ if (at_resp->lines) {
+ line = (const char *) at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ }
-/* Modem Responses */
-static void on_response_imc_modem_set_power_status(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- ImcRespCbData *resp_cb_data = user_data;
- TelModemPowerStatus *status;
- gboolean powered = FALSE;
+ if (g_slist_length(tokens) < 1) {
+ dbg("err cause not specified or string corrupted");
- TelModemResult result = TEL_MODEM_RESULT_FAILURE;
- dbg("Enter");
+ modem_get_imei_resp.result = TCORE_RETURN_3GPP_ERROR;
+ } else {
+ int response = atoi(g_slist_nth_data(tokens, 0));
+ err("error response: %d", response);
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
-
- if (at_resp && at_resp->success)
- result = TEL_MODEM_RESULT_SUCCESS;
-
- status = (TelModemPowerStatus *)
- IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
-
- /* Update Core Object */
- switch (*status) {
- case TEL_MODEM_POWER_ON:
- dbg("Setting Modem Power status [ON] - [%s]",
- (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
- powered = TRUE;
- break;
- case TEL_MODEM_POWER_OFF:
- dbg("Setting Modem Power status [OFF] - [%s]",
- (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
- powered = FALSE;
- break;
- default:
- warn("Unexpected - Setting Modem Power status [RESET] - [%s]",
- (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
- break;
+ /* TODO: CMEE error mapping is required. */
+ modem_get_imei_resp.result = TCORE_RETURN_3GPP_ERROR;
+ }
}
- tcore_modem_set_powered(co, powered);
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
+ /* Send Response */
+ ur = tcore_pending_ref_user_request(pending);
+ tcore_user_request_send_response(ur,
+ TRESP_MODEM_GET_IMEI,
+ sizeof(struct tresp_modem_get_imei), &modem_get_imei_resp);
- /* Free callback data */
- imc_destroy_resp_cb_data(resp_cb_data);
+OUT:
+ tcore_at_tok_free(tokens);
}
-static void on_response_imc_modem_set_flight_mode(TcorePending *p,
- guint data_len, const void *data, void *user_data)
+static void on_response_modem_get_version(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- ImcRespCbData *resp_cb_data = user_data;
- gboolean *enable;
+ const TcoreATResponse *at_resp = data;
+ struct tresp_modem_get_version modem_get_version_resp;
+ UserRequest *ur = NULL;
+ GSList *tokens = NULL;
+ const char *line = NULL;
- TelModemResult result = TEL_MODEM_RESULT_FAILURE;
- dbg("Enter");
+ memset(&modem_get_version_resp, 0, sizeof(struct tresp_modem_get_version));
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
+ if (at_resp->success > 0) {
+ CoreObject *co = NULL;
+ PrivateData *priv_data = NULL;
- if (at_resp && at_resp->success)
- result = TEL_MODEM_RESULT_SUCCESS;
+ char *software_version = NULL;
+ char *hardware_version = NULL;
+ char *calibration_date = NULL;
+ char *product_code = NULL;
+ char *model_id = NULL;
- enable = (gboolean *)IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data);
+ dbg("RESPONSE OK");
- dbg("Setting Modem Fiight mode - [%s] - [%s]",
- (*enable ? "ON": "OFF"),
- (result == TEL_MODEM_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
+ if (at_resp->lines) {
+ line = (const char *) at_resp->lines->data;
- /* Update Core Object */
- (void)tcore_modem_set_flight_mode_state(co, *enable);
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) == 1) {
+ software_version = g_slist_nth_data(tokens, 0);
+ dbg("Software version: [%s]", software_version);
+ } else if (g_slist_length(tokens) == 5) {
+ software_version = g_slist_nth_data(tokens, 0);
+ hardware_version = g_slist_nth_data(tokens, 1);
+ calibration_date = g_slist_nth_data(tokens, 2);
+ product_code = g_slist_nth_data(tokens, 3);
+ model_id = g_slist_nth_data(tokens, 4);
+
+ dbg("Software version: [%s] Hardware version: [%s] " \
+ "Calibration: [%s] Product code: [%s] Model ID: [%s]",
+ software_version, hardware_version,
+ calibration_date, product_code, model_id);
+ } else {
+ err("Invalid message");
+ goto OUT;
+ }
+ }
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
+ co = tcore_pending_ref_core_object(pending);
+ priv_data = tcore_object_ref_user_data(co);
- /* Free callback data */
- imc_destroy_resp_cb_data(resp_cb_data);
+ /*
+ * Update response structure and Cache data
+ */
+ priv_data->version_valid = TRUE;
+
+ /* Software version */
+ if (software_version) {
+ snprintf(modem_get_version_resp.software,
+ 33, "%s", software_version);
+ snprintf(priv_data->software,
+ 33, "%s", software_version);
+ }
- /*
- * In case Flight mode is set to OFF, we need to trigger
- * Network Registration.
- *
- * This is taken care by Network module which hooks on
- * Set Flight mode Request of Modem module.
- */
-}
+ /* Hardware version */
+ if (hardware_version) {
+ snprintf(modem_get_version_resp.hardware,
+ 33, "%s", hardware_version);
+ snprintf(priv_data->hardware,
+ 33, "%s", hardware_version);
+ }
-/* Current modem does not support this operation */
-#if 0
-static void on_response_imc_modem_get_version(TcorePending *p,
- guint data_len, const void *data, void *user_data)
-{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- ImcRespCbData *resp_cb_data = user_data;
- TelModemVersion version = {{0}, {0}, {0}, {0}};
+ /* Calibration date */
+ if (calibration_date) {
+ snprintf(modem_get_version_resp.calibration,
+ 33, "%s", calibration_date);
+ snprintf(priv_data->calibration,
+ 33, "%s", calibration_date);
+ }
- TelModemResult result = TEL_MODEM_RESULT_FAILURE;
- dbg("Enter");
+ /* Product code */
+ if (product_code) {
+ snprintf(modem_get_version_resp.product_code,
+ 33, "%s", product_code);
+ snprintf(priv_data->product_code,
+ 33, "%s", product_code);
+ }
+ } else {
+ dbg("RESPONSE NOK");
+ if (at_resp->lines) {
+ line = (const char *) at_resp->lines->data;
+ tokens = tcore_at_tok_new(line);
+ }
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
+ if (g_slist_length(tokens) < 1) {
+ dbg("err cause not specified or string corrupted");
- if (at_resp) {
- if (at_resp->lines) {
- const gchar *line;
- GSList *tokens = NULL;
+ modem_get_version_resp.result = TCORE_RETURN_3GPP_ERROR;
+ } else {
+ int response = atoi(g_slist_nth_data(tokens, 0));
+ err("error response: %d", response);
- line = (const gchar *)at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) > 0) {
- if (at_resp->success) {
- gchar *sw_ver = NULL, *hw_ver = NULL;
- gchar *calib_date = NULL, *p_code = NULL;
-
- sw_ver = g_slist_nth_data(tokens, 0);
- hw_ver = g_slist_nth_data(tokens, 1);
- calib_date = g_slist_nth_data(tokens, 2);
- p_code = g_slist_nth_data(tokens, 3);
- if (sw_ver != NULL){
- g_strlcpy(version.software_version,
- sw_ver,
- TEL_MODEM_VERSION_LENGTH_MAX + 1);
- }
- if (hw_ver != NULL){
- g_strlcpy(version.hardware_version,
- hw_ver,
- TEL_MODEM_VERSION_LENGTH_MAX + 1);
- }
- if (calib_date != NULL){
- g_strlcpy(version.calibration_date,
- calib_date,
- TEL_MODEM_VERSION_LENGTH_MAX + 1);
- }
- if (p_code != NULL){
- g_strlcpy(version.product_code,
- p_code,
- TEL_MODEM_VERSION_LENGTH_MAX + 1);
- }
- dbg("Version - Software: [%s] Hardware: [%s] "
- "Calibration date: [%s] Product "
- "Code: [%s]", sw_ver, hw_ver,
- calib_date, p_code);
-
- result = TEL_MODEM_RESULT_SUCCESS;
- } else {
- err("RESPONSE - [NOK]");
- err("[%s]", g_slist_nth_data(tokens, 0));
- }
- } else {
- err("Invalid response message");
- result = TEL_MODEM_RESULT_UNKNOWN_FAILURE;
- }
- tcore_at_tok_free(tokens);
+ /* TODO: CMEE error mapping is required. */
+ modem_get_version_resp.result = TCORE_RETURN_3GPP_ERROR;
}
}
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, &version, resp_cb_data->cb_data);
+ /* Send Response */
+ ur = tcore_pending_ref_user_request(pending);
+ tcore_user_request_send_response(ur,
+ TRESP_MODEM_GET_VERSION,
+ sizeof(struct tresp_modem_get_version), &modem_get_version_resp);
- /* Free callback data */
- imc_destroy_resp_cb_data(resp_cb_data);
+OUT:
+ tcore_at_tok_free(tokens);
}
-#endif
-static void on_response_imc_modem_get_imei(TcorePending *p,
- guint data_len, const void *data, void *user_data)
+static enum tcore_hook_return on_hook_modem_sim_init_status(Server *s,
+ CoreObject *source, enum tcore_notification_command command,
+ unsigned int data_len, void *data, void *user_data)
{
- const TcoreAtResponse *at_resp = data;
- CoreObject *co = tcore_pending_ref_core_object(p);
- ImcRespCbData *resp_cb_data = user_data;
- gchar imei[TEL_MODEM_IMEI_LENGTH_MAX +1] = {0};
+ const struct tnoti_sim_status *noti_sim_status;
- TelModemResult result = TEL_MODEM_RESULT_FAILURE;
- dbg("Enter");
+ dbg("SIM INIT Status");
- tcore_check_return_assert(co != NULL);
- tcore_check_return_assert(resp_cb_data != NULL);
+ noti_sim_status = data;
+ if (noti_sim_status == NULL) {
+ err("SIM notification data is NULL");
+ return TCORE_HOOK_RETURN_CONTINUE;
+ }
- if (at_resp) {
- if (at_resp->lines) {
- const gchar *line;
- GSList *tokens = NULL;
+ /* If SIM is initialized, Enable STK and and attach to Network */
+ dbg("SIM Status: [%d]", noti_sim_status->sim_status);
+ if (noti_sim_status->sim_status == SIM_STATUS_INIT_COMPLETED) {
+ TcorePlugin *plugin;
+ CoreObject *co_network;
+ CoreObject *co_sat;
+
+ dbg("SIM ready for attach!!! Enable STK and attach to Network");
+
+ plugin = tcore_object_ref_plugin(source);
+
+ co_network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK);
+ if (co_network) {
+ /* Sending AT+COPS */
+ tcore_prepare_and_send_at_request(co_network,
+ "AT+COPS=0", NULL,
+ TCORE_AT_NO_RESULT, NULL,
+ on_response_network_registration, NULL,
+ NULL, NULL, 0, NULL, NULL);
+ }
- line = (const gchar *)at_resp->lines->data;
- tokens = tcore_at_tok_new(line);
- if (g_slist_length(tokens) == 1) {
- if (at_resp->success) {
- dbg("RESPONSE - [OK]");
- g_strlcpy(imei,
- (const gchar *)g_slist_nth_data(tokens, 0),
- TEL_MODEM_IMEI_LENGTH_MAX+1);
- dbg("IMEI: [%s]", imei);
-
- result = TEL_MODEM_RESULT_SUCCESS;
- } else {
- err("RESPONSE - [NOK]");
- err("[%s]", g_slist_nth_data(tokens, 0));
- }
- } else {
- err("Invalid response message");
- result = TEL_MODEM_RESULT_UNKNOWN_FAILURE;
- }
- tcore_at_tok_free(tokens);
+ co_sat = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SAT);
+ if (co_sat) {
+ /* Sending AT+CFUN=6 */
+ tcore_prepare_and_send_at_request(co_sat,
+ "AT+CFUN=6", NULL,
+ TCORE_AT_NO_RESULT, NULL,
+ on_response_enable_proactive_command, NULL,
+ NULL, NULL, 0, NULL, NULL);
}
- }
- /* Invoke callback */
- if (resp_cb_data->cb)
- resp_cb_data->cb(co, (gint)result, imei, resp_cb_data->cb_data);
+ }
- /* Free callback data */
- imc_destroy_resp_cb_data(resp_cb_data);
+ return TCORE_HOOK_RETURN_CONTINUE;
}
-/* Modem Operations */
-/*
- * Operation - set_power_status
- *
- * Request -
- * AT-Command: AT+CFUN=<fun>
- * where,
- * <fun>
- * 0 Mode to switch off MS
- * ... Other modes are available for other oprations
- *
- * Response -
- * Success: (No Result)
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn imc_modem_set_power_status(CoreObject *co,
- TelModemPowerStatus status,
- TcoreObjectResponseCallback cb, void *cb_data)
+gboolean modem_power_on(TcorePlugin *plugin)
{
- gchar *at_cmd;
- guint power_mode;
-
- ImcRespCbData *resp_cb_data;
- TelReturn ret;
-
- if (status == TEL_MODEM_POWER_ON) {
- warn("Modem Power ON - Not supported by CP");
- return TEL_RETURN_OPERATION_NOT_SUPPORTED;
- } else if (status == TEL_MODEM_POWER_ERROR) {
- err("Modem Power ERROR - Invalid mode");
- return TEL_RETURN_INVALID_PARAMETER;
- } else {
- dbg("Modem Power OFF");
- power_mode = 0;
+ Server *server;
+ CoreObject *co_modem = NULL;
+ struct treq_modem_set_flightmode flight_mode_set;
+ struct tnoti_modem_power modem_power;
+ Storage *strg = NULL;
+
+ co_modem = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
+ if (co_modem == NULL) {
+ err("Modem Core object is NULL");
+ return FALSE;
}
- /* AT-Command */
- at_cmd = g_strdup_printf("AT+CFUN=%d", power_mode);
+ /* Set Modem Power State to 'ON' */
+ tcore_modem_set_powered(co_modem, TRUE);
- /* Response callback data */
- resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
- &status, sizeof(TelModemPowerStatus));
+ server = tcore_plugin_ref_server(plugin);
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_imc_modem_set_power_status, resp_cb_data,
- on_send_imc_request, NULL);
- IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Power Status");
+ /* Get Flight mode from VCONFKEY */
+ strg = tcore_server_find_storage(server, "vconf");
+ flight_mode_set.enable = tcore_storage_get_bool(strg, STORAGE_KEY_FLIGHT_MODE_BOOL);
- /* Free resources */
- g_free(at_cmd);
+ /*
+ * Set Flight mode as per AP settings
+ */
+ if (flight_mode_set.enable) { /* Radio OFF */
+ dbg("Enabling Flight mode");
+
+ tcore_prepare_and_send_at_request(co_modem,
+ "AT+CFUN=4", NULL,
+ TCORE_AT_NO_RESULT, NULL,
+ on_response_modem_set_flight_mode, NULL,
+ NULL, NULL, 0, NULL, NULL);
+
+ /* Set Flight mode TRUE */
+ tcore_modem_set_flight_mode_state(co_modem, TRUE);
+ } else { /* Radio ON */
+ dbg("Disabling Flight mode");
+
+ tcore_prepare_and_send_at_request(co_modem,
+ "AT+CFUN=1", NULL,
+ TCORE_AT_NO_RESULT, NULL,
+ on_response_modem_set_flight_mode, NULL,
+ NULL, NULL, 0, NULL, NULL);
+
+ /* Set Flight mode FALSE */
+ tcore_modem_set_flight_mode_state(co_modem, FALSE);
+ }
- return ret;
+ /* Get IMEI */
+ tcore_prepare_and_send_at_request(co_modem,
+ "AT+CGSN", NULL,
+ TCORE_AT_NUMERIC, NULL,
+ on_response_modem_get_imei, NULL,
+ NULL, NULL, 0, NULL, NULL);
+
+ /* Get Version Number */
+ tcore_prepare_and_send_at_request(co_modem,
+ "AT+CGMR", NULL,
+ TCORE_AT_SINGLELINE, NULL,
+ on_response_modem_get_version, NULL,
+ NULL, NULL, 0, NULL, NULL);
+
+ /* Send Notification - MODEM_POWER */
+ modem_power.state = MODEM_STATE_ONLINE;
+
+ dbg("Sending notification - Modem Power state: [ONLINE]");
+ tcore_server_send_notification(server, co_modem,
+ TNOTI_MODEM_POWER,
+ sizeof(modem_power), &modem_power);
+
+ return TRUE;
}
-/*
- * Operation - set_flight_mode
- *
- * Request -
- * AT-Command: AT+CFUN=<fun>
- * where,
- * <fun>
- * 0 Mode to switch off MS
- * 1 Full functionality
- * 4 Mode to disable phone both transmit and receive
- * RF circuits. Airplane mode.
- * ... Other modes are available for other oprations
- *
- * Response -
- * Success: (No Result)
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn imc_modem_set_flight_mode(CoreObject *co, gboolean enable,
- TcoreObjectResponseCallback cb, void *cb_data)
+static TReturn modem_power_off(CoreObject *co_modem, UserRequest *ur)
{
- gchar *at_cmd;
- guint power_mode;
+ TcoreHal *hal;
- ImcRespCbData *resp_cb_data;
- TelReturn ret;
+ hal = tcore_object_get_hal(co_modem);
+ if (FALSE == tcore_hal_get_power_state(hal)) {
+ struct tresp_modem_power_off modem_power_off_resp;
- if (enable) {
- dbg("Flight mode - [ON]");
- power_mode = 4;
- } else {
- dbg("Flight mode - [OFF]");
- power_mode = 1;
- }
+ err("Modem is in Powered OFF state!");
- /* AT-Command */
- at_cmd = g_strdup_printf("AT+CFUN=%d", power_mode);
+ modem_power_off_resp.result = TCORE_RETURN_SUCCESS;
- /* Response callback data */
- resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
- &enable, sizeof(gboolean));
+ tcore_user_request_send_response(ur,
+ TRESP_MODEM_POWER_OFF,
+ sizeof(struct tresp_modem_power_off), &modem_power_off_resp);
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- at_cmd, NULL,
- TCORE_AT_COMMAND_TYPE_NO_RESULT,
- NULL,
- on_response_imc_modem_set_flight_mode, resp_cb_data,
- on_send_imc_request, NULL);
- IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Set Flight mode");
+ return TCORE_RETURN_SUCCESS;
+ }
- /* Free resources */
- g_free(at_cmd);
+ dbg("[Request] Modem Power OFF - Command: [%s]", "AT+CFUN=0");
- return ret;
+ return tcore_prepare_and_send_at_request(co_modem,
+ "AT+CFUN=0", NULL,
+ TCORE_AT_NO_RESULT, ur,
+ on_response_modem_power_off, hal,
+ on_confirmation_modem_message_send, NULL,
+ 0, NULL, NULL);
}
-/*
- * Operation - get_flight_mode
- *
- * Request -
- * AT-Command: None
- * Fetch information from Core Object
- *
- * Response - flight_mode (gboolean)
- */
-static TelReturn imc_modem_get_flight_mode(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
+static TReturn modem_get_imei(CoreObject *co_modem, UserRequest *ur)
{
- gboolean flight_mode;
+ PrivateData *priv_data = NULL;
+ TcoreHal *hal;
+
+ dbg("Exit");
+
+ hal = tcore_object_get_hal(co_modem);
+ if (FALSE == tcore_hal_get_power_state(hal)) {
+ err("CP not ready!");
+ return TCORE_RETURN_ENOSYS;
+ }
+
+ /*
+ * Check if valid IMEI is available in Cache -
+ * if Yes, then provide form Cache;
+ * else, fetch from CP
+ */
+ priv_data = tcore_object_ref_user_data(co_modem);
+ if (priv_data && priv_data->imei_valid) {
+ struct tresp_modem_get_imei modem_get_imei_resp;
+ TReturn ret;
+
+ memset(&modem_get_imei_resp, 0x0, sizeof(struct tresp_modem_get_imei));
+
+ modem_get_imei_resp.result = TCORE_RETURN_SUCCESS;
+ memcpy(modem_get_imei_resp.imei,
+ priv_data->imei, MODEM_DEVICE_IMEI_LEN_MAX);
+
+ dbg("Valid IMEI information present in cache - IMEI: [%s]",
+ modem_get_imei_resp.imei);
- /* Fetch Flight mode from Core Object */
- (void)tcore_modem_get_flight_mode_state(co, &flight_mode);
- dbg("Modem Flight mode - [%s]", (flight_mode ? "ON": "OFF"));
+ /* Send Response */
+ ret = tcore_user_request_send_response(ur,
+ TRESP_MODEM_GET_IMEI,
+ sizeof(struct tresp_modem_get_imei), &modem_get_imei_resp);
+ if (ret == TCORE_RETURN_SUCCESS)
+ tcore_user_request_unref(ur);
- /* Invoke response callback */
- if (cb)
- cb(co, (gint)TEL_MODEM_RESULT_SUCCESS, &flight_mode, cb_data);
+ return ret;
+ }
+
+ dbg("[Request] Get IMEI - Command: [%s]", "AT+CGSN");
- return TEL_RETURN_SUCCESS;
+ return tcore_prepare_and_send_at_request(co_modem,
+ "AT+CGSN", NULL,
+ TCORE_AT_NUMERIC, ur,
+ on_response_modem_get_imei, hal,
+ on_confirmation_modem_message_send, NULL,
+ 0, NULL, NULL);
}
-/*
- * Operation - get_version
- *
- * Request -
- * AT-Command: AT+CGMR
- *
- * Response - version (TelModemVersion)
- * Success: (Single line) -
- * <sw_ver>, <hw_ver>, <calib_date>, <p_code>
- * OK
- * Note:
- * Success Response is different from standard 3GPP AT-Command (+CGMR)
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn imc_modem_get_version(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
+
+static TReturn modem_get_version(CoreObject *co_modem, UserRequest *ur)
{
- dbg("entry");
+ PrivateData *priv_data = NULL;
+ TcoreHal *hal;
- /* Current modem does not support this operation */
-#if 0
- ImcRespCbData *resp_cb_data;
- TelReturn ret;
+ hal = tcore_object_get_hal(co_modem);
+ if (FALSE == tcore_hal_get_power_state(hal)) {
+ err("CP not ready!");
+ return TCORE_RETURN_ENOSYS;
+ }
+
+ /*
+ * Check if valid Version information is available in Cache -
+ * if Yes, then provide form Cache;
+ * else, fetch from CP
+ */
+ priv_data = tcore_object_ref_user_data(co_modem);
+ if (priv_data && priv_data->version_valid) {
+ struct tresp_modem_get_version modem_get_version_resp;
+ TReturn ret;
+
+ memset(&modem_get_version_resp, 0x0, sizeof(struct tresp_modem_get_version));
+
+ modem_get_version_resp.result = TCORE_RETURN_SUCCESS;
+ snprintf(modem_get_version_resp.software,
+ 33, "%s", priv_data->software);
+ snprintf(modem_get_version_resp.hardware,
+ 33, "%s", priv_data->hardware);
+ snprintf(modem_get_version_resp.calibration,
+ 33, "%s", priv_data->calibration);
+ snprintf(modem_get_version_resp.product_code,
+ 33, "%s", priv_data->product_code);
+
+ dbg("Valid Version information present in cache -" \
+ "Software: [%s] Hardware: [%s] Calibration: [%s] Product code: [%s]",
+ modem_get_version_resp.software, modem_get_version_resp.hardware,
+ modem_get_version_resp.calibration, modem_get_version_resp.product_code);
+
+ /* Send Response */
+ ret = tcore_user_request_send_response(ur,
+ TRESP_MODEM_GET_VERSION,
+ sizeof(struct tresp_modem_get_version), &modem_get_version_resp);
+ if (ret == TCORE_RETURN_SUCCESS)
+ tcore_user_request_unref(ur);
+
+ return ret;
+ }
- /* Response callback data */
- resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
- NULL, 0);
+ dbg("[Request] Get VERSION - Command: [%s]", "AT+CGMR");
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
+ return tcore_prepare_and_send_at_request(co_modem,
"AT+CGMR", NULL,
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- TCORE_PENDING_PRIORITY_DEFAULT,
- NULL,
- on_response_imc_modem_get_version, resp_cb_data,
- on_send_imc_request, NULL,
+ TCORE_AT_SINGLELINE, ur,
+ on_response_modem_get_version, hal,
+ on_confirmation_modem_message_send, NULL,
0, NULL, NULL);
- IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get Version");
+}
- return ret;
-#endif
+static TReturn modem_set_flight_mode(CoreObject *co_modem, UserRequest *ur)
+{
+ TcoreHal *hal = NULL;
+ const struct treq_modem_set_flightmode *req_data = NULL;
+ char *cmd_str = NULL;
+
+ hal = tcore_object_get_hal(co_modem);
+ if (FALSE == tcore_hal_get_power_state(hal)) {
+ err("CP not ready!");
+ return TCORE_RETURN_ENOSYS;
+ }
- dbg("exit");
- return TEL_RETURN_OPERATION_NOT_SUPPORTED;
+ req_data = tcore_user_request_ref_data(ur, NULL);
+ if (req_data->enable)
+ cmd_str = "AT+CFUN=4";
+ else
+ cmd_str = "AT+CFUN=1";
+
+ dbg("[Request] Set Modem Flight mode [%s] - Command: [%s]",
+ (req_data->enable ? "ON" : "OFF"), cmd_str);
+
+ return tcore_prepare_and_send_at_request(co_modem,
+ (const char *)cmd_str, NULL,
+ TCORE_AT_NO_RESULT, ur,
+ on_response_modem_set_flight_mode, hal,
+ on_confirmation_modem_message_send, NULL,
+ 0, NULL, NULL);
}
-/*
- * Operation - get_imei
- *
- * Request -
- * AT-Command: AT+CGSN
- *
- * Response - imei (gchar array of length 20+'\0' bytes)
- * Success: (Single line)
- * <IMEI>
- * OK
- * Failure:
- * +CME ERROR: <error>
- */
-static TelReturn imc_modem_get_imei(CoreObject *co,
- TcoreObjectResponseCallback cb, void *cb_data)
+static TReturn modem_get_flight_mode(CoreObject *co_modem, UserRequest *ur)
{
- ImcRespCbData *resp_cb_data;
- TelReturn ret;
+ struct tresp_modem_get_flightmode modem_get_flightmode_resp;
+ TReturn ret;
- dbg("Enter");
+ dbg("[Request] Get Modem Flight mode");
- /* Response callback data */
- resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
- NULL, 0);
+ memset(&modem_get_flightmode_resp, 0x0, sizeof(struct tresp_modem_get_flightmode));
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
- "AT+CGSN", NULL,
- TCORE_AT_COMMAND_TYPE_NUMERIC,
- NULL,
- on_response_imc_modem_get_imei, resp_cb_data,
- on_send_imc_request, NULL);
- IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "Get IMEI");
+ modem_get_flightmode_resp.result = TCORE_RETURN_SUCCESS;
+ modem_get_flightmode_resp.enable = tcore_modem_get_flight_mode_state(co_modem);
+ dbg("Flight mode: [%s]", (modem_get_flightmode_resp.enable ? "ON" : "OFF"));
+
+ ret = tcore_user_request_send_response(ur,
+ TRESP_MODEM_GET_FLIGHTMODE,
+ sizeof(struct tresp_modem_get_flightmode), &modem_get_flightmode_resp);
+ if (ret == TCORE_RETURN_SUCCESS)
+ tcore_user_request_unref(ur);
return ret;
}
-/* Modem Operations */
-static TcoreModemOps imc_modem_ops = {
- .set_power_status = imc_modem_set_power_status,
- .set_flight_mode = imc_modem_set_flight_mode,
- .get_flight_mode = imc_modem_get_flight_mode,
- .get_version = imc_modem_get_version,
- .get_imei = imc_modem_get_imei
+/* Modem operations */
+static struct tcore_modem_operations modem_ops = {
+ .power_on = NULL,
+ .power_off = modem_power_off,
+ .power_reset = NULL,
+ .set_flight_mode = modem_set_flight_mode,
+ .get_flight_mode = modem_get_flight_mode,
+ .get_imei = modem_get_imei,
+ .get_version = modem_get_version,
+ .get_sn = NULL,
+ .dun_pin_ctrl = NULL,
};
-gboolean imc_modem_init(TcorePlugin *p, CoreObject *co)
+gboolean imc_modem_init(TcorePlugin *plugin, CoreObject *co_modem)
{
+ PrivateData *priv_data = NULL;
+
dbg("Enter");
/* Set operations */
- tcore_modem_set_ops(co, &imc_modem_ops);
+ tcore_modem_set_ops(co_modem, &modem_ops, TCORE_OPS_TYPE_CP);
+
+ /* Private data */
+ priv_data = g_malloc0(sizeof(PrivateData));
+ priv_data->imei_valid = FALSE;
+ priv_data->version_valid = FALSE;
+ tcore_object_link_user_data(co_modem, priv_data);
- /* Add Callbacks */
- tcore_object_add_callback(co, "+XDRVI:", on_event_imc_nvm_update, NULL);
+ /* Notification hooks */
+ tcore_server_add_notification_hook(tcore_plugin_ref_server(plugin),
+ TNOTI_SIM_STATUS, on_hook_modem_sim_init_status, NULL);
+
+ dbg("Registering for +XDRVI event");
+ tcore_object_add_callback(co_modem,
+ "+XDRVI", on_event_modem_nvm_update, NULL);
dbg("Exit");
return TRUE;
}
-void imc_modem_exit(TcorePlugin *p, CoreObject *co)
+void imc_modem_exit(TcorePlugin *plugin, CoreObject *co_modem)
{
+ PrivateData *priv_data = NULL;
+
dbg("Exit");
+
+ priv_data = tcore_object_ref_user_data(co_modem);
+ g_free(priv_data);
}
/*
* NV Manager - Support for Remote File System
*/
/* NVM Hook */
-static gboolean __imc_nvm_modem_rfs_hook(const char *data)
+static gboolean __modem_rfs_hook(const char *data)
{
- if (data != NULL)
- if (data[NVM_FUNCTION_ID_OFFSET] == XDRV_INDICATION)
- return TRUE;
+ if (data && data[NVM_FUNCTION_ID_OFFSET] == XDRV_INDICATION)
+ return TRUE;
return FALSE;
}
-/* NVM Event */
-gboolean on_event_imc_nvm_update(CoreObject *co,
+/* NVM event Notification */
+static gboolean on_event_modem_nvm_update(CoreObject *co_modem,
const void *event_info, void *user_data)
{
GSList *tokens = NULL;
dbg("NV data processed successfully");
/* Acknowledge NV Update */
- __imc_modem_send_nvm_update_ack(co);
+ modem_send_nvm_update_ack(co_modem);
return ret;
} else {
if (g_slist_length(tokens) < 3) {
err("XDRVI event with less number of tokens, Ignore!!!");
ret = FALSE;
- }
- else if (IUFP_GROUP_ID != atoi(g_slist_nth_data(tokens, 0))) {
+ } else if (IUFP_GROUP_ID != atoi(g_slist_nth_data(tokens, 0))) {
err("Group ID mismatch, Ignore!!!");
ret = FALSE;
- }
- else {
- switch (atoi(g_slist_nth_data(tokens, 1))) {
- case IUFP_UPDATE_REQ:
- dbg("NV Update Request");
-
- /* Acknowledge the Update Request */
- __imc_modem_send_nvm_update_request_ack(co);
- break;
-
- case IUFP_NO_PENDING_UPDATE:
- dbg("NO pending NV Update(s)!!!");
- /* Can send FLUSH request to get fresh updates */
- break;
-
- default:
- err("Unspported Function ID [%d], Ignore", atoi(g_slist_nth_data(tokens, 1)));
- ret = FALSE;
+ } else {
+ int command = atoi(g_slist_nth_data(tokens, 1));
+ switch (command) {
+ case IUFP_UPDATE_REQ:
+ dbg("NV Update Request");
+
+ /* Acknowledge the Update Request */
+ modem_send_nvm_update_request_ack(co_modem);
+ break;
+
+ case IUFP_NO_PENDING_UPDATE:
+ dbg("NO pending NV Update(s)!!!");
+ /* Can send FLUSH request to get fresh updates */
+ break;
+
+ default:
+ err("Unspported Function ID [%d], Ignore", command);
+ ret = FALSE;
+ break;
}
}
return ret;
}
-/* NVM Register */
-void imc_modem_register_nvm(CoreObject *co)
+/* NVM Responses */
+static gboolean __modem_check_nvm_response(const void *data, int command)
+{
+ const TcoreATResponse *at_resp = data;
+ const char *line;
+ char *resp_str;
+ GSList *tokens = NULL;
+ gboolean ret = FALSE;
+ dbg("Entered");
+
+ /* +XDRV: <group_id>,<function_id>,<xdrv_result>[,<response_n>] */
+ if (NULL == at_resp) {
+ err("Input data is NULL");
+ return FALSE;
+ }
+
+ if (at_resp->success <= 0) {
+ dbg("Response NOK");
+ return FALSE;
+ }
+
+ dbg("RESPONSE OK");
+ line = (const char *) (((GSList *) at_resp->lines)->data);
+ tokens = tcore_at_tok_new(line);
+
+ /* Group ID */
+ resp_str = g_slist_nth_data(tokens, 0);
+ if (NULL == resp_str) {
+ err("Group ID is missing ");
+ goto OUT;
+ } else if (IUFP_GROUP_ID != atoi(resp_str)) {
+ err("Group ID mismatch");
+ goto OUT;
+ }
+
+ /* Function ID */
+ resp_str = g_slist_nth_data(tokens, 1);
+ if (NULL == resp_str) {
+ err("Function ID is missing ");
+ goto OUT;
+ } else if (command != atoi(resp_str)) {
+ err("Function ID mismatch");
+ goto OUT;
+ }
+
+ /* XDRV Result */
+ resp_str = g_slist_nth_data(tokens, 2);
+ if (NULL == resp_str) {
+ err("XDRV result is missing ");
+ goto OUT;
+ } else if (XDRV_RESULT_OK != atoi(resp_str)) {
+ err("XDRV result[%d] ", atoi(resp_str));
+ goto OUT;
+ }
+
+ /* Result code */
+ resp_str = g_slist_nth_data(tokens, 3);
+ if (NULL == resp_str) {
+ err("UTA result is missing ");
+ goto OUT;
+ } else if (UTA_SUCCESS != atoi(resp_str)) {
+ err("uta result[%d] ", atoi(resp_str));
+ goto OUT;
+ }
+
+ ret = TRUE;
+
+OUT:
+ tcore_at_tok_free(tokens);
+
+ dbg("Exit");
+ return ret;
+}
+
+static void on_response_modem_unsuspend_nvm_updates(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
+{
+ /* Check NVM response */
+ if (TRUE == __modem_check_nvm_response(data, IUFP_SUSPEND)) {
+ dbg("Priority level is set to get all updates since Boot-up");
+
+ /* Create NV data file */
+ if (nvm_create_nvm_data() == FALSE)
+ err("Failed to Create NV data file");
+
+ return;
+ }
+
+ err("Response NOT OK");
+}
+
+static void on_response_modem_send_nvm_update_ack(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
+{
+ /* Check NVM response */
+ if (TRUE == __modem_check_nvm_response(data, IUFP_UPDATE_ACK)) {
+ dbg("[UPDATE ACK] OK");
+ return;
+ }
+
+ err("[UPDATE ACK] NOT OK");
+}
+
+static void on_response_modem_send_nvm_update_request_ack(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
+{
+ /* Check NVM response */
+ if (TRUE == __modem_check_nvm_response(data, IUFP_UPDATE_REQ_ACK)) {
+ dbg("[REQUEST ACK] OK");
+ return;
+ }
+
+ err("[REQUEST ACK] NOT OK");
+}
+
+static void on_response_modem_register_nvm(TcorePending *pending,
+ int data_len, const void *data, void *user_data)
+{
+ /* Check NVM response */
+ if (TRUE == __modem_check_nvm_response(data, IUFP_REGISTER)) {
+ dbg("Registering successful!");
+
+ /* Send SUSPEND_UPDATE for all UPDATES */
+ modem_unsuspend_nvm_updates(tcore_pending_ref_core_object(pending));
+
+ dbg("Exit");
+ return;
+ }
+
+ err("Response NOT OK");
+}
+
+/* NVM Requests */
+static void modem_unsuspend_nvm_updates(CoreObject *co_modem)
+{
+ char *cmd_str;
+ TReturn ret;
+
+ dbg("Entered");
+
+ /* Prepare AT-Command */
+ cmd_str = g_strdup_printf("AT+XDRV=%d, %d, %d, %d",
+ IUFP_GROUP_ID, IUFP_SUSPEND,
+ 0, UTA_FLASH_PLUGIN_PRIO_UNSUSPEND_ALL);
+
+ /* Prepare pending request */
+ ret = tcore_prepare_and_send_at_request(co_modem,
+ cmd_str, "+XDRV:",
+ TCORE_AT_SINGLELINE, NULL,
+ on_response_modem_unsuspend_nvm_updates, NULL,
+ NULL, NULL, 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS)
+ err("IUFP_SUSPEND - Unable to send AT-Command");
+ else
+ dbg("IUFP_SUSPEND - Successfully sent AT-Command");
+
+ g_free(cmd_str);
+}
+
+static void modem_send_nvm_update_ack(CoreObject *co_modem)
+{
+ char *cmd_str;
+ TReturn ret;
+
+ dbg("Entered");
+
+ /* Prepare AT-Command */
+ cmd_str = g_strdup_printf("AT+XDRV=%s, %s", IUFP_GROUP, IUFP_UPDATE_ACK_STR);
+
+ /* Prepare pending request */
+ ret = tcore_prepare_and_send_at_request(co_modem,
+ cmd_str, "+XDRV:",
+ TCORE_AT_SINGLELINE, NULL,
+ on_response_modem_send_nvm_update_ack, NULL,
+ NULL, NULL, 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS)
+ err("IUFP_UPDATE_ACK - Unable to send AT-Command");
+ else
+ dbg("IUFP_UPDATE_ACK - Successfully sent AT-Command");
+
+ g_free(cmd_str);
+}
+
+static void modem_send_nvm_update_request_ack(CoreObject *co_modem)
+{
+ char *cmd_str;
+ TReturn ret;
+
+ dbg("Entered");
+
+ /* Prepare AT-Command */
+ cmd_str = g_strdup_printf("AT+XDRV=%s, %s", IUFP_GROUP, IUFP_UPDATE_REQ_ACK_STR);
+
+ /* Prepare pending request */
+ ret = tcore_prepare_and_send_at_request(co_modem,
+ cmd_str, "+XDRV:",
+ TCORE_AT_SINGLELINE, NULL,
+ on_response_modem_send_nvm_update_request_ack, NULL,
+ NULL, NULL, 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS)
+ err("IUFP_UPDATE_REQ_ACK - Unable to send AT-Ccommand");
+ else
+ dbg("IUFP_UPDATE_REQ_ACK - Successfully sent AT-Command");
+
+ g_free(cmd_str);
+}
+
+void modem_register_nvm(CoreObject *co_modem)
{
char *cmd_str;
- TelReturn ret;
+ TReturn ret;
+
+ dbg("Entered");
/* Prepare AT-Command */
cmd_str = g_strdup_printf("AT+XDRV=%s, %s, %s",
- IUFP_GROUP, IUFP_REGISTER_STR, XDRV_ENABLE);
+ IUFP_GROUP, IUFP_REGISTER_STR, XDRV_ENABLE);
- /* Send Request to modem */
- ret = tcore_at_prepare_and_send_request(co,
+ /* Prepare pending request */
+ ret = tcore_prepare_and_send_at_request(co_modem,
cmd_str, "+XDRV:",
- TCORE_AT_COMMAND_TYPE_SINGLELINE,
- NULL,
- __on_response_modem_register_nvm, NULL,
- on_send_imc_request, NULL);
- if (ret != TEL_RETURN_SUCCESS) {
- err("Failed to process request - [Register NVM]");
- }
- else {
+ TCORE_AT_SINGLELINE, NULL,
+ on_response_modem_register_nvm, NULL,
+ NULL, NULL, 0, NULL, NULL);
+ if (ret != TCORE_RETURN_SUCCESS) {
+ err("IUFP_REGISTER (Enable) -Unable to send AT-Command");
+ } else {
+ dbg("IUFP_REGISTER (Enable) -Successfully sent AT-Command");
+
/* Add RFS hook */
- dbg("Adding NVM hook");
- tcore_at_add_hook(tcore_object_get_hal(co), __imc_nvm_modem_rfs_hook);
+ /* Todo unblock this api */
+ tcore_at_add_hook(tcore_object_get_hal(co_modem),
+ __modem_rfs_hook);
}
g_free(cmd_str);