Coding rules
[platform/adaptation/artik/lbs-plugin-gps-artik7.git] / gps-plugin / src / gps_plugin_replay.c
1 /*
2  * gps replay plugin
3  *
4  * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
7  *                      Genie Kim <daejins.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <glib.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <sys/time.h>
29 #include <sys/stat.h>
30
31 #include <gps_plugin_intf.h>
32 #include <tzplatform_config.h>
33
34 #include "gps_plugin_debug.h"
35 #include "nmea_parser.h"
36 #include "setting.h"
37
38 #include "peripheral_io.h"
39 #include "peripheral_gdbus_i2c.h"
40 #include "peripheral_common.h"
41 #include "peripheral_internal.h"
42
43 #define REPLAY_NMEA_SET_SIZE            4096
44 #define REPLAY_NMEA_SENTENCE_SIZE       128
45
46 /*
47  * NMEA PACKET CMD for BerryGPS-IMU
48  */
49 #define PMK_CMD_WAKEUP_MODE             "$PMTK161,1*28\r\n"
50 #define PMK_CMD_STANDBY_MODE    "$PMTK161,0*28\r\n"
51
52 /*
53  * ARTIK7 UART PORT has only one.
54  */
55 #define GPS_UART_PORT 4
56 #define GPS_UART_BUFF_SIZE 1024
57
58 gps_event_cb g_gps_event_cb = NULL;
59 void *g_user_data = NULL;
60
61 peripheral_uart_h uart_hndl = NULL;
62
63 typedef struct {
64         FILE *fd;
65         FILE *batch_fd;
66         int interval;
67         int replay_mode;
68         int lcd_mode;
69
70         int batch_mode;
71         int batch_client_count;
72         int batch_interval;
73         int batch_period;
74         int num_of_batch;
75         time_t batch_start_time;
76         gboolean is_flush;
77
78         pos_data_t *pos_data;
79         batch_data_t *batch_data;
80         sv_data_t *sv_data;
81         nmea_data_t *nmea_data;
82
83         GSource *timeout_src;
84         GMainContext *default_context;
85 } replay_timeout;
86
87 replay_timeout *g_replay_timer = NULL;
88
89 int gps_plugin_replay_gps_init(gps_event_cb gps_event_cb, void *user_data);
90 int gps_plugin_replay_gps_deinit(gps_failure_reason_t *reason_code);
91 int gps_plugin_replay_gps_request(gps_action_t gps_action, void *gps_action_data, gps_failure_reason_t *reason_code);
92
93 static const gps_plugin_interface g_gps_plugin_replay_interface = {
94         gps_plugin_replay_gps_init,
95         gps_plugin_replay_gps_deinit,
96         gps_plugin_replay_gps_request
97 };
98
99 static int gps_uart_close()
100 {
101         int ret;
102
103         ret = peripheral_uart_close(uart_hndl);
104         if (ret < 0) {
105                 _E("GPS Uart Port Close failed !!");
106                 return FALSE;
107         }
108         uart_hndl = NULL;
109         _D("GPS Uart Port Close Successful !!");
110         return TRUE;
111 }
112
113 static int gps_uart_open()
114 {
115         int ret;
116
117         ret = peripheral_uart_open(GPS_UART_PORT, &uart_hndl);
118         if (ret < 0) {
119                 _E("GPS Uart Port Open failed !!");
120                 return FALSE;
121         }
122         _D("GPS Uart Port Open Successful !!");
123         ret = peripheral_uart_set_baud_rate(uart_hndl, PERIPHERAL_UART_BAUD_RATE_9600);
124         if (ret < 0) {
125                 _E("GPS Uart Port Open failed !!");
126                 goto ERROR;
127         }
128         ret = peripheral_uart_set_byte_size(uart_hndl, PERIPHERAL_UART_BYTE_SIZE_8BIT);
129         if (ret < 0) {
130                 _E("GPS Uart Set Mode failed !!");
131                 goto ERROR;
132         }
133         ret = peripheral_uart_set_parity(uart_hndl, PERIPHERAL_UART_PARITY_NONE);
134         if (ret < 0) {
135                 _E("GPS Uart Set Mode failed !!");
136                 goto ERROR;
137         }
138         ret = peripheral_uart_set_stop_bits(uart_hndl, PERIPHERAL_UART_STOP_BITS_1BIT);
139         if (ret < 0) {
140                 _E("GPS Uart Set Mode failed !!");
141                 goto ERROR;
142         }
143         ret = peripheral_uart_set_flow_control(uart_hndl,
144                         PERIPHERAL_UART_HARDWARE_FLOW_CONTROL_AUTO_RTSCTS,
145                         PERIPHERAL_UART_SOFTWARE_FLOW_CONTROL_NONE);
146         if (ret < 0) {
147                 _E("GPS Uart Set Flow Control Open failed !!");
148                 goto ERROR;
149         }
150         return TRUE;
151 ERROR:
152         gps_uart_close();
153         return FALSE;
154 }
155
156 static int gps_uart_read(char *buf, int len)
157 {
158         int length;
159
160         /* ERROR if the length is less than 0 */
161         if ((length = peripheral_uart_read(uart_hndl, (uint8_t *)buf, len)) < PERIPHERAL_ERROR_NONE)
162                 _E("GPS Uart Read failed !!");
163
164         return length;
165 }
166
167 void gps_plugin_replay_pos_event(pos_data_t *data)
168 {
169         gps_event_info_t gps_event;
170         time_t timestamp;
171
172         memset(&gps_event, 0, sizeof(gps_event_info_t));
173         time(&timestamp);
174
175         gps_event.event_id = GPS_EVENT_REPORT_POSITION;
176
177         if (data == NULL) {
178                 LOG_PLUGIN(DBG_ERR, "NULL POS data.");
179                 gps_event.event_data.pos_ind.error = GPS_ERR_COMMUNICATION;
180         } else {
181                 gps_event.event_data.pos_ind.error = GPS_ERR_NONE;
182                 gps_event.event_data.pos_ind.pos.timestamp = timestamp;
183                 gps_event.event_data.pos_ind.pos.latitude = data->latitude;
184                 gps_event.event_data.pos_ind.pos.longitude = data->longitude;
185                 gps_event.event_data.pos_ind.pos.altitude = data->altitude;
186                 gps_event.event_data.pos_ind.pos.speed = data->speed;
187                 gps_event.event_data.pos_ind.pos.bearing = data->bearing;
188                 gps_event.event_data.pos_ind.pos.hor_accuracy = data->hor_accuracy;
189                 gps_event.event_data.pos_ind.pos.ver_accuracy = data->ver_accuracy;
190         }
191
192         if (g_gps_event_cb != NULL)
193                 g_gps_event_cb(&gps_event, g_user_data);
194 }
195
196 void gps_plugin_replay_batch_event(pos_data_t *data, replay_timeout *timer)
197 {
198         char buf[256] = {0, };
199         time_t timestamp;
200         time(&timestamp);
201
202         const char *batch_path = tzplatform_mkpath(TZ_SYS_MEDIA, "lbs-server/location_batch.log");
203         if (timer->batch_fd == NULL) {
204
205                 struct stat st = {0};
206                 const char *lbs_server_path = tzplatform_mkpath(TZ_SYS_MEDIA, "lbs-server");
207                 if (stat(lbs_server_path, &st) == -1) {
208                         if (mkdir(lbs_server_path, 0777) == -1) {
209                                 LOG_PLUGIN(DBG_ERR, "Fail to create lbs-server folder");
210                                 return ;
211                         }
212                 }
213
214                 timer->batch_fd = fopen(batch_path, "w+");
215                 if (timer->batch_fd == NULL) {
216                         LOG_PLUGIN(DBG_ERR, "Fail to open file [Not available batch_fd]");
217                         return ;
218                 }
219         }
220
221         if (data != NULL) {
222
223                 g_snprintf(buf, 256, "%ld;%.6lf;%.6lf;%.2lf;%.2lf;%.2lf;%.2lf;%.2lf;\n",
224                                                 timestamp, data->latitude, data->longitude, data->altitude,
225                                                 data->speed, data->bearing, data->hor_accuracy, data->ver_accuracy);
226                 LOG_PLUGIN(DBG_LOW, "Add location info to batch file [%s]", buf);
227         }
228
229         if (timer->lcd_mode == VCONFKEY_PM_STATE_NORMAL) {
230                 fwrite(buf, 1, strlen(buf), timer->batch_fd);
231
232                 (timer->num_of_batch)++ ;
233                 timer->is_flush = TRUE;
234         } else {
235                 if ((timestamp - timer->batch_start_time) % timer->batch_interval == 0) {
236                         fwrite(buf, 1, strlen(buf), timer->batch_fd);
237                         (timer->num_of_batch)++ ;
238                 }
239                 if ((timestamp - timer->batch_start_time) >= timer->batch_period)
240                         timer->is_flush = TRUE;
241         }
242
243         if (timer->is_flush) {
244                 LOG_PLUGIN(DBG_LOW, "Batch invoked, Batch interval is expired or Batch stopped");
245                 gps_event_info_t gps_event;
246                 memset(&gps_event, 0, sizeof(gps_event_info_t));
247
248                 if (timer->batch_fd != NULL) {
249                         if (fclose(timer->batch_fd) != 0)
250                                 LOG_PLUGIN(DBG_ERR, "Fail to close file");
251                         timer->batch_fd = NULL;
252                 }
253
254                 gps_event.event_id = GPS_EVENT_REPORT_BATCH;
255                 timer->batch_start_time = timestamp;
256                 timer->is_flush = FALSE;
257
258                 if (timer->num_of_batch < 1) {
259                         LOG_PLUGIN(DBG_ERR, "There is no Batch data");
260                         gps_event.event_data.batch_ind.error = GPS_ERR_COMMUNICATION;
261                 } else {
262                         gps_event.event_data.batch_ind.error = GPS_ERR_NONE;
263                         gps_event.event_data.batch_ind.batch.num_of_location = timer->num_of_batch;
264                 }
265
266                 if (g_gps_event_cb != NULL) {
267                         g_gps_event_cb(&gps_event, g_user_data);
268                         timer->num_of_batch = 0;
269                 }
270         }
271 }
272
273 void gps_plugin_replay_sv_event(sv_data_t *data)
274 {
275         int i;
276         gps_event_info_t gps_event;
277         time_t timestamp;
278
279         memset(&gps_event, 0, sizeof(gps_event_info_t));
280         time(&timestamp);
281         gps_event.event_id = GPS_EVENT_REPORT_SATELLITE;
282
283         if (data == NULL) {
284                 LOG_PLUGIN(DBG_ERR, "NULL SV data.");
285                 gps_event.event_data.sv_ind.error = GPS_ERR_COMMUNICATION;
286         } else {
287                 gps_event.event_data.sv_ind.error = GPS_ERR_NONE;
288                 gps_event.event_data.sv_ind.sv.timestamp = timestamp;
289                 gps_event.event_data.sv_ind.sv.pos_valid = data->pos_valid;
290                 gps_event.event_data.sv_ind.sv.num_of_sat = data->num_of_sat;
291                 for (i = 0; i < data->num_of_sat; i++) {
292                         gps_event.event_data.sv_ind.sv.sat[i].used = data->sat[i].used;
293                         gps_event.event_data.sv_ind.sv.sat[i].prn = data->sat[i].prn;
294                         gps_event.event_data.sv_ind.sv.sat[i].snr = data->sat[i].snr;
295                         gps_event.event_data.sv_ind.sv.sat[i].elevation = data->sat[i].elevation;
296                         gps_event.event_data.sv_ind.sv.sat[i].azimuth = data->sat[i].azimuth;
297                 }
298         }
299
300         if (g_gps_event_cb != NULL)
301                 g_gps_event_cb(&gps_event, g_user_data);
302 }
303
304 void gps_plugin_replay_nmea_event(nmea_data_t *data)
305 {
306         gps_event_info_t gps_event;
307         time_t timestamp;
308
309         memset(&gps_event, 0, sizeof(gps_event_info_t));
310         time(&timestamp);
311
312         gps_event.event_id = GPS_EVENT_REPORT_NMEA;
313
314         if (data == NULL) {
315                 LOG_PLUGIN(DBG_ERR, "NULL NMEA data.");
316                 gps_event.event_data.nmea_ind.error = GPS_ERR_COMMUNICATION;
317         } else {
318                 if (data->len > REPLAY_NMEA_SENTENCE_SIZE) {
319                         LOG_PLUGIN(DBG_WARN, "The Size of NMEA[ %d ] is larger then max ", data->len);
320                         data->len = REPLAY_NMEA_SENTENCE_SIZE;
321                         gps_event.event_data.nmea_ind.error = GPS_ERR_COMMUNICATION;
322                 } else {
323                         gps_event.event_data.nmea_ind.error = GPS_ERR_NONE;
324                 }
325                 gps_event.event_data.nmea_ind.nmea.timestamp = timestamp;
326                 gps_event.event_data.nmea_ind.nmea.len = data->len;
327                 gps_event.event_data.nmea_ind.nmea.data = (char *)malloc(data->len);
328                 g_return_if_fail(gps_event.event_data.nmea_ind.nmea.data);
329
330                 memset(gps_event.event_data.nmea_ind.nmea.data, 0x00, data->len);
331                 memcpy(gps_event.event_data.nmea_ind.nmea.data, data->data, data->len);
332         }
333
334         if (g_gps_event_cb != NULL)
335                 g_gps_event_cb(&gps_event, g_user_data);
336
337         if (gps_event.event_data.nmea_ind.nmea.data != NULL) {
338                 free(gps_event.event_data.nmea_ind.nmea.data);
339                 gps_event.event_data.nmea_ind.nmea.data = NULL;
340         }
341 }
342
343 void gps_plugin_respond_start_session(gboolean ret)
344 {
345         gps_event_info_t gps_event;
346         gps_event.event_id = GPS_EVENT_START_SESSION;
347
348         if (ret == TRUE)
349                 gps_event.event_data.start_session_rsp.error = GPS_ERR_NONE;
350         else
351                 gps_event.event_data.start_session_rsp.error = GPS_ERR_COMMUNICATION;
352
353         if (g_gps_event_cb != NULL)
354                 g_gps_event_cb(&gps_event, g_user_data);
355 }
356
357 void gps_plugin_respond_stop_session(void)
358 {
359         gps_event_info_t gps_event;
360
361         gps_event.event_id = GPS_EVENT_STOP_SESSION;
362         gps_event.event_data.stop_session_rsp.error = GPS_ERR_NONE;
363
364         if (g_gps_event_cb != NULL)
365                 g_gps_event_cb(&gps_event, g_user_data);
366 }
367
368 gboolean gps_plugin_read_uart(replay_timeout *timer, char *nmea_data)
369 {
370         char buf[GPS_UART_BUFF_SIZE] = { 0, };
371         char *endstr = NULL;
372         int len = 0;
373         char *str = NULL;
374
375         if (uart_hndl == NULL) {
376                 LOG_PLUGIN(DBG_ERR, "uart handle is NULL");
377                 return FALSE;
378         }
379
380         if (nmea_data == NULL) {
381                 LOG_PLUGIN(DBG_ERR, "nmea_data is NULL");
382                 gps_uart_close();
383                 timer->fd = NULL;
384                 return FALSE;
385         }
386
387         if ((len = gps_uart_read(buf, GPS_UART_BUFF_SIZE)) < 0) {
388                 LOG_PLUGIN(DBG_ERR, "gps_uart_read ERROR");
389                 return TRUE;
390         }
391
392         /*  remove uncompleted sentences */
393         endstr = rindex(buf, '\n');
394         if (endstr != NULL)
395                 *endstr = '\0';
396         else
397                 return TRUE;
398
399         str = (char *)strtok(buf, "\n");
400         while (str != NULL) {
401                 if (strncmp(str, "$GP", 3) == 0) {
402                         if (strlen(nmea_data) + strlen(str) > REPLAY_NMEA_SET_SIZE) {
403                                 LOG_PLUGIN(DBG_ERR, "read nmea data size is too long");
404                                 break;
405                         } else {
406                                 strncpy(nmea_data + strlen(nmea_data), str, strlen(str) - 1);
407                         }
408                         timer->nmea_data->len = strlen(str);
409                         timer->nmea_data->data = str;
410                         gps_plugin_replay_nmea_event(timer->nmea_data);
411                 }
412                 str = (char *)strtok(NULL, "\n");
413         }
414         return TRUE;
415 }
416
417 gboolean gps_plugin_replay_read_nmea(replay_timeout *timer, char *nmea_data)
418 {
419         gboolean ret = FALSE;
420         int ref = 0;
421         char buf[REPLAY_NMEA_SENTENCE_SIZE] = { 0, };
422
423         if (timer->fd == NULL) {
424                 LOG_PLUGIN(DBG_ERR, "nmea fd is NULL");
425                 return FALSE;
426         }
427
428         if (nmea_data == NULL) {
429                 LOG_PLUGIN(DBG_ERR, "nmea_data is NULL");
430                 fclose(timer->fd);
431                 timer->fd = NULL;
432                 return FALSE;
433         }
434
435         while (fgets(buf, REPLAY_NMEA_SENTENCE_SIZE, timer->fd) != NULL) {
436                 if (strncmp(buf, "$GPGGA", 6) == 0) {
437                         ref++;
438                         if (ref > 1) {
439                                 fseek(timer->fd, -strlen(buf), SEEK_CUR);
440                                 /* LOG_PLUGIN(DBG_LOW, "2nd GPGGA : stop to read nmea data"); */
441                                 ret = TRUE;
442                                 break;
443                         } else if (ref == 1) {
444                                 /* LOG_PLUGIN(DBG_LOW, "1st GPGGA : start to read nmea data"); */
445                                 strncpy(nmea_data, buf, strlen(buf) - 1);
446                         }
447                 } else {
448                         if (strlen(nmea_data) + strlen(buf) > REPLAY_NMEA_SET_SIZE) {
449                                 LOG_PLUGIN(DBG_ERR, "read nmea data size is too long");
450                                 break;
451                         } else {
452                                 strncpy(nmea_data + strlen(nmea_data), buf, strlen(buf) - 1);
453                         }
454                 }
455                 timer->nmea_data->len = strlen(buf);
456                 timer->nmea_data->data = buf;
457                 gps_plugin_replay_nmea_event(timer->nmea_data);
458         }
459
460         if (feof(timer->fd)) {
461                 LOG_PLUGIN(DBG_ERR, "end of file");
462                 rewind(timer->fd);
463                 ret = TRUE;
464         } else {
465                 /* LOG_PLUGIN(DBG_LOW, "read nmea data [%s]", nmea_data); */
466         }
467         return ret;
468 }
469
470 gboolean gps_plugin_replay_read_manual(pos_data_t *pos_data)
471 {
472         gboolean ret = TRUE;
473
474         if (setting_get_double(VCONFKEY_LOCATION_MANUAL_LATITUDE, &pos_data->latitude) == FALSE) {
475                 LOG_PLUGIN(DBG_ERR, "Fail to get latitude");
476                 ret = FALSE;
477         }
478         if (setting_get_double(VCONFKEY_LOCATION_MANUAL_LONGITUDE, &pos_data->longitude) == FALSE) {
479                 LOG_PLUGIN(DBG_ERR, "Fail to get longitude");
480                 ret = FALSE;
481         }
482         if (setting_get_double(VCONFKEY_LOCATION_MANUAL_ALTITUDE, &pos_data->altitude) == FALSE) {
483                 LOG_PLUGIN(DBG_ERR, "Fail to get altitude");
484                 ret = FALSE;
485         }
486
487         return ret;
488 }
489
490 gboolean gps_plugin_replay_timeout_cb(gpointer data)
491 {
492         gboolean ret = FALSE;
493         read_error_t err = READ_SUCCESS;
494         char nmea_data[REPLAY_NMEA_SET_SIZE] = { 0, };
495         replay_timeout *timer = (replay_timeout *) data;
496
497         if (timer == NULL) {
498                 LOG_PLUGIN(DBG_ERR, "replay handel[timer] is NULL");
499                 return FALSE;
500         }
501
502         memset(timer->pos_data, 0, sizeof(pos_data_t));
503         memset(timer->batch_data, 0, sizeof(batch_data_t));
504         memset(timer->sv_data, 0, sizeof(sv_data_t));
505
506         if (timer->replay_mode == REPLAY_NMEA) {
507                 if (gps_plugin_read_uart(timer, nmea_data) == FALSE) {
508                         LOG_PLUGIN(DBG_ERR, "Fail to read nmea data from peripheral uart");
509                         return FALSE;
510                 } else {
511                         err = nmea_parser(nmea_data, timer->pos_data, timer->sv_data);
512                         if (err == READ_ERROR) {
513                                 LOG_PLUGIN(DBG_ERR, "Fail to parser nmea data from peripheral uart");
514                                 /*return FALSE; */
515                         } else if (err == READ_NOT_FIXED) {
516                                 LOG_PLUGIN(DBG_LOW, "GPS position is not fixed");
517                                 timer->sv_data->pos_valid = FALSE;
518                         }
519                 }
520         } else if (timer->replay_mode == REPLAY_MANUAL) {
521                 if (gps_plugin_replay_read_manual(timer->pos_data) == FALSE) {
522                         LOG_PLUGIN(DBG_ERR, "Fail to read manual data");
523                         err = READ_ERROR;
524                         return FALSE;
525                 } else {
526                         timer->sv_data->pos_valid = TRUE;
527                         err = READ_SUCCESS;
528                 }
529         } else if (timer->replay_mode == REPLAY_OFF) {
530                 if (gps_plugin_replay_read_nmea(timer, nmea_data) == FALSE) {
531                         LOG_PLUGIN(DBG_ERR, "Fail to read nmea data from file");
532                         return FALSE;
533                 } else {
534                         err = nmea_parser(nmea_data, timer->pos_data, timer->sv_data);
535                         if (err == READ_ERROR) {
536                                 LOG_PLUGIN(DBG_ERR, "Fail to parser nmea data from file");
537                                 /*return FALSE; */
538                         } else if (err == READ_NOT_FIXED) {
539                                 LOG_PLUGIN(DBG_LOW, "GPS position is not fixed");
540                                 timer->sv_data->pos_valid = FALSE;
541                         }
542                 }
543         }
544
545         if (g_gps_event_cb != NULL) {
546                 if (err != READ_NOT_FIXED) {
547                         if (timer->batch_mode == BATCH_MODE_ON) {
548                                 gps_plugin_replay_batch_event(timer->pos_data, timer);
549                         }
550
551                         gps_plugin_replay_pos_event(timer->pos_data);
552                 }
553
554                 gps_plugin_replay_sv_event(timer->sv_data);
555         }
556         ret = TRUE;
557         return ret;
558 }
559
560 void gps_plugin_stop_replay_mode(replay_timeout *timer)
561 {
562         if (timer->replay_mode == REPLAY_NMEA && gps_uart_close() == FALSE)
563                 LOG_PLUGIN(DBG_ERR, "peripheral_uart_close failed");
564         else if (timer->replay_mode == REPLAY_OFF && fclose(timer->fd) != 0)
565                 LOG_PLUGIN(DBG_ERR, "fclose failed");
566
567         timer->fd = NULL;
568
569         if (timer->timeout_src != NULL && timer->default_context != NULL && !g_source_is_destroyed(timer->timeout_src)) {
570                 if (timer->default_context == g_source_get_context(timer->timeout_src)) {
571                         g_source_destroy(timer->timeout_src);
572                         LOG_PLUGIN(DBG_LOW, "g_source_destroy timeout_src");
573                 } else {
574                         LOG_PLUGIN(DBG_WARN, "timer->timeout_src is attatched to 0x%x (actual 0x%x)",
575                                         g_source_get_context(timer->timeout_src), timer->default_context);
576                 }
577                 timer->timeout_src = NULL;
578                 timer->default_context = NULL;
579         } else {
580                 LOG_PLUGIN(DBG_WARN, "timeout_src or default_context is NULL or timeout_src is already destroyed");
581         }
582         gps_plugin_respond_stop_session();
583 }
584
585 gboolean gps_plugin_get_nmea_fd(replay_timeout *timer)
586 {
587         char replay_file_path[256];
588         char *str;
589
590         str = setting_get_string(VCONFKEY_LOCATION_NMEA_FILE_NAME);
591         if (str == NULL)
592                 return FALSE;
593
594         const char *nmea_file_path = tzplatform_mkpath(TZ_SYS_MEDIA, "lbs-server/replay/");
595         snprintf(replay_file_path, sizeof(replay_file_path), "%s%s", nmea_file_path, str);
596         SECLOG_PLUGIN(DBG_ERR, "replay file name : %s", replay_file_path);
597         free(str);
598
599         timer->fd = fopen(replay_file_path, "r");
600         if (timer->fd == NULL) {
601                 SECLOG_PLUGIN(DBG_ERR, "fopen(%s) failed", replay_file_path);
602                 const char *default_nmea_log = tzplatform_mkpath(TZ_SYS_RO_ETC, "lbs-server/replay/nmea_replay.log");
603                 timer->fd = fopen(default_nmea_log, "r");
604                 if (timer->fd == NULL) {
605                         SECLOG_PLUGIN(DBG_ERR, "fopen(%s) failed", default_nmea_log);
606                         return FALSE;
607                 }
608         }
609         return TRUE;
610 }
611
612 gboolean gps_plugin_start_replay_mode(replay_timeout *timer)
613 {
614         LOG_PLUGIN(DBG_LOW, "gps_plugin_start replay mode");
615         gboolean ret = FALSE;
616
617         if (timer->replay_mode == REPLAY_NMEA) {
618                 if (gps_uart_open() == FALSE)
619                         return FALSE;
620         } else if (timer->replay_mode == REPLAY_OFF) {
621                 if (gps_plugin_get_nmea_fd(timer) == FALSE)
622                         return FALSE;
623         }
624
625         if (timer->default_context == NULL) {
626                 timer->default_context = g_main_context_default();
627
628                 if (timer->default_context == NULL)
629                         return ret;
630         }
631
632         if (timer->timeout_src != NULL) {
633                 LOG_PLUGIN(DBG_ERR, "timeout_src is already existed");
634                 ret = FALSE;
635         } else {
636                 timer->timeout_src = g_timeout_source_new_seconds(timer->interval);
637                 if (timer->timeout_src != NULL) {
638                         g_source_set_callback(timer->timeout_src, &gps_plugin_replay_timeout_cb, timer, NULL);
639                         if (g_source_attach(timer->timeout_src, timer->default_context) > 0) {
640                                 LOG_PLUGIN(DBG_LOW, "timeout_src(0x%x) is created & attatched to 0x%x", timer->timeout_src, timer->default_context);
641                                 ret = TRUE;
642                         } else {
643                                 gps_plugin_stop_replay_mode(timer);
644                                 ret = FALSE;
645                         }
646                 }
647         }
648
649         gps_plugin_respond_start_session(ret);
650
651         return ret;
652 }
653
654 gboolean gps_plugin_update_batch_mode(replay_timeout *timer, int batch_interval, int batch_period)
655 {
656         gboolean ret = FALSE;
657         time_t timestamp;
658         time(&timestamp);
659
660         if (timer->batch_mode == BATCH_MODE_OFF) {
661                 timer->batch_mode = BATCH_MODE_ON;
662                 timer->batch_client_count = 0;
663         }
664         timer->batch_client_count++;
665
666         timer->batch_interval = batch_interval;
667         timer->batch_period = batch_period;
668         timer->batch_start_time = timestamp;
669
670         LOG_PLUGIN(DBG_LOW, "batch_client_count = %d", timer->batch_client_count);
671         return ret;
672 }
673
674 void gps_plugin_stop_batch_mode(replay_timeout *timer, int batch_interval, int batch_period)
675 {
676         if (timer->batch_client_count > 0)
677                 timer->batch_client_count--;
678
679         LOG_PLUGIN(DBG_ERR, "batch_client_count = %d", timer->batch_client_count);
680         if (timer->batch_client_count <= 0) {
681                 timer->batch_mode = BATCH_MODE_OFF;
682                 timer->batch_interval = 0;
683                 timer->batch_period = 0;
684
685                 if (timer->batch_fd != NULL) {
686                         fclose(timer->batch_fd);
687                         timer->batch_fd = NULL;
688                         timer->num_of_batch = 0;
689                 }
690         } else {
691                 timer->batch_interval = batch_interval;
692                 timer->batch_period = batch_period;
693                 time_t timestamp;
694                 time(&timestamp);
695                 timer->batch_start_time = timestamp;
696         }
697 }
698
699 static void replay_mode_changed_cb(keynode_t *key, void *data)
700 {
701         if (setting_get_int(VCONFKEY_LOCATION_REPLAY_MODE, &g_replay_timer->replay_mode) == FALSE)
702                 g_replay_timer->replay_mode = REPLAY_OFF;
703
704         if (g_replay_timer->replay_mode == REPLAY_NMEA) {
705                 if (gps_plugin_get_nmea_fd(g_replay_timer) == FALSE)
706                         LOG_PLUGIN(DBG_ERR, "Fail to get nmea fd.");
707
708         } else {
709                 if (g_replay_timer->fd != NULL) {
710                         fclose(g_replay_timer->fd);
711                         g_replay_timer->fd = NULL;
712                 }
713         }
714         return;
715 }
716
717 static void display_mode_changed_cb(keynode_t * key, void *data)
718 {
719         if (setting_get_int(VCONFKEY_PM_STATE, &g_replay_timer->lcd_mode) == FALSE) {
720                 LOG_PLUGIN(DBG_ERR, "Fail to get lcd state");
721                 g_replay_timer->lcd_mode = VCONFKEY_PM_STATE_LCDOFF;
722         }
723
724         if (g_replay_timer->lcd_mode == VCONFKEY_PM_STATE_NORMAL)
725                 g_replay_timer->is_flush = TRUE;
726
727         return;
728 }
729
730 replay_timeout *gps_plugin_replay_timer_init()
731 {
732         replay_timeout *timer = NULL;
733
734         timer = (replay_timeout *) malloc(sizeof(replay_timeout));
735         if (timer == NULL) {
736                 LOG_PLUGIN(DBG_ERR, "replay_timeout allocation is failed.");
737                 return NULL;
738         }
739
740         timer->fd = NULL;
741         timer->interval = 1;
742
743         timer->batch_fd = NULL;
744         timer->num_of_batch = 0;
745         timer->batch_client_count = 0;
746         timer->batch_mode = BATCH_MODE_OFF;
747         timer->batch_interval = 0;
748         timer->batch_period = 0;
749         timer->is_flush = FALSE;
750
751         if (setting_get_int(VCONFKEY_LOCATION_REPLAY_MODE, &timer->replay_mode) == FALSE)
752                 timer->replay_mode = REPLAY_OFF;
753
754         setting_notify_key_changed(VCONFKEY_LOCATION_REPLAY_MODE, replay_mode_changed_cb);
755
756         if (setting_get_int(VCONFKEY_PM_STATE, &timer->lcd_mode) == FALSE)
757                 timer->lcd_mode = VCONFKEY_PM_STATE_LCDOFF;
758
759         setting_notify_key_changed(VCONFKEY_PM_STATE, display_mode_changed_cb);
760
761         timer->pos_data = (pos_data_t *) malloc(sizeof(pos_data_t));
762         if (timer->pos_data == NULL) {
763                 LOG_PLUGIN(DBG_ERR, "pos_data allocation is failed.");
764                 free(timer);
765                 return NULL;
766         }
767
768         timer->batch_data = (batch_data_t *) malloc(sizeof(batch_data_t));
769         if (timer->batch_data == NULL) {
770                 LOG_PLUGIN(DBG_ERR, "batch_data allocation is failed.");
771                 free(timer->pos_data);
772                 free(timer);
773                 return NULL;
774         }
775
776         timer->sv_data = (sv_data_t *) malloc(sizeof(sv_data_t));
777         if (timer->sv_data == NULL) {
778                 LOG_PLUGIN(DBG_ERR, "sv_data allocation is failed.");
779                 free(timer->pos_data);
780                 free(timer->batch_data);
781                 free(timer);
782                 return NULL;
783         }
784
785         timer->nmea_data = (nmea_data_t *) malloc(sizeof(nmea_data_t));
786         if (timer->nmea_data == NULL) {
787                 LOG_PLUGIN(DBG_ERR, "nmea_data allocation is failed.");
788                 free(timer->pos_data);
789                 free(timer->batch_data);
790                 free(timer->sv_data);
791                 free(timer);
792                 return NULL;
793         }
794
795         timer->timeout_src = NULL;
796         timer->default_context = NULL;
797
798         return timer;
799 }
800
801 void gps_plugin_replay_timer_deinit(replay_timeout *timer)
802 {
803         if (timer == NULL)
804                 return;
805
806         if (timer->pos_data != NULL) {
807                 free(timer->pos_data);
808                 timer->pos_data = NULL;
809         }
810         if (timer->sv_data != NULL) {
811                 free(timer->sv_data);
812                 timer->sv_data = NULL;
813         }
814         if (timer->nmea_data != NULL) {
815                 free(timer->nmea_data);
816                 timer->nmea_data = NULL;
817         }
818
819         setting_ignore_key_changed(VCONFKEY_LOCATION_REPLAY_MODE, replay_mode_changed_cb);
820
821         free(timer);
822         timer = NULL;
823 }
824
825 int gps_plugin_replay_gps_init(gps_event_cb gps_event_cb, void *user_data)
826 {
827         g_gps_event_cb = gps_event_cb;
828         g_replay_timer = gps_plugin_replay_timer_init();
829         g_user_data = user_data;
830
831         return TRUE;
832 }
833
834 int gps_plugin_replay_gps_deinit(gps_failure_reason_t *reason_code)
835 {
836         gps_plugin_replay_timer_deinit(g_replay_timer);
837         g_gps_event_cb = NULL;
838         g_user_data = NULL;
839
840         peripheral_uart_close(uart_hndl);
841         _D("GPS Uart Port Close Successful !!");
842
843         return TRUE;
844 }
845
846 int gps_plugin_replay_gps_request(gps_action_t gps_action, void *gps_action_data, gps_failure_reason_t *reason_code)
847 {
848         gps_action_start_data_t *gps_start_data = gps_action_data;
849
850         switch (gps_action) {
851         case GPS_ACTION_SEND_PARAMS:
852                 break;
853         case GPS_ACTION_START_SESSION:
854                 gps_plugin_start_replay_mode(g_replay_timer);
855                 break;
856         case GPS_ACTION_STOP_SESSION:
857                 gps_plugin_stop_replay_mode(g_replay_timer);
858                 break;
859         case GPS_ACTION_START_BATCH:
860                 if (!gps_start_data->session_status)    /* need to start */
861                         gps_plugin_start_replay_mode(g_replay_timer);
862
863                 gps_plugin_update_batch_mode(g_replay_timer, gps_start_data->interval, gps_start_data->period);
864                 break;
865         case GPS_ACTION_STOP_BATCH:
866                 if (!gps_start_data->session_status)    /* need to stop */
867                         gps_plugin_stop_replay_mode(g_replay_timer);
868
869                 gps_plugin_stop_batch_mode(g_replay_timer, gps_start_data->interval, gps_start_data->period);
870                 break;
871         case GPS_INDI_SUPL_VERIFICATION:
872         case GPS_INDI_SUPL_DNSQUERY:
873         case GPS_ACTION_START_FACTTEST:
874         case GPS_ACTION_STOP_FACTTEST:
875         case GPS_ACTION_REQUEST_SUPL_NI:
876                 LOG_PLUGIN(DBG_LOW, "Don't use action type : [ %d ]", gps_action);
877                 break;
878         default:
879                 break;
880         }
881
882         return TRUE;
883 }
884
885 EXPORT_API const gps_plugin_interface *get_gps_plugin_interface()
886 {
887         return &g_gps_plugin_replay_interface;
888 }