summaryrefslogtreecommitdiff
path: root/gps-plugin
diff options
context:
space:
mode:
Diffstat (limited to 'gps-plugin')
-rw-r--r--gps-plugin/Makefile.am17
-rw-r--r--gps-plugin/include/gps_plugin_debug.h51
-rw-r--r--gps-plugin/include/nmea_parser.h34
-rw-r--r--gps-plugin/include/setting.h52
-rw-r--r--gps-plugin/src/gps_plugin_replay.c538
-rw-r--r--gps-plugin/src/nmea_parser.c381
-rw-r--r--gps-plugin/src/setting.c74
7 files changed, 1147 insertions, 0 deletions
diff --git a/gps-plugin/Makefile.am b/gps-plugin/Makefile.am
new file mode 100644
index 0000000..4a699dd
--- /dev/null
+++ b/gps-plugin/Makefile.am
@@ -0,0 +1,17 @@
+################# Build library ################
+lib_LTLIBRARIES = libSLP-lbs-plugin-replay.la
+
+libSLP_lbs_plugin_replay_la_SOURCES = \
+ $(srcdir)/src/nmea_parser.c \
+ $(srcdir)/src/gps_plugin_replay.c \
+ $(srcdir)/src/setting.c
+
+libSLP_lbs_plugin_replay_la_CFLAGS = -Wall -fPIC -fvisibility=hidden -DEXPORT_API="__attribute__((visibility(\"default\")))" \
+ -I$(srcdir)/include \
+ $(GPS_MANAGER_PLUGIN_CFLAGS) \
+ $(VCONF_CFLAGS) \
+ $(DLOG_CFLAGS)
+
+libSLP_lbs_plugin_replay_la_LDFLAGS = -Wl,--hash-style=both -Wl,--as-needed \
+ $(VCONF_LIBS) \
+ $(DLOG_LIBS)
diff --git a/gps-plugin/include/gps_plugin_debug.h b/gps-plugin/include/gps_plugin_debug.h
new file mode 100644
index 0000000..4e38254
--- /dev/null
+++ b/gps-plugin/include/gps_plugin_debug.h
@@ -0,0 +1,51 @@
+/*
+ * gps-manager replay plugin
+ *
+ * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
+ * Genie Kim <daejins.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.
+ */
+
+#ifndef __GPS_PLUGIN_DEBUG_H__
+#define __GPS_PLUGIN_DEBUG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GPS_DLOG
+#define GPS_DLOG_DEBUG // filename and line number will be shown
+
+#ifdef GPS_DLOG
+#include <dlog.h>
+#define TAG_GPS_PLUGIN "gps-plugin"
+
+#define DBG_LOW LOG_DEBUG
+#define DBG_INFO LOG_INFO
+#define DBG_WARN LOG_WARN
+#define DBG_ERR LOG_ERROR
+
+#ifdef GPS_DLOG_DEBUG // Debug mode
+#define LOG_PLUGIN(dbg_lvl,fmt,args...) SLOG(dbg_lvl, TAG_GPS_PLUGIN, "[%-40s: %-4d] "fmt, __FILE__, __LINE__, ##args)
+#else // Release(commercial) mode
+#define LOG_PLUGIN(dbg_lvl,fmt,args...) SLOG(dbg_lvl, TAG_GPS_PLUGIN, fmt, ##args)
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/gps-plugin/include/nmea_parser.h b/gps-plugin/include/nmea_parser.h
new file mode 100644
index 0000000..1726036
--- /dev/null
+++ b/gps-plugin/include/nmea_parser.h
@@ -0,0 +1,34 @@
+/*
+ * gps-manager replay plugin
+ *
+ * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
+ * Genie Kim <daejins.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.
+ */
+
+#ifndef NMEA_PARSER_H
+#define NMEA_PARSER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+int nmea_parser(char *data, pos_data_t * pos, sv_data_t * sv);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif
diff --git a/gps-plugin/include/setting.h b/gps-plugin/include/setting.h
new file mode 100644
index 0000000..ba04ff5
--- /dev/null
+++ b/gps-plugin/include/setting.h
@@ -0,0 +1,52 @@
+/*
+ * gps-manager replay plugin
+ *
+ * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
+ * Genie Kim <daejins.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.
+ */
+
+#ifndef _SETTING_H_
+#define _SETTING_H_
+
+#include <vconf.h>
+#include <vconf-internal-location-keys.h>
+
+#define NMEA_FILE_PATH "/opt/media/gps-manager/replay/"
+#define DEFAULT_NMEA_LOG "/etc/gps-manager/replay/nmea_replay.log"
+
+typedef enum {
+ REPLAY_OFF = 0,
+ REPLAY_NMEA,
+ REPLAY_MANUAL,
+ REPLAY_MODE_MAX
+} replay_mode_t;
+
+typedef enum {
+ READ_ERROR = -1,
+ READ_SUCCESS = 0,
+ READ_NOT_FIXED = 1,
+} read_error_t;
+
+int setting_get_int(const char *path, int *val);
+int setting_get_double(const char *path, double *val);
+char *setting_get_string(const char *path);
+
+typedef void (*key_changed_cb) (keynode_t * key, void *data);
+
+int setting_notify_key_changed(const char *path, void *key_changed_cb);
+int setting_ignore_key_changed(const char *path, void *key_changed_cb);
+#endif /* _SETTING_H_ */
diff --git a/gps-plugin/src/gps_plugin_replay.c b/gps-plugin/src/gps_plugin_replay.c
new file mode 100644
index 0000000..4672bc5
--- /dev/null
+++ b/gps-plugin/src/gps_plugin_replay.c
@@ -0,0 +1,538 @@
+/*
+ * gps-manager replay plugin
+ *
+ * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
+ * Genie Kim <daejins.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 <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include <gps_manager_plugin_intf.h>
+
+#include "gps_plugin_debug.h"
+#include "nmea_parser.h"
+#include "setting.h"
+
+#define REPLAY_NMEA_SET_SIZE 4096
+#define REPLAY_NMEA_SENTENCE_SIZE 128
+
+gps_event_cb g_gps_event_cb = NULL;
+
+typedef struct {
+ FILE *fd;
+ int interval;
+ int replay_mode;
+
+ pos_data_t *pos_data;
+ sv_data_t *sv_data;
+ nmea_data_t *nmea_data;
+
+ GSource *timeout_src;
+ GMainContext *default_context;
+} replay_timeout;
+
+replay_timeout *g_replay_timer = NULL;
+
+int gps_plugin_replay_gps_init(gps_event_cb gps_event_cb, gps_server_param_t * gps_params);
+int gps_plugin_replay_gps_deinit(gps_failure_reason_t * reason_code);
+int gps_plugin_replay_gps_request(gps_action_t gps_action, void *data, gps_failure_reason_t * reason_code);
+
+static const gps_plugin_interface g_gps_plugin_replay_interface = {
+ gps_plugin_replay_gps_init,
+ gps_plugin_replay_gps_deinit,
+ gps_plugin_replay_gps_request
+};
+
+void gps_plugin_replay_pos_event(pos_data_t * data)
+{
+ gps_event_info_t gps_event;
+ time_t timestamp;
+
+ memset(&gps_event, 0, sizeof(gps_event_info_t));
+ time(&timestamp);
+
+ gps_event.event_id = GPS_EVENT_REPORT_POSITION;
+
+ if (data == NULL) {
+ LOG_PLUGIN(DBG_ERR, "NULL POS data.");
+ gps_event.event_data.pos_ind.error = GPS_ERR_COMMUNICATION;
+ } else {
+ gps_event.event_data.pos_ind.error = GPS_ERR_NONE;
+ gps_event.event_data.pos_ind.pos.timestamp = timestamp;
+ gps_event.event_data.pos_ind.pos.latitude = data->latitude;
+ gps_event.event_data.pos_ind.pos.longitude = data->longitude;
+ gps_event.event_data.pos_ind.pos.altitude = data->altitude;
+ gps_event.event_data.pos_ind.pos.speed = data->speed;
+ gps_event.event_data.pos_ind.pos.bearing = data->bearing;
+ gps_event.event_data.pos_ind.pos.hor_accuracy = data->hor_accuracy;
+ gps_event.event_data.pos_ind.pos.ver_accuracy = data->ver_accuracy;
+ }
+
+ //LOG_PLUGIN(DBG_LOW, "%d / %f / %f / %f", gps_event.event_data.pos_ind.pos.timestamp, gps_event.event_data.pos_ind.pos.latitude, gps_event.event_data.pos_ind.pos.longitude, gps_event.event_data.pos_ind.pos.altitude);
+
+ if (g_gps_event_cb != NULL) {
+ g_gps_event_cb(&gps_event);
+ }
+}
+
+void gps_plugin_replay_sv_event(sv_data_t * data)
+{
+ int i;
+ gps_event_info_t gps_event;
+ time_t timestamp;
+
+ memset(&gps_event, 0, sizeof(gps_event_info_t));
+ time(&timestamp);
+ gps_event.event_id = GPS_EVENT_REPORT_SATELLITE;
+
+ if (data == NULL) {
+ LOG_PLUGIN(DBG_ERR, "NULL SV data.");
+ gps_event.event_data.sv_ind.error = GPS_ERR_COMMUNICATION;
+ } else {
+ gps_event.event_data.sv_ind.error = GPS_ERR_NONE;
+ gps_event.event_data.sv_ind.sv.timestamp = timestamp;
+ gps_event.event_data.sv_ind.sv.pos_valid = data->pos_valid;
+ gps_event.event_data.sv_ind.sv.num_of_sat = data->num_of_sat;
+ for (i = 0; i < data->num_of_sat; i++) {
+ gps_event.event_data.sv_ind.sv.sat[i].used = data->sat[i].used;
+ gps_event.event_data.sv_ind.sv.sat[i].prn = data->sat[i].prn;
+ gps_event.event_data.sv_ind.sv.sat[i].snr = data->sat[i].snr;
+ gps_event.event_data.sv_ind.sv.sat[i].elevation = data->sat[i].elevation;
+ gps_event.event_data.sv_ind.sv.sat[i].azimuth = data->sat[i].azimuth;
+ }
+ }
+
+ if (g_gps_event_cb != NULL) {
+ g_gps_event_cb(&gps_event);
+ }
+}
+
+void gps_plugin_replay_nmea_event(nmea_data_t * data)
+{
+ gps_event_info_t gps_event;
+ time_t timestamp;
+
+ memset(&gps_event, 0, sizeof(gps_event_info_t));
+ time(&timestamp);
+
+ gps_event.event_id = GPS_EVENT_REPORT_NMEA;
+
+ if (data == NULL) {
+ LOG_PLUGIN(DBG_ERR, "NULL NMEA data.");
+ gps_event.event_data.nmea_ind.error = GPS_ERR_COMMUNICATION;
+ } else {
+ if (data->len > REPLAY_NMEA_SENTENCE_SIZE) {
+ LOG_PLUGIN(DBG_WARN, "The Size of NMEA[ %d ] is larger then max ", data->len);
+ data->len = REPLAY_NMEA_SENTENCE_SIZE;
+ gps_event.event_data.nmea_ind.error = GPS_ERR_COMMUNICATION;
+ } else {
+ gps_event.event_data.nmea_ind.error = GPS_ERR_NONE;
+ }
+ gps_event.event_data.nmea_ind.nmea.timestamp = timestamp;
+ gps_event.event_data.nmea_ind.nmea.len = data->len;
+ gps_event.event_data.nmea_ind.nmea.data = (char *)malloc(data->len);
+ memset(gps_event.event_data.nmea_ind.nmea.data, 0x00, data->len);
+ memcpy(gps_event.event_data.nmea_ind.nmea.data, data->data, data->len);
+ //LOG_PLUGIN(DBG_LOW, "NMEA[%d] : %s", gps_event.event_data.nmea_ind.nmea.len, gps_event.event_data.nmea_ind.nmea.data);
+ }
+
+ if (g_gps_event_cb != NULL) {
+ g_gps_event_cb(&gps_event);
+ }
+
+ if (gps_event.event_data.nmea_ind.nmea.data != NULL) {
+ free(gps_event.event_data.nmea_ind.nmea.data);
+ gps_event.event_data.nmea_ind.nmea.data = NULL;
+ }
+}
+
+void gps_plugin_respond_start_session(gboolean ret)
+{
+ gps_event_info_t gps_event;
+ gps_event.event_id = GPS_EVENT_START_SESSION;
+
+ if (ret == TRUE) {
+ gps_event.event_data.start_session_rsp.error = GPS_ERR_NONE;
+ } else {
+ gps_event.event_data.start_session_rsp.error = GPS_ERR_COMMUNICATION;
+ }
+
+ if (g_gps_event_cb != NULL) {
+ g_gps_event_cb(&gps_event);
+ }
+}
+
+void gps_plugin_respond_stop_session(void)
+{
+ gps_event_info_t gps_event;
+
+ gps_event.event_id = GPS_EVENT_STOP_SESSION;
+ gps_event.event_data.stop_session_rsp.error = GPS_ERR_NONE;
+
+ if (g_gps_event_cb != NULL) {
+ g_gps_event_cb(&gps_event);
+ }
+}
+
+gboolean gps_plugin_replay_read_nmea(replay_timeout * timer, char *nmea_data)
+{
+ gboolean ret = FALSE;
+ int ref = 0;
+ char buf[REPLAY_NMEA_SENTENCE_SIZE] = { 0, };
+
+ if (timer->fd == NULL) {
+ LOG_PLUGIN(DBG_ERR, "nmea fd is NULL");
+ return FALSE;
+ }
+
+ if (nmea_data == NULL) {
+ LOG_PLUGIN(DBG_ERR, "nmea_data is NULL");
+ fclose(timer->fd);
+ timer->fd = NULL;
+ return FALSE;
+ }
+
+ while (fgets(buf, REPLAY_NMEA_SENTENCE_SIZE, timer->fd) != NULL) {
+ if (strncmp(buf, "$GPGGA", 6) == 0) {
+ ref++;
+ if (ref > 1) {
+ fseek(timer->fd, -strlen(buf), SEEK_CUR);
+ LOG_PLUGIN(DBG_LOW, "2nd GPGGA : stop to read nmea data");
+ ret = TRUE;
+ break;
+ } else if (ref == 1) {
+ LOG_PLUGIN(DBG_LOW, "1st GPGGA : start to read nmea data");
+ strncpy(nmea_data, buf, strlen(buf));
+ }
+ } else {
+ if (strlen(nmea_data) + strlen(buf) > REPLAY_NMEA_SET_SIZE) {
+ LOG_PLUGIN(DBG_ERR, "read nmea data size is too long");
+ break;
+ } else {
+ strncat(nmea_data, buf, strlen(buf));
+ }
+ }
+ timer->nmea_data->len = strlen(buf);
+ timer->nmea_data->data = buf;
+ gps_plugin_replay_nmea_event(timer->nmea_data);
+ }
+
+ if (feof(timer->fd)) {
+ LOG_PLUGIN(DBG_ERR, "end of file");
+ rewind(timer->fd);
+ ret = TRUE;
+ } else {
+ LOG_PLUGIN(DBG_LOW, "read nmea data [%s]", nmea_data);
+ }
+ return ret;
+}
+
+gboolean gps_plugin_replay_read_manual(pos_data_t * pos_data)
+{
+ gboolean ret = TRUE;
+
+ if (setting_get_double(VCONFKEY_LOCATION_MANUAL_LATITUDE, &pos_data->latitude) == FALSE) {
+ LOG_PLUGIN(DBG_ERR, "Fail to get latitude");
+ ret = FALSE;
+ }
+ if (setting_get_double(VCONFKEY_LOCATION_MANUAL_LONGITUDE, &pos_data->longitude) == FALSE) {
+ LOG_PLUGIN(DBG_ERR, "Fail to get longitude");
+ ret = FALSE;
+ }
+ if (setting_get_double(VCONFKEY_LOCATION_MANUAL_ALTITUDE, &pos_data->altitude) == FALSE) {
+ LOG_PLUGIN(DBG_ERR, "Fail to get altitude");
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+gboolean gps_plugin_replay_timeout_cb(gpointer data)
+{
+ gboolean ret = FALSE;
+ read_error_t err = READ_SUCCESS;
+ char nmea_data[REPLAY_NMEA_SET_SIZE] = { 0, };
+ replay_timeout *timer = (replay_timeout *) data;
+
+ if (timer == NULL) {
+ LOG_PLUGIN(DBG_ERR, "replay handel[timer] is NULL");
+ return FALSE;
+ }
+
+ memset(timer->pos_data, 0, sizeof(pos_data_t));
+ memset(timer->sv_data, 0, sizeof(sv_data_t));
+
+ if (timer->replay_mode == REPLAY_NMEA) {
+ if (gps_plugin_replay_read_nmea(timer, nmea_data) == FALSE) {
+ LOG_PLUGIN(DBG_ERR, "Fail to read nmea data from file");
+ return FALSE;
+ } else {
+ err = nmea_parser(nmea_data, timer->pos_data, timer->sv_data);
+ if (err == READ_ERROR) {
+ LOG_PLUGIN(DBG_ERR, "Fail to parser nmea data from file");
+ return FALSE;
+ } else if (err == READ_NOT_FIXED) {
+ LOG_PLUGIN(DBG_LOW, "GPS position is not fixed");
+ timer->sv_data->pos_valid = FALSE;
+ }
+ }
+ } else if (timer->replay_mode == REPLAY_MANUAL) {
+ if (gps_plugin_replay_read_manual(timer->pos_data) == FALSE) {
+ LOG_PLUGIN(DBG_ERR, "Fail to read manual data");
+ err = READ_ERROR;
+ return FALSE;
+ } else {
+ timer->sv_data->pos_valid = TRUE;
+ err = READ_SUCCESS;
+ }
+ } else if (timer->replay_mode == REPLAY_OFF) {
+ LOG_PLUGIN(DBG_WARN, "replay_mode is OFF");
+ err = READ_NOT_FIXED;
+ timer->sv_data->pos_valid = FALSE;
+ }
+
+ if (g_gps_event_cb != NULL) {
+ if (err != READ_NOT_FIXED) {
+ gps_plugin_replay_pos_event(timer->pos_data);
+ }
+ gps_plugin_replay_sv_event(timer->sv_data);
+ }
+ ret = TRUE;
+ return ret;
+}
+
+void gps_plugin_stop_replay_mode(replay_timeout * timer)
+{
+ if (timer->replay_mode == REPLAY_NMEA && fclose(timer->fd) != 0) {
+ LOG_PLUGIN(DBG_ERR, "fclose failed");
+ }
+ timer->fd = NULL;
+
+ if (timer->timeout_src != NULL && timer->default_context != NULL && !g_source_is_destroyed(timer->timeout_src)) {
+ if (timer->default_context == g_source_get_context(timer->timeout_src)) {
+ g_source_destroy(timer->timeout_src);
+ LOG_PLUGIN(DBG_LOW, "g_source_destroy timeout_src");
+ } else {
+ LOG_PLUGIN(DBG_WARN, "timer->timeout_src is attatched to 0x%x (actual 0x%x)",
+ g_source_get_context(timer->timeout_src), timer->default_context);
+ }
+ timer->timeout_src = NULL;
+ timer->default_context = NULL;
+ } else {
+ LOG_PLUGIN(DBG_WARN, "timeout_src or default_context is NULL or timeout_src is already destroyed");
+ }
+ gps_plugin_respond_stop_session();
+}
+
+gboolean gps_plugin_get_nmea_fd(replay_timeout * timer)
+{
+ char replay_file_path[256];
+
+ snprintf(replay_file_path, sizeof(replay_file_path), NMEA_FILE_PATH"%s", setting_get_string(VCONFKEY_LOCATION_NMEA_FILE_NAME));
+ LOG_PLUGIN(DBG_ERR, "replay file name : %s", replay_file_path);
+
+ timer->fd = fopen(replay_file_path, "r");
+ if (timer->fd == NULL) {
+ LOG_PLUGIN(DBG_ERR, "fopen(%s) failed", replay_file_path);
+ timer->fd = fopen(DEFAULT_NMEA_LOG, "r");
+ if (timer->fd == NULL) {
+ LOG_PLUGIN(DBG_ERR, "fopen(%s) failed", DEFAULT_NMEA_LOG);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+gboolean gps_plugin_start_replay_mode(replay_timeout * timer)
+{
+ gboolean ret = FALSE;
+
+ if (timer->replay_mode == REPLAY_NMEA) {
+ if (gps_plugin_get_nmea_fd(timer) == FALSE) {
+ return FALSE;
+ }
+ }
+
+ if (timer->default_context == NULL) {
+ timer->default_context = g_main_context_default();
+ if (timer->default_context == NULL) {
+ return ret;
+ }
+ }
+
+ if (timer->timeout_src != NULL) {
+ LOG_PLUGIN(DBG_ERR, "timeout_src is already existed");
+ ret = FALSE;
+ } else {
+ timer->timeout_src = g_timeout_source_new_seconds(timer->interval);
+ if (timer->timeout_src != NULL) {
+ g_source_set_callback(timer->timeout_src, &gps_plugin_replay_timeout_cb, timer, NULL);
+ if (g_source_attach(timer->timeout_src, timer->default_context) > 0) {
+ LOG_PLUGIN(DBG_LOW, "timeout_src(0x%x) is created & attatched to 0x%x", timer->timeout_src,
+ timer->default_context);
+ ret = TRUE;
+ } else {
+ gps_plugin_stop_replay_mode(timer);
+ ret = FALSE;
+ }
+ }
+ }
+ gps_plugin_respond_start_session(ret);
+
+ return ret;
+}
+
+static void replay_mode_changed_cb(keynode_t * key, void *data)
+{
+ if (setting_get_int(VCONFKEY_LOCATION_REPLAY_MODE, &g_replay_timer->replay_mode) == FALSE) {
+ g_replay_timer->replay_mode = REPLAY_OFF;
+ }
+
+ if (g_replay_timer->replay_mode == REPLAY_NMEA) {
+ if (gps_plugin_get_nmea_fd(g_replay_timer) == FALSE) {
+ LOG_PLUGIN(DBG_ERR, "Fail to get nmea fd.");
+ }
+ } else {
+ if (g_replay_timer->fd != NULL) {
+ fclose(g_replay_timer->fd);
+ g_replay_timer->fd = NULL;
+ }
+ }
+ return;
+}
+
+replay_timeout *gps_plugin_replay_timer_init()
+{
+ replay_timeout *timer = NULL;
+
+ timer = (replay_timeout *) malloc(sizeof(replay_timeout));
+ if (timer == NULL) {
+ LOG_PLUGIN(DBG_ERR, "replay_timeout allocation is failed.");
+ return NULL;
+ }
+
+ timer->fd = NULL;
+ timer->interval = 1;
+ if (setting_get_int(VCONFKEY_LOCATION_REPLAY_MODE, &timer->replay_mode) == FALSE) {
+ timer->replay_mode = REPLAY_OFF;
+ }
+ setting_notify_key_changed(VCONFKEY_LOCATION_REPLAY_MODE, replay_mode_changed_cb);
+
+ timer->pos_data = (pos_data_t *) malloc(sizeof(pos_data_t));
+ if (timer->pos_data == NULL) {
+ LOG_PLUGIN(DBG_ERR, "pos_data allocation is failed.");
+ free(timer);
+ return NULL;
+ }
+
+ timer->sv_data = (sv_data_t *) malloc(sizeof(sv_data_t));
+ if (timer->sv_data == NULL) {
+ LOG_PLUGIN(DBG_ERR, "sv_data allocation is failed.");
+ free(timer->pos_data);
+ free(timer);
+ return NULL;
+ }
+
+ timer->nmea_data = (nmea_data_t *) malloc(sizeof(nmea_data_t));
+ if (timer->nmea_data == NULL) {
+ LOG_PLUGIN(DBG_ERR, "nmea_data allocation is failed.");
+ free(timer->pos_data);
+ free(timer->sv_data);
+ free(timer);
+ return NULL;
+ }
+
+ timer->timeout_src = NULL;
+ timer->default_context = NULL;
+
+ return timer;
+}
+
+void gps_plugin_replay_timer_deinit(replay_timeout * timer)
+{
+ if (timer == NULL) {
+ return;
+ }
+
+ if (timer->pos_data != NULL) {
+ free(timer->pos_data);
+ timer->pos_data = NULL;
+ }
+ if (timer->sv_data != NULL) {
+ free(timer->sv_data);
+ timer->sv_data = NULL;
+ }
+ if (timer->nmea_data != NULL) {
+ free(timer->nmea_data);
+ timer->nmea_data = NULL;
+ }
+
+ setting_ignore_key_changed(VCONFKEY_LOCATION_REPLAY_MODE, replay_mode_changed_cb);
+
+ free(timer);
+ timer = NULL;
+}
+
+int gps_plugin_replay_gps_init(gps_event_cb gps_event_cb, gps_server_param_t * gps_params)
+{
+ g_gps_event_cb = gps_event_cb;
+ g_replay_timer = gps_plugin_replay_timer_init();
+
+ return TRUE;
+}
+
+int gps_plugin_replay_gps_deinit(gps_failure_reason_t * reason_code)
+{
+ gps_plugin_replay_timer_deinit(g_replay_timer);
+
+ return TRUE;
+}
+
+int gps_plugin_replay_gps_request(gps_action_t gps_action, void *data, gps_failure_reason_t * reason_code)
+{
+ switch (gps_action) {
+ case GPS_ACTION_SEND_PARAMS:
+ break;
+ case GPS_ACTION_START_SESSION:
+ gps_plugin_start_replay_mode(g_replay_timer);
+ break;
+ case GPS_ACTION_STOP_SESSION:
+ gps_plugin_stop_replay_mode(g_replay_timer);
+ break;
+ case GPS_INDI_SUPL_VERIFICATION:
+ case GPS_INDI_SUPL_DNSQUERY:
+ case GPS_ACTION_START_FACTTEST:
+ case GPS_ACTION_STOP_FACTTEST:
+ case GPS_ACTION_REQUEST_SUPL_NI:
+ LOG_PLUGIN(DBG_LOW, "Don't use action type : [ %d ]", gps_action);
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+EXPORT_API const gps_plugin_interface *get_gps_plugin_interface()
+{
+ return &g_gps_plugin_replay_interface;
+}
diff --git a/gps-plugin/src/nmea_parser.c b/gps-plugin/src/nmea_parser.c
new file mode 100644
index 0000000..63650dc
--- /dev/null
+++ b/gps-plugin/src/nmea_parser.c
@@ -0,0 +1,381 @@
+/*
+ * gps-manager replay plugin
+ *
+ * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
+ * Genie Kim <daejins.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 <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <gps_manager_plugin_intf.h>
+
+#include "gps_plugin_debug.h"
+#include "nmea_parser.h"
+#include "setting.h"
+
+#define MAX_NMEA_SENTENCES 32
+#define MAX_TOEKNS 25
+
+#define DECIMAL_TO_DEGREE 60.0
+#define METER_TO_FEET 3.2808399
+#define KNOT_TO_MPS 0.5144444
+#define KMPH_TO_MPS 0.2777778
+
+#define NORTH 1
+#define SOUTH -1
+#define EAST 1
+#define WEST -1
+
+int used_sat[MAX_GPS_NUM_SAT_USED] = { 0, };
+
+static char nmea_parser_c2n(char ch)
+{
+ if (ch <= '9') {
+ return ch - '0';
+ } else {
+ return (ch - 'A') + 10;
+ }
+}
+
+int nmea_parser_verify_checksum(char *nmea_sen)
+{
+ int ret = -1;
+ int i;
+ int checksum = 0;
+ int sum = 0;
+
+ for (i = 0; i < strlen(nmea_sen) && (nmea_sen[i] != '*'); i++) {
+ checksum ^= nmea_sen[i];
+ }
+
+ if (++i + 1 < strlen(nmea_sen)) {
+ sum = (nmea_parser_c2n(nmea_sen[i]) << 4) + nmea_parser_c2n(nmea_sen[i + 1]);
+ }
+
+ if (sum == checksum) {
+ ret = 0;
+ } else {
+ LOG_PLUGIN(DBG_LOW, "NMEA checksum is INVALID");
+ ret = -1;
+ }
+ return ret;
+}
+
+int nmea_parser_tokenize(char input[], char *token[])
+{
+ char *s = input;
+ int num_tokens = 0;
+ int state;
+
+ token[num_tokens] = s;
+ num_tokens++;
+ state = 0;
+ LOG_PLUGIN(DBG_LOW, "input:%s \n", input);
+
+ while ((*s != 0) && (num_tokens < MAX_TOEKNS)) {
+ switch (state) {
+ case 0:
+ if (*s == ',') {
+ *s = 0;
+ state = 1;
+ }
+ break;
+ case 1:
+ token[num_tokens++] = s;
+ if (*s == ',') {
+ *s = 0;
+ } else {
+ state = 0;
+ }
+ break;
+ }
+ s++;
+ }
+ return num_tokens;
+}
+
+static double nmea_parser_get_latitude(const char *lat, const char *bearing)
+{
+ double latitude = 0.0;
+ int ns;
+ int deg;
+ double remainder;
+
+ if ((*lat == 0) || (*bearing == 0)) {
+ return latitude;
+ }
+
+ ns = (*bearing == 'N') ? NORTH : SOUTH;
+
+ latitude = atof(lat);
+ deg = (int)(latitude / 100.0);
+ remainder = latitude - (deg * 100.0);
+ latitude = (deg + (remainder / DECIMAL_TO_DEGREE)) * ns;
+
+ return latitude;
+}
+
+static double nmea_parser_get_longitude(const char *lon, const char *bearing)
+{
+ double longitude = 0.0;
+ int ew;
+ int deg;
+ double remainder;
+
+ if (*lon == 0 || (*bearing == 0)) {
+ return longitude;
+ }
+
+ ew = (*bearing == 'E') ? EAST : WEST;
+
+ longitude = atof(lon);
+ deg = (int)(longitude / 100.0);
+ remainder = longitude - (deg * 100.0);
+ longitude = (deg + (remainder / DECIMAL_TO_DEGREE)) * ew;
+
+ return longitude;
+}
+
+static double nmea_parser_get_altitude(const char *alt, const char *unit)
+{
+ double altitude;
+
+ if (*alt == 0) {
+ return 0.0;
+ }
+
+ altitude = atof(alt);
+ altitude = (*unit == 'M') ? altitude : altitude * METER_TO_FEET;
+
+ return altitude;
+}
+
+static int nmea_parser_gpgga(char *token[], pos_data_t * pos, sv_data_t * sv)
+{
+ double latitude, longitude, altitude, eph, geoid;
+ int utctime, num_of_sat_used, quality;
+
+ quality = atoi(token[6]);
+
+ if (quality == 0) {
+ LOG_PLUGIN(DBG_LOW, "Not fixed");
+ sv->pos_valid = FALSE;
+ return READ_NOT_FIXED;
+ }
+
+ utctime = atoi(token[1]);
+ latitude = nmea_parser_get_latitude(token[2], token[3]);
+ longitude = nmea_parser_get_longitude(token[4], token[5]);
+ altitude = nmea_parser_get_altitude(token[9], token[10]);
+ num_of_sat_used = atoi(token[7]);
+ eph = atof(token[8]);
+ geoid = nmea_parser_get_altitude(token[11], token[12]);
+
+ pos->latitude = latitude;
+ pos->longitude = longitude;
+ pos->altitude = altitude;
+
+ sv->pos_valid = TRUE;
+
+ return READ_SUCCESS;
+}
+
+static int nmea_parser_gprmc(char *token[], pos_data_t * pos)
+{
+ int date, utctime;
+ char *status;
+ double latitude, longitude, speed, bearing, magvar;
+
+ status = token[2]; //warn = *token[2];
+ if (strcmp(status, "V") == 0) {
+ LOG_PLUGIN(DBG_LOW, "Not fixed");
+ return READ_NOT_FIXED;
+ }
+
+ utctime = atoi(token[1]);
+ latitude = nmea_parser_get_latitude(token[3], token[4]);
+ longitude = nmea_parser_get_longitude(token[5], token[6]);
+ speed = atof(token[7]);
+ bearing = atof(token[8]);
+ date = atoi(token[9]);
+ magvar = atof(token[10]);
+
+ pos->latitude = latitude;
+ pos->longitude = longitude;
+ pos->speed = speed * KNOT_TO_MPS;
+ pos->bearing = bearing;
+
+ return READ_SUCCESS;
+}
+
+static int nmea_parser_gpgll(char *token[], pos_data_t * pos)
+{
+ char *status;
+ double latitude, longitude;
+
+ status = token[6]; //warn = *token[2];
+ if (strcmp(status, "V") == 0) {
+ LOG_PLUGIN(DBG_LOW, "Not fixed");
+ return READ_NOT_FIXED;
+ }
+
+ latitude = nmea_parser_get_latitude(token[1], token[2]);
+ longitude = nmea_parser_get_longitude(token[3], token[4]);
+
+ pos->latitude = latitude;
+ pos->longitude = longitude;
+
+ return READ_SUCCESS;
+}
+
+static int nmea_parser_gpgsa(char *token[], pos_data_t * pos)
+{
+ char selection_type;
+ int i, fix_type;
+ double pdop, hdop, vdop;
+
+ fix_type = atoi(token[2]);
+ if (fix_type == 1) {
+ LOG_PLUGIN(DBG_LOW, "Not fixed");
+ return READ_NOT_FIXED;
+ }
+
+ selection_type = *token[1];
+
+ memset(used_sat, 0, sizeof(used_sat));
+ for (i = 0; i < MAX_GPS_NUM_SAT_USED; i++) {
+ used_sat[i] = atoi(token[i + 3]);
+ }
+
+ pdop = atof(token[15]);
+ hdop = atof(token[16]);
+ vdop = atof(token[17]);
+
+ return READ_SUCCESS;
+}
+
+static int nmea_parser_gpvtg(char *token[], pos_data_t * pos)
+{
+ double true_course, magnetic_course, knot_speed, kmh_speed;
+
+ true_course = atof(token[1]);
+ magnetic_course = atof(token[3]);
+ knot_speed = atof(token[5]);
+ kmh_speed = atof(token[7]);
+
+ pos->speed = kmh_speed * KMPH_TO_MPS;
+ pos->bearing = true_course;
+
+ return READ_SUCCESS;
+}
+
+static int nmea_parser_gpgsv(char *token[], sv_data_t * sv)
+{
+ int i, j;
+ int p, q, iter;
+ int num_sen, msg_num, num_sv;
+
+ num_sen = atoi(token[1]);
+ msg_num = atoi(token[2]);
+ if (msg_num < 1) {
+ LOG_PLUGIN(DBG_LOW, "There is not GSV message");
+ return READ_ERROR;
+ }
+
+ num_sv = atoi(token[3]);
+ sv->num_of_sat = num_sv;
+ iter = ((num_sv < (msg_num * 4)) ? (num_sv - ((msg_num - 1) * 4)) : 4);
+ for (i = 0; i < iter; i++) {
+ q = (i + 1) * 4;
+ p = i + 4 * (msg_num - 1);
+ sv->sat[p].prn = atoi(token[q]);
+ for (j = 0; j < MAX_GPS_NUM_SAT_USED; j++) {
+ if (sv->sat[p].prn == used_sat[j]) {
+ sv->sat[p].used = 1;
+ break;
+ } else {
+ sv->sat[p].used = 0;
+ }
+ }
+ sv->sat[p].elevation = atoi(token[q + 1]);
+ sv->sat[p].azimuth = atoi(token[q + 2]);
+ sv->sat[p].snr = atoi(token[q + 3]);
+ }
+ return READ_SUCCESS;
+}
+
+int nmea_parser_sentence(char *sentence, char *token[], pos_data_t * pos, sv_data_t * sv)
+{
+ int ret = READ_ERROR;
+ if (strcmp(sentence, "GPGGA") == 0) {
+ ret = nmea_parser_gpgga(token, pos, sv);
+ } else if (strcmp(sentence, "GPRMC") == 0) {
+ ret = nmea_parser_gprmc(token, pos);
+ } else if (strcmp(sentence, "GPGLL") == 0) {
+ ret = nmea_parser_gpgll(token, pos);
+ } else if (strcmp(sentence, "GPGSA") == 0) {
+ ret = nmea_parser_gpgsa(token, pos);
+ } else if (strcmp(sentence, "GPVTG") == 0) {
+ ret = nmea_parser_gpvtg(token, pos);
+ } else if (strcmp(sentence, "GPGSV") == 0) {
+ ret = nmea_parser_gpgsv(token, sv);
+ } else {
+ LOG_PLUGIN(DBG_LOW, "Unsupported sentence : [%s]\n", sentence);
+ }
+
+ return ret;
+}
+
+int nmea_parser(char *data, pos_data_t * pos, sv_data_t * sv)
+{
+ int ret = READ_SUCCESS;
+ read_error_t err;
+ int num_sen = 0;
+ int count = 0;
+ char *last = NULL;
+ char *nmea_sen[MAX_NMEA_SENTENCES] = { 0, };
+ char *token[MAX_TOEKNS] = { 0, };
+
+ nmea_sen[num_sen] = (char *)strtok_r((char *)data, "$", &last);
+ while (nmea_sen[num_sen] != NULL) {
+ num_sen++;
+ nmea_sen[num_sen] = (char *)strtok_r(NULL, "$", &last);
+ }
+ LOG_PLUGIN(DBG_LOW, "Number of NMEA sentences:%d \n", num_sen);
+
+ while (num_sen > 0) {
+ if (nmea_parser_verify_checksum(nmea_sen[count]) == 0) {
+ nmea_parser_tokenize(nmea_sen[count], token);
+ err = nmea_parser_sentence(token[0], token, pos, sv);
+ if (err == READ_NOT_FIXED) {
+ LOG_PLUGIN(DBG_LOW, "NOT Fixed");
+ ret = err;
+ } else if (err == READ_ERROR) {
+ ret = err;
+ break;
+ }
+ } else {
+ LOG_PLUGIN(DBG_ERR, "[NMEA Parser] %dth sentense : Invalid Checksum\n", count);
+ }
+ count++;
+ num_sen--;
+ }
+
+ return ret;
+}
diff --git a/gps-plugin/src/setting.c b/gps-plugin/src/setting.c
new file mode 100644
index 0000000..347b39f
--- /dev/null
+++ b/gps-plugin/src/setting.c
@@ -0,0 +1,74 @@
+/*
+ * gps-manager replay plugin
+ *
+ * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
+ * Genie Kim <daejins.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 <string.h>
+#include <glib.h>
+#include "setting.h"
+#include "gps_plugin_debug.h"
+
+int setting_get_int(const char *path, int *val)
+{
+ int ret = vconf_get_int(path, val);
+ if (ret == 0) {
+ ret = TRUE;
+ } else {
+ LOG_PLUGIN(DBG_ERR, "vconf_get_int failed, [%s]", path);
+ ret = FALSE;
+ }
+ return ret;
+}
+
+int setting_get_double(const char *path, double *val)
+{
+ int ret = vconf_get_dbl(path, val);
+ if (ret == 0) {
+ ret = TRUE;
+ } else {
+ LOG_PLUGIN(DBG_ERR, "vconf_get_int failed, [%s]", path);
+ ret = FALSE;
+ }
+ return ret;
+}
+
+char *setting_get_string(const char *path)
+{
+ return vconf_get_str(path);
+}
+
+int setting_notify_key_changed(const char *path, void *key_changed_cb)
+{
+ int ret = TRUE;
+ if (vconf_notify_key_changed(path, key_changed_cb, NULL) != 0) {
+ LOG_PLUGIN(DBG_ERR, "Fail to vconf_notify_key_changed [%s]", path);
+ ret = FALSE;
+ }
+ return ret;
+}
+
+int setting_ignore_key_changed(const char *path, void *key_changed_cb)
+{
+ int ret = TRUE;
+ if (vconf_ignore_key_changed(path, key_changed_cb) != 0) {
+ LOG_PLUGIN(DBG_ERR, "Fail to vconf_ignore_key_changed [%s]", path);
+ ret = FALSE;
+ }
+ return ret;
+}