4 * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
7 * Genie Kim <daejins.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-provider.h>
40 LocModStatusCB status_cb;
41 LocModPositionCB pos_cb;
42 LocModVelocityCB vel_cb;
48 status_callback (GeoclueProvider *provider,
52 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)userdata;
53 g_return_if_fail(gpsd->status_cb);
56 case GEOCLUE_STATUS_ERROR:
57 case GEOCLUE_STATUS_UNAVAILABLE:
58 case GEOCLUE_STATUS_ACQUIRING:
59 MOD_LOGD("Status callback>> GEOCLUE_STATUS_ACQUIRING/ERROR/UNAVAILABLE");
60 gpsd->status_cb(FALSE, LOCATION_STATUS_NO_FIX, gpsd->userdata);
62 case GEOCLUE_STATUS_AVAILABLE:
63 MOD_LOGD("Status callback>> GEOCLUE_STATUS_AVAILABLE");
64 gpsd->status_cb(TRUE, LOCATION_STATUS_3D_FIX, gpsd->userdata);
72 position_callback (GeocluePosition *position,
73 GeocluePositionFields fields,
78 GeoclueAccuracy *accuracy,
81 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)userdata;
82 g_return_if_fail(gpsd->pos_cb);
84 GeoclueAccuracyLevel level;
87 geoclue_accuracy_get_details (accuracy, &level, &horiz_acc, &vert_acc);
89 LocationPosition *pos = NULL;
90 LocationAccuracy *acc = NULL;
92 if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
93 fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
94 if(fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)
95 pos = location_position_new (timestamp, latitude, longitude, altitude, LOCATION_STATUS_3D_FIX);
96 else pos = location_position_new (timestamp, latitude, longitude, 0, LOCATION_STATUS_2D_FIX);
97 } else pos = location_position_new (0, 0, 0, 0, LOCATION_STATUS_NO_FIX);
100 GeoclueAccuracyLevel level;
103 geoclue_accuracy_get_details (accuracy, &level, &horiz_acc, &vert_acc);
104 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, horiz_acc, vert_acc);
105 } else acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, horiz_acc, vert_acc);
107 MOD_LOGD("Position callback>> time(%d) lat(%f) long(%f) alt(%f) status(%d) acc_level(%d) hoz_acc(%f) vert_acc(%f)",
108 pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status,
109 acc->level, acc->horizontal_accuracy, acc->vertical_accuracy);
110 gpsd->pos_cb(TRUE, pos, acc, gpsd->userdata);
111 location_position_free (pos);
112 location_accuracy_free (acc);
116 velocity_callback (GeoclueVelocity *velocity,
117 GeoclueVelocityFields fields,
124 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)userdata;
125 g_return_if_fail(gpsd->vel_cb);
127 LocationVelocity *vel = NULL;
128 LocationAccuracy *acc = NULL;
130 if (fields & GEOCLUE_VELOCITY_FIELDS_SPEED &&
131 fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION) {
132 if (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB) vel = location_velocity_new (timestamp, speed, direction, climb);
133 else vel = location_velocity_new (timestamp, speed, direction, 0);
134 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, 0, 0);
136 vel = location_velocity_new (0, 0, 0, 0);
137 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0, 0);
139 MOD_LOGD("Velocity callback>> timestamp(%d) speed(%f) direction(%f) climb(%f) acc_level(%d) hoz_acc(%f) vert_acc(%f)",
140 vel->timestamp, vel->speed, vel->direction, vel->climb,
141 acc->level, acc->horizontal_accuracy, acc->vertical_accuracy);
143 gpsd->vel_cb(TRUE, vel, acc, gpsd->userdata);
144 location_velocity_free (vel);
145 location_accuracy_free (acc);
149 _unref_geoclue(GeoclueGpsdData* gpsd)
152 g_signal_handlers_disconnect_by_func(G_OBJECT (GEOCLUE_PROVIDER(gpsd->pos)), G_CALLBACK (status_callback), gpsd);
153 g_signal_handlers_disconnect_by_func(G_OBJECT (GEOCLUE_PROVIDER(gpsd->pos)), G_CALLBACK (position_callback), gpsd);
154 g_object_unref (gpsd->pos);
158 if( gpsd->vel != NULL){
159 g_signal_handlers_disconnect_by_func(G_OBJECT (GEOCLUE_PROVIDER(gpsd->vel)), G_CALLBACK (velocity_callback), gpsd);
160 g_object_unref (gpsd->vel);
163 gpsd->is_started = FALSE;
167 _ref_geoclue(GeoclueGpsdData* gpsd)
169 if(gpsd->is_started == TRUE){
170 MOD_LOGW ("geoclue-gpsd is alredy started");
174 gchar *service, *path;
175 service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.Gpsd");
176 path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/Gpsd");
179 gpsd->pos = geoclue_position_new (service, path);
182 gpsd->vel = geoclue_velocity_new (service, path);
186 if(!gpsd->pos || !gpsd->vel){
187 MOD_LOGW ("Error while creating Geoclue object.");
188 _unref_geoclue(gpsd);
192 gpsd->is_started = TRUE;
193 g_signal_connect (G_OBJECT (GEOCLUE_PROVIDER(gpsd->pos)), "status-changed", G_CALLBACK (status_callback), gpsd);
194 g_signal_connect (G_OBJECT (GEOCLUE_PROVIDER(gpsd->pos)), "position-changed", G_CALLBACK (position_callback), gpsd);
195 g_signal_connect (G_OBJECT (GEOCLUE_PROVIDER(gpsd->vel)), "velocity-changed", G_CALLBACK (velocity_callback), gpsd);
201 start(gpointer handle, LocModStatusCB status_cb, LocModPositionCB pos_cb, LocModVelocityCB vel_cb, gpointer userdata)
204 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)handle;
205 g_return_val_if_fail(gpsd, LOCATION_ERROR_NOT_AVAILABLE);
206 g_return_val_if_fail(status_cb, LOCATION_ERROR_NOT_AVAILABLE);
207 g_return_val_if_fail(pos_cb, LOCATION_ERROR_NOT_AVAILABLE);
208 g_return_val_if_fail(vel_cb, LOCATION_ERROR_NOT_AVAILABLE);
210 gpsd->status_cb = status_cb;
211 gpsd->pos_cb = pos_cb;
212 gpsd->vel_cb = vel_cb;
213 gpsd->userdata = userdata;
214 if (!_ref_geoclue(gpsd)) return LOCATION_ERROR_NOT_AVAILABLE;
215 return LOCATION_ERROR_NONE;
219 stop(gpointer handle)
222 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)handle;
223 g_return_val_if_fail(gpsd, LOCATION_ERROR_NOT_AVAILABLE);
224 g_return_val_if_fail(gpsd->status_cb, LOCATION_ERROR_NOT_AVAILABLE);
225 _unref_geoclue(gpsd);
226 gpsd->status_cb(FALSE, LOCATION_STATUS_NO_FIX, gpsd->userdata);
227 return LOCATION_ERROR_NONE;
233 LocationPosition **position,
234 LocationAccuracy **accuracy)
236 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)handle;
237 g_return_val_if_fail(gpsd, LOCATION_ERROR_NOT_AVAILABLE);
238 g_return_val_if_fail(gpsd->pos, LOCATION_ERROR_NOT_AVAILABLE);
239 g_return_val_if_fail(position, LOCATION_ERROR_PARAMETER);
240 g_return_val_if_fail(accuracy, LOCATION_ERROR_PARAMETER);
242 GeocluePositionFields fields;
244 double lat, lon, alt;
245 GeoclueAccuracy *_accuracy = NULL;
246 GError *error = NULL;
248 fields = geoclue_position_get_position (gpsd->pos, ×tamp,
252 MOD_LOGD ("Error getting position: %s", error->message);
253 g_error_free (error);
254 return LOCATION_ERROR_NOT_AVAILABLE;
257 if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
258 fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
259 if(fields & GEOCLUE_POSITION_FIELDS_ALTITUDE) *position = location_position_new (timestamp, lat, lon, alt, LOCATION_STATUS_3D_FIX);
260 else *position = location_position_new (timestamp, lat, lon, 0, LOCATION_STATUS_2D_FIX);
261 } else *position = location_position_new (0, 0, 0, 0, LOCATION_STATUS_NO_FIX);
264 GeoclueAccuracyLevel level;
267 geoclue_accuracy_get_details (_accuracy, &level, &horiz_acc, &vert_acc);
268 *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, horiz_acc, vert_acc);
269 geoclue_accuracy_free (_accuracy);
270 } else *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0, 0);
272 return LOCATION_ERROR_NONE;
278 LocationVelocity **velocity,
279 LocationAccuracy **accuracy)
281 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)handle;
282 g_return_val_if_fail(gpsd, LOCATION_ERROR_NOT_AVAILABLE);
283 g_return_val_if_fail(gpsd->vel, LOCATION_ERROR_NOT_AVAILABLE);
284 g_return_val_if_fail(velocity, LOCATION_ERROR_PARAMETER);
285 g_return_val_if_fail(accuracy, LOCATION_ERROR_PARAMETER);
287 GeoclueVelocityFields fields;
289 double spd, dir, climb;
290 GError *error = NULL;
292 fields = geoclue_velocity_get_velocity (gpsd->vel, ×tamp,
296 MOD_LOGD ("Error getting velocity: %s", error->message);
297 g_error_free (error);
298 return LOCATION_ERROR_NOT_AVAILABLE;
301 if (fields & GEOCLUE_VELOCITY_FIELDS_SPEED &&
302 fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION) {
303 if (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB) *velocity = location_velocity_new (timestamp, spd, dir, climb);
304 else *velocity = location_velocity_new (timestamp, spd, dir, 0);
305 *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, 0, 0);
307 *velocity = location_velocity_new (0, 0, 0, 0);
308 *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0, 0);
310 return LOCATION_ERROR_NONE;
314 get_nmea(gpointer handle,
317 MOD_LOGD("get_nmea: not available");
318 return LOCATION_ERROR_NOT_AVAILABLE;
322 get_satellite(gpointer handle,
323 LocationSatellite **satellite)
325 MOD_LOGD("get_satellite: not available");
326 return LOCATION_ERROR_NOT_AVAILABLE;
330 set_devname(gpointer handle,
333 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)handle;
334 g_return_val_if_fail(gpsd, LOCATION_ERROR_NOT_AVAILABLE);
335 g_return_val_if_fail(gpsd->devname, LOCATION_ERROR_NOT_AVAILABLE);
336 g_return_val_if_fail(devname, LOCATION_ERROR_PARAMETER);
337 MOD_LOGD("set_devname: %s --> %s", gpsd->devname, devname);
338 g_stpcpy(gpsd->devname, devname);
340 return LOCATION_ERROR_NONE;
345 get_devname(gpointer handle,
348 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)handle;
349 g_return_val_if_fail(gpsd, LOCATION_ERROR_NOT_AVAILABLE);
350 g_return_val_if_fail(gpsd->devname, LOCATION_ERROR_NOT_AVAILABLE);
351 g_return_val_if_fail(devname, LOCATION_ERROR_PARAMETER);
353 *devname = g_strdup(gpsd->devname);
354 MOD_LOGD("get_devname: %s", *devname);
356 return LOCATION_ERROR_NONE;
359 LOCATION_MODULE_API gpointer
360 init(LocModGpsOps* ops)
363 g_return_val_if_fail(ops, NULL);
366 ops->get_position = get_position;
367 ops->get_velocity = get_velocity;
369 if (dladdr(&get_position, &info) == 0) {
370 MOD_LOGD("failed to get module name");
371 } else if (g_str_has_prefix(info.dli_fname, "gps")) {
372 ops->get_nmea = get_nmea;
373 ops->get_satellite = get_satellite;
374 ops->set_devname = set_devname;
375 ops->get_devname = get_devname;
378 GeoclueGpsdData* gpsd = g_new0(GeoclueGpsdData, 1);
379 g_return_val_if_fail(gpsd, NULL);
381 g_stpcpy(gpsd->devname, "/dev/rfcomm0");
384 gpsd->status_cb= NULL;
387 gpsd->userdata = NULL;
388 gpsd->is_started = FALSE;
390 return (gpointer)gpsd;
393 LOCATION_MODULE_API void
394 shutdown(gpointer handle)
396 MOD_LOGD("shutdown");
397 GeoclueGpsdData* gpsd = (GeoclueGpsdData*)handle;
398 g_return_if_fail(gpsd);
399 _unref_geoclue(gpsd);
400 if(gpsd->status_cb) gpsd->status_cb(FALSE, LOCATION_STATUS_NO_FIX, gpsd->userdata);