+/*
+ * gps-manager
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
+ * Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@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 <signal.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <string.h>
+
+#include "server.h"
+#include "gps_manager_data_types.h"
+#include "gps_manager_plugin_intf.h"
+#include "nmea_logger.h"
+#include "data_connection.h"
+#include "setting.h"
+#include "plugin_module.h"
+#include "debug_util.h"
+#include "last_position.h"
+
+#include <MapiControl.h>
+#include <MapiTransport.h>
+#include <MapiMessage.h>
+#include <sysman.h>
+
+#include <vconf.h>
+#include <vconf-keys.h>
+#include <pmapi.h>
+#include <dlog.h>
+#include <heynoti.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gthread.h>
+#include <dbus/dbus-glib.h>
+
+#define GPS_NI_POPUP "/usr/bin/gps_popup"
+#define GPS_NI_BTN "BTN"
+#define GPS_NI_WITHOUT_BTN "NONE"
+#define YES_EXIT_STATUS 174
+#define NO_EXIT_STATUS 175
+
+#define REPLAY_MODULE "replay"
+
+typedef struct {
+ void *handle;
+ char *name;
+} gps_plugin_handler_t;
+
+gps_plugin_handler_t g_gps_plugin;
+gps_server_param_t g_gps_params;
+
+pos_data_t *gps_pos_data = NULL;
+sv_data_t *gps_sv_data = NULL;
+nmea_data_t *gps_nmea_data = NULL;
+last_pos_t *gps_last_pos = NULL;
+
+int g_dnet_used = 0;
+
+gboolean logging_enabled = FALSE;
+gboolean replay_enabled = FALSE;
+
+static pthread_t msg_thread = 0; /* Register SUPL NI cb to msg server Thread */
+static pthread_t popup_thread = 0; /* Register SUPL NI cb to msg server Thread */
+static int msg_thread_status;
+
+gps_session_state_t gps_session_state = GPS_SESSION_STOPPED;
+
+struct gps_callbacks g_update_cb;
+void *g_user_data;
+
+static int _gps_server_gps_event_cb(gps_event_info_t * gps_event_info);
+
+static void _gps_mode_changed_cb(keynode_t * key, void *data)
+{
+ int int_val;
+
+ if (setting_get_int(GPS_SESSION, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! GPS_SESSION setting get failed");
+ int_val = GPS_SESSION_TRACKING_MODE;
+ }
+ g_gps_params.session_type = int_val;
+
+ if (setting_get_int(GPS_OPERATION, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! GPS_OPERATION setting get failed");
+ int_val = GPS_OPERATION_STANDALONE;
+ }
+ g_gps_params.operation_mode = int_val;
+
+ if (setting_get_int(GPS_STARTING, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! GPS_STARTING setting get failed");
+ int_val = GPS_STARTING_HOT_;
+ }
+ g_gps_params.starting_type = int_val;
+
+ return;
+}
+
+static void _gps_supl_changed_cb(keynode_t * key, void *data)
+{
+ int int_val;
+ char *str;
+
+ str = setting_get_string(SUPL_SERVER);
+
+ if (str == NULL) {
+ snprintf(g_gps_params.supl_url, MAX_SUPL_URL_LEN, "%s", SUPL_SERVER_URL_DEFAULT);
+ LOG_GPS(DBG_ERR, "vconf fail to get Server URL [Default URL]");
+ } else {
+ snprintf(g_gps_params.supl_url, MAX_SUPL_URL_LEN, "%s", str);
+ }
+
+ if (setting_get_int(SUPL_PORT, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! SUPL_PORT setting get failed");
+ int_val = SUPL_SERVER_PORT_DEFAULT;
+ }
+ g_gps_params.supl_port = int_val;
+
+ return;
+}
+
+static void _gps_setting_changed_cb(keynode_t * key, void *data)
+{
+ int int_val;
+
+ if (setting_get_int(SUPL_SSL, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! SUPL_SSL setting get failed");
+ int_val = 0;
+ }
+ g_gps_params.ssl_mode = int_val;
+ return;
+}
+
+static void _gps_nmea_changed_cb(keynode_t * key, void *data)
+{
+ int int_val;
+ if (setting_get_int(NMEA_LOGGING, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "NMEA_LOGGING get Failed.");
+ int_val = 0;
+ }
+ logging_enabled = (int_val == 1) ? TRUE : FALSE;
+ return;
+}
+
+static gboolean get_replay_enabled()
+{
+ int int_val;
+ gboolean ret;
+
+ if (setting_get_int(REPLAY_ENABLED, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "REPLAY_ENABLED get Failed.");
+ int_val = 0;
+ }
+
+ ret = (int_val == 1) ? TRUE : FALSE;
+
+ return ret;
+}
+
+static void reload_plugin_module()
+{
+ char *module_name;
+ gps_failure_reason_t ReasonCode = GPS_FAILURE_CAUSE_NORMAL;
+
+ if (replay_enabled == TRUE) {
+ module_name = REPLAY_MODULE;
+ } else {
+ module_name = g_gps_plugin.name;
+ }
+
+ LOG_GPS(DBG_LOW, "Loading plugin.name : %s", module_name);
+
+ if (!get_plugin_module()->deinit(&ReasonCode)) {
+ LOG_GPS(DBG_ERR, "Fail to GPS plugin deinit");
+ } else {
+ unload_plugin_module(&g_gps_plugin.handle);
+ if (!load_plugin_module(module_name, &g_gps_plugin.handle)) {
+ LOG_GPS(DBG_ERR, "Fail to load %s plugin", module_name);
+ } else {
+ if (!get_plugin_module()->init(_gps_server_gps_event_cb, &g_gps_params)) {
+ LOG_GPS(DBG_ERR, "Fail to %s plugin init", module_name);
+ return;
+ }
+ }
+ }
+}
+
+static void _gps_replay_changed_cb(keynode_t * key, void *data)
+{
+
+ replay_enabled = get_replay_enabled();
+ reload_plugin_module();
+
+ return;
+}
+
+static void _gps_server_set_indicator(int gps_state)
+{
+ int ret;
+ int wps_state = 0;
+
+ setting_get_int(VCONFKEY_WPS_STATE, &wps_state);
+ LOG_GPS(DBG_LOW, "gps state : [%d], wps state : [%d]", gps_state, wps_state);
+
+ if (gps_state == POSITION_CONNECTED || wps_state == POSITION_CONNECTED) {
+ ret = setting_set_int(VCONFKEY_GPS_STATE, POSITION_CONNECTED);
+ } else {
+ if (gps_state == POSITION_OFF && wps_state == POSITION_OFF) {
+ ret = setting_set_int(VCONFKEY_GPS_STATE, POSITION_OFF);
+ } else {
+ ret = setting_set_int(VCONFKEY_GPS_STATE, POSITION_SEARCHING);
+ }
+ }
+
+ if (ret == 1) {
+ LOG_GPS(DBG_LOW, "Succesee to set indicator");
+ } else {
+ LOG_GPS(DBG_ERR, "Fail to setting_set_int(VCONF_GPS_STATE, ...)");
+ }
+}
+
+static gboolean _initialize_data()
+{
+ gboolean result = TRUE;
+ if (gps_pos_data == NULL) {
+ gps_pos_data = (pos_data_t *) malloc(sizeof(pos_data_t));
+ if (gps_pos_data == NULL) {
+ LOG_GPS(DBG_ERR, "Failed to alloc gps_pos_data");
+ result = FALSE;
+ } else {
+ memset(gps_pos_data, 0x00, sizeof(pos_data_t));
+ }
+ }
+
+ if (gps_sv_data == NULL) {
+ gps_sv_data = (sv_data_t *) malloc(sizeof(sv_data_t));
+ if (gps_sv_data == NULL) {
+ LOG_GPS(DBG_ERR, "Failed to alloc gps_sv_data");
+ result = FALSE;
+ } else {
+ memset(gps_sv_data, 0x00, sizeof(sv_data_t));
+ }
+ }
+
+ if (gps_nmea_data == NULL) {
+ gps_nmea_data = (nmea_data_t *) malloc(sizeof(nmea_data_t));
+ if (gps_nmea_data == NULL) {
+ LOG_GPS(DBG_ERR, "Failed to alloc gps_nmea_data");
+ result = FALSE;
+ } else {
+ memset(gps_nmea_data, 0x00, sizeof(nmea_data_t));
+ }
+ }
+
+ if (gps_last_pos == NULL) {
+ gps_last_pos = (last_pos_t *) malloc(sizeof(last_pos_t));
+ if (gps_last_pos == NULL) {
+ LOG_GPS(DBG_ERR, "Failed to alloc gps_last_pos");
+ result = FALSE;
+ } else {
+ memset(gps_last_pos, 0x00, sizeof(last_pos_t));
+ }
+ }
+ return result;
+}
+
+int request_start_session()
+{
+ int status = TRUE;
+ gps_failure_reason_t reason_code = GPS_FAILURE_CAUSE_NORMAL;
+
+ if (gps_session_state != GPS_SESSION_STOPPED && gps_session_state != GPS_SESSION_STOPPING) {
+ LOG_GPS(DBG_LOW, "Main: GPS Session Already Started!");
+ return TRUE;
+ }
+
+ status = get_plugin_module()->request(GPS_ACTION_START_SESSION, &g_gps_params, &reason_code);
+
+ if (status == FALSE) {
+ LOG_GPS(DBG_ERR, "Main: sending GPS_ACTION_START_SESSION Fail !");
+ return FALSE;
+ }
+
+ LOG_GPS(DBG_LOW, "Main: sending GPS_ACTION_START_SESSION OK !");
+ _initialize_data();
+
+ gps_session_state = GPS_SESSION_STARTING;
+ LOG_GPS(DBG_LOW, "==GPSSessionState[%d]", gps_session_state);
+ setting_ignore_key_changed(REPLAY_ENABLED, _gps_replay_changed_cb);
+
+ return TRUE;
+}
+
+int request_stop_session()
+{
+ unsigned int status = TRUE;
+ gboolean cur_replay_enabled = FALSE;
+ gps_failure_reason_t reason_code = GPS_FAILURE_CAUSE_NORMAL;
+
+ LOG_GPS(DBG_LOW, "Main: Stop GPS Session, ==GPSSessionState[%d]", gps_session_state);
+ if (gps_session_state == GPS_SESSION_STARTED || gps_session_state == GPS_SESSION_STARTING) {
+ status = get_plugin_module()->request(GPS_ACTION_STOP_SESSION, NULL, &reason_code);
+ if (status) {
+ gps_session_state = GPS_SESSION_STOPPING;
+ LOG_GPS(DBG_LOW, "==GPSSessionState[%d]", gps_session_state);
+ cur_replay_enabled = get_replay_enabled();
+ if (replay_enabled != cur_replay_enabled) {
+ replay_enabled = cur_replay_enabled;
+ reload_plugin_module();
+ }
+ setting_notify_key_changed(REPLAY_ENABLED, _gps_replay_changed_cb);
+ } else {
+ LOG_GPS(DBG_LOW, " plugin->request to LBS_GPS_STOP_SESSION Failed, reasonCode =%d", reason_code);
+ }
+ } else {
+ // If request is not sent, keep the client registed
+ LOG_GPS(DBG_LOW,
+ " LBS_GPS_STOP_SESSION is not sent because the GPS state is not started, keep the client registed ");
+ }
+ return status;
+}
+
+static void _gps_plugin_handler_init(char *module_name)
+{
+ g_gps_plugin.handle = NULL;
+ g_gps_plugin.name = (char *)malloc(strlen(module_name) + 1);
+ snprintf(g_gps_plugin.name, strlen(module_name) + 1, "%s", module_name);
+}
+
+static void _gps_plugin_handler_deinit()
+{
+ if (g_gps_plugin.handle != NULL) {
+ g_gps_plugin.handle = NULL;
+ }
+
+ if (g_gps_plugin.name != NULL) {
+ free(g_gps_plugin.name);
+ g_gps_plugin.name = NULL;
+ }
+}
+
+static void _gps_read_params()
+{
+ int int_val = 0;
+ char *str;
+
+ if (setting_get_int(GPS_SESSION, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! GPS_SESSION setting get failed");
+ int_val = GPS_SESSION_TRACKING_MODE; //set to default
+ }
+ g_gps_params.session_type = int_val;
+
+ if (setting_get_int(GPS_OPERATION, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! GPS_OPERATION setting get failed");
+ int_val = GPS_OPERATION_STANDALONE; //set to default
+ }
+ g_gps_params.operation_mode = int_val;
+
+ if (setting_get_int(GPS_STARTING, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! TING_MODE setting get failed");
+ int_val = GPS_STARTING_HOT_;
+ }
+ g_gps_params.starting_type = int_val;
+
+ g_gps_params.time_bn_fixes = 1;
+
+ str = setting_get_string(SUPL_SERVER);
+ if (str == NULL) {
+ snprintf(g_gps_params.supl_url, MAX_SUPL_URL_LEN, "%s", SUPL_SERVER_URL_DEFAULT);
+ LOG_GPS(DBG_ERR, "vconf fail to get Server URL [Default URL]");
+ } else {
+ snprintf(g_gps_params.supl_url, MAX_SUPL_URL_LEN, "%s", str);
+ }
+
+ if (setting_get_int(SUPL_PORT, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! SUPL_PORT setting get failed");
+ int_val = SUPL_SERVER_PORT_DEFAULT;
+ }
+ g_gps_params.supl_port = int_val;
+
+ LOG_GPS(DBG_LOW, "First Read!! SUPL server:%s, port:%d", g_gps_params.supl_url, g_gps_params.supl_port);
+
+ if (setting_get_int(SUPL_SSL, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//ERROR!! SUPL_SSL setting get failed");
+ int_val = 0;
+ }
+ g_gps_params.ssl_mode = int_val;
+
+ if (setting_get_int(NMEA_LOGGING, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//NMEA_LOGGING get Failed.");
+ int_val = 0;
+ }
+ logging_enabled = (int_val == 1) ? TRUE : FALSE;
+
+ if (setting_get_int(REPLAY_ENABLED, &int_val) == FALSE) {
+ LOG_GPS(DBG_ERR, "//REPLAY_ENABLED get Failed.");
+ int_val = 0;
+ }
+ replay_enabled = (int_val == 1) ? TRUE : FALSE;
+}
+
+static void _gps_notify_params()
+{
+ setting_notify_key_changed(GPS_SESSION, _gps_mode_changed_cb);
+ setting_notify_key_changed(GPS_OPERATION, _gps_mode_changed_cb);
+ setting_notify_key_changed(GPS_STARTING, _gps_mode_changed_cb);
+ setting_notify_key_changed(SUPL_SERVER, _gps_supl_changed_cb);
+ setting_notify_key_changed(SUPL_PORT, _gps_supl_changed_cb);
+ setting_notify_key_changed(SUPL_SSL, _gps_setting_changed_cb);
+ setting_notify_key_changed(NMEA_LOGGING, _gps_nmea_changed_cb);
+ setting_notify_key_changed(REPLAY_ENABLED, _gps_replay_changed_cb);
+}
+
+static void _gps_ignore_params()
+{
+ setting_ignore_key_changed(GPS_SESSION, _gps_mode_changed_cb);
+ setting_ignore_key_changed(GPS_OPERATION, _gps_mode_changed_cb);
+ setting_ignore_key_changed(GPS_STARTING, _gps_mode_changed_cb);
+ setting_ignore_key_changed(SUPL_SERVER, _gps_supl_changed_cb);
+ setting_ignore_key_changed(SUPL_PORT, _gps_supl_changed_cb);
+ setting_ignore_key_changed(SUPL_SSL, _gps_setting_changed_cb);
+ setting_ignore_key_changed(NMEA_LOGGING, _gps_nmea_changed_cb);
+ setting_ignore_key_changed(REPLAY_ENABLED, _gps_replay_changed_cb);
+}
+
+static void _gps_server_start_event()
+{
+ LOG_GPS(DBG_LOW, "==GPSSessionState [%d] -> [%d]", gps_session_state, GPS_SESSION_STARTED);
+ gps_session_state = GPS_SESSION_STARTED;
+
+ if (logging_enabled) {
+ start_nmea_log();
+ }
+
+ if (gps_pos_data == NULL) {
+ gps_pos_data = (pos_data_t *) malloc(sizeof(pos_data_t));
+ if (gps_pos_data == NULL) {
+ LOG_GPS(DBG_WARN, "//callback: gps_pos_data re-malloc Failed!!");
+ } else {
+ memset(gps_pos_data, 0x00, sizeof(pos_data_t));
+ }
+ }
+ if (gps_sv_data == NULL) {
+ gps_sv_data = (sv_data_t *) malloc(sizeof(sv_data_t));
+ if (gps_sv_data == NULL) {
+ LOG_GPS(DBG_WARN, "//callback: gps_sv_data re-malloc Failed!!");
+ } else {
+ memset(gps_sv_data, 0x00, sizeof(sv_data_t));
+ }
+ }
+ if (gps_nmea_data == NULL) {
+ gps_nmea_data = (nmea_data_t *) malloc(sizeof(nmea_data_t));
+ if (gps_nmea_data == NULL) {
+ LOG_GPS(DBG_WARN, "//callback: gps_nmea_data re-malloc Failed!!");
+ } else {
+ memset(gps_nmea_data, 0x00, sizeof(nmea_data_t));
+ }
+ }
+
+ if (gps_last_pos == NULL) {
+ gps_last_pos = (last_pos_t *) malloc(sizeof(last_pos_t));
+ if (gps_last_pos == NULL) {
+ LOG_GPS(DBG_WARN, "//callback: gps_last_pos re-malloc Failed!!");
+ } else {
+ memset(gps_last_pos, 0x00, sizeof(last_pos_t));
+ gps_manager_get_last_position(gps_last_pos);
+ }
+ }
+
+ _gps_server_set_indicator(POSITION_SEARCHING);
+ pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
+}
+
+static void _gps_server_stop_event()
+{
+ LOG_GPS(DBG_LOW, "==GPSSessionState [%d] -> [%d]", gps_session_state, GPS_SESSION_STOPPED);
+ gps_session_state = GPS_SESSION_STOPPED;
+ LOG_GPS(DBG_LOW, "==GPSSessionState[%d]", gps_session_state);
+
+ _gps_server_set_indicator(POSITION_OFF);
+ pm_unlock_state(LCD_NORMAL, PM_RESET_TIMER);
+
+ if (logging_enabled) {
+ stop_nmea_log();
+ }
+
+ if (gps_pos_data != NULL) {
+ free(gps_pos_data);
+ gps_pos_data = NULL;
+ }
+ if (gps_sv_data != NULL) {
+ free(gps_sv_data);
+ gps_sv_data = NULL;
+ }
+ if (gps_nmea_data != NULL) {
+ free(gps_nmea_data);
+ gps_nmea_data = NULL;
+ }
+ if (gps_last_pos != NULL) {
+ free(gps_last_pos);
+ gps_last_pos = NULL;
+ }
+}
+
+static void _report_pos_event(gps_event_info_t * gps_event)
+{
+ if (gps_pos_data != NULL) {
+ memcpy(gps_pos_data, &(gps_event->event_data.pos_ind.pos), sizeof(pos_data_t));
+ g_update_cb.pos_cb(gps_pos_data, gps_event->event_data.pos_ind.error, g_user_data);
+ if (gps_manager_distance_to_last_position(gps_pos_data, gps_last_pos) != -1) {
+ gps_manager_update_last_position(gps_pos_data, gps_last_pos);
+ }
+ memset(gps_pos_data, 0x00, sizeof(pos_data_t));
+ } else {
+ LOG_GPS(DBG_ERR, "gps_sv_data is NULL");
+ }
+}
+
+static void _report_sv_event(gps_event_info_t * gps_event)
+{
+ if (gps_sv_data != NULL) {
+ memcpy(gps_sv_data, &(gps_event->event_data.sv_ind.sv), sizeof(sv_data_t));
+ g_update_cb.sv_cb(gps_sv_data, g_user_data);
+ memset(gps_sv_data, 0x00, sizeof(sv_data_t));
+ } else {
+ LOG_GPS(DBG_ERR, "gps_sv_data is NULL");
+ }
+}
+
+static void _report_nmea_event(gps_event_info_t * gps_event)
+{
+ if (gps_nmea_data == NULL) {
+ LOG_GPS(DBG_ERR, "gps_nmea_data is NULL");
+ return;
+ }
+
+ gps_nmea_data->len = gps_event->event_data.nmea_ind.nmea.len;
+ LOG_GPS(DBG_LOW, "gps_nmea_data->len : [%d]", gps_nmea_data->len);
+ gps_nmea_data->data = (char *)malloc(gps_nmea_data->len);
+ memset(gps_nmea_data->data, 0x00, gps_nmea_data->len);
+ memcpy(gps_nmea_data->data, gps_event->event_data.nmea_ind.nmea.data, gps_nmea_data->len);
+ g_update_cb.nmea_cb(gps_nmea_data, g_user_data);
+ free(gps_nmea_data->data);
+ memset(gps_nmea_data, 0x00, sizeof(nmea_data_t));
+
+ if (logging_enabled) {
+ int nmea_len;
+ char *p_nmea_data;
+ nmea_len = gps_event->event_data.nmea_ind.nmea.len;
+ p_nmea_data = gps_event->event_data.nmea_ind.nmea.data;
+ write_nmea_log(p_nmea_data, nmea_len);
+ }
+}
+
+static int _gps_server_open_data_connection()
+{
+ LOG_GPS(DBG_LOW, "Enter _gps_server_open_data_connection");
+
+ g_dnet_used++;
+
+ if (g_dnet_used > 1) {
+ LOG_GPS(DBG_LOW, "g_dnet_used : [ %d ]", g_dnet_used);
+ return TRUE;
+ } else {
+ LOG_GPS(DBG_LOW, "First open the data connection");
+ }
+
+ unsigned char result;
+
+ result = start_pdp_connection();
+
+ if (result == TRUE) {
+ LOG_GPS(DBG_LOW, "//Open PDP Conn for SUPL Success.");
+ } else {
+ LOG_GPS(DBG_ERR, "//Open PDP Conn for SUPL Fail.");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static int _gps_server_close_data_connection()
+{
+ LOG_GPS(DBG_LOW, "Enter _gps_server_close_data_connection");
+
+ if (g_dnet_used > 0) {
+ g_dnet_used--;
+ }
+
+ if (g_dnet_used != 0) {
+ LOG_GPS(DBG_LOW, "Cannot stop the data connection! [ g_dnet_used : %d ]", g_dnet_used);
+ return TRUE;
+ } else {
+ LOG_GPS(DBG_LOW, "Close the data connection");
+ }
+
+ unsigned char result;
+
+ result = stop_pdp_connection();
+ if (result == TRUE) {
+ LOG_GPS(DBG_LOW, "Close PDP Conn for SUPL Success.");
+ } else {
+ LOG_GPS(DBG_ERR, "//Close PDP Conn for SUPL Fail.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int _gps_server_resolve_dns(char *domain)
+{
+ LOG_GPS(DBG_LOW, "Enter _gps_server_resolve_dns");
+
+ unsigned char result;
+ gps_failure_reason_t reason_code = GPS_FAILURE_CAUSE_NORMAL;
+ unsigned int ipaddr;
+ int port;
+
+ result = query_dns(domain, &ipaddr, &port);
+ if (result == TRUE) {
+ LOG_GPS(DBG_LOW, "Success to resolve domain name [ %s ] / ipaddr [ %u ]", domain, ipaddr);
+ get_plugin_module()->request(GPS_INDI_SUPL_DNSQUERY, (void *)(&ipaddr), &reason_code);
+ } else {
+ ipaddr = 0;
+ LOG_GPS(DBG_ERR, "Fail to resolve domain name [ %s ] / ipaddr [ %u ]", domain, ipaddr);
+ get_plugin_module()->request(GPS_INDI_SUPL_DNSQUERY, (void *)(&ipaddr), &reason_code);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void _gps_server_send_facttest_result(double snr_data, int prn, unsigned short result)
+{
+}
+
+static int _gps_server_gps_event_cb(gps_event_info_t * gps_event_info)
+{
+ FUNC_ENTRANCE_SERVER;
+ int result = TRUE;
+ if (gps_event_info == NULL) {
+ LOG_GPS(DBG_WARN, "//NULL pointer variable passed");
+ return result;
+ }
+
+ switch (gps_event_info->event_id) {
+ case GPS_EVENT_START_SESSION:
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_START_SESSION :::::::::::::::");
+ if (gps_event_info->event_data.start_session_rsp.error == GPS_ERR_NONE) {
+ _gps_server_start_event();
+ } else {
+ LOG_GPS(DBG_ERR, "//Start Session Failed, error : %d",
+ gps_event_info->event_data.start_session_rsp.error);
+ }
+ break;
+ case GPS_EVENT_SET_OPTION:
+ {
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_SET_OPTION :::::::::::::::");
+ if (gps_event_info->event_data.set_option_rsp.error != GPS_ERR_NONE) {
+ LOG_GPS(DBG_ERR, "//Set Option Failed, error : %d",
+ gps_event_info->event_data.set_option_rsp.error);
+ }
+ }
+ break;
+
+ case GPS_EVENT_STOP_SESSION:
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_STOP_SESSION :::::::::::::::");
+ if (gps_event_info->event_data.stop_session_rsp.error == GPS_ERR_NONE) {
+ _gps_server_close_data_connection();
+ _gps_server_stop_event();
+ } else {
+ LOG_GPS(DBG_ERR, "//Stop Session Failed, error : %d",
+ gps_event_info->event_data.stop_session_rsp.error);
+ }
+
+ break;
+ case GPS_EVENT_REPORT_POSITION:
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_POSITION :::::::::::::::");
+ if (gps_event_info->event_data.pos_ind.error == GPS_ERR_NONE) {
+ _report_pos_event(gps_event_info);
+ } else {
+ LOG_GPS(DBG_ERR, "GPS_EVENT_POSITION Failed, error : %d", gps_event_info->event_data.pos_ind.error);
+ }
+ break;
+ case GPS_EVENT_REPORT_SATELLITE:
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_SATELLITE :::::::::::::::");
+ if (gps_event_info->event_data.sv_ind.error == GPS_ERR_NONE) {
+ if (gps_event_info->event_data.sv_ind.sv.pos_valid) {
+ _gps_server_set_indicator(POSITION_CONNECTED);
+ } else {
+ _gps_server_set_indicator(POSITION_SEARCHING);
+ }
+ _report_sv_event(gps_event_info);
+ } else {
+ LOG_GPS(DBG_ERR, "GPS_EVENT_SATELLITE Failed, error : %d", gps_event_info->event_data.sv_ind.error);
+ }
+ break;
+ case GPS_EVENT_REPORT_NMEA:
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_NMEA :::::::::::::::");
+ if (gps_event_info->event_data.nmea_ind.error == GPS_ERR_NONE) {
+ _report_nmea_event(gps_event_info);
+ } else {
+ LOG_GPS(DBG_ERR, "GPS_EVENT_NMEA Failed, error : %d", gps_event_info->event_data.nmea_ind.error);
+ }
+ break;
+ case GPS_EVENT_ERR_CAUSE:
+ break;
+ case GPS_EVENT_AGPS_VERIFICATION_INDI:
+ break;
+ case GPS_EVENT_GET_IMSI:
+ break;
+ case GPS_EVENT_GET_REF_LOCATION:
+ break;
+ case GPS_EVENT_OPEN_DATA_CONNECTION:
+ {
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_OPEN_DATA_CONNECTION :::::::::::::::");
+ result = _gps_server_open_data_connection();
+ }
+ break;
+ case GPS_EVENT_CLOSE_DATA_CONNECTION:
+ {
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_CLOSE_DATA_CONNECTION :::::::::::::::");
+ result = _gps_server_close_data_connection();
+ }
+ break;
+ case GPS_EVENT_DNS_LOOKUP_IND:
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_DNS_LOOKUP_IND :::::::::::::::");
+ if (gps_event_info->event_data.dns_query_ind.error == GPS_ERR_NONE) {
+ result = _gps_server_resolve_dns(gps_event_info->event_data.dns_query_ind.domain_name);
+ } else {
+ result = FALSE;
+ }
+ if (result == TRUE) {
+ LOG_GPS(DBG_LOW, "Success to get the DNS Query about [ %s ]",
+ gps_event_info->event_data.dns_query_ind.domain_name);
+ }
+ break;
+ case GPS_EVENT_FACTORY_TEST:
+ LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_FACTORY_TEST :::::::::::::::");
+ if (gps_event_info->event_data.factory_test_rsp.error == GPS_ERR_NONE) {
+ LOG_GPS(DBG_LOW, "[LBS server] Response Factory test result success");
+ _gps_server_send_facttest_result(gps_event_info->event_data.factory_test_rsp.snr,
+ gps_event_info->event_data.factory_test_rsp.prn, TRUE);
+ } else {
+ LOG_GPS(DBG_ERR, "//[LBS server] Response Factory test result ERROR");
+ _gps_server_send_facttest_result(gps_event_info->event_data.factory_test_rsp.snr,
+ gps_event_info->event_data.factory_test_rsp.prn, FALSE);
+ }
+ break;
+ default:
+ LOG_GPS(DBG_WARN, "//Error: Isettingalid Event Type %d", gps_event_info->event_id);
+ break;
+ }
+ return result;
+}
+
+static void *_gps_launch_popup(void *data)
+{
+ gps_ni_popup_data_t *msgData = (gps_ni_popup_data_t *) data;
+
+ int status;
+ char *argv[5];
+ char temp[16];
+ gps_failure_reason_t reason_code;
+
+ // Max size of SMS message is 255
+ // Max size of WAP PUSH is ??????
+ snprintf(temp, sizeof(temp), "%d", msgData->msg_size);
+
+ argv[0] = GPS_NI_POPUP;
+ if (msgData->num_btn == 2)
+ argv[1] = GPS_NI_BTN;
+ else
+ argv[1] = GPS_NI_WITHOUT_BTN;
+ argv[2] = temp;
+ argv[3] = msgData->msg_body;
+ argv[4] = NULL;
+
+ if (msgData->num_btn == 2) {
+ wait(&status);
+ if (status != YES_EXIT_STATUS && status != NO_EXIT_STATUS)
+ status = YES_EXIT_STATUS;
+ status = status / 256;
+ } else {
+ // Popup application Timer is 2 sec
+ sleep(2);
+ status = YES_EXIT_STATUS;
+ }
+
+ status = NO_EXIT_STATUS - status;
+ LOG_GPS(DBG_LOW, "EXIT_STATUS from the LBS Popup is [ %d ]", status);
+
+ agps_supl_ni_info_t info;
+ info.msg_body = (char *)msgData->msg_body;
+ info.msg_size = msgData->msg_size;
+ info.status = status;
+
+ if (!get_plugin_module()->request(GPS_ACTION_REQUEST_SUPL_NI, &info, &reason_code)) {
+ LOG_GPS(DBG_ERR, "Failed to request SUPL NI (code:%d)", reason_code);
+ }
+
+ return NULL;
+
+}
+
+static void _gps_supl_networkinit_smscb(MSG_HANDLE_T hMsgHandle, msg_message_t msg, void *user_param)
+{
+ LOG_GPS(DBG_ERR, "_gps_supl_networkinit_smscb is called");
+ LOG_GPS(DBG_ERR, "SUPLNI MSG size is [ %d ]", msg_get_message_body_size(msg));
+
+ gps_ni_popup_data_t new_message;
+ memset(&new_message, 0x00, sizeof(new_message));
+
+ new_message.msg_body = (char *)msg_sms_get_message_body(msg);
+ new_message.msg_size = msg_get_message_body_size(msg);
+ // TODO: Button number of LBS Popup
+ new_message.num_btn = 2;
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (pthread_create(&popup_thread, &attr, _gps_launch_popup, &new_message) != 0) {
+ LOG_GPS(DBG_WARN, "Can not make pthread......");
+ }
+
+}
+
+static void _gps_supl_networkinit_wappushcb(MSG_HANDLE_T hMsgHandle, const char *pPushHeader, const char *pPushBody,
+ int pushBodyLen, void *user_param)
+{
+ LOG_GPS(DBG_ERR, "_gps_supl_networkinit_wappushcb is called");
+ LOG_GPS(DBG_ERR, "SUPLNI WAPPush MSG size is [ %d ]", pushBodyLen);
+
+ gps_ni_popup_data_t new_message;
+ memset(&new_message, 0x00, sizeof(new_message));
+
+ new_message.msg_body = (char *)pPushBody;
+ new_message.msg_size = pushBodyLen;
+ // TODO: Button number of LBS Popup
+ new_message.num_btn = 2;
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (pthread_create(&popup_thread, &attr, _gps_launch_popup, &new_message) != 0) {
+ LOG_GPS(DBG_WARN, "Can not make pthread......");
+ }
+
+}
+
+static void *_gps_register_msgfwcb()
+{
+ MSG_HANDLE_T msgHandle = NULL;
+ MSG_ERROR_T err = MSG_SUCCESS;
+
+ int setValue = 0;
+ int ret;
+
+ int cnt = 60;
+
+ while (cnt > 0) {
+ ret = vconf_get_bool(VCONFKEY_MSG_SERVER_READY, &setValue);
+
+ if (ret == -1) {
+ LOG_GPS(DBG_WARN, "Fail to get VCONFKEY_MSG_SERVER_READY");
+ return NULL;
+ }
+
+ if (setValue) {
+ LOG_GPS(DBG_LOW, "MSG server is READY!!");
+ cnt = -1;
+ } else {
+ sleep(5);
+ cnt--;
+ if (cnt == 0) {
+ LOG_GPS(DBG_WARN, "Never connect to MSG Server for 300 secs.");
+ return NULL;
+ }
+ }
+ }
+
+ err = msg_open_msg_handle(&msgHandle);
+
+ if (err != MSG_SUCCESS) {
+ LOG_GPS(DBG_WARN, "Fail to MsgOpenMsgHandle. Error type = [ %d ]", err);
+ return NULL;
+ }
+
+ err = msg_reg_sms_message_callback(msgHandle, &_gps_supl_networkinit_smscb, 7275, NULL);
+
+ if (err != MSG_SUCCESS) {
+ LOG_GPS(DBG_WARN, "Fail to MsgRegSmsMessageCallback. Error type = [ %d ]", err);
+ return NULL;
+ }
+
+ err = msg_reg_lbs_message_callback(msgHandle, &_gps_supl_networkinit_wappushcb, NULL);
+
+ if (err != MSG_SUCCESS) {
+ LOG_GPS(DBG_WARN, "Fail to MsgRegLBSMessageCallback. Error type = [ %d ]", err);
+ return NULL;
+ }
+
+ LOG_GPS(DBG_LOW, "Success to lbs_register_msgfwcb");
+ return NULL;
+
+}
+
+static void _gps_hibernation_enter_callback(void *data)
+{
+ LOG_GPS(DBG_LOW, "Enter the _gps_hibernation_enter_callback");
+
+ if (msg_thread != 0) {
+ pthread_cancel(msg_thread);
+
+ pthread_join(msg_thread, (void *)&msg_thread_status);
+ msg_thread = 0;
+ }
+}
+
+static void _gps_hibernation_leave_callback(void *data)
+{
+ LOG_GPS(DBG_LOW, "Enter the _gps_hibernation_leave_callback");
+
+ if (msg_thread != 0) {
+ pthread_cancel(msg_thread);
+
+ pthread_join(msg_thread, (void *)&msg_thread_status);
+ msg_thread = 0;
+ }
+ if (pthread_create(&msg_thread, NULL, _gps_register_msgfwcb, NULL) != 0) {
+ LOG_GPS(DBG_WARN, "Can not make pthread......");
+ }
+}
+
+static void _print_help()
+{
+ printf("Usage: gps-manager [OPTION] [NAME]\n"
+ " -h Help\n"
+ " -l [NAME] Load a specific plugin module\n");
+ exit(0);
+}
+
+static int _parse_argument(const int argc, char **argv, const int buffer_size, char *out_buffer)
+{
+ int opt;
+
+ memset(out_buffer, 0x00, buffer_size);
+ while ((opt = getopt(argc, argv, "hl:")) != -1) {
+ switch (opt) {
+ case 'l':
+ snprintf(out_buffer, buffer_size, "%s", optarg);
+ break;
+ case 'h':
+ default:
+ _print_help();
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int initialize_server(int argc, char **argv)
+{
+ char module_name[16];
+
+ _parse_argument(argc, argv, sizeof(module_name), module_name);
+
+ FUNC_ENTRANCE_SERVER;
+
+ _gps_plugin_handler_init(module_name);
+ _gps_read_params();
+ _gps_notify_params();
+
+ if (!load_plugin_module(g_gps_plugin.name, &g_gps_plugin.handle)) {
+ LOG_GPS(DBG_ERR, "Failed to load plugin module.");
+ return -1;
+ }
+
+ LOG_GPS(DBG_LOW, "after read parameters......");
+
+ if (!get_plugin_module()->init(_gps_server_gps_event_cb, &g_gps_params)) {
+ LOG_GPS(DBG_WARN, "//GPS Initialization failed");
+ return -1;
+ }
+ // Register SUPL NI cb to MSG server
+ if (pthread_create(&msg_thread, NULL, _gps_register_msgfwcb, NULL) != 0) {
+ LOG_GPS(DBG_WARN, "Can not make pthread......");
+ }
+ // Register Hibernation cb to re-connect msg-server
+ int notifd;
+ notifd = heynoti_init();
+ heynoti_subscribe(notifd, "HIBERNATION_ENTER", _gps_hibernation_enter_callback, NULL);
+ heynoti_subscribe(notifd, "HIBERNATION_LEAVE", _gps_hibernation_leave_callback, NULL);
+ heynoti_attach_handler(notifd);
+
+ LOG_GPS(DBG_LOW, "Initialization is completed.");
+
+ return 0;
+}
+
+int deinitialize_server()
+{
+ gps_failure_reason_t ReasonCode = GPS_FAILURE_CAUSE_NORMAL;
+
+ // Wait termination of msg thread
+ pthread_join(msg_thread, (void *)&msg_thread_status);
+
+ _gps_ignore_params();
+
+ if (!get_plugin_module()->deinit(&ReasonCode)) {
+ LOG_GPS(DBG_WARN, "GPS De-Initialization failed.");
+ }
+
+ unload_plugin_module(g_gps_plugin.handle);
+ _gps_plugin_handler_deinit();
+
+ return 0;
+}
+
+int register_update_callbacks(struct gps_callbacks *gps_callback, void *user_data)
+{
+ g_update_cb = *gps_callback;
+ g_user_data = user_data;
+ return 0;
+}