4 * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
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>
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <location-module.h>
26 #include <geoclue/geoclue-position.h>
27 #include <geoclue/geoclue-velocity.h>
28 #include <geoclue/geoclue-satellite.h>
29 #include <geoclue/geoclue-nmea.h>
30 #include <geoclue/geoclue-provider.h>
44 GeoclueSatellite *sat;
45 LocModStatusCB status_cb;
46 LocModPositionCB pos_cb;
47 LocModVelocityCB vel_cb;
53 status_callback (GeoclueProvider *provider,
57 GpsManagerData* gps_manager = (GpsManagerData*)userdata;
58 g_return_if_fail (gps_manager);
59 g_return_if_fail (gps_manager->status_cb);
62 case GEOCLUE_STATUS_ERROR:
63 case GEOCLUE_STATUS_UNAVAILABLE:
64 case GEOCLUE_STATUS_ACQUIRING:
65 MOD_LOGD("GEOCLUE_STATUS_ACQUIRING/ERROR/UNAVAILABLE");
66 gps_manager->status_cb(FALSE, LOCATION_STATUS_NO_FIX, gps_manager->userdata);
68 case GEOCLUE_STATUS_AVAILABLE:
69 MOD_LOGD("GEOCLUE_STATUS_AVAILABLE");
70 gps_manager->status_cb(TRUE, LOCATION_STATUS_3D_FIX, gps_manager->userdata);
78 satellite_callback (GeoclueSatellite *satellite,
81 int satellite_visible,
88 MOD_LOGD("satellite_callback!!!\n");
89 MOD_LOGD("timestamp: %d", timestamp);
90 MOD_LOGD("satellite_used: %d", satellite_used);
91 MOD_LOGD("satellite_visible: %d", satellite_visible);
93 for (idx = 0; idx < satellite_used; idx++) {
94 MOD_LOGD ("used_prn[%d] : %d", idx, g_array_index (used_prn, guint, idx));
96 for (idx = 0; idx < satellite_visible; idx++) {
97 GValueArray *vals = (GValueArray*)g_ptr_array_index (sat_info, idx);
98 gint prn = g_value_get_int (g_value_array_get_nth (vals, 0));
99 gint elev = g_value_get_int (g_value_array_get_nth (vals, 1));
100 gint azim = g_value_get_int (g_value_array_get_nth (vals, 2));
101 gint snr = g_value_get_int (g_value_array_get_nth (vals, 3));
102 MOD_LOGD ("visible_prn[%d] : elev %d azim %d snr %d", prn, elev, azim, snr);
106 nmea_callback (GeoclueNmea *nmea,
114 position_callback (GeocluePosition *position,
115 GeocluePositionFields fields,
120 GeoclueAccuracy *accuracy,
123 GpsManagerData* gps_manager = (GpsManagerData*)userdata;
124 g_return_if_fail (gps_manager);
125 g_return_if_fail (gps_manager->pos_cb);
127 GeoclueAccuracyLevel level;
130 geoclue_accuracy_get_details (accuracy, &level, &horiz_acc, &vert_acc);
132 LocationPosition *pos = NULL;
133 LocationAccuracy *acc = NULL;
135 if ((fields & GEOCLUE_POSITION_FIELDS_LATITUDE) &&
136 (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) {
137 if (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE) {
138 pos = location_position_new (timestamp,
142 LOCATION_STATUS_3D_FIX);
144 pos = location_position_new (timestamp,
148 LOCATION_STATUS_2D_FIX);
151 pos = location_position_new (0.0,
155 LOCATION_STATUS_NO_FIX);
159 GeoclueAccuracyLevel level;
162 geoclue_accuracy_get_details (accuracy, &level, &horiz_acc, &vert_acc);
163 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, horiz_acc, vert_acc);
165 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, horiz_acc, vert_acc);
168 MOD_LOGD("time(%d) lat(%f) long(%f) alt(%f) status(%d) acc_level(%d) hoz_acc(%f) vert_acc(%f)",
169 pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status,
170 acc->level, acc->horizontal_accuracy, acc->vertical_accuracy);
172 gps_manager->pos_cb(TRUE, pos, acc, gps_manager->userdata);
173 location_position_free (pos);
174 location_accuracy_free (acc);
179 velocity_callback (GeoclueVelocity *velocity,
180 GeoclueVelocityFields fields,
187 GpsManagerData* gps_manager = (GpsManagerData*)userdata;
188 g_return_if_fail (gps_manager);
189 g_return_if_fail (gps_manager->vel_cb);
191 LocationVelocity *vel = NULL;
192 LocationAccuracy *acc = NULL;
194 if (fields & GEOCLUE_VELOCITY_FIELDS_SPEED &&
195 fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION) {
196 if (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB) vel = location_velocity_new (timestamp, speed, direction, climb);
197 else vel = location_velocity_new (timestamp, speed, direction, 0);
198 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, 0, 0);
200 vel = location_velocity_new (0, 0, 0, 0);
201 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0, 0);
203 MOD_LOGD("timestamp(%d) speed(%f) direction(%f) climb(%f) acc_level(%d) hoz_acc(%f) vert_acc(%f)",
204 vel->timestamp, vel->speed, vel->direction, vel->climb,
205 acc->level, acc->horizontal_accuracy, acc->vertical_accuracy);
207 gps_manager->vel_cb(TRUE, vel, acc, gps_manager->userdata);
208 location_velocity_free (vel);
209 location_accuracy_free (acc);
213 unref_gps_manager(GpsManagerData* gps_manager)
215 if(gps_manager->pos) {
216 g_signal_handlers_disconnect_by_func(G_OBJECT (GEOCLUE_PROVIDER(gps_manager->pos)), G_CALLBACK (status_callback), gps_manager);
217 g_signal_handlers_disconnect_by_func(G_OBJECT (GEOCLUE_PROVIDER(gps_manager->pos)), G_CALLBACK (position_callback), gps_manager);
218 g_object_unref (gps_manager->pos);
219 gps_manager->pos = NULL;
222 if(gps_manager->vel){
223 g_signal_handlers_disconnect_by_func(G_OBJECT (GEOCLUE_PROVIDER(gps_manager->vel)), G_CALLBACK (velocity_callback), gps_manager);
224 g_object_unref (gps_manager->vel);
225 gps_manager->vel = NULL;
228 if(gps_manager->nmea) {
229 g_object_unref (gps_manager->nmea);
230 gps_manager->nmea = NULL;
233 if(gps_manager->sat) {
234 g_object_unref (gps_manager->sat);
235 gps_manager->sat = NULL;
237 gps_manager->is_started = FALSE;
241 ref_gps_manager(GpsManagerData* gps_manager)
243 if(gps_manager->is_started == TRUE){
244 MOD_LOGW ("gps-manager is alredy started");
248 gchar *service, *path;
249 service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.GpsManager");
250 path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/GpsManager");
251 if(!gps_manager->pos){
252 gps_manager->pos = geoclue_position_new (service, path);
254 if(!gps_manager->vel){
255 gps_manager->vel = geoclue_velocity_new (service, path);
257 if(!gps_manager->nmea){
258 gps_manager->nmea = geoclue_nmea_new (service, path);
260 if(!gps_manager->sat){
261 gps_manager->sat = geoclue_satellite_new (service, path);
265 if (!gps_manager->pos || !gps_manager->vel || !gps_manager->nmea || !gps_manager->sat) {
266 MOD_LOGW ("Error while creating Geoclue object.");
267 unref_gps_manager(gps_manager);
271 gps_manager->is_started = TRUE;
273 ret = g_signal_connect (G_OBJECT (GEOCLUE_PROVIDER(gps_manager->pos)), "status-changed", G_CALLBACK (status_callback), gps_manager);
274 g_debug ("gsignal_connect status-changed %d", ret);
275 ret = g_signal_connect (G_OBJECT (GEOCLUE_PROVIDER(gps_manager->pos)), "position-changed", G_CALLBACK (position_callback), gps_manager);
276 g_debug ("gsignal_connect position-changed %d", ret);
277 ret = g_signal_connect (G_OBJECT (GEOCLUE_PROVIDER(gps_manager->vel)), "velocity-changed", G_CALLBACK (velocity_callback), gps_manager);
278 g_debug ("gsignal_connect velocity-changed %d", ret);
279 ret = g_signal_connect (G_OBJECT (GEOCLUE_PROVIDER(gps_manager->sat)), "satellite-changed", G_CALLBACK (satellite_callback), gps_manager);
280 g_debug ("gsignal_connect satellite-changed %d", ret);
281 ret = g_signal_connect (G_OBJECT (GEOCLUE_PROVIDER(gps_manager->nmea)), "nmea-changed", G_CALLBACK (nmea_callback), gps_manager);
282 g_debug ("gsignal_connect nmea-changed %d", ret);
288 start (gpointer handle,
289 LocModStatusCB status_cb,
290 LocModPositionCB pos_cb,
291 LocModVelocityCB vel_cb,
295 GpsManagerData* gps_manager = (GpsManagerData*)handle;
296 g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
297 g_return_val_if_fail(status_cb, LOCATION_ERROR_NOT_AVAILABLE);
298 g_return_val_if_fail(pos_cb, LOCATION_ERROR_NOT_AVAILABLE);
299 g_return_val_if_fail(vel_cb, LOCATION_ERROR_NOT_AVAILABLE);
301 gps_manager->status_cb = status_cb;
302 gps_manager->pos_cb = pos_cb;
303 gps_manager->vel_cb = vel_cb;
304 gps_manager->userdata = userdata;
306 if (!ref_gps_manager(gps_manager)) return LOCATION_ERROR_NOT_AVAILABLE;
307 return LOCATION_ERROR_NONE;
311 stop(gpointer handle)
314 GpsManagerData* gps_manager = (GpsManagerData*)handle;
315 g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
316 g_return_val_if_fail(gps_manager->status_cb, LOCATION_ERROR_NOT_AVAILABLE);
317 unref_gps_manager(gps_manager);
318 gps_manager->status_cb (FALSE, LOCATION_STATUS_NO_FIX, gps_manager->userdata);
319 return LOCATION_ERROR_NONE;
323 get_position(gpointer handle,
324 LocationPosition **position,
325 LocationAccuracy **accuracy)
327 MOD_LOGD("get_position");
328 GpsManagerData* gps_manager = (GpsManagerData*)handle;
329 g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
330 g_return_val_if_fail(gps_manager->pos, LOCATION_ERROR_NOT_AVAILABLE);
331 g_return_val_if_fail(position, LOCATION_ERROR_PARAMETER);
332 g_return_val_if_fail(accuracy, LOCATION_ERROR_PARAMETER);
334 GeocluePositionFields fields;
336 double lat, lon, alt;
337 GeoclueAccuracy *_accuracy = NULL;
338 GError *error = NULL;
340 fields = geoclue_position_get_position (gps_manager->pos, ×tamp,
344 MOD_LOGD ("Error getting position: %s", error->message);
345 g_error_free (error);
346 return LOCATION_ERROR_NOT_AVAILABLE;
349 if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
350 fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
351 if(fields & GEOCLUE_POSITION_FIELDS_ALTITUDE) *position = location_position_new (timestamp, lat, lon, alt, LOCATION_STATUS_3D_FIX);
352 else *position = location_position_new (timestamp, lat, lon, 0, LOCATION_STATUS_2D_FIX);
353 } else *position = location_position_new (0, 0, 0, 0, LOCATION_STATUS_NO_FIX);
356 GeoclueAccuracyLevel level;
359 geoclue_accuracy_get_details (_accuracy, &level, &horiz_acc, &vert_acc);
360 *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, horiz_acc, vert_acc);
361 geoclue_accuracy_free (_accuracy);
362 } else *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0, 0);
364 return LOCATION_ERROR_NONE;
368 get_velocity(gpointer handle,
369 LocationVelocity **velocity,
370 LocationAccuracy **accuracy)
372 MOD_LOGD("get_velocity");
373 GpsManagerData* gps_manager = (GpsManagerData*)handle;
374 g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
375 g_return_val_if_fail(gps_manager->vel, LOCATION_ERROR_NOT_AVAILABLE);
376 g_return_val_if_fail(velocity, LOCATION_ERROR_PARAMETER);
377 g_return_val_if_fail(accuracy, LOCATION_ERROR_PARAMETER);
379 GeoclueVelocityFields fields;
381 double spd, dir, climb;
382 GError *error = NULL;
384 fields = geoclue_velocity_get_velocity (gps_manager->vel, ×tamp,
388 MOD_LOGD ("Error getting velocity: %s", error->message);
389 g_error_free (error);
390 return LOCATION_ERROR_NOT_AVAILABLE;
393 if (fields & GEOCLUE_VELOCITY_FIELDS_SPEED &&
394 fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION) {
395 if (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB) *velocity = location_velocity_new (timestamp, spd, dir, climb);
396 else *velocity = location_velocity_new (timestamp, spd, dir, 0);
397 *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, 0, 0);
399 *velocity = location_velocity_new (0, 0, 0, 0);
400 *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0, 0);
402 return LOCATION_ERROR_NONE;
406 get_nmea(gpointer handle,
409 MOD_LOGD("get_nmea");
410 GpsManagerData* gps_manager = (GpsManagerData*)handle;
411 g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
412 g_return_val_if_fail(gps_manager->nmea, LOCATION_ERROR_NOT_AVAILABLE);
413 g_return_val_if_fail(nmea_data, LOCATION_ERROR_PARAMETER);
415 gboolean ret = FALSE;
417 char* _nmea_data = NULL;
418 GError *error = NULL;
419 ret = geoclue_nmea_get_nmea (gps_manager->nmea, ×tamp, &_nmea_data, &error);
421 MOD_LOGD ("\t Error getting nmea: %s", error->message);
422 g_error_free (error);
423 return LOCATION_ERROR_NOT_AVAILABLE;
425 *nmea_data = g_strdup(_nmea_data);
427 return LOCATION_ERROR_NONE;
431 get_satellite(gpointer handle,
432 LocationSatellite **satellite)
434 MOD_LOGD("get_satellite");
435 GpsManagerData* gps_manager = (GpsManagerData*)handle;
436 g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
437 g_return_val_if_fail(gps_manager->sat, LOCATION_ERROR_NOT_AVAILABLE);
438 g_return_val_if_fail(satellite, LOCATION_ERROR_PARAMETER);
444 GArray *u_prn = NULL;
445 GPtrArray *sat_info = NULL;
446 GError *error = NULL;
448 geoclue_satellite_get_satellite (gps_manager->sat, ×tamp, &sat_used, &sat_vis, &u_prn, &sat_info, &error);
450 MOD_LOGW("\t Error getting satellite: %s", error->message);
451 g_error_free (error);
452 return LOCATION_ERROR_NOT_AVAILABLE;
454 *satellite = location_satellite_new (sat_vis);
456 for (idx=0; idx<sat_vis; idx++) {
457 GValueArray *vals = (GValueArray*)g_ptr_array_index (sat_info, idx);
458 gint prn = g_value_get_int (g_value_array_get_nth (vals, 0));
459 gint elev = g_value_get_int (g_value_array_get_nth (vals, 1));
460 gint azim = g_value_get_int (g_value_array_get_nth (vals, 2));
461 gint snr = g_value_get_int (g_value_array_get_nth (vals, 3));
464 gboolean is_used = FALSE;
465 for (used_idx = 0 ; used_idx < sat_used ; used_idx++) {
466 if ((guint)prn == (guint)g_array_index(u_prn, guint, used_idx)) {
471 location_satellite_set_satellite_details(*satellite, idx, (guint)prn, is_used, (guint)elev, (guint)azim, (guint)snr);
474 if (u_prn) g_array_free (u_prn, TRUE);
475 if (sat_info) g_ptr_array_free (sat_info, TRUE);
477 return LOCATION_ERROR_NONE;
481 set_devname(gpointer handle,
484 GpsManagerData* gps_manager = (GpsManagerData*)handle;
485 g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
486 g_return_val_if_fail(gps_manager->devname, LOCATION_ERROR_NOT_AVAILABLE);
487 g_return_val_if_fail(devname, LOCATION_ERROR_PARAMETER);
488 MOD_LOGD("set_devname: %s --> %s", gps_manager->devname, devname);
489 g_stpcpy(gps_manager->devname, devname);
491 return LOCATION_ERROR_NONE;
496 get_devname(gpointer handle,
499 GpsManagerData* gps_manager = (GpsManagerData*)handle;
500 g_return_val_if_fail(gps_manager, LOCATION_ERROR_NOT_AVAILABLE);
501 g_return_val_if_fail(gps_manager->devname, LOCATION_ERROR_NOT_AVAILABLE);
502 g_return_val_if_fail(devname, LOCATION_ERROR_PARAMETER);
503 *devname = g_strdup(gps_manager->devname);
504 MOD_LOGD("get_devname: %s", *devname);
506 return LOCATION_ERROR_NONE;
509 LOCATION_MODULE_API gpointer
510 init(LocModGpsOps* ops)
513 g_return_val_if_fail(ops, NULL);
516 ops->get_position = get_position;
517 ops->get_velocity = get_velocity;
519 if (dladdr(&get_position, &info) == 0) {
520 MOD_LOGD ("Failed to get module name");
521 } else if (g_str_has_prefix(info.dli_fname, "gps")) {
522 ops->get_nmea = get_nmea;
523 ops->get_satellite = get_satellite;
524 ops->set_devname = set_devname;
525 ops->get_devname = get_devname;
528 GpsManagerData* gps_manager = g_new0(GpsManagerData, 1);
529 g_return_val_if_fail(gps_manager, NULL);
531 g_stpcpy(gps_manager->devname, "/dev/ttySAC1");
532 gps_manager->pos = NULL;
533 gps_manager->vel = NULL;
534 gps_manager->nmea = NULL;
535 gps_manager->sat = NULL;
536 gps_manager->status_cb= NULL;
537 gps_manager->pos_cb = NULL;
538 gps_manager->vel_cb = NULL;
539 gps_manager->userdata = NULL;
540 gps_manager->is_started = FALSE;
542 return (gpointer)gps_manager;
545 LOCATION_MODULE_API void
546 shutdown(gpointer handle)
548 MOD_LOGD("shutdown");
549 g_return_if_fail(handle);
550 GpsManagerData* gps_manager = (GpsManagerData*)handle;
551 unref_gps_manager(gps_manager);
552 if(gps_manager->status_cb) gps_manager->status_cb(FALSE, LOCATION_STATUS_NO_FIX, gps_manager->userdata);