update for beta universally
[framework/location/libslp-location.git] / location / location-gps.c
1 /*
2  * libslp-location
3  *
4  * Copyright (c) 2010-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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "location/location-setting.h"
27 #include "location/location-log.h"
28
29 #include "location/location-module-internal.h"
30
31 #include "location/location-gps.h"
32 #include "location/location-marshal.h"
33 #include "location/location-ielement.h"
34 #include "location/location-signaling-util.h"
35 #include "location/location-common-util.h"
36
37
38 typedef struct _LocationGpsPrivate {
39         LocationGpsMod*         mod;
40         gboolean                is_started;
41         gboolean                set_noti;
42         gboolean                enabled;
43         guint                   interval;
44         LocationPosition*       pos;
45         LocationVelocity*       vel;
46         LocationAccuracy*       acc;
47         GList*                  boundary_list;
48         ZoneStatus              zone_status;
49 } LocationGpsPrivate;
50
51 enum {
52         PROP_0,
53         PROP_DEV_NAME,
54         PROP_METHOD_TYPE,
55         PROP_LAST_POSITION,
56         PROP_UPDATE_INTERVAL,
57         PROP_BOUNDARY,
58         PROP_REMOVAL_BOUNDARY,
59         PROP_NMEA,
60         PROP_SATELLITE,
61         PROP_MAX
62 };
63
64 static guint32 signals[LAST_SIGNAL] = {0, };
65 static GParamSpec *properties[PROP_MAX] = {NULL, };
66
67 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_GPS, LocationGpsPrivate))
68
69 static void location_ielement_interface_init (LocationIElementInterface *iface);
70
71 G_DEFINE_TYPE_WITH_CODE (LocationGps, location_gps, G_TYPE_OBJECT,
72                          G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT,
73                          location_ielement_interface_init));
74
75 static void
76 gps_status_cb (gboolean enabled,
77         LocationStatus status,
78         gpointer self)
79 {
80         LOCATION_LOGD("gps_status_cb");
81         g_return_if_fail(self);
82         LocationGpsPrivate* priv = GET_PRIVATE(self);
83         enable_signaling(self, signals, &(priv->enabled), enabled, status);
84 }
85
86 static void
87 gps_position_cb (gboolean enabled,
88         LocationPosition *pos,
89         LocationAccuracy *acc,
90         gpointer self)
91 {
92         LOCATION_LOGD("gps_position_cb");
93         g_return_if_fail(self);
94         g_return_if_fail(pos);
95         g_return_if_fail(acc);
96         LocationGpsPrivate* priv = GET_PRIVATE(self);
97         enable_signaling(self, signals, &(priv->enabled), enabled, pos->status);
98         position_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->pos), &(priv->acc), priv->boundary_list, &(priv->zone_status), enabled, pos, acc);
99 }
100
101 static void
102 gps_velocity_cb (gboolean enabled,
103         LocationVelocity *vel,
104         LocationAccuracy *acc,
105         gpointer self)
106 {
107         LOCATION_LOGD("gps_velocity_cb");
108         g_return_if_fail(self);
109         LocationGpsPrivate* priv = GET_PRIVATE(self);
110         velocity_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->vel), enabled, vel, acc);
111 }
112
113 static void
114 location_setting_gps_cb (keynode_t *key,
115         gpointer self)
116 {
117         LOCATION_LOGD("location_setting_gps_cb");
118         g_return_if_fail(key);
119         g_return_if_fail(self);
120         LocationGpsPrivate* priv = GET_PRIVATE(self);
121         g_return_if_fail (priv->mod);
122         g_return_if_fail (priv->mod->handler);
123
124         int ret = LOCATION_ERROR_NONE;
125
126         if (0 == location_setting_get_key_val(key) && priv->mod->ops.stop && priv->is_started) {
127                 LOCATION_LOGD("location stopped by setting");
128                 ret = priv->mod->ops.stop(priv->mod->handler);
129                 if (ret == LOCATION_ERROR_NONE) priv->is_started = FALSE;
130         }
131         else if (1 == location_setting_get_key_val(key) && priv->mod->ops.start && !priv->is_started) {
132                 LOCATION_LOGD("location resumed by setting");
133                 ret = priv->mod->ops.start (priv->mod->handler, gps_status_cb, gps_position_cb, gps_velocity_cb, self);
134                 if (ret == LOCATION_ERROR_NONE) priv->is_started = TRUE;
135         }
136 }
137
138 static int
139 location_gps_start (LocationGps *self)
140 {
141         LOCATION_LOGD("location_gps_start");
142         LocationGpsPrivate* priv = GET_PRIVATE(self);
143         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
144         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
145         g_return_val_if_fail (priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
146
147         if (priv->is_started == TRUE) return LOCATION_ERROR_NONE;
148
149         int ret = LOCATION_ERROR_NONE;
150         int noti_err = 0;
151
152         if (!location_setting_get_int(GPS_ENABLED)) {
153                 ret = LOCATION_ERROR_NOT_ALLOWED;
154         }
155         else {
156                 ret = priv->mod->ops.start (priv->mod->handler, gps_status_cb, gps_position_cb, gps_velocity_cb, self);
157                 if (ret == LOCATION_ERROR_NONE) {
158                         priv->is_started = TRUE;
159                 }
160                 else {
161                         return ret;
162                 }
163         }
164
165         if(priv->set_noti == FALSE) {
166                 noti_err = location_setting_add_notify (GPS_ENABLED, location_setting_gps_cb, self);
167                 if (noti_err != 0) {
168                         return LOCATION_ERROR_UNKNOWN;
169                 }
170                 priv->set_noti = TRUE;
171         }
172
173         return ret;
174 }
175
176 static int
177 location_gps_stop (LocationGps *self)
178 {
179         LOCATION_LOGD("location_gps_stop");
180         LocationGpsPrivate* priv = GET_PRIVATE(self);
181         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
182         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
183         g_return_val_if_fail (priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE);
184
185         int ret = LOCATION_ERROR_NONE;
186         int noti_err = 0;
187
188         if ( priv->is_started == TRUE) {
189                 ret = priv->mod->ops.stop (priv->mod->handler);
190                 if (ret == LOCATION_ERROR_NONE) {
191                         priv->is_started = FALSE;
192                 }
193                 else {
194                         return ret;
195                 }
196         }
197
198         if(priv->set_noti == TRUE) {
199                 noti_err = location_setting_ignore_notify (GPS_ENABLED, location_setting_gps_cb);
200                 if (noti_err != 0) {
201                         return LOCATION_ERROR_UNKNOWN;
202                 }
203                 priv->set_noti = FALSE;
204         }
205
206         return ret;
207 }
208
209 static void
210 location_gps_dispose (GObject *gobject)
211 {
212         LOCATION_LOGD("location_gps_dispose");
213         G_OBJECT_CLASS (location_gps_parent_class)->dispose (gobject);
214 }
215
216 static void
217 location_gps_finalize (GObject *gobject)
218 {
219         LOCATION_LOGD("location_gps_finalize");
220         LocationGpsPrivate* priv = GET_PRIVATE(gobject);
221         module_free(priv->mod, "gps");
222         priv->mod = NULL;
223         G_OBJECT_CLASS (location_gps_parent_class)->finalize (gobject);
224 }
225
226 static void
227 location_gps_set_property (GObject *object,
228         guint property_id,
229         const GValue *value,
230         GParamSpec *pspec)
231 {
232         LocationGpsPrivate* priv = GET_PRIVATE(object);
233
234         g_return_if_fail (priv->mod);
235         g_return_if_fail (priv->mod->handler);
236         LocModGpsOps ops = priv->mod->ops;
237
238         int ret = 0;
239         switch (property_id){
240                 case PROP_DEV_NAME: {
241                         char* devname = g_value_dup_string(value);
242                         LOCATION_LOGD("Set prop>> device_name: %s", devname);
243                         if(ops.set_devname)
244                                 ops.set_devname(priv->mod->handler, devname);
245                         g_free(devname);
246                         break;
247                 }
248                 case PROP_BOUNDARY: {
249                         GList *boundary_list = g_list_copy(g_value_get_pointer(value));
250                         ret = set_prop_boundary(&priv->boundary_list, boundary_list);
251                         if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret);
252                         break;
253                 }
254                 case PROP_REMOVAL_BOUNDARY: {
255                         LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value);
256                         ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
257                         if(ret != 0) LOCATION_LOGD("Removal boundary. Error[%d]", ret);
258                         break;
259                 }
260                 case PROP_UPDATE_INTERVAL: {
261                         guint interval = g_value_get_uint(value);
262                         LOCATION_LOGD("Set prop>> update-interval: %u", interval);
263                         if(interval > 0) {
264                                 if(interval < LOCATION_UPDATE_INTERVAL_MAX)
265                                         priv->interval = interval;
266                                 else
267                                         priv->interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
268                         }
269                         else
270                                 priv->interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
271                         break;
272                 }
273                 default:
274                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
275                         break;
276         }
277 }
278
279 static void
280 location_gps_get_property (GObject *object,
281         guint property_id,
282         GValue *value,
283         GParamSpec *pspec)
284 {
285         LocationGpsPrivate *priv = GET_PRIVATE (object);
286
287         g_return_if_fail (priv->mod);
288         g_return_if_fail (priv->mod->handler);
289         LocModGpsOps ops = priv->mod->ops;
290         switch (property_id) {
291                 case PROP_DEV_NAME: {
292                         char* devname = NULL;
293                         if(ops.get_devname)
294                                 ops.get_devname(priv->mod->handler, &devname);
295                         LOCATION_LOGD ("Get prop>> device_name: %s", devname);
296                         g_value_set_string (value, devname);
297                         g_free(devname);
298                         break;
299                 }
300                 case PROP_METHOD_TYPE:
301                         g_value_set_int(value, LOCATION_METHOD_GPS);
302                         break;
303                 case PROP_LAST_POSITION:
304                         g_value_set_boxed (value, priv->pos);
305                         break;
306                 case PROP_UPDATE_INTERVAL:
307                         g_value_set_uint(value, priv->interval);
308                         break;
309                 case PROP_BOUNDARY:
310                         g_value_set_pointer(value, g_list_first(priv->boundary_list));
311                         break;
312                 case PROP_NMEA: {
313                         char *nmea_data = NULL;
314                         if (ops.get_nmea &&  LOCATION_ERROR_NONE == ops.get_nmea(priv->mod->handler, &nmea_data) && nmea_data) {
315                                 LOCATION_LOGD("Get prop>> Lastest nmea: \n%s", nmea_data);
316                                 g_value_set_string(value, nmea_data);
317                                 g_free(nmea_data);
318                         } else {
319                                 LOCATION_LOGW("Get prop>> Lastest nmea: failed");
320                                 g_value_set_string(value, NULL);
321                         }
322                         break;
323                 }
324                 case PROP_SATELLITE: {
325                         LocationSatellite *satellite = NULL;
326                         if (ops.get_satellite && priv->mod->handler && LOCATION_ERROR_NONE == ops.get_satellite(priv->mod->handler, &satellite) && satellite){
327                                 LOCATION_LOGD("Get prop>> Last sat: num_used(%d) num_view(%d)", satellite->num_of_sat_used, satellite->num_of_sat_inview);
328                                 g_value_set_boxed (value, satellite);
329                                 location_satellite_free(satellite);
330                         } else {
331                                 LOCATION_LOGW("Get prop>> Last sat: failed");
332                                 g_value_set_boxed (value, NULL);
333                         }
334                         break;
335                 }
336                 default:
337                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
338                         break;
339         }
340 }
341
342 static int
343 location_gps_get_position (LocationGps *self,
344         LocationPosition **position,
345         LocationAccuracy **accuracy)
346 {
347         LOCATION_LOGD("location_gps_get_position");
348
349         LocationGpsPrivate *priv = GET_PRIVATE (self);
350         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
351         setting_retval_if_fail(GPS_ENABLED);
352
353         LocModGpsOps ops = priv->mod->ops;
354         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
355         g_return_val_if_fail (ops.get_position, LOCATION_ERROR_NOT_AVAILABLE);
356         return ops.get_position(priv->mod->handler, position, accuracy);
357 }
358
359 static int
360 location_gps_get_velocity (LocationGps *self,
361         LocationVelocity **velocity,
362         LocationAccuracy **accuracy)
363 {
364         LOCATION_LOGD("location_gps_get_velocity");
365
366         LocationGpsPrivate *priv = GET_PRIVATE (self);
367         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
368         setting_retval_if_fail(GPS_ENABLED);
369
370         LocModGpsOps ops = priv->mod->ops;
371         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
372         g_return_val_if_fail (ops.get_velocity, LOCATION_ERROR_NOT_AVAILABLE);
373         return ops.get_velocity(priv->mod->handler, velocity, accuracy);
374 }
375
376 static void
377 location_ielement_interface_init (LocationIElementInterface *iface)
378 {
379         iface->start = (TYPE_START_FUNC)location_gps_start;
380         iface->stop = (TYPE_STOP_FUNC)location_gps_stop;
381         iface->get_position = (TYPE_GET_POSITION)location_gps_get_position;
382         iface->get_velocity = (TYPE_GET_VELOCITY)location_gps_get_velocity;
383 }
384
385 static void
386 location_gps_init (LocationGps *self)
387 {
388         LOCATION_LOGD("location_gps_init");
389         LocationGpsPrivate* priv = GET_PRIVATE(self);
390
391         priv->mod = (LocationGpsMod*)module_new("gps");
392         if(!priv->mod) LOCATION_LOGW("module loading failed");
393
394         priv->is_started = FALSE;
395         priv->set_noti = FALSE;
396         priv->enabled= FALSE;
397         priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
398
399         priv->pos = NULL;
400         priv->vel = NULL;
401         priv->acc = NULL;
402         priv->zone_status = ZONE_STATUS_NONE;
403         priv->boundary_list = NULL;
404 }
405
406 static void
407 location_gps_class_init (LocationGpsClass *klass)
408 {
409         LOCATION_LOGD("location_gps_class_init");
410         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
411
412         gobject_class->set_property = location_gps_set_property;
413         gobject_class->get_property = location_gps_get_property;
414
415         gobject_class->dispose = location_gps_dispose;
416         gobject_class->finalize = location_gps_finalize;
417
418         g_type_class_add_private (klass, sizeof (LocationGpsPrivate));
419
420         signals[SERVICE_ENABLED] = g_signal_new ("service-enabled",
421                         G_TYPE_FROM_CLASS (klass),
422                         G_SIGNAL_RUN_FIRST |
423                         G_SIGNAL_NO_RECURSE,
424                         G_STRUCT_OFFSET (LocationGpsClass, enabled),
425                         NULL, NULL,
426                         location_VOID__UINT,
427                         G_TYPE_NONE, 1,
428                         G_TYPE_UINT);
429
430         signals[SERVICE_DISABLED] = g_signal_new ("service-disabled",
431                         G_TYPE_FROM_CLASS (klass),
432                         G_SIGNAL_RUN_FIRST |
433                         G_SIGNAL_NO_RECURSE,
434                         G_STRUCT_OFFSET (LocationGpsClass, disabled),
435                         NULL, NULL,
436                         location_VOID__UINT,
437                         G_TYPE_NONE, 1,
438                         G_TYPE_UINT);
439
440         signals[SERVICE_UPDATED] = g_signal_new ("service-updated",
441                         G_TYPE_FROM_CLASS (klass),
442                         G_SIGNAL_RUN_FIRST |
443                         G_SIGNAL_NO_RECURSE,
444                         G_STRUCT_OFFSET (LocationGpsClass, updated),
445                         NULL, NULL,
446                         location_VOID__UINT_POINTER_POINTER,
447                         G_TYPE_NONE, 3,
448                         G_TYPE_UINT,
449                         G_TYPE_POINTER,
450                         G_TYPE_POINTER);
451
452         signals[ZONE_IN] = g_signal_new ("zone-in",
453                         G_TYPE_FROM_CLASS (klass),
454                         G_SIGNAL_RUN_FIRST |
455                         G_SIGNAL_NO_RECURSE,
456                         G_STRUCT_OFFSET (LocationGpsClass, zone_in),
457                         NULL, NULL,
458                         location_VOID__UINT_POINTER_POINTER,
459                         G_TYPE_NONE, 3,
460                         G_TYPE_UINT,
461                         G_TYPE_POINTER,
462                         G_TYPE_POINTER);
463
464         signals[ZONE_OUT] = g_signal_new ("zone-out",
465                         G_TYPE_FROM_CLASS (klass),
466                         G_SIGNAL_RUN_FIRST |
467                         G_SIGNAL_NO_RECURSE,
468                         G_STRUCT_OFFSET (LocationGpsClass, zone_out),
469                         NULL, NULL,
470                         location_VOID__UINT_POINTER_POINTER,
471                         G_TYPE_NONE, 3,
472                         G_TYPE_UINT,
473                         G_TYPE_POINTER,
474                         G_TYPE_POINTER);
475
476         properties[PROP_DEV_NAME] = g_param_spec_string ("dev-name",
477                         "gps device name prop",
478                         "gps device name",
479                         "/dev/rfcomm0",
480                         G_PARAM_READWRITE);
481
482         properties[PROP_METHOD_TYPE] = g_param_spec_int ("method",
483                         "method type",
484                         "location method type name",
485                         LOCATION_METHOD_GPS,
486                         LOCATION_METHOD_GPS,
487                         LOCATION_METHOD_GPS,
488                         G_PARAM_READABLE);
489
490         properties[PROP_LAST_POSITION]  = g_param_spec_boxed ("last-position",
491                         "gps last position prop",
492                         "gps last position data",
493                         LOCATION_TYPE_POSITION,
494                         G_PARAM_READABLE);
495
496         properties[PROP_UPDATE_INTERVAL] = g_param_spec_uint ("update-interval",
497                         "gps update interval prop",
498                         "gps update interval data",
499                         LOCATION_UPDATE_INTERVAL_MIN,
500                         LOCATION_UPDATE_INTERVAL_MAX,
501                         LOCATION_UPDATE_INTERVAL_DEFAULT,
502                         G_PARAM_READWRITE);
503
504         properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary",
505                         "gps boundary prop",
506                         "gps boundary data",
507                         G_PARAM_READWRITE);
508
509         properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
510                         "gps removal boundary prop",
511                         "gps removal boundary data",
512                         LOCATION_TYPE_BOUNDARY,
513                         G_PARAM_READWRITE);
514
515
516         properties[PROP_NMEA] = g_param_spec_string ("nmea",
517                         "gps NMEA name prop",
518                         "gps NMEA",
519                         NULL,
520                         G_PARAM_READABLE);
521
522         properties[PROP_SATELLITE] = g_param_spec_boxed ("satellite",
523                         "gps satellite prop",
524                         "gps satellite data",
525                         LOCATION_TYPE_SATELLITE,
526                         G_PARAM_READABLE);
527
528         g_object_class_install_properties (gobject_class,
529                         PROP_MAX,
530                         properties);
531
532 }