Add basic support for a location detection framework
[platform/upstream/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 /**
98  * connman_location_get_data:
99  * @location: Location structure
100  *
101  * Get private location data pointer
102  */
103 void *connman_location_get_data(struct connman_location *location)
104 {
105         return location->driver_data;
106 }
107
108 /**
109  * connman_location_set_data:
110  * @location: Location structure
111  * @data: data pointer
112  *
113  * Set private location data pointer
114  */
115 void connman_location_set_data(struct connman_location *location, void *data)
116 {
117         location->driver_data = data;
118 }
119
120 static GSList *driver_list = NULL;
121
122 static gint compare_priority(gconstpointer a, gconstpointer b)
123 {
124         const struct connman_location_driver *driver1 = a;
125         const struct connman_location_driver *driver2 = b;
126
127         return driver2->priority - driver1->priority;
128 }
129
130 /**
131  * connman_location_driver_register:
132  * @driver: Location driver definition
133  *
134  * Register a new Location driver
135  *
136  * Returns: %0 on success
137  */
138 int connman_location_driver_register(struct connman_location_driver *driver)
139 {
140         DBG("driver %p name %s", driver, driver->name);
141
142         driver_list = g_slist_insert_sorted(driver_list, driver,
143                                                         compare_priority);
144
145         return 0;
146 }
147
148 /**
149  * connman_location_driver_unregister:
150  * @driver: Location driver definition
151  *
152  * Remove a previously registered Location driver
153  */
154 void connman_location_driver_unregister(struct connman_location_driver *driver)
155 {
156         DBG("driver %p name %s", driver, driver->name);
157
158         driver_list = g_slist_remove(driver_list, driver);
159 }
160
161 /**
162  * connman_location_report_result:
163  * @location: location structure
164  * @result: result information
165  *
166  * Report result of a location detection
167  */
168 void connman_location_report_result(struct connman_location *location,
169                                         enum connman_location_result result)
170 {
171         DBG("location %p result %d", location, result);
172
173         if (location == NULL)
174                 return;
175
176         if (location->result == result)
177                 return;
178
179         location->result = result;
180
181         switch (location->result) {
182         case CONNMAN_LOCATION_RESULT_UNKNOWN:
183                 return;
184         case CONNMAN_LOCATION_RESULT_PORTAL:
185                 //__connman_service_indicate_state(location->service,
186                 //                              CONNMAN_SERVICE_STATE_LOGIN);
187                 break;
188         case CONNMAN_LOCATION_RESULT_ONLINE:
189                 //__connman_service_indicate_state(location->service,
190                 //                              CONNMAN_SERVICE_STATE_ONLINE);
191                 break;
192         }
193 }
194
195 struct connman_location *__connman_location_create(struct connman_service *service)
196 {
197         struct connman_location *location;
198
199         DBG("service %p", service);
200
201         if (service == NULL)
202                 return NULL;
203
204         location = g_try_new0(struct connman_location, 1);
205         if (location == NULL)
206                 return NULL;
207
208         DBG("location %p", location);
209
210         location->refcount = 1;
211
212         location->service = service;
213         location->result = CONNMAN_LOCATION_RESULT_UNKNOWN;
214
215         return location;
216 }
217
218 int __connman_location_detect(struct connman_service *service)
219 {
220         struct connman_location *location;
221         GSList *list;
222
223         DBG("service %p", service);
224
225         location = __connman_service_get_location(service);
226         if (location == NULL)
227                 return -EINVAL;
228
229         if (location->driver)
230                 return -EBUSY;
231
232         for (list = driver_list; list; list = list->next) {
233                 struct connman_location_driver *driver = list->data;
234
235                 DBG("driver %p name %s", driver, driver->name);
236
237                 if (driver->detect(location) == 0) {
238                         location->driver = driver;
239                         break;
240                 }
241         }
242
243         if (location->driver == NULL)
244                 connman_location_report_result(location,
245                                         CONNMAN_LOCATION_RESULT_ONLINE);
246
247         return 0;
248 }
249
250 int __connman_location_finish(struct connman_service *service)
251 {
252         struct connman_location *location;
253
254         DBG("service %p", service);
255
256         location = __connman_service_get_location(service);
257         if (location == NULL)
258                 return -EINVAL;
259
260         if (location->driver) {
261                 location->driver->finish(location);
262                 location->driver = NULL;
263         }
264
265         return 0;
266 }
267
268 int __connman_location_init(void)
269 {
270         return 0;
271 }
272
273 void __connman_location_cleanup(void)
274 {
275 }