diff options
Diffstat (limited to 'gps-plugin')
-rw-r--r-- | gps-plugin/Makefile.am | 17 | ||||
-rw-r--r-- | gps-plugin/include/gps_plugin_debug.h | 51 | ||||
-rw-r--r-- | gps-plugin/include/nmea_parser.h | 34 | ||||
-rw-r--r-- | gps-plugin/include/setting.h | 52 | ||||
-rw-r--r-- | gps-plugin/src/gps_plugin_replay.c | 538 | ||||
-rw-r--r-- | gps-plugin/src/nmea_parser.c | 381 | ||||
-rw-r--r-- | gps-plugin/src/setting.c | 74 |
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(×tamp); + + 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(×tamp); + 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(×tamp); + + 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; +} |