Release Tizen2.0 beta
[framework/location/gps-manager.git] / gps-manager / server.c
1 /*
2  * gps-manager
3  *
4  * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.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 <signal.h>
24 #include <stdlib.h>
25
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <pthread.h>
32 #include <string.h>
33
34 #include "server.h"
35 #include "gps_manager_data_types.h"
36 #include "gps_manager_plugin_intf.h"
37 #include "nmea_logger.h"
38 #include "data_connection.h"
39 #include "setting.h"
40 #include "plugin_module.h"
41 #include "debug_util.h"
42 #include "last_position.h"
43
44 #include <msg.h>
45 #include <msg_transport.h>
46 #include <sysman.h>
47
48 #include <vconf.h>
49 #include <vconf-keys.h>
50 #include <pmapi.h>
51 #include <dlog.h>
52 #include <heynoti.h>
53
54 #include <glib.h>
55 #include <glib-object.h>
56 #if !GLIB_CHECK_VERSION (2, 31, 0)
57 #include <glib/gthread.h>
58 #endif
59 #include <dbus/dbus-glib.h>
60
61 #define GPS_NI_POPUP            "/usr/bin/gps_popup"
62 #define GPS_NI_BTN              "BTN"
63 #define GPS_NI_WITHOUT_BTN      "NONE"
64 #define YES_EXIT_STATUS         174
65 #define NO_EXIT_STATUS          175
66
67 #define REPLAY_MODULE           "replay"
68
69 typedef struct {
70         void *handle;
71         char *name;
72 } gps_plugin_handler_t;
73
74 gps_plugin_handler_t g_gps_plugin;
75 gps_server_param_t g_gps_params;
76
77 pos_data_t *gps_pos_data = NULL;
78 sv_data_t *gps_sv_data = NULL;
79 nmea_data_t *gps_nmea_data = NULL;
80 pos_data_t *gps_last_pos = NULL;
81
82 int g_dnet_used = 0;
83
84 gboolean logging_enabled = FALSE;
85 gboolean replay_enabled = FALSE;
86
87 static pthread_t msg_thread = 0;        /* Register SUPL NI cb to msg server Thread */
88 static pthread_t popup_thread = 0;      /* Register SUPL NI cb to msg server Thread */
89 static int msg_thread_status;
90
91 gps_session_state_t gps_session_state = GPS_SESSION_STOPPED;
92
93 struct gps_callbacks g_update_cb;
94 void *g_user_data;
95
96 static int _gps_server_gps_event_cb(gps_event_info_t * gps_event_info);
97
98 static void _gps_mode_changed_cb(keynode_t * key, void *data)
99 {
100         int int_val;
101
102         if (setting_get_int(VCONFKEY_LOCATION_GPS_SESSION, &int_val) == FALSE) {
103                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_GPS_SESSION setting");
104                 int_val = GPS_SESSION_TRACKING_MODE;
105         }
106         g_gps_params.session_type = int_val;
107
108         if (setting_get_int(VCONFKEY_LOCATION_GPS_OPERATION, &int_val) == FALSE) {
109                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_GPS_OPERATION setting");
110                 int_val = GPS_OPERATION_STANDALONE;
111         }
112         g_gps_params.operation_mode = int_val;
113
114         if (setting_get_int(VCONFKEY_LOCATION_GPS_STARTING, &int_val) == FALSE) {
115                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_GPS_STARTING setting");
116                 int_val = GPS_STARTING_HOT_;
117         }
118         g_gps_params.starting_type = int_val;
119
120         return;
121 }
122
123 static void _gps_supl_changed_cb(keynode_t * key, void *data)
124 {
125         int int_val;
126         char *str;
127
128         str = setting_get_string(VCONFKEY_LOCATION_SUPL_SERVER);
129
130         if (str == NULL) {
131                 snprintf(g_gps_params.supl_url, MAX_SUPL_URL_LEN, "%s", SUPL_SERVER_URL_DEFAULT);
132                 LOG_GPS(DBG_ERR, "vconf fail to get Server URL [Default URL]");
133         } else {
134                 snprintf(g_gps_params.supl_url, MAX_SUPL_URL_LEN, "%s", str);
135         }
136
137         if (setting_get_int(VCONFKEY_LOCATION_SUPL_PORT, &int_val) == FALSE) {
138                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_SUPL_PORT setting");
139                 int_val = SUPL_SERVER_PORT_DEFAULT;
140         }
141         g_gps_params.supl_port = int_val;
142
143         return;
144 }
145
146 static void _gps_setting_changed_cb(keynode_t * key, void *data)
147 {
148         int int_val;
149
150         if (setting_get_int(VCONFKEY_LOCATION_SUPL_SSL, &int_val) == FALSE) {
151                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_SUPL_SSL setting");
152                 int_val = 0;
153         }
154         g_gps_params.ssl_mode = int_val;
155         return;
156 }
157
158 static void _gps_nmea_changed_cb(keynode_t * key, void *data)
159 {
160         int int_val;
161         if (setting_get_int(VCONFKEY_LOCATION_NMEA_LOGGING, &int_val) == FALSE) {
162                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_NMEA_LOGGING setting");
163                 int_val = 0;
164         }
165         logging_enabled = (int_val == 1) ? TRUE : FALSE;
166         return;
167 }
168
169 static gboolean get_replay_enabled()
170 {
171         int int_val;
172         gboolean ret;
173
174         if (setting_get_int(VCONFKEY_LOCATION_REPLAY_ENABLED, &int_val) == FALSE) {
175                 LOG_GPS(DBG_ERR, "//ERROR get VCONFKEY_LOCATION_REPLAY_ENABLED setting");
176                 int_val = 0;
177         }
178
179         ret = (int_val == 1) ? TRUE : FALSE;
180
181         return ret;
182 }
183
184 static void reload_plugin_module()
185 {
186         char *module_name;
187         gps_failure_reason_t ReasonCode = GPS_FAILURE_CAUSE_NORMAL;
188
189         if (replay_enabled == TRUE) {
190                 module_name = REPLAY_MODULE;
191         } else {
192                 module_name = g_gps_plugin.name;
193         }
194
195         LOG_GPS(DBG_LOW, "Loading plugin.name : %s", module_name);
196
197         if (!get_plugin_module()->deinit(&ReasonCode)) {
198                 LOG_GPS(DBG_ERR, "Fail to GPS plugin deinit");
199         } else {
200                 unload_plugin_module(&g_gps_plugin.handle);
201                 if (!load_plugin_module(module_name, &g_gps_plugin.handle)) {
202                         LOG_GPS(DBG_ERR, "Fail to load %s plugin", module_name);
203                 } else {
204                         if (!get_plugin_module()->init(_gps_server_gps_event_cb, &g_gps_params)) {
205                                 LOG_GPS(DBG_ERR, "Fail to %s plugin init", module_name);
206                                 return;
207                         }
208                 }
209         }
210 }
211
212 static void _gps_replay_changed_cb(keynode_t * key, void *data)
213 {
214         replay_enabled = get_replay_enabled();
215         reload_plugin_module();
216
217         return;
218 }
219
220 static void _position_state_changed_cb(keynode_t * key, void *data)
221 {
222         int ret;
223         int gps_state = 0;
224         int wps_state = 0;
225
226         setting_get_int(VCONFKEY_LOCATION_GPS_STATE, &gps_state);
227         setting_get_int(VCONFKEY_LOCATION_WPS_STATE, &wps_state);
228         LOG_GPS(DBG_LOW, "gps state : [%d], wps state : [%d]", gps_state, wps_state);
229
230         if (gps_state == POSITION_CONNECTED || wps_state == POSITION_CONNECTED) {
231                 ret = setting_set_int(VCONFKEY_LOCATION_POSITION_STATE, POSITION_CONNECTED);
232         } else {
233                 if (gps_state == POSITION_OFF && wps_state == POSITION_OFF) {
234                         ret = setting_set_int(VCONFKEY_LOCATION_POSITION_STATE, POSITION_OFF);
235                 } else {
236                         ret = setting_set_int(VCONFKEY_LOCATION_POSITION_STATE, POSITION_SEARCHING);
237                 }
238         }
239
240         return;
241 }
242
243 static void _gps_server_set_gps_state(int gps_state)
244 {
245         int ret;
246
247         switch (gps_state) {
248         case POSITION_CONNECTED:
249                 ret = setting_set_int(VCONFKEY_LOCATION_GPS_STATE, POSITION_CONNECTED);
250                 break;
251         case POSITION_SEARCHING:
252                 ret = setting_set_int(VCONFKEY_LOCATION_GPS_STATE, POSITION_SEARCHING);
253                 break;
254         case POSITION_OFF:
255                 ret = setting_set_int(VCONFKEY_LOCATION_GPS_STATE, POSITION_OFF);
256                 break;
257         default:
258                 ret = setting_set_int(VCONFKEY_LOCATION_GPS_STATE, POSITION_OFF);
259                 break;
260         }
261
262         if (ret == 1) {
263                 LOG_GPS(DBG_LOW, "Succesee to set indicator");
264         } else {
265                 LOG_GPS(DBG_ERR, "Fail to setting_set_int(VCONF_GPS_STATE, ...)");
266         }
267 }
268
269 static gboolean _initialize_data()
270 {
271         gboolean result = TRUE;
272         if (gps_pos_data == NULL) {
273                 gps_pos_data = (pos_data_t *) malloc(sizeof(pos_data_t));
274                 if (gps_pos_data == NULL) {
275                         LOG_GPS(DBG_ERR, "Failed to alloc gps_pos_data");
276                         result = FALSE;
277                 } else {
278                         memset(gps_pos_data, 0x00, sizeof(pos_data_t));
279                 }
280         }
281
282         if (gps_sv_data == NULL) {
283                 gps_sv_data = (sv_data_t *) malloc(sizeof(sv_data_t));
284                 if (gps_sv_data == NULL) {
285                         LOG_GPS(DBG_ERR, "Failed to alloc gps_sv_data");
286                         result = FALSE;
287                 } else {
288                         memset(gps_sv_data, 0x00, sizeof(sv_data_t));
289                 }
290         }
291
292         if (gps_nmea_data == NULL) {
293                 gps_nmea_data = (nmea_data_t *) malloc(sizeof(nmea_data_t));
294                 if (gps_nmea_data == NULL) {
295                         LOG_GPS(DBG_ERR, "Failed to alloc gps_nmea_data");
296                         result = FALSE;
297                 } else {
298                         memset(gps_nmea_data, 0x00, sizeof(nmea_data_t));
299                 }
300         }
301
302         if (gps_last_pos == NULL) {
303                 gps_last_pos = (pos_data_t *) malloc(sizeof(pos_data_t));
304                 if (gps_last_pos == NULL) {
305                         LOG_GPS(DBG_ERR, "Failed to alloc gps_last_pos");
306                         result = FALSE;
307                 } else {
308                         memset(gps_last_pos, 0x00, sizeof(pos_data_t));
309                 }
310         }
311         return result;
312 }
313
314 int request_start_session()
315 {
316         gboolean status = TRUE;
317         gps_failure_reason_t reason_code = GPS_FAILURE_CAUSE_NORMAL;
318
319         if (gps_session_state != GPS_SESSION_STOPPED && gps_session_state != GPS_SESSION_STOPPING) {
320                 LOG_GPS(DBG_LOW, "Main: GPS Session Already Started!");
321                 return TRUE;
322         }
323
324         gps_session_state = GPS_SESSION_STARTING;
325         LOG_GPS(DBG_LOW, "==GPSSessionState[%d]", gps_session_state);
326         status = get_plugin_module()->request(GPS_ACTION_START_SESSION, &g_gps_params, &reason_code);
327
328         if (status == FALSE) {
329                 LOG_GPS(DBG_ERR, "Main: sending GPS_ACTION_START_SESSION Fail !");
330                 return FALSE;
331         }
332
333         LOG_GPS(DBG_LOW, "Main: sending GPS_ACTION_START_SESSION OK !");
334         _initialize_data();
335
336         setting_ignore_key_changed(VCONFKEY_LOCATION_REPLAY_ENABLED, _gps_replay_changed_cb);
337
338         return TRUE;
339 }
340
341 int request_stop_session()
342 {
343         gboolean status = TRUE;
344         gboolean cur_replay_enabled = FALSE;
345         gps_failure_reason_t reason_code = GPS_FAILURE_CAUSE_NORMAL;
346
347         LOG_GPS(DBG_LOW, "Main: Stop GPS Session, ==GPSSessionState[%d]", gps_session_state);
348         if (gps_session_state == GPS_SESSION_STARTED || gps_session_state == GPS_SESSION_STARTING) {
349                 status = get_plugin_module()->request(GPS_ACTION_STOP_SESSION, NULL, &reason_code);
350                 if (status) {
351                         gps_session_state = GPS_SESSION_STOPPING;
352                         LOG_GPS(DBG_LOW, "==GPSSessionState[%d]", gps_session_state);
353                         cur_replay_enabled = get_replay_enabled();
354                         if (replay_enabled != cur_replay_enabled) {
355                                 replay_enabled = cur_replay_enabled;
356                                 reload_plugin_module();
357                         }
358                         setting_notify_key_changed(VCONFKEY_LOCATION_REPLAY_ENABLED, _gps_replay_changed_cb);
359                 } else {
360                         LOG_GPS(DBG_LOW, "  plugin->request to LBS_GPS_STOP_SESSION Failed, reasonCode =%d", reason_code);
361                 }
362         } else {
363                 // If request is not sent, keep the client registed
364                 LOG_GPS(DBG_LOW,
365                         " LBS_GPS_STOP_SESSION is not sent because the GPS state is not started, keep the client registed ");
366         }
367         return status;
368 }
369
370 static void _gps_plugin_handler_init(char *module_name)
371 {
372         g_gps_plugin.handle = NULL;
373         g_gps_plugin.name = (char *)malloc(strlen(module_name) + 1);
374         snprintf(g_gps_plugin.name, strlen(module_name) + 1, "%s", module_name);
375         if (strcmp(REPLAY_MODULE, g_gps_plugin.name) == 0) {
376                 setting_set_int(VCONFKEY_LOCATION_REPLAY_ENABLED, 1);
377         } else {
378                 setting_set_int(VCONFKEY_LOCATION_REPLAY_ENABLED, 0);
379         }
380 }
381
382 static void _gps_plugin_handler_deinit()
383 {
384         setting_set_int(VCONFKEY_LOCATION_REPLAY_ENABLED, 0);
385
386         if (g_gps_plugin.handle != NULL) {
387                 g_gps_plugin.handle = NULL;
388         }
389
390         if (g_gps_plugin.name != NULL) {
391                 free(g_gps_plugin.name);
392                 g_gps_plugin.name = NULL;
393         }
394 }
395
396 static void _gps_read_params()
397 {
398         int int_val = 0;
399         char *str;
400
401         if (setting_get_int(VCONFKEY_LOCATION_GPS_SESSION, &int_val) == FALSE) {
402                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_GPS_SESSION setting");
403                 int_val = GPS_SESSION_TRACKING_MODE;
404         }
405         g_gps_params.session_type = int_val;
406
407         if (setting_get_int(VCONFKEY_LOCATION_GPS_OPERATION, &int_val) == FALSE) {
408                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_GPS_OPERATION setting");
409                 int_val = GPS_OPERATION_STANDALONE;
410         }
411         g_gps_params.operation_mode = int_val;
412
413         if (setting_get_int(VCONFKEY_LOCATION_GPS_STARTING, &int_val) == FALSE) {
414                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_GPS_STATING setting");
415                 int_val = GPS_STARTING_HOT_;
416         }
417         g_gps_params.starting_type = int_val;
418
419         g_gps_params.time_bn_fixes = 1;
420
421         str = setting_get_string(VCONFKEY_LOCATION_SUPL_SERVER);
422         if (str == NULL) {
423                 snprintf(g_gps_params.supl_url, MAX_SUPL_URL_LEN, "%s", SUPL_SERVER_URL_DEFAULT);
424                 LOG_GPS(DBG_ERR, "vconf fail to get Server URL [Default URL]");
425         } else {
426                 snprintf(g_gps_params.supl_url, MAX_SUPL_URL_LEN, "%s", str);
427         }
428
429         if (setting_get_int(VCONFKEY_LOCATION_SUPL_PORT, &int_val) == FALSE) {
430                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_SUPL_PORT setting");
431                 int_val = SUPL_SERVER_PORT_DEFAULT;
432         }
433         g_gps_params.supl_port = int_val;
434
435         LOG_GPS(DBG_LOW, "First Read!! SUPL server:%s, port:%d", g_gps_params.supl_url, g_gps_params.supl_port);
436
437         if (setting_get_int(VCONFKEY_LOCATION_SUPL_SSL, &int_val) == FALSE) {
438                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_SUPL_SSL setting");
439                 int_val = 0;
440         }
441         g_gps_params.ssl_mode = int_val;
442
443         if (setting_get_int(VCONFKEY_LOCATION_NMEA_LOGGING, &int_val) == FALSE) {
444                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_NMEA_LOGGING setting");
445                 int_val = 0;
446         }
447         logging_enabled = (int_val == 1) ? TRUE : FALSE;
448
449         if (setting_get_int(VCONFKEY_LOCATION_REPLAY_ENABLED, &int_val) == FALSE) {
450                 LOG_GPS(DBG_ERR, "//ERROR!! get VCONFKEY_LOCATION_REPLAY_ENABLED setting");
451                 int_val = 0;
452         }
453         replay_enabled = (int_val == 1) ? TRUE : FALSE;
454 }
455
456 static void _gps_notify_params()
457 {
458         setting_notify_key_changed(VCONFKEY_LOCATION_GPS_SESSION, _gps_mode_changed_cb);
459         setting_notify_key_changed(VCONFKEY_LOCATION_GPS_OPERATION, _gps_mode_changed_cb);
460         setting_notify_key_changed(VCONFKEY_LOCATION_GPS_STARTING, _gps_mode_changed_cb);
461         setting_notify_key_changed(VCONFKEY_LOCATION_SUPL_SERVER, _gps_supl_changed_cb);
462         setting_notify_key_changed(VCONFKEY_LOCATION_SUPL_PORT, _gps_supl_changed_cb);
463         setting_notify_key_changed(VCONFKEY_LOCATION_SUPL_SSL, _gps_setting_changed_cb);
464         setting_notify_key_changed(VCONFKEY_LOCATION_NMEA_LOGGING, _gps_nmea_changed_cb);
465         setting_notify_key_changed(VCONFKEY_LOCATION_REPLAY_ENABLED, _gps_replay_changed_cb);
466         setting_notify_key_changed(VCONFKEY_LOCATION_GPS_STATE, _position_state_changed_cb);
467         setting_notify_key_changed(VCONFKEY_LOCATION_WPS_STATE, _position_state_changed_cb);
468 }
469
470 static void _gps_ignore_params()
471 {
472         setting_ignore_key_changed(VCONFKEY_LOCATION_GPS_SESSION, _gps_mode_changed_cb);
473         setting_ignore_key_changed(VCONFKEY_LOCATION_GPS_OPERATION, _gps_mode_changed_cb);
474         setting_ignore_key_changed(VCONFKEY_LOCATION_GPS_STARTING, _gps_mode_changed_cb);
475         setting_ignore_key_changed(VCONFKEY_LOCATION_SUPL_SERVER, _gps_supl_changed_cb);
476         setting_ignore_key_changed(VCONFKEY_LOCATION_SUPL_PORT, _gps_supl_changed_cb);
477         setting_ignore_key_changed(VCONFKEY_LOCATION_SUPL_SSL, _gps_setting_changed_cb);
478         setting_ignore_key_changed(VCONFKEY_LOCATION_NMEA_LOGGING, _gps_nmea_changed_cb);
479         setting_ignore_key_changed(VCONFKEY_LOCATION_REPLAY_ENABLED, _gps_replay_changed_cb);
480         setting_ignore_key_changed(VCONFKEY_LOCATION_GPS_STATE, _position_state_changed_cb);
481         setting_ignore_key_changed(VCONFKEY_LOCATION_WPS_STATE, _position_state_changed_cb);
482 }
483
484 static void _gps_server_start_event()
485 {
486         LOG_GPS(DBG_LOW, "==GPSSessionState [%d] -> [%d]", gps_session_state, GPS_SESSION_STARTED);
487         gps_session_state = GPS_SESSION_STARTED;
488
489         if (logging_enabled) {
490                 LOG_GPS(DBG_LOW, "NMEA STARTED");
491                 start_nmea_log();
492         }
493
494         if (gps_pos_data == NULL) {
495                 gps_pos_data = (pos_data_t *) malloc(sizeof(pos_data_t));
496                 if (gps_pos_data == NULL) {
497                         LOG_GPS(DBG_WARN, "//callback: gps_pos_data re-malloc Failed!!");
498                 } else {
499                         memset(gps_pos_data, 0x00, sizeof(pos_data_t));
500                 }
501         }
502         if (gps_sv_data == NULL) {
503                 gps_sv_data = (sv_data_t *) malloc(sizeof(sv_data_t));
504                 if (gps_sv_data == NULL) {
505                         LOG_GPS(DBG_WARN, "//callback: gps_sv_data re-malloc Failed!!");
506                 } else {
507                         memset(gps_sv_data, 0x00, sizeof(sv_data_t));
508                 }
509         }
510         if (gps_nmea_data == NULL) {
511                 gps_nmea_data = (nmea_data_t *) malloc(sizeof(nmea_data_t));
512                 if (gps_nmea_data == NULL) {
513                         LOG_GPS(DBG_WARN, "//callback: gps_nmea_data re-malloc Failed!!");
514                 } else {
515                         memset(gps_nmea_data, 0x00, sizeof(nmea_data_t));
516                 }
517         }
518
519         if (gps_last_pos == NULL) {
520                 gps_last_pos = (pos_data_t *) malloc(sizeof(pos_data_t));
521                 if (gps_last_pos == NULL) {
522                         LOG_GPS(DBG_WARN, "//callback: gps_last_pos re-malloc Failed!!");
523                 } else {
524                         memset(gps_last_pos, 0x00, sizeof(pos_data_t));
525                         gps_manager_get_last_position(gps_last_pos);
526                 }
527         }
528
529         _gps_server_set_gps_state(POSITION_SEARCHING);
530         pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
531 }
532
533 static void _gps_server_stop_event()
534 {
535         LOG_GPS(DBG_LOW, "==GPSSessionState [%d] -> [%d]", gps_session_state, GPS_SESSION_STOPPED);
536         gps_session_state = GPS_SESSION_STOPPED;
537         LOG_GPS(DBG_LOW, "==GPSSessionState[%d]", gps_session_state);
538
539         _gps_server_set_gps_state(POSITION_OFF);
540         pm_unlock_state(LCD_NORMAL, PM_RESET_TIMER);
541
542         if (logging_enabled) {
543                 LOG_GPS(DBG_LOW, "NMEA STOPPED");
544                 stop_nmea_log();
545         }
546
547         if (gps_pos_data != NULL) {
548                 free(gps_pos_data);
549                 gps_pos_data = NULL;
550         }
551         if (gps_sv_data != NULL) {
552                 free(gps_sv_data);
553                 gps_sv_data = NULL;
554         }
555         if (gps_nmea_data != NULL) {
556                 free(gps_nmea_data);
557                 gps_nmea_data = NULL;
558         }
559         if (gps_last_pos != NULL) {
560                 free(gps_last_pos);
561                 gps_last_pos = NULL;
562         }
563 }
564
565 static void _report_pos_event(gps_event_info_t * gps_event)
566 {
567         if (gps_pos_data != NULL) {
568                 memcpy(gps_pos_data, &(gps_event->event_data.pos_ind.pos), sizeof(pos_data_t));
569                 memcpy(gps_last_pos, gps_pos_data, sizeof(pos_data_t));
570                 g_update_cb.pos_cb(gps_pos_data, gps_event->event_data.pos_ind.error, g_user_data);
571                 gps_manager_set_last_position(gps_last_pos);
572                 memset(gps_pos_data, 0x00, sizeof(pos_data_t));
573         } else {
574                 LOG_GPS(DBG_ERR, "gps_pos_data is NULL");
575         }
576 }
577
578 static void _report_sv_event(gps_event_info_t * gps_event)
579 {
580         if (gps_sv_data != NULL) {
581                 memcpy(gps_sv_data, &(gps_event->event_data.sv_ind.sv), sizeof(sv_data_t));
582                 g_update_cb.sv_cb(gps_sv_data, g_user_data);
583                 memset(gps_sv_data, 0x00, sizeof(sv_data_t));
584         } else {
585                 LOG_GPS(DBG_ERR, "gps_sv_data is NULL");
586         }
587 }
588
589 static void _report_nmea_event(gps_event_info_t * gps_event)
590 {
591         if (gps_nmea_data == NULL) {
592                 LOG_GPS(DBG_ERR, "gps_nmea_data is NULL");
593                 return;
594         }
595
596         gps_nmea_data->len = gps_event->event_data.nmea_ind.nmea.len;
597         LOG_GPS(DBG_LOW, "gps_nmea_data->len : [%d]", gps_nmea_data->len);
598         gps_nmea_data->data = (char *)malloc(gps_nmea_data->len);
599         memset(gps_nmea_data->data, 0x00, gps_nmea_data->len);
600         memcpy(gps_nmea_data->data, gps_event->event_data.nmea_ind.nmea.data, gps_nmea_data->len);
601         g_update_cb.nmea_cb(gps_nmea_data, g_user_data);
602         free(gps_nmea_data->data);
603         memset(gps_nmea_data, 0x00, sizeof(nmea_data_t));
604
605         if (logging_enabled) {
606                 int nmea_len;
607                 char *p_nmea_data;
608                 nmea_len = gps_event->event_data.nmea_ind.nmea.len;
609                 p_nmea_data = gps_event->event_data.nmea_ind.nmea.data;
610                 write_nmea_log(p_nmea_data, nmea_len);
611         }
612 }
613
614 static int _gps_server_open_data_connection()
615 {
616         LOG_GPS(DBG_LOW, "Enter _gps_server_open_data_connection");
617
618         g_dnet_used++;
619
620         if (g_dnet_used > 1) {
621                 LOG_GPS(DBG_LOW, "g_dnet_used : [ %d ]", g_dnet_used);
622                 return TRUE;
623         } else {
624                 LOG_GPS(DBG_LOW, "First open the data connection");
625         }
626
627         unsigned char result;
628
629         result = start_pdp_connection();
630
631         if (result == TRUE) {
632                 LOG_GPS(DBG_LOW, "//Open PDP Conn for SUPL Success.");
633         } else {
634                 LOG_GPS(DBG_ERR, "//Open PDP Conn for SUPL Fail.");
635                 return FALSE;
636         }
637         return TRUE;
638 }
639
640 static int _gps_server_close_data_connection()
641 {
642         LOG_GPS(DBG_LOW, "Enter _gps_server_close_data_connection");
643
644         if (g_dnet_used > 0) {
645                 g_dnet_used--;
646         }
647
648         if (g_dnet_used != 0) {
649                 LOG_GPS(DBG_LOW, "Cannot stop the data connection! [ g_dnet_used : %d ]", g_dnet_used);
650                 return TRUE;
651         } else {
652                 LOG_GPS(DBG_LOW, "Close the data connection");
653         }
654
655         unsigned char result;
656
657         result = stop_pdp_connection();
658         if (result == TRUE) {
659                 LOG_GPS(DBG_LOW, "Close PDP Conn for SUPL Success.");
660         } else {
661                 LOG_GPS(DBG_ERR, "//Close PDP Conn for SUPL Fail.");
662                 return FALSE;
663         }
664
665         return TRUE;
666 }
667
668 static int _gps_server_resolve_dns(char *domain)
669 {
670         LOG_GPS(DBG_LOW, "Enter _gps_server_resolve_dns");
671
672         unsigned char result;
673         gps_failure_reason_t reason_code = GPS_FAILURE_CAUSE_NORMAL;
674         unsigned int ipaddr;
675         int port;
676
677         result = query_dns(domain, &ipaddr, &port);
678         if (result == TRUE) {
679                 LOG_GPS(DBG_LOW, "Success to resolve domain name [ %s ] / ipaddr [ %u ]", domain, ipaddr);
680                 get_plugin_module()->request(GPS_INDI_SUPL_DNSQUERY, (void *)(&ipaddr), &reason_code);
681         } else {
682                 ipaddr = 0;
683                 LOG_GPS(DBG_ERR, "Fail to resolve domain name [ %s ] / ipaddr [ %u ]", domain, ipaddr);
684                 get_plugin_module()->request(GPS_INDI_SUPL_DNSQUERY, (void *)(&ipaddr), &reason_code);
685                 return FALSE;
686         }
687
688         return TRUE;
689 }
690
691 static void _gps_server_send_facttest_result(double snr_data, int prn, unsigned short result)
692 {
693 }
694
695 static int _gps_server_gps_event_cb(gps_event_info_t * gps_event_info)
696 {
697         FUNC_ENTRANCE_SERVER;
698         int result = TRUE;
699         if (gps_event_info == NULL) {
700                 LOG_GPS(DBG_WARN, "//NULL pointer variable passed");
701                 return result;
702         }
703
704         switch (gps_event_info->event_id) {
705         case GPS_EVENT_START_SESSION:
706                 LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_START_SESSION :::::::::::::::");
707                 if (gps_event_info->event_data.start_session_rsp.error == GPS_ERR_NONE) {
708                         _gps_server_start_event();
709                 } else {
710                         LOG_GPS(DBG_ERR, "//Start Session Failed, error : %d",
711                                 gps_event_info->event_data.start_session_rsp.error);
712                 }
713                 break;
714         case GPS_EVENT_SET_OPTION:
715                 {
716                         LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_SET_OPTION :::::::::::::::");
717                         if (gps_event_info->event_data.set_option_rsp.error != GPS_ERR_NONE) {
718                                 LOG_GPS(DBG_ERR, "//Set Option Failed, error : %d",
719                                         gps_event_info->event_data.set_option_rsp.error);
720                         }
721                 }
722                 break;
723
724         case GPS_EVENT_STOP_SESSION:
725                 LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_STOP_SESSION :::::::::::::::");
726                 if (gps_event_info->event_data.stop_session_rsp.error == GPS_ERR_NONE) {
727                         _gps_server_close_data_connection();
728                         _gps_server_stop_event();
729                 } else {
730                         LOG_GPS(DBG_ERR, "//Stop Session Failed, error : %d",
731                                 gps_event_info->event_data.stop_session_rsp.error);
732                 }
733
734                 break;
735         case GPS_EVENT_REPORT_POSITION:
736                 LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_POSITION :::::::::::::::");
737                 if (gps_event_info->event_data.pos_ind.error == GPS_ERR_NONE) {
738                         _report_pos_event(gps_event_info);
739                 } else {
740                         LOG_GPS(DBG_ERR, "GPS_EVENT_POSITION Failed, error : %d", gps_event_info->event_data.pos_ind.error);
741                 }
742                 break;
743         case GPS_EVENT_REPORT_SATELLITE:
744                 LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_SATELLITE :::::::::::::::");
745                 if (gps_event_info->event_data.sv_ind.error == GPS_ERR_NONE) {
746                         if (gps_event_info->event_data.sv_ind.sv.pos_valid) {
747                                 _gps_server_set_gps_state(POSITION_CONNECTED);
748                         } else {
749                                 _gps_server_set_gps_state(POSITION_SEARCHING);
750                         }
751                         _report_sv_event(gps_event_info);
752                 } else {
753                         LOG_GPS(DBG_ERR, "GPS_EVENT_SATELLITE Failed, error : %d", gps_event_info->event_data.sv_ind.error);
754                 }
755                 break;
756         case GPS_EVENT_REPORT_NMEA:
757                 LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_NMEA :::::::::::::::");
758                 if (gps_event_info->event_data.nmea_ind.error == GPS_ERR_NONE) {
759                         _report_nmea_event(gps_event_info);
760                 } else {
761                         LOG_GPS(DBG_ERR, "GPS_EVENT_NMEA Failed, error : %d", gps_event_info->event_data.nmea_ind.error);
762                 }
763                 break;
764         case GPS_EVENT_ERR_CAUSE:
765                 break;
766         case GPS_EVENT_AGPS_VERIFICATION_INDI:
767                 break;
768         case GPS_EVENT_GET_IMSI:
769                 break;
770         case GPS_EVENT_GET_REF_LOCATION:
771                 break;
772         case GPS_EVENT_OPEN_DATA_CONNECTION:
773                 {
774                         LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_OPEN_DATA_CONNECTION :::::::::::::::");
775                         result = _gps_server_open_data_connection();
776                 }
777                 break;
778         case GPS_EVENT_CLOSE_DATA_CONNECTION:
779                 {
780                         LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_CLOSE_DATA_CONNECTION :::::::::::::::");
781                         result = _gps_server_close_data_connection();
782                 }
783                 break;
784         case GPS_EVENT_DNS_LOOKUP_IND:
785                 LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_DNS_LOOKUP_IND :::::::::::::::");
786                 if (gps_event_info->event_data.dns_query_ind.error == GPS_ERR_NONE) {
787                         result = _gps_server_resolve_dns(gps_event_info->event_data.dns_query_ind.domain_name);
788                 } else {
789                         result = FALSE;
790                 }
791                 if (result == TRUE) {
792                         LOG_GPS(DBG_LOW, "Success to get the DNS Query about [ %s ]",
793                                 gps_event_info->event_data.dns_query_ind.domain_name);
794                 }
795                 break;
796         case GPS_EVENT_FACTORY_TEST:
797                 LOG_GPS(DBG_LOW, "<<::::::::::: GPS_EVENT_FACTORY_TEST :::::::::::::::");
798                 if (gps_event_info->event_data.factory_test_rsp.error == GPS_ERR_NONE) {
799                         LOG_GPS(DBG_LOW, "[LBS server] Response Factory test result success");
800                         _gps_server_send_facttest_result(gps_event_info->event_data.factory_test_rsp.snr,
801                                                          gps_event_info->event_data.factory_test_rsp.prn, TRUE);
802                 } else {
803                         LOG_GPS(DBG_ERR, "//[LBS server] Response Factory test result ERROR");
804                         _gps_server_send_facttest_result(gps_event_info->event_data.factory_test_rsp.snr,
805                                                          gps_event_info->event_data.factory_test_rsp.prn, FALSE);
806                 }
807                 break;
808         default:
809                 LOG_GPS(DBG_WARN, "//Error: Isettingalid Event Type %d", gps_event_info->event_id);
810                 break;
811         }
812         return result;
813 }
814
815 static void *_gps_launch_popup(void *data)
816 {
817         gps_ni_popup_data_t *msgData = (gps_ni_popup_data_t *) data;
818
819         int status;
820         char *argv[5];
821         char temp[16];
822         gps_failure_reason_t reason_code;
823
824         // Max size of SMS message is 255
825         // Max size of WAP PUSH is ??????
826         snprintf(temp, sizeof(temp), "%d", msgData->msg_size);
827
828         argv[0] = GPS_NI_POPUP;
829         if (msgData->num_btn == 2)
830                 argv[1] = GPS_NI_BTN;
831         else
832                 argv[1] = GPS_NI_WITHOUT_BTN;
833         argv[2] = temp;
834         argv[3] = msgData->msg_body;
835         argv[4] = NULL;
836
837         if (msgData->num_btn == 2) {
838                 wait(&status);
839                 if (status != YES_EXIT_STATUS && status != NO_EXIT_STATUS)
840                         status = YES_EXIT_STATUS;
841                 status = status / 256;
842         } else {
843                 // Popup application Timer is 2 sec
844                 sleep(2);
845                 status = YES_EXIT_STATUS;
846         }
847
848         status = NO_EXIT_STATUS - status;
849         LOG_GPS(DBG_LOW, "EXIT_STATUS from the LBS Popup is [ %d ]", status);
850
851         agps_supl_ni_info_t info;
852         info.msg_body = (char *)msgData->msg_body;
853         info.msg_size = msgData->msg_size;
854         info.status = status;
855
856         if (!get_plugin_module()->request(GPS_ACTION_REQUEST_SUPL_NI, &info, &reason_code)) {
857                 LOG_GPS(DBG_ERR, "Failed to request SUPL NI (code:%d)", reason_code);
858         }
859
860         return NULL;
861
862 }
863
864 static void _gps_supl_networkinit_smscb(msg_handle_t hMsgHandle, msg_struct_t msg, void *user_param)
865 {
866         LOG_GPS(DBG_ERR, "_gps_supl_networkinit_smscb is called");
867
868         gps_ni_popup_data_t new_message;
869         memset(&new_message, 0x00, sizeof(new_message));
870
871         msg_get_int_value(msg, MSG_MESSAGE_DATA_SIZE_INT, &new_message.msg_size);
872         msg_get_str_value(msg, MSG_MESSAGE_SMS_DATA_STR, new_message.msg_body, new_message.msg_size);
873         
874         // TODO: Button number of LBS Popup
875         new_message.num_btn = 2;
876
877         pthread_attr_t attr;
878         pthread_attr_init(&attr);
879         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
880
881         if (pthread_create(&popup_thread, &attr, _gps_launch_popup, &new_message) != 0) {
882                 LOG_GPS(DBG_WARN, "Can not make pthread......");
883         }
884
885 }
886
887 static void _gps_supl_networkinit_wappushcb(msg_handle_t hMsgHandle, const char *pPushHeader, const char *pPushBody,
888                                             int pushBodyLen, void *user_param)
889 {
890         LOG_GPS(DBG_ERR, "_gps_supl_networkinit_wappushcb is called");
891         LOG_GPS(DBG_ERR, "SUPLNI WAPPush MSG size is [ %d ]", pushBodyLen);
892
893         gps_ni_popup_data_t new_message;
894         memset(&new_message, 0x00, sizeof(new_message));
895
896         new_message.msg_body = (char *)pPushBody;
897         new_message.msg_size = pushBodyLen;
898         // TODO: Button number of LBS Popup
899         new_message.num_btn = 2;
900
901         pthread_attr_t attr;
902         pthread_attr_init(&attr);
903         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
904
905         if (pthread_create(&popup_thread, &attr, _gps_launch_popup, &new_message) != 0) {
906                 LOG_GPS(DBG_WARN, "Can not make pthread......");
907         }
908
909 }
910
911 static void *_gps_register_msgfwcb()
912 {
913         msg_handle_t msgHandle = NULL;
914         msg_error_t err = MSG_SUCCESS;
915
916         int setValue = 0;
917         int ret;
918
919         int cnt = 60;
920
921         while (cnt > 0) {
922                 ret = vconf_get_bool(VCONFKEY_MSG_SERVER_READY, &setValue);
923
924                 if (ret == -1) {
925                         LOG_GPS(DBG_WARN, "Fail to get VCONFKEY_MSG_SERVER_READY");
926                         return NULL;
927                 }
928
929                 if (setValue) {
930                         LOG_GPS(DBG_LOW, "MSG server is READY!!");
931                         cnt = -1;
932                 } else {
933                         sleep(5);
934                         cnt--;
935                         if (cnt == 0) {
936                                 LOG_GPS(DBG_WARN, "Never connect to MSG Server for 300 secs.");
937                                 return NULL;
938                         }
939                 }
940         }
941
942         err = msg_open_msg_handle(&msgHandle);
943
944         if (err != MSG_SUCCESS) {
945                 LOG_GPS(DBG_WARN, "Fail to MsgOpenMsgHandle. Error type = [ %d ]", err);
946                 return NULL;
947         }
948
949         err = msg_reg_sms_message_callback(msgHandle, &_gps_supl_networkinit_smscb, 7275, NULL);
950
951         if (err != MSG_SUCCESS) {
952                 LOG_GPS(DBG_WARN, "Fail to MsgRegSmsMessageCallback. Error type = [ %d ]", err);
953                 return NULL;
954         }
955
956         err = msg_reg_lbs_message_callback(msgHandle, &_gps_supl_networkinit_wappushcb, NULL);
957
958         if (err != MSG_SUCCESS) {
959                 LOG_GPS(DBG_WARN, "Fail to MsgRegLBSMessageCallback. Error type = [ %d ]", err);
960                 return NULL;
961         }
962
963         LOG_GPS(DBG_LOW, "Success to lbs_register_msgfwcb");
964         return NULL;
965
966 }
967
968 static void _gps_hibernation_enter_callback(void *data)
969 {
970         LOG_GPS(DBG_LOW, "Enter the _gps_hibernation_enter_callback");
971
972         if (msg_thread != 0) {
973                 pthread_cancel(msg_thread);
974
975                 pthread_join(msg_thread, (void *)&msg_thread_status);
976                 msg_thread = 0;
977         }
978 }
979
980 static void _gps_hibernation_leave_callback(void *data)
981 {
982         LOG_GPS(DBG_LOW, "Enter the _gps_hibernation_leave_callback");
983
984         if (msg_thread != 0) {
985                 pthread_cancel(msg_thread);
986
987                 pthread_join(msg_thread, (void *)&msg_thread_status);
988                 msg_thread = 0;
989         }
990         if (pthread_create(&msg_thread, NULL, _gps_register_msgfwcb, NULL) != 0) {
991                 LOG_GPS(DBG_WARN, "Can not make pthread......");
992         }
993 }
994
995 static void _print_help()
996 {
997         printf("Usage: gps-manager [OPTION] [NAME]\n"
998                " -h         Help\n"
999                " -l [NAME]  Load a specific plugin module\n");
1000         exit(0);
1001 }
1002
1003 static int _parse_argument(const int argc, char **argv, const int buffer_size, char *out_buffer)
1004 {
1005         int opt;
1006
1007         memset(out_buffer, 0x00, buffer_size);
1008         while ((opt = getopt(argc, argv, "hl:")) != -1) {
1009                 switch (opt) {
1010                 case 'l':
1011                         snprintf(out_buffer, buffer_size, "%s", optarg);
1012                         break;
1013                 case 'h':
1014                 default:
1015                         _print_help();
1016                         break;
1017                 }
1018         }
1019
1020         return 0;
1021 }
1022
1023 int initialize_server(int argc, char **argv)
1024 {
1025         char module_name[16];
1026
1027         _parse_argument(argc, argv, sizeof(module_name), module_name);
1028
1029         FUNC_ENTRANCE_SERVER;
1030
1031         _gps_plugin_handler_init(module_name);
1032         _gps_read_params();
1033         _gps_notify_params();
1034
1035         if (!load_plugin_module(g_gps_plugin.name, &g_gps_plugin.handle)) {
1036                 LOG_GPS(DBG_ERR, "Fail to load plugin module.");
1037                 return -1;
1038         }
1039
1040         if (!get_plugin_module()->init(_gps_server_gps_event_cb, &g_gps_params)) {
1041                 LOG_GPS(DBG_WARN, "Fail to gps-manager module initialization");
1042                 return -1;
1043         }
1044
1045         // Register SUPL NI cb to MSG server
1046         if (pthread_create(&msg_thread, NULL, _gps_register_msgfwcb, NULL) != 0) {
1047                 LOG_GPS(DBG_WARN, "Can not make pthread......");
1048         }
1049         // Register Hibernation cb to re-connect msg-server
1050         int notifd;
1051         notifd = heynoti_init();
1052         heynoti_subscribe(notifd, "HIBERNATION_ENTER", _gps_hibernation_enter_callback, NULL);
1053         heynoti_subscribe(notifd, "HIBERNATION_LEAVE", _gps_hibernation_leave_callback, NULL);
1054         heynoti_attach_handler(notifd);
1055
1056         LOG_GPS(DBG_LOW, "Initialization is completed.");
1057
1058         return 0;
1059 }
1060
1061 int deinitialize_server()
1062 {
1063         gps_failure_reason_t ReasonCode = GPS_FAILURE_CAUSE_NORMAL;
1064
1065         // Wait termination of msg thread
1066         pthread_join(msg_thread, (void *)&msg_thread_status);
1067
1068         _gps_ignore_params();
1069
1070         if (!get_plugin_module()->deinit(&ReasonCode)) {
1071                 LOG_GPS(DBG_WARN, "Fail to gps-manager module de-initialization");
1072         }
1073         unload_plugin_module(g_gps_plugin.handle);
1074
1075         _gps_plugin_handler_deinit();
1076
1077         return 0;
1078 }
1079
1080 int register_update_callbacks(struct gps_callbacks *gps_callback, void *user_data)
1081 {
1082         g_update_cb = *gps_callback;
1083         g_user_data = user_data;
1084         return 0;
1085 }