Fix naming of interface flags
[connman] / src / iface.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007  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 <string.h>
27 #include <arpa/inet.h>
28
29 #include <glib.h>
30 #include <gdbus.h>
31
32 #include <hal/libhal.h>
33
34 #include "connman.h"
35
36 static GSList *drivers = NULL;
37
38 int connman_iface_register(struct connman_iface_driver *driver)
39 {
40         DBG("driver %p", driver);
41
42         drivers = g_slist_append(drivers, driver);
43
44         return 0;
45 }
46
47 void connman_iface_unregister(struct connman_iface_driver *driver)
48 {
49         DBG("driver %p", driver);
50
51         drivers = g_slist_remove(drivers, driver);
52 }
53
54 static GSList *interfaces = NULL;
55
56 static void device_free(void *data)
57 {
58         struct connman_iface *iface = data;
59
60         DBG("iface %p", iface);
61
62         if (iface->driver && iface->driver->remove)
63                 iface->driver->remove(iface);
64
65         g_free(iface->path);
66         g_free(iface->udi);
67         g_free(iface->sysfs);
68         g_free(iface);
69 }
70
71 static int probe_device(LibHalContext *ctx,
72                         struct connman_iface_driver *driver, const char *udi)
73 {
74         DBusConnection *conn;
75         struct connman_iface *iface;
76         char *temp, *sysfs;
77         int err;
78
79         DBG("ctx %p driver %p udi %s", ctx, driver, udi);
80
81         if (!driver->probe)
82                 return -1;
83
84         iface = g_try_new0(struct connman_iface, 1);
85         if (iface == NULL)
86                 return -1;
87
88         temp = g_path_get_basename(udi);
89         iface->path = g_strdup_printf("%s/%s", CONNMAN_IFACE_BASEPATH, temp);
90         g_free(temp);
91
92         iface->udi = g_strdup(udi);
93
94         DBG("path %s", iface->path);
95
96         sysfs = libhal_device_get_property_string(ctx, udi,
97                                                 "linux.sysfs_path", NULL);
98         if (sysfs != NULL)
99                 iface->sysfs = g_strdup(sysfs);
100
101         iface->type = CONNMAN_IFACE_TYPE_UNKNOWN;
102         iface->flags = 0;
103
104         DBG("iface %p", iface);
105
106         err = driver->probe(iface);
107         if (err < 0) {
108                 device_free(iface);
109                 return -1;
110         }
111
112         iface->driver = driver;
113
114         conn = libhal_ctx_get_dbus_connection(ctx);
115
116         g_dbus_register_object(conn, iface->path, iface, device_free);
117
118         interfaces = g_slist_append(interfaces, iface);
119
120         if ((iface->flags & CONNMAN_IFACE_FLAG_IPV4) &&
121                                                 driver->get_ipv4) {
122                 driver->get_ipv4(iface, &iface->ipv4);
123
124                 DBG("address %s", inet_ntoa(iface->ipv4.address));
125         }
126
127         return 0;
128 }
129
130 static void device_added(LibHalContext *ctx, const char *udi)
131 {
132         GSList *list;
133
134         DBG("ctx %p udi %s", ctx, udi);
135
136         for (list = drivers; list; list = list->next) {
137                 struct connman_iface_driver *driver = list->data;
138
139                 if (driver->capability == NULL)
140                         continue;
141
142                 if (libhal_device_query_capability(ctx, udi,
143                                         driver->capability, NULL) == TRUE) {
144                         if (probe_device(ctx, driver, udi) == 0)
145                                 break;
146                 }
147         }
148 }
149
150 static void device_removed(LibHalContext *ctx, const char *udi)
151 {
152         DBusConnection *conn;
153         GSList *list;
154
155         DBG("ctx %p udi %s", ctx, udi);
156
157         conn = libhal_ctx_get_dbus_connection(ctx);
158
159         for (list = interfaces; list; list = list->next) {
160                 struct connman_iface *iface = list->data;
161
162                 if (strcmp(udi, iface->udi) == 0) {
163                         interfaces = g_slist_remove(interfaces, iface);
164                         g_dbus_unregister_object(conn, iface->path);
165                         break;
166                 }
167         }
168 }
169
170 static void probe_driver(LibHalContext *ctx,
171                                 struct connman_iface_driver *driver)
172 {
173         char **list;
174         int num;
175
176         DBG("ctx %p driver %p", ctx, driver);
177
178         list = libhal_find_device_by_capability(ctx,
179                                         driver->capability, &num, NULL);
180         if (list) {
181                 char **tmp = list;
182
183                 while (*tmp) {
184                         probe_device(ctx, driver, *tmp);
185                         tmp++;
186                 }
187
188                 libhal_free_string_array(list);
189         }
190 }
191
192 static void find_devices(LibHalContext *ctx)
193 {
194         GSList *list;
195
196         DBG("ctx %p", ctx);
197
198         for (list = drivers; list; list = list->next) {
199                 struct connman_iface_driver *driver = list->data;
200
201                 DBG("driver %p", driver);
202
203                 if (driver->capability == NULL)
204                         continue;
205
206                 probe_driver(ctx, driver);
207         }
208 }
209
210 static LibHalContext *hal_ctx = NULL;
211
212 static void hal_init(void *data)
213 {
214         DBusConnection *conn = data;
215
216         DBG("conn %p", conn);
217
218         if (hal_ctx != NULL)
219                 return;
220
221         hal_ctx = libhal_ctx_new();
222         if (hal_ctx == NULL)
223                 return;
224
225         if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) {
226                 libhal_ctx_free(hal_ctx);
227                 return;
228         }
229
230         if (libhal_ctx_init(hal_ctx, NULL) == FALSE) {
231                 libhal_ctx_free(hal_ctx);
232                 return ;
233         }
234
235         libhal_ctx_set_device_added(hal_ctx, device_added);
236         libhal_ctx_set_device_removed(hal_ctx, device_removed);
237
238         //libhal_ctx_set_device_new_capability(hal_ctx, new_capability);
239         //libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability);
240
241         find_devices(hal_ctx);
242 }
243
244 static void hal_cleanup(void *data)
245 {
246         DBusConnection *conn = data;
247         GSList *list;
248
249         DBG("conn %p", conn);
250
251         if (hal_ctx == NULL)
252                 return;
253
254         for (list = interfaces; list; list = list->next) {
255                 struct connman_iface *iface = list->data;
256
257                 DBG("path %s", iface->path);
258
259                 g_dbus_unregister_object(conn, iface->path);
260         }
261
262         g_slist_free(interfaces);
263
264         interfaces = NULL;
265
266         libhal_ctx_shutdown(hal_ctx, NULL);
267
268         libhal_ctx_free(hal_ctx);
269
270         hal_ctx = NULL;
271 }
272
273 static DBusConnection *connection = NULL;
274 static guint hal_watch = 0;
275
276 int __connman_iface_init(DBusConnection *conn)
277 {
278         DBG("conn %p", conn);
279
280         connection = dbus_connection_ref(conn);
281         if (connection == NULL)
282                 return -1;
283
284         hal_init(connection);
285
286         hal_watch = g_dbus_add_watch(connection, "org.freedesktop.Hal",
287                                 hal_init, hal_cleanup, connection, NULL);
288
289         return 0;
290 }
291
292 void __connman_iface_cleanup(void)
293 {
294         DBG("conn %p", connection);
295
296         g_dbus_remove_watch(connection, hal_watch);
297
298         hal_cleanup(connection);
299
300         dbus_connection_unref(connection);
301 }