removed wrong contact points & added two authors
[platform/core/location/lbs-server.git] / module / passive_module.c
1 /*
2  * lbs-server
3  *
4  * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <glib.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <vconf.h>
25 #include <vconf-internal-location-keys.h>
26 #include <location-module.h>
27
28 #include <dlfcn.h>
29 #include <lbs_dbus_client.h>
30 #include <lbs_agps.h>
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "log.h"
37
38 #define MAX_GPS_LOC_ITEM        7
39 #define MAX_NPS_LOC_ITEM        6
40 #define UNNECESSARY_INTERVAL 1
41 #define LBS_FUSED_STATUS_NONE           0
42
43 typedef struct {
44         lbs_client_dbus_h lbs_client;
45         LocModPositionExtCB pos_cb;
46         LocModSatelliteCB sat_cb;
47         gpointer userdata;
48 } ModPassiveData;
49
50 static void satellite_callback(GVariant *param, void *user_data)
51 {
52         ModPassiveData *module = (ModPassiveData *)user_data;
53         g_return_if_fail(module);
54         g_return_if_fail(module->sat_cb);
55
56         guint idx;
57         guint used_idx;
58         guint *used_prn_array = NULL;
59         gboolean ret = FALSE;
60         int timestamp = 0, satellite_used = 0, satellite_visible = 0;
61
62         LocationSatellite *sat = NULL;
63         GVariant *used_prn = NULL;
64         GVariantIter *used_prn_iter = NULL;
65         GVariant *sat_info = NULL;
66         GVariantIter *sat_iter = NULL;
67         int prn = 0, elev = 0, azim = 0, snr = 0;
68
69         g_variant_get(param, "(iii@ai@a(iiii))", &timestamp, &satellite_used, &satellite_visible, &used_prn, &sat_info);
70         g_variant_get(used_prn, "ai", &used_prn_iter);
71         g_variant_get(sat_info, "a(iiii)", &sat_iter);
72         MOD_LOGD("timestamp [%d], satellite_used [%d], satellite_visible[%d]", timestamp, satellite_used, satellite_visible);
73         int tmp_prn = 0;
74         int num_of_used_prn = g_variant_iter_n_children(used_prn_iter);
75         if (num_of_used_prn > 0) {
76                 used_prn_array = (guint *)g_new0(guint, num_of_used_prn);
77                 g_return_if_fail(used_prn_array);
78                 for (idx = 0; idx < num_of_used_prn; idx++) {
79                         ret = g_variant_iter_next(used_prn_iter, "i", &tmp_prn);
80                         if (ret == FALSE)
81                                 break;
82                         used_prn_array[idx] = tmp_prn;
83                 }
84         }
85         sat = location_satellite_new(satellite_visible);
86
87         sat->timestamp = timestamp;
88         sat->num_of_sat_inview = satellite_visible;
89         sat->num_of_sat_used = satellite_used;
90
91         GVariant *tmp_var = NULL;
92         for (idx = 0; idx < satellite_visible; idx++) {
93                 gboolean used = FALSE;
94                 tmp_var = g_variant_iter_next_value(sat_iter);
95                 g_variant_get(tmp_var, "(iiii)", &prn, &elev, &azim, &snr);
96                 if (used_prn_array != NULL) {
97                         for (used_idx = 0; used_idx < satellite_used; used_idx++) {
98                                 if (prn == used_prn_array[used_idx]) {
99                                         used = TRUE;
100                                         break;
101                                 }
102                         }
103                 }
104                 location_satellite_set_satellite_details(sat, idx, prn, used, elev, azim, snr);
105                 g_variant_unref(tmp_var);
106         }
107
108         module->sat_cb(TRUE, sat, module->userdata);
109         location_satellite_free(sat);
110         g_variant_iter_free(used_prn_iter);
111         g_variant_iter_free(sat_iter);
112         g_variant_unref(used_prn);
113         g_variant_unref(sat_info);
114
115         if (used_prn_array) {
116                 g_free(used_prn_array);
117                 used_prn_array = NULL;
118         }
119 }
120
121 static void position_callback(GVariant *param, void *user_data)
122 {
123         ModPassiveData *module = (ModPassiveData *)user_data;
124         g_return_if_fail(module);
125         g_return_if_fail(module->pos_cb);
126
127         int method = 0, fields = 0 , timestamp = 0 , level = 0;
128         double latitude = 0.0, longitude = 0.0, altitude = 0.0, speed = 0.0, direction = 0.0, climb = 0.0, horizontal = 0.0, vertical = 0.0;
129         GVariant *accuracy = NULL;
130
131         g_variant_get(param, "(iiidddddd@(idd))", &method, &fields, &timestamp, &latitude, &longitude, &altitude, &speed, &direction, &climb, &accuracy);
132         g_variant_get(accuracy, "(idd)", &level, &horizontal, &vertical);
133
134         LocationPosition *pos = NULL;
135         LocationVelocity *vel = NULL;
136         LocationAccuracy *acc = NULL;
137
138         pos = location_position_new(timestamp, latitude, longitude, altitude, LOCATION_STATUS_3D_FIX);
139         vel = location_velocity_new(timestamp, speed, direction, climb);
140         acc = location_accuracy_new(LOCATION_ACCURACY_LEVEL_DETAILED, horizontal, vertical);
141
142         module->pos_cb(TRUE, pos, vel, acc, module->userdata);
143
144         location_position_free(pos);
145         location_velocity_free(vel);
146         location_accuracy_free(acc);
147         g_variant_unref(accuracy);
148 }
149
150 static void on_signal_callback(const gchar *sig, GVariant *param, gpointer user_data)
151 {
152         if (!g_strcmp0(sig, "SatelliteChanged"))
153                 satellite_callback(param, user_data);
154         else if (!g_strcmp0(sig, "PositionChanged"))
155                 position_callback(param, user_data);
156         else
157                 MOD_LOGD("Invaild signal[%s]", sig);
158 }
159
160 static int start(gpointer handle, guint pos_update_interval, LocModStatusCB status_cb, LocModPositionExtCB pos_cb, LocModSatelliteCB sat_cb, gpointer userdata)
161 {
162         MOD_LOGD("start");
163         ModPassiveData *module = (ModPassiveData *) handle;
164         g_return_val_if_fail(module, LOCATION_ERROR_NOT_AVAILABLE);
165         g_return_val_if_fail(pos_cb, LOCATION_ERROR_NOT_AVAILABLE);
166
167         module->pos_cb = pos_cb;
168         module->sat_cb = sat_cb;
169         module->userdata = userdata;
170
171         int ret = LBS_CLIENT_ERROR_NONE;
172         ret = lbs_client_create(LBS_CLIENT_METHOD_PASSIVE , &(module->lbs_client));
173         if (ret != LBS_CLIENT_ERROR_NONE || !module->lbs_client) {
174                 MOD_LOGE("Fail to create lbs_client_h. Error[%d]", ret);
175                 return LOCATION_ERROR_NOT_AVAILABLE;
176         }
177         MOD_LOGD("fused handle(%p) pos_cb(%p) user_data(%p)", module, module->pos_cb, module->userdata);
178
179         ret = lbs_client_start(module->lbs_client, UNNECESSARY_INTERVAL, LBS_CLIENT_LOCATION_CB | LBS_CLIENT_SATELLITE_CB, on_signal_callback, LBS_FUSED_STATUS_NONE, module);
180         if (ret != LBS_CLIENT_ERROR_NONE) {
181                 if (ret == LBS_CLIENT_ERROR_ACCESS_DENIED) {
182                         MOD_LOGE("Access denied[%d]", ret);
183                         return LOCATION_ERROR_NOT_ALLOWED;
184                 }
185                 MOD_LOGE("Fail to start lbs_client_h. Error[%d]", ret);
186                 lbs_client_destroy(module->lbs_client);
187                 module->lbs_client = NULL;
188
189                 return LOCATION_ERROR_NOT_AVAILABLE;
190         }
191
192         return LOCATION_ERROR_NONE;
193 }
194
195 static int stop(gpointer handle)
196 {
197         MOD_LOGD("stop");
198         ModPassiveData *module = (ModPassiveData *) handle;
199         g_return_val_if_fail(module, LOCATION_ERROR_NOT_AVAILABLE);
200         g_return_val_if_fail(module->lbs_client, LOCATION_ERROR_NOT_AVAILABLE);
201
202         int ret = LBS_CLIENT_ERROR_NONE;
203
204         ret = lbs_client_stop(module->lbs_client, UNNECESSARY_INTERVAL, LBS_FUSED_STATUS_NONE);
205         MOD_LOGE("stop gps interval [%d]", UNNECESSARY_INTERVAL);
206         if (ret != LBS_CLIENT_ERROR_NONE) {
207                 MOD_LOGE("Fail to stop. Error[%d]", ret);
208                 lbs_client_destroy(module->lbs_client);
209                 module->lbs_client = NULL;
210                 return LOCATION_ERROR_NOT_AVAILABLE;
211         }
212
213         ret = lbs_client_destroy(module->lbs_client);
214         if (ret != LBS_CLIENT_ERROR_NONE) {
215                 MOD_LOGE("Fail to destroy. Error[%d]", ret);
216                 return LOCATION_ERROR_NOT_AVAILABLE;
217         }
218         module->lbs_client = NULL;
219
220         module->pos_cb = NULL;
221         module->sat_cb = NULL;
222
223         return LOCATION_ERROR_NONE;
224 }
225
226 static int get_last_position(gpointer handle, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy)
227 {
228         MOD_LOGD("get_last_position");
229         ModPassiveData *module = (ModPassiveData *) handle;
230         g_return_val_if_fail(module, LOCATION_ERROR_NOT_AVAILABLE);
231         g_return_val_if_fail(position, LOCATION_ERROR_PARAMETER);
232         g_return_val_if_fail(velocity, LOCATION_ERROR_PARAMETER);
233         g_return_val_if_fail(accuracy, LOCATION_ERROR_PARAMETER);
234
235         int timestamp = 0;
236         char location[128] = {0,};
237         char *last_location[MAX_GPS_LOC_ITEM] = {0,};
238         char *last = NULL;
239         char *str = NULL;
240         double longitude = 0.0, latitude = 0.0, altitude = 0.0;
241         double speed = 0.0, direction = 0.0;
242         double hor_accuracy = 0.0, ver_accuracy = 0.0;
243         int index = 0;
244         LocationStatus status = LOCATION_STATUS_NO_FIX;
245         LocationAccuracyLevel level = LOCATION_ACCURACY_LEVEL_NONE;
246
247         *position = NULL;
248         *velocity = NULL;
249         *accuracy = NULL;
250
251         if (vconf_get_int(VCONFKEY_LOCATION_LAST_GPS_TIMESTAMP, &timestamp)) {
252                 MOD_LOGD("Error to get VCONFKEY_LOCATION_LAST_GPS_TIMESTAMP");
253                 return LOCATION_ERROR_NOT_AVAILABLE;
254         } else {
255                 if (timestamp != 0) {
256                         if (vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_LATITUDE, &latitude) ||
257                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_LONGITUDE, &longitude) ||
258                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_ALTITUDE, &altitude) ||
259                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_SPEED, &speed) ||
260                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_DIRECTION, &direction) ||
261                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_HOR_ACCURACY, &hor_accuracy) ||
262                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_VER_ACCURACY, &ver_accuracy)) {
263                                 return LOCATION_ERROR_NOT_AVAILABLE;
264                         }
265                 } else {
266                         if (vconf_get_int(VCONFKEY_LOCATION_NV_LAST_GPS_TIMESTAMP, &timestamp))
267                                 return LOCATION_ERROR_NOT_AVAILABLE;
268
269                         str = vconf_get_str(VCONFKEY_LOCATION_NV_LAST_GPS_LOCATION);
270                         if (str == NULL)
271                                 return LOCATION_ERROR_NOT_AVAILABLE;
272
273                         snprintf(location, sizeof(location), "%s", str);
274                         free(str);
275
276                         index = 0;
277                         last_location[index] = (char *)strtok_r(location, ";", &last);
278                         while (last_location[index] != NULL) {
279                                 switch (index) {
280                                 case 0:
281                                         latitude = strtod(last_location[index], NULL);
282                                         break;
283                                 case 1:
284                                         longitude = strtod(last_location[index], NULL);
285                                         break;
286                                 case 2:
287                                         altitude = strtod(last_location[index], NULL);
288                                         break;
289                                 case 3:
290                                         speed = strtod(last_location[index], NULL);
291                                         break;
292                                 case 4:
293                                         direction = strtod(last_location[index], NULL);
294                                         break;
295                                 case 5:
296                                         hor_accuracy = strtod(last_location[index], NULL);
297                                         break;
298                                 case 6:
299                                         ver_accuracy = strtod(last_location[index], NULL);
300                                         break;
301                                 default:
302                                         break;
303                                 }
304                                 if (++index == MAX_GPS_LOC_ITEM) break;
305                                 last_location[index] = (char *)strtok_r(NULL, ";", &last);
306                         }
307                 }
308         }
309
310         if (timestamp)
311                 status = LOCATION_STATUS_3D_FIX;
312         else
313                 return LOCATION_ERROR_NOT_AVAILABLE;
314
315         level = LOCATION_ACCURACY_LEVEL_DETAILED;
316         *position = location_position_new(timestamp, latitude, longitude, altitude, status);
317         *velocity = location_velocity_new((guint) timestamp, speed, direction, 0.0);
318         *accuracy = location_accuracy_new(level, hor_accuracy, ver_accuracy);
319
320         return LOCATION_ERROR_NONE;
321 }
322
323 static int get_last_wps_position(gpointer handle, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy)
324 {
325         MOD_LOGD("get_last_wps_position");
326         ModPassiveData *module = (ModPassiveData *) handle;
327         g_return_val_if_fail(module, LOCATION_ERROR_NOT_AVAILABLE);
328         g_return_val_if_fail(position, LOCATION_ERROR_PARAMETER);
329         g_return_val_if_fail(velocity, LOCATION_ERROR_PARAMETER);
330         g_return_val_if_fail(accuracy, LOCATION_ERROR_PARAMETER);
331
332         int timestamp = 0;
333         char location[128] = {0,};
334         char *last_location[MAX_NPS_LOC_ITEM] = {0,};
335         char *last = NULL;
336         char *str = NULL;
337         double latitude = 0.0, longitude = 0.0, altitude = 0.0;
338         double speed = 0.0, direction = 0.0;
339         double hor_accuracy = 0.0;
340         int index = 0;
341         LocationStatus status = LOCATION_STATUS_NO_FIX;
342         LocationAccuracyLevel level = LOCATION_ACCURACY_LEVEL_NONE;
343
344         *position = NULL;
345         *velocity = NULL;
346         *accuracy = NULL;
347
348         if (vconf_get_int(VCONFKEY_LOCATION_LAST_WPS_TIMESTAMP, &timestamp)) {
349                 MOD_LOGD("Error to get VCONFKEY_LOCATION_LAST_WPS_TIMESTAMP");
350                 return LOCATION_ERROR_NOT_AVAILABLE;
351         } else {
352                 if (timestamp != 0) {
353                         if (vconf_get_int(VCONFKEY_LOCATION_LAST_WPS_TIMESTAMP, &timestamp) ||
354                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_WPS_LATITUDE, &latitude) ||
355                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_WPS_LONGITUDE, &longitude) ||
356                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_WPS_ALTITUDE, &altitude) ||
357                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_WPS_SPEED, &speed) ||
358                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_WPS_DIRECTION, &direction) ||
359                                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_WPS_HOR_ACCURACY, &hor_accuracy)) {
360                                 return LOCATION_ERROR_NOT_AVAILABLE;
361                         }
362                 } else {
363                         if (vconf_get_int(VCONFKEY_LOCATION_NV_LAST_WPS_TIMESTAMP, &timestamp)) {
364                                 MOD_LOGD("Last timestamp failed");
365                                 return LOCATION_ERROR_NOT_AVAILABLE;
366                         }
367                         str = vconf_get_str(VCONFKEY_LOCATION_NV_LAST_WPS_LOCATION);
368                         if (str == NULL) {
369                                 MOD_LOGD("Last wps is null");
370                                 return LOCATION_ERROR_NOT_AVAILABLE;
371                         }
372                         snprintf(location, sizeof(location), "%s", str);
373                         free(str);
374
375                         index = 0;
376                         last_location[index] = (char *)strtok_r(location, ";", &last);
377                         while (last_location[index] != NULL) {
378                                 switch (index) {
379                                 case 0:
380                                         latitude = strtod(last_location[index], NULL);
381                                         break;
382                                 case 1:
383                                         longitude = strtod(last_location[index], NULL);
384                                         break;
385                                 case 2:
386                                         altitude = strtod(last_location[index], NULL);
387                                         break;
388                                 case 3:
389                                         speed = strtod(last_location[index], NULL);
390                                         break;
391                                 case 4:
392                                         direction = strtod(last_location[index], NULL);
393                                         break;
394                                 case 5:
395                                         hor_accuracy = strtod(last_location[index], NULL);
396                                         break;
397                                 default:
398                                         break;
399                                 }
400                                 if (++index == MAX_NPS_LOC_ITEM) break;
401                                 last_location[index] = (char *)strtok_r(NULL, ";", &last);
402                         }
403                 }
404         }
405
406         if (timestamp)
407                 status = LOCATION_STATUS_3D_FIX;
408         else
409                 return LOCATION_ERROR_NOT_AVAILABLE;
410
411         level = LOCATION_ACCURACY_LEVEL_STREET;
412         *position = location_position_new((guint) timestamp, latitude, longitude, altitude, status);
413         *velocity = location_velocity_new((guint) timestamp, speed, direction, 0.0);
414         *accuracy = location_accuracy_new(level, hor_accuracy, -1.0);
415
416         return LOCATION_ERROR_NONE;
417 }
418
419 LOCATION_MODULE_API gpointer init(LocModPassiveOps *ops)
420 {
421         MOD_LOGD("init");
422
423         g_return_val_if_fail(ops, NULL);
424         ops->start = start;
425         ops->stop = stop;
426         ops->get_last_position = get_last_position;
427         ops->get_last_wps_position = get_last_wps_position;
428
429         ModPassiveData *module = g_new0(ModPassiveData, 1);
430         g_return_val_if_fail(module, NULL);
431
432         module->pos_cb = NULL;
433         module->sat_cb = NULL;
434         module->userdata = NULL;
435
436         return (gpointer) module;
437 }
438
439 LOCATION_MODULE_API void shutdown(gpointer handle)
440 {
441         MOD_LOGD("shutdown");
442         g_return_if_fail(handle);
443         ModPassiveData *module = (ModPassiveData *) handle;
444
445         if (module->lbs_client) {
446                 lbs_client_stop(module->lbs_client, UNNECESSARY_INTERVAL, LBS_FUSED_STATUS_NONE);
447                 lbs_client_destroy(module->lbs_client);
448                 module->lbs_client = NULL;
449         }
450
451         module->pos_cb = NULL;
452         module->sat_cb = NULL;
453
454         g_free(module);
455         module = NULL;
456 }