Make gps-manager build against Tizen generic
[platform/core/location/gps-manager.git] / module / module_gps_manager.c
1 /*
2  * gps-manager
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 <glib.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
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "log.h"
37
38 typedef struct {
39         char devname[256];
40         lbs_client_dbus_h lbs_client;
41         LocModStatusCB status_cb;
42         LocModPositionExtCB pos_cb;
43         LocModSatelliteCB sat_cb;
44         gpointer userdata;
45         gboolean is_started;
46 } GpsManagerData;
47
48 #define GPS_MANAGER_SERVICE_NAME        "org.tizen.lbs.Providers.GpsManager"
49 #define GPS_MANAGER_SERVICE_PATH        "/org/tizen/lbs/Providers/GpsManager"
50
51 #define MPS_TO_KMPH     3.6     // 1 m/s = 3.6 km/h
52
53 static void status_callback(GVariant *param, void *user_data)
54 {
55         GpsManagerData *gps_manager = (GpsManagerData *) user_data;
56         g_return_if_fail(param);
57         g_return_if_fail(gps_manager);
58         g_return_if_fail(gps_manager->status_cb);
59
60         int status = 0;
61
62         g_variant_get (param, "(i)", &status);
63
64         if (status == 3) {      //TODO:  LBS_STATUS_AVAILABLE ?
65                 MOD_LOGD("LBS_STATUS_AVAILABLE");
66                 gps_manager->status_cb(TRUE, LOCATION_STATUS_3D_FIX, gps_manager->userdata);
67         }
68         else {
69                 MOD_LOGD("LBS_STATUS_ACQUIRING/ERROR/UNAVAILABLE. Status[%d]", status);
70                 gps_manager->status_cb(FALSE, LOCATION_STATUS_NO_FIX, gps_manager->userdata);
71         }
72 }
73
74 static void satellite_callback(GVariant *param, void *user_data)
75 {
76         GpsManagerData *gps_manager = (GpsManagerData *)user_data;
77         g_return_if_fail(gps_manager);
78         g_return_if_fail(gps_manager->sat_cb);
79
80         guint idx;
81         guint used_idx;
82         guint *used_prn_array = NULL;
83         gboolean ret = FALSE;
84         int timestamp = 0, satellite_used = 0, satellite_visible = 0;
85
86         LocationSatellite *sat = NULL;
87         GVariant *used_prn = NULL;
88         GVariantIter *used_prn_iter = NULL;
89         GVariant *sat_info = NULL;
90         GVariantIter *sat_iter = NULL;
91         int prn = 0, elev = 0, azim = 0, snr = 0;
92
93         g_variant_get(param, "(iii@ai@a(iiii))", &timestamp, &satellite_used, &satellite_visible, &used_prn, &sat_info);
94         g_variant_get(used_prn, "ai", &used_prn_iter);
95         g_variant_get(sat_info, "a(iiii)", &sat_iter);
96         MOD_LOGD("timestamp [%d], satellite_used [%d], satellite_visible[%d]", timestamp, satellite_used, satellite_visible);
97         int tmp_prn = 0;
98         int num_of_used_prn = g_variant_iter_n_children (used_prn_iter);
99         if (num_of_used_prn > 0) {
100                 used_prn_array = (guint *)g_new0(guint, num_of_used_prn);
101                 for (idx = 0; idx < num_of_used_prn; idx++) {
102                         ret = g_variant_iter_next(used_prn_iter, "i", &tmp_prn);
103                         if (ret == FALSE)
104                                 break;
105                         used_prn_array[idx] = tmp_prn;
106                 }
107         }
108
109         sat = location_satellite_new(satellite_visible);
110
111         sat->timestamp = timestamp;
112         sat->num_of_sat_inview = satellite_visible;
113         sat->num_of_sat_used = satellite_used;
114
115         GVariant *tmp_var = NULL;
116         for (idx = 0; idx < satellite_visible; idx++) {
117                 gboolean used = FALSE;
118                 tmp_var = g_variant_iter_next_value (sat_iter);
119                 g_variant_get (tmp_var, "(iiii)",  &prn, &elev, &azim, &snr);
120                 if (used_prn_array != NULL) {
121                         for (used_idx = 0; used_idx < satellite_used; used_idx++) {
122                                 if (prn == used_prn_array[used_idx]) {
123                                         used = TRUE;
124                                         break;
125                                 }
126                         }
127                 }
128                 MOD_LOGD("prn[%d] : used %d elev %d azim %d snr %d", prn, used, elev, azim, snr);
129                 location_satellite_set_satellite_details(sat, idx, prn, used, elev, azim, snr);
130         }
131
132         gps_manager->sat_cb(TRUE, sat, gps_manager->userdata);
133         location_satellite_free(sat);
134
135         if (used_prn_array) {
136                 g_free(used_prn_array);
137                 used_prn_array = NULL;
138         }
139 }
140
141 #if 0
142 static void nmea_callback(GeoclueNmea * nmea, int timestamp, char *data, gpointer userdata)
143 {
144 }
145 #endif
146
147 static void position_callback(GVariant *param, void *user_data)
148 {
149         MOD_LOGD("position_callback");
150         GpsManagerData *gps_manager = (GpsManagerData *)user_data;
151         g_return_if_fail(gps_manager);
152         g_return_if_fail(gps_manager->pos_cb);
153
154         int fields = 0 ,timestamp = 0 , level = 0;
155         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;
156         GVariant *accuracy = NULL;
157
158         g_variant_get(param, "(iidddddd@(idd))", &fields, &timestamp, &latitude, &longitude, &altitude, &speed, &direction, &climb, &accuracy);
159         g_variant_get(accuracy, "(idd)", &level, &horizontal, &vertical);
160
161         LocationPosition *pos = NULL;
162         LocationVelocity *vel = NULL;
163         LocationAccuracy *acc = NULL;
164
165         if (altitude) {
166                 pos = location_position_new(timestamp, latitude, longitude, altitude, LOCATION_STATUS_3D_FIX);
167         } else {
168                 pos = location_position_new(timestamp, latitude, longitude, 0.0, LOCATION_STATUS_2D_FIX);
169         }
170
171         vel = location_velocity_new(timestamp, speed, direction, climb);
172
173         acc = location_accuracy_new(LOCATION_ACCURACY_LEVEL_DETAILED, horizontal, vertical);
174
175         MOD_LOGD
176             ("time(%d) lat(%f) long(%f) alt(%f) status(%d) acc_level(%d) hoz_acc(%f) vert_acc(%f)",
177              pos->timestamp, pos->latitude, pos->longitude, pos->altitude,
178              pos->status, acc->level, acc->horizontal_accuracy, acc->vertical_accuracy);
179
180         gps_manager->pos_cb(TRUE, pos, vel, acc, gps_manager->userdata);
181
182         location_position_free(pos);
183         location_velocity_free(vel);
184         location_accuracy_free(acc);
185 }
186
187 static void on_signal_callback(GDBusConnection *conn, const gchar *name, const gchar *path, const gchar *interface, const gchar *sig, GVariant *param, gpointer user_data)
188 {
189         MOD_LOGD("name : %s, path : %s, interface : %s, sig : %s\n", name, path, interface, sig);
190
191         if (!g_strcmp0(sig, "SatelliteChanged")) {
192                 MOD_LOGD("SatelliteChanged");
193                 satellite_callback(param, user_data);
194         }
195         else if (!g_strcmp0(sig, "PositionChanged")) {
196                 MOD_LOGD("PositionChanged");
197                 position_callback(param, user_data);
198         }
199         else if (!g_strcmp0(sig, "StatusChanged")) {
200                 MOD_LOGD("StatusChanged");
201                 status_callback(param, user_data);
202         }
203         else {
204                 MOD_LOGD("Invaild signal[%s]", sig);
205         }
206 }
207
208 static int start(gpointer handle, LocModStatusCB status_cb, LocModPositionExtCB pos_cb, LocModSatelliteCB sat_cb, gpointer userdata)
209 {
210         MOD_LOGD("start");
211         GpsManagerData *gps_manager = (GpsManagerData *) handle;
212         g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
213         g_return_val_if_fail(status_cb, LOCATION_ERROR_NOT_AVAILABLE);
214         g_return_val_if_fail(pos_cb, LOCATION_ERROR_NOT_AVAILABLE);
215
216         gps_manager->status_cb = status_cb;
217         gps_manager->pos_cb = pos_cb;
218         gps_manager->sat_cb = sat_cb;
219         gps_manager->userdata = userdata;
220
221         int ret = LBS_CLIENT_ERROR_NONE;
222         ret = lbs_client_create (GPS_MANAGER_SERVICE_NAME, GPS_MANAGER_SERVICE_PATH, &(gps_manager->lbs_client));
223         if (ret != LBS_CLIENT_ERROR_NONE || !gps_manager->lbs_client) {
224                 MOD_LOGE("Fail to create lbs_client_h. Error[%d]", ret);
225                 return LOCATION_ERROR_NOT_AVAILABLE;
226         }
227         MOD_LOGD("gps-manger(%x)", gps_manager);
228         MOD_LOGD("pos_cb (%x), user_data(%x)", gps_manager->pos_cb, gps_manager->userdata);
229
230         ret = lbs_client_start (gps_manager->lbs_client, LBS_CLIENT_LOCATION_CB | LBS_CLIENT_LOCATION_STATUS_CB | LBS_CLIENT_SATELLITE_CB, on_signal_callback, gps_manager);
231         if (ret != LBS_CLIENT_ERROR_NONE) {
232                 MOD_LOGE("Fail to start lbs_client_h. Error[%d]", ret);
233                 return LOCATION_ERROR_NOT_AVAILABLE;
234         }
235
236         return LOCATION_ERROR_NONE;
237 }
238
239 static int stop(gpointer handle)
240 {
241         MOD_LOGD("stop");
242         GpsManagerData *gps_manager = (GpsManagerData *) handle;
243         g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
244         g_return_val_if_fail(gps_manager->lbs_client, LOCATION_ERROR_NOT_AVAILABLE);
245         g_return_val_if_fail(gps_manager->status_cb, LOCATION_ERROR_NOT_AVAILABLE);
246
247         int ret = LBS_CLIENT_ERROR_NONE;
248
249         ret = lbs_client_stop (gps_manager->lbs_client);
250         if (ret != LBS_CLIENT_ERROR_NONE) {
251                 MOD_LOGE("Fail to stop. Error[%d]", ret);
252                 return LOCATION_ERROR_NOT_AVAILABLE;
253         }
254
255         lbs_client_destroy(gps_manager->lbs_client);
256         gps_manager->lbs_client = NULL;
257
258         if (gps_manager->status_cb) {
259                 gps_manager->status_cb (FALSE, LOCATION_STATUS_NO_FIX, gps_manager->userdata);
260         }
261
262         gps_manager->status_cb = NULL;
263         gps_manager->pos_cb = NULL;
264         gps_manager->sat_cb = NULL;
265
266         return LOCATION_ERROR_NONE;
267 }
268
269 static int get_nmea(gpointer handle, gchar ** nmea_data)
270 {
271         MOD_LOGD("get_nmea");
272         GpsManagerData *gps_manager = (GpsManagerData *) handle;
273         g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
274         g_return_val_if_fail(nmea_data, LOCATION_ERROR_PARAMETER);
275
276         gboolean ret = FALSE;
277         int timestamp = 0;
278         ret = lbs_client_get_nmea(gps_manager->lbs_client, &timestamp, nmea_data);
279         if (ret) {
280                 MOD_LOGE("\t Error getting nmea: %d", ret);
281                 return LOCATION_ERROR_NOT_AVAILABLE;
282         }
283
284         return LOCATION_ERROR_NONE;
285 }
286
287 static int get_last_position(gpointer handle, LocationPosition ** position, LocationVelocity ** velocity, LocationAccuracy ** accuracy)
288 {
289         MOD_LOGD("get_last_position");
290         GpsManagerData *gps_manager = (GpsManagerData *) handle;
291         g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
292         g_return_val_if_fail(position, LOCATION_ERROR_PARAMETER);
293         g_return_val_if_fail(accuracy, LOCATION_ERROR_PARAMETER);
294
295         int timestamp = 0;
296         double longitude = 0.0, latitude = 0.0, altitude = 0.0;
297         double speed = 0.0, direction = 0.0;
298         double hor_accuracy = 0.0, ver_accuracy = 0.0;
299         LocationStatus status = LOCATION_STATUS_NO_FIX;
300         LocationAccuracyLevel level = LOCATION_ACCURACY_LEVEL_NONE;
301
302         if (vconf_get_int(VCONFKEY_LOCATION_LAST_GPS_TIMESTAMP, &timestamp) ||
303                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_LATITUDE, &latitude) ||
304                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_LONGITUDE, &longitude) ||
305                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_ALTITUDE, &altitude) ||
306                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_SPEED, &speed) ||
307                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_DIRECTION, &direction) ||
308                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_HOR_ACCURACY, &hor_accuracy) ||
309                 vconf_get_dbl(VCONFKEY_LOCATION_LAST_GPS_VER_ACCURACY, &ver_accuracy)) {
310                 *position = NULL;
311                 *accuracy = NULL;
312                 return LOCATION_ERROR_NOT_AVAILABLE;
313         }
314
315         if (timestamp) {
316                 if (altitude) status = LOCATION_STATUS_3D_FIX;
317                 else status = LOCATION_STATUS_2D_FIX;
318         }
319         else {
320                 *position = NULL;
321                 *accuracy = NULL;
322                 return LOCATION_ERROR_NOT_AVAILABLE;
323         }
324
325         level = LOCATION_ACCURACY_LEVEL_DETAILED;
326         *position = location_position_new(timestamp, latitude, longitude, altitude, status);
327         *velocity = location_velocity_new ((guint) timestamp, speed * MPS_TO_KMPH, direction, 0.0);
328         *accuracy = location_accuracy_new(level, hor_accuracy, ver_accuracy);
329
330         return LOCATION_ERROR_NONE;
331 }
332
333 static int set_devname(gpointer handle, const char *devname)
334 {
335         GpsManagerData *gps_manager = (GpsManagerData *) handle;
336         g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
337         g_return_val_if_fail(gps_manager->devname, LOCATION_ERROR_NOT_AVAILABLE);
338         g_return_val_if_fail(devname, LOCATION_ERROR_PARAMETER);
339         MOD_LOGD("set_devname: %s --> %s", gps_manager->devname, devname);
340         g_stpcpy(gps_manager->devname, devname);
341
342         return LOCATION_ERROR_NONE;
343 }
344
345 static int get_devname(gpointer handle, char **devname)
346 {
347         GpsManagerData *gps_manager = (GpsManagerData *) handle;
348         g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
349         g_return_val_if_fail(gps_manager->devname, LOCATION_ERROR_NOT_AVAILABLE);
350         g_return_val_if_fail(devname, LOCATION_ERROR_PARAMETER);
351         *devname = g_strdup(gps_manager->devname);
352         MOD_LOGD("get_devname: %s", *devname);
353
354         return LOCATION_ERROR_NONE;
355 }
356
357 LOCATION_MODULE_API gpointer init(LocModGpsOps * ops)
358 {
359         MOD_LOGD("init");
360
361         g_return_val_if_fail(ops, NULL);
362         ops->start = start;
363         ops->stop = stop;
364         ops->get_last_position = get_last_position;
365
366         Dl_info info;
367         if (dladdr(&get_last_position, &info) == 0) {
368                 MOD_LOGD("Failed to get module name");
369         } else if (g_strrstr(info.dli_fname, "gps")) {
370                 ops->get_nmea = get_nmea;
371                 ops->set_devname = set_devname;
372                 ops->get_devname = get_devname;
373         }
374
375         GpsManagerData *gps_manager = g_new0(GpsManagerData, 1);
376         g_return_val_if_fail(gps_manager, NULL);
377
378         g_stpcpy(gps_manager->devname, "/dev/ttySAC1");
379         gps_manager->status_cb = NULL;
380         gps_manager->pos_cb = NULL;
381         gps_manager->userdata = NULL;
382         gps_manager->is_started = FALSE;
383
384         return (gpointer) gps_manager;
385 }
386
387 LOCATION_MODULE_API void shutdown(gpointer handle)
388 {
389         MOD_LOGD("shutdown");
390         g_return_if_fail(handle);
391         GpsManagerData *gps_manager = (GpsManagerData *) handle;
392         if (gps_manager->lbs_client) {
393                 lbs_client_destroy(gps_manager->lbs_client);
394                 gps_manager->lbs_client = NULL;
395         }
396
397         g_free(gps_manager);
398
399 }