dbus: Add connman_dbus_setting_changed_*()
[framework/connectivity/connman.git] / src / location.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "connman.h"
27
28 struct connman_location {
29         gint refcount;
30         struct connman_service *service;
31         enum connman_location_result result;
32
33         struct connman_location_driver *driver;
34         void *driver_data;
35 };
36
37 /**
38  * connman_location_ref:
39  * @location: Location structure
40  *
41  * Increase reference counter of location
42  */
43 struct connman_location *connman_location_ref(struct connman_location *location)
44 {
45         g_atomic_int_inc(&location->refcount);
46
47         return location;
48 }
49
50 /**
51  * connman_location_unref:
52  * @location: Location structure
53  *
54  * Decrease reference counter of location
55  */
56 void connman_location_unref(struct connman_location *location)
57 {
58         if (g_atomic_int_dec_and_test(&location->refcount) == FALSE)
59                 return;
60
61         if (location->driver) {
62                 location->driver->finish(location);
63                 location->driver = NULL;
64         }
65
66         g_free(location);
67 }
68
69 /**
70  * connman_location_get_type:
71  * @location: Location structure
72  *
73  * Get the service type of location
74  */
75 enum connman_service_type connman_location_get_type(struct connman_location *location)
76 {
77         if (location == NULL)
78                 return CONNMAN_SERVICE_TYPE_UNKNOWN;
79
80         return connman_service_get_type(location->service);
81 }
82
83 /**
84  * connman_location_get_interface:
85  * @location: location structure
86  *
87  * Get network interface of location
88  */
89 char *connman_location_get_interface(struct connman_location *location)
90 {
91         if (location == NULL)
92                 return NULL;
93
94         return connman_service_get_interface(location->service);
95 }
96
97 struct connman_service *connman_location_get_service(
98                                         struct connman_location *location)
99 {
100         return location->service;
101 }
102 /**
103  * connman_location_get_data:
104  * @location: Location structure
105  *
106  * Get private location data pointer
107  */
108 void *connman_location_get_data(struct connman_location *location)
109 {
110         return location->driver_data;
111 }
112
113 /**
114  * connman_location_set_data:
115  * @location: Location structure
116  * @data: data pointer
117  *
118  * Set private location data pointer
119  */
120 void connman_location_set_data(struct connman_location *location, void *data)
121 {
122         location->driver_data = data;
123 }
124
125 static GSList *driver_list = NULL;
126
127 static gint compare_priority(gconstpointer a, gconstpointer b)
128 {
129         const struct connman_location_driver *driver1 = a;
130         const struct connman_location_driver *driver2 = b;
131
132         return driver2->priority - driver1->priority;
133 }
134
135 /**
136  * connman_location_driver_register:
137  * @driver: Location driver definition
138  *
139  * Register a new Location driver
140  *
141  * Returns: %0 on success
142  */
143 int connman_location_driver_register(struct connman_location_driver *driver)
144 {
145         DBG("driver %p name %s", driver, driver->name);
146
147         driver_list = g_slist_insert_sorted(driver_list, driver,
148                                                         compare_priority);
149
150         return 0;
151 }
152
153 /**
154  * connman_location_driver_unregister:
155  * @driver: Location driver definition
156  *
157  * Remove a previously registered Location driver
158  */
159 void connman_location_driver_unregister(struct connman_location_driver *driver)
160 {
161         DBG("driver %p name %s", driver, driver->name);
162
163         driver_list = g_slist_remove(driver_list, driver);
164 }
165
166 /**
167  * connman_location_report_result:
168  * @location: location structure
169  * @result: result information
170  *
171  * Report result of a location detection
172  */
173 void connman_location_report_result(struct connman_location *location,
174                                         enum connman_location_result result)
175 {
176         DBG("location %p result %d", location, result);
177
178         if (location == NULL)
179                 return;
180
181         if (location->result == result)
182                 return;
183
184         location->result = result;
185
186         switch (location->result) {
187         case CONNMAN_LOCATION_RESULT_UNKNOWN:
188                 return;
189         case CONNMAN_LOCATION_RESULT_PORTAL:
190                 __connman_service_request_login(location->service);
191                 break;
192         case CONNMAN_LOCATION_RESULT_ONLINE:
193                 __connman_service_indicate_state(location->service,
194                                                 CONNMAN_SERVICE_STATE_ONLINE,
195                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
196                 break;
197         }
198 }
199
200 struct connman_location *__connman_location_create(struct connman_service *service)
201 {
202         struct connman_location *location;
203
204         DBG("service %p", service);
205
206         if (service == NULL)
207                 return NULL;
208
209         location = g_try_new0(struct connman_location, 1);
210         if (location == NULL)
211                 return NULL;
212
213         DBG("location %p", location);
214
215         location->refcount = 1;
216
217         location->service = service;
218         location->result = CONNMAN_LOCATION_RESULT_UNKNOWN;
219
220         return location;
221 }
222
223 int __connman_location_detect(struct connman_service *service)
224 {
225         struct connman_location *location;
226         GSList *list;
227
228         DBG("service %p", service);
229
230         location = __connman_service_get_location(service);
231         if (location == NULL)
232                 return -EINVAL;
233
234         if (location->driver) {
235                 location->result = CONNMAN_LOCATION_RESULT_UNKNOWN;
236                 location->driver->finish(location);
237
238                 if (location->driver->detect(location) == 0)
239                         return 0;
240
241                 location->driver = NULL;
242         }
243
244         for (list = driver_list; list; list = list->next) {
245                 struct connman_location_driver *driver = list->data;
246
247                 DBG("driver %p name %s", driver, driver->name);
248
249                 if (driver->detect(location) == 0) {
250                         location->driver = driver;
251                         break;
252                 }
253         }
254
255         if (location->driver == NULL)
256                 connman_location_report_result(location,
257                                         CONNMAN_LOCATION_RESULT_ONLINE);
258
259         return 0;
260 }
261
262 int __connman_location_finish(struct connman_service *service)
263 {
264         struct connman_location *location;
265
266         DBG("service %p", service);
267
268         location = __connman_service_get_location(service);
269         if (location == NULL)
270                 return -EINVAL;
271
272         location->result = CONNMAN_LOCATION_RESULT_UNKNOWN;
273
274         if (location->driver) {
275                 location->driver->finish(location);
276                 location->driver = NULL;
277         }
278
279         return 0;
280 }
281
282 int __connman_location_init(void)
283 {
284         DBG("");
285
286         return 0;
287 }
288
289 void __connman_location_cleanup(void)
290 {
291         DBG("");
292 }