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