5b69e7dce9bba999d101ac36e01f793d2a00b90c
[platform/core/location/lbs-location.git] / location / 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/location-setting.h"
27 #include "location/location-log.h"
28
29 #include "location/location-module-internal.h"
30
31 #include "location/location-wps.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  * forward definitions
38  */
39
40 typedef struct _LocationWpsPrivate {
41         LocationWpsMod* mod;
42         gboolean is_started;
43         gboolean enabled;
44         guint    interval;
45         LocationPosition *pos;
46         LocationVelocity *vel;
47         LocationAccuracy *acc;
48         GList *boundary_list;
49         ZoneStatus zone_status;
50 } LocationWpsPrivate;
51
52 enum {
53         PROP_0,
54         PROP_METHOD_TYPE,
55         PROP_LAST_POSITION,
56         PROP_UPDATE_INTERVAL,
57         PROP_BOUNDARY,
58         PROP_REMOVAL_BOUNDARY,
59         PROP_MAX
60 };
61
62 static guint32 signals[LAST_SIGNAL] = {0, };
63 static GParamSpec *properties[PROP_MAX] = {NULL, };
64
65 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_WPS, LocationWpsPrivate))
66
67 static void location_ielement_interface_init (LocationIElementInterface *iface);
68
69 G_DEFINE_TYPE_WITH_CODE (LocationWps, location_wps, G_TYPE_OBJECT,
70                          G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT,
71                          location_ielement_interface_init));
72
73 static void
74 wps_status_cb (gboolean enabled,
75         LocationStatus status,
76         gpointer self)
77 {
78         LOCATION_LOGD("wps_status_cb");
79         g_return_if_fail(self);
80         LocationWpsPrivate* priv = GET_PRIVATE(self);
81         enable_signaling(self, signals, &(priv->enabled), enabled, status);
82 }
83
84 static void
85 wps_position_cb (gboolean enabled,
86         LocationPosition *pos,
87         LocationAccuracy *acc,
88         gpointer self)
89 {
90         LOCATION_LOGD("wps_position_cb");
91         g_return_if_fail(self);
92         g_return_if_fail(pos);
93         g_return_if_fail(acc);
94         LocationWpsPrivate* priv = GET_PRIVATE(self);
95         enable_signaling(self, signals, &(priv->enabled), enabled, pos->status);
96         position_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->pos), &(priv->acc), priv->boundary_list, &(priv->zone_status), enabled, pos, acc);
97 }
98
99 static void
100 wps_velocity_cb(gboolean enabled,
101         LocationVelocity *vel,
102         LocationAccuracy *acc,
103         gpointer self)
104 {
105         LOCATION_LOGD("wps_velocity_cb");
106         g_return_if_fail(self);
107         LocationWpsPrivate* priv = GET_PRIVATE(self);
108         velocity_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->vel), enabled, vel, acc);
109 }
110
111 static void
112 location_setting_wps_cb(keynode_t *key,
113         gpointer self)
114 {
115         LOCATION_LOGD("location_setting_wps_cb");
116         g_return_if_fail(key);
117         g_return_if_fail(self);
118         LocationWpsPrivate* priv = GET_PRIVATE(self);
119         g_return_if_fail (priv->mod);
120         g_return_if_fail (priv->mod->handler);
121         if (0 == location_setting_get_key_val(key) && priv->mod->ops.stop) {
122                 LOCATION_LOGD("location stopped by setting");
123                 priv->mod->ops.stop(priv->mod->handler);
124         }
125         else if (1 == location_setting_get_key_val(key) && priv->mod->ops.start) {
126                 LOCATION_LOGD("location resumed by setting");
127                 priv->mod->ops.start (priv->mod->handler, wps_status_cb, wps_position_cb, wps_velocity_cb, self);
128         }
129 }
130
131 static int
132 location_wps_start (LocationWps *self)
133 {
134         LOCATION_LOGD("location_wps_start");
135         LocationWpsPrivate* priv = GET_PRIVATE(self);
136         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
137         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
138         g_return_val_if_fail (priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
139         setting_retval_if_fail (GPS_ENABLED);
140         setting_retval_if_fail (NETWORK_ENABLED);
141         if (priv->is_started == TRUE) return LOCATION_ERROR_NONE;
142
143         int ret = priv->mod->ops.start (priv->mod->handler, wps_status_cb, wps_position_cb, wps_velocity_cb, self);
144         if (ret == LOCATION_ERROR_NONE) {
145                 priv->is_started = TRUE;
146                 location_setting_add_notify (GPS_ENABLED, location_setting_wps_cb, self);
147                 location_setting_add_notify (NETWORK_ENABLED, location_setting_wps_cb, self);
148         }
149         return ret;
150 }
151
152 static int
153 location_wps_stop (LocationWps *self)
154 {
155         LOCATION_LOGD("location_wps_stop");
156         LocationWpsPrivate* priv = GET_PRIVATE(self);
157         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
158         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
159         g_return_val_if_fail (priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE);
160         if( priv->is_started == FALSE) return LOCATION_ERROR_NONE;
161
162         int ret = priv->mod->ops.stop (priv->mod->handler);
163         if (ret == LOCATION_ERROR_NONE) {
164                 priv->is_started = FALSE;
165                 location_setting_ignore_notify (GPS_ENABLED, location_setting_wps_cb);
166                 location_setting_ignore_notify (NETWORK_ENABLED, location_setting_wps_cb);
167         }
168         return ret;
169 }
170
171 static void
172 location_wps_dispose (GObject *gobject)
173 {
174         LOCATION_LOGD("location_wps_dispose");
175         G_OBJECT_CLASS (location_wps_parent_class)->dispose (gobject);
176 }
177
178 static void
179 location_wps_finalize (GObject *gobject)
180 {
181         LOCATION_LOGD("location_wps_finalize");
182         LocationWpsPrivate* priv = GET_PRIVATE(gobject);
183         module_free(priv->mod, "wps");
184         G_OBJECT_CLASS (location_wps_parent_class)->finalize (gobject);
185 }
186
187 static void
188 location_wps_set_property (GObject *object,
189         guint property_id,
190         const GValue *value,
191         GParamSpec *pspec)
192 {
193         LocationWpsPrivate* priv = GET_PRIVATE(object);
194         int ret = 0;
195
196         switch (property_id){
197                 case PROP_BOUNDARY:{
198                         GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
199                         ret = set_prop_boundary(&priv->boundary_list, boundary_list);
200                         if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret);
201                         break;
202                 }
203                 case PROP_REMOVAL_BOUNDARY: {
204                         LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value);
205                         ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
206                         if(ret != 0) LOCATION_LOGD("Set removal boundary. Error[%d]", ret);
207                         break;
208                 }
209                 case PROP_UPDATE_INTERVAL: {
210                         guint interval = g_value_get_uint(value);
211                         if(interval > 0) {
212                                 if(interval < LOCATION_UPDATE_INTERVAL_MAX)
213                                         priv->interval = interval;
214                                 else
215                                         priv->interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
216                         }
217                         else
218                                 priv->interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
219                         break;
220                 }
221                 default:
222                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
223                         break;
224         }
225 }
226
227 static void
228 location_wps_get_property (GObject *object,
229         guint property_id,
230         GValue *value,
231         GParamSpec *pspec)
232 {
233         LocationWpsPrivate *priv = GET_PRIVATE (object);
234
235         switch (property_id){
236                 case PROP_METHOD_TYPE:
237                         g_value_set_int(value, LOCATION_METHOD_WPS);
238                         break;
239                 case PROP_LAST_POSITION:
240                         g_value_set_boxed (value, priv->pos);
241                         break;
242                 case PROP_BOUNDARY:
243                         g_value_set_pointer(value, g_list_first(priv->boundary_list));
244                         break;
245                 case PROP_UPDATE_INTERVAL:
246                         g_value_set_uint(value, priv->interval);
247                         break;
248                 default:
249                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
250                         break;
251         }
252 }
253
254 static int
255 location_wps_get_position (LocationWps *self,
256         LocationPosition **position,
257         LocationAccuracy **accuracy)
258 {
259         LOCATION_LOGD("location_wps_get_position");
260
261         LocationWpsPrivate *priv = GET_PRIVATE (self);
262         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
263         setting_retval_if_fail(GPS_ENABLED);
264         setting_retval_if_fail(NETWORK_ENABLED);
265
266         LocModWpsOps ops = priv->mod->ops;
267         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
268         g_return_val_if_fail (ops.get_position, LOCATION_ERROR_NOT_AVAILABLE);
269         return ops.get_position(priv->mod->handler, position, accuracy);
270 }
271
272 static int
273 location_wps_get_velocity (LocationWps *self,
274         LocationVelocity **velocity,
275         LocationAccuracy **accuracy)
276 {
277         LOCATION_LOGD("location_wps_get_velocity");
278
279         LocationWpsPrivate *priv = GET_PRIVATE (self);
280         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
281         setting_retval_if_fail(GPS_ENABLED);
282         setting_retval_if_fail(NETWORK_ENABLED);
283
284         LocModWpsOps ops = priv->mod->ops;
285         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
286         g_return_val_if_fail (ops.get_velocity, LOCATION_ERROR_NOT_AVAILABLE);
287         return ops.get_velocity(priv->mod->handler, velocity, accuracy);
288 }
289
290 static void
291 location_ielement_interface_init (LocationIElementInterface *iface)
292 {
293         iface->start = (TYPE_START_FUNC)location_wps_start;
294         iface->stop = (TYPE_STOP_FUNC)location_wps_stop;
295         iface->get_position = (TYPE_GET_POSITION)location_wps_get_position;
296         iface->get_velocity = (TYPE_GET_VELOCITY)location_wps_get_velocity;
297 }
298
299 static void
300 location_wps_init (LocationWps *self)
301 {
302         LOCATION_LOGD("location_wps_init");
303         LocationWpsPrivate* priv = GET_PRIVATE(self);
304
305         priv->mod = (LocationWpsMod*)module_new("wps");
306         if(!priv->mod) LOCATION_LOGW("module loading failed");
307
308         priv->is_started = FALSE;
309         priv->enabled= FALSE;
310         priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
311
312         priv->pos = NULL;
313         priv->vel = NULL;
314         priv->acc = NULL;
315         priv->zone_status = ZONE_STATUS_NONE;
316         priv->boundary_list = NULL;
317 }
318
319 static void
320 location_wps_class_init (LocationWpsClass *klass)
321 {
322         LOCATION_LOGD("location_wps_class_init");
323         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
324
325         gobject_class->set_property = location_wps_set_property;
326         gobject_class->get_property = location_wps_get_property;
327
328         gobject_class->dispose = location_wps_dispose;
329         gobject_class->finalize = location_wps_finalize;
330
331         g_type_class_add_private (klass, sizeof (LocationWpsPrivate));
332
333         signals[SERVICE_ENABLED] = g_signal_new ("service-enabled",
334                         G_TYPE_FROM_CLASS (klass),
335                         G_SIGNAL_RUN_FIRST |
336                         G_SIGNAL_NO_RECURSE,
337                         G_STRUCT_OFFSET (LocationWpsClass, enabled),
338                         NULL, NULL,
339                         location_VOID__UINT,
340                         G_TYPE_NONE, 1,
341                         G_TYPE_UINT);
342
343         signals[SERVICE_DISABLED] = g_signal_new ("service-disabled",
344                         G_TYPE_FROM_CLASS (klass),
345                         G_SIGNAL_RUN_FIRST |
346                         G_SIGNAL_NO_RECURSE,
347                         G_STRUCT_OFFSET (LocationWpsClass, disabled),
348                         NULL, NULL,
349                         location_VOID__UINT,
350                         G_TYPE_NONE, 1,
351                         G_TYPE_UINT);
352
353         signals[SERVICE_UPDATED] = g_signal_new ("service-updated",
354                         G_TYPE_FROM_CLASS (klass),
355                         G_SIGNAL_RUN_FIRST |
356                         G_SIGNAL_NO_RECURSE,
357                         G_STRUCT_OFFSET (LocationWpsClass, updated),
358                         NULL, NULL,
359                         location_VOID__UINT_POINTER_POINTER,
360                         G_TYPE_NONE, 3,
361                         G_TYPE_UINT,
362                         G_TYPE_POINTER,
363                         G_TYPE_POINTER);
364
365         signals[ZONE_IN] = g_signal_new ("zone-in",
366                         G_TYPE_FROM_CLASS (klass),
367                         G_SIGNAL_RUN_FIRST |
368                         G_SIGNAL_NO_RECURSE,
369                         G_STRUCT_OFFSET (LocationWpsClass, zone_in),
370                         NULL, NULL,
371                         location_VOID__UINT_POINTER_POINTER,
372                         G_TYPE_NONE, 3,
373                         G_TYPE_UINT,
374                         G_TYPE_POINTER,
375                         G_TYPE_POINTER);
376
377         signals[ZONE_OUT] = g_signal_new ("zone-out",
378                         G_TYPE_FROM_CLASS (klass),
379                         G_SIGNAL_RUN_FIRST |
380                         G_SIGNAL_NO_RECURSE,
381                         G_STRUCT_OFFSET (LocationWpsClass, zone_out),
382                         NULL, NULL,
383                         location_VOID__UINT_POINTER_POINTER,
384                         G_TYPE_NONE, 3,
385                         G_TYPE_UINT,
386                         G_TYPE_POINTER,
387                         G_TYPE_POINTER);
388
389         properties[PROP_METHOD_TYPE] = g_param_spec_int ("method",
390                         "method type",
391                         "location method type name",
392                         LOCATION_METHOD_WPS,
393                         LOCATION_METHOD_WPS,
394                         LOCATION_METHOD_WPS,
395                         G_PARAM_READABLE);
396
397         properties[PROP_LAST_POSITION] = g_param_spec_boxed ("last-position",
398                         "wps last position prop",
399                         "wps last position data",
400                         LOCATION_TYPE_POSITION,
401                         G_PARAM_READABLE);
402
403         properties[PROP_UPDATE_INTERVAL] = g_param_spec_uint ("update-interval",
404                         "wps update interval prop",
405                         "wps update interval data",
406                         LOCATION_UPDATE_INTERVAL_MIN,
407                         LOCATION_UPDATE_INTERVAL_MAX,
408                         LOCATION_UPDATE_INTERVAL_DEFAULT,
409                         G_PARAM_READWRITE);
410
411         properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary",
412                         "wps boundary prop",
413                         "wps boundary data",
414                         G_PARAM_READWRITE);
415
416         properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
417                         "wps removal boundary prop",
418                         "wps removal boundary data",
419                         LOCATION_TYPE_BOUNDARY,
420                         G_PARAM_READWRITE);
421
422         g_object_class_install_properties (gobject_class,
423                         PROP_MAX,
424                         properties);
425 }
426