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