5 * Copyright (C) 2007 Intel Corporation. All rights reserved.
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.
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.
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
27 #include <arpa/inet.h>
32 #include <hal/libhal.h>
36 static GSList *drivers = NULL;
38 int connman_iface_register(struct connman_iface_driver *driver)
40 DBG("driver %p", driver);
42 drivers = g_slist_append(drivers, driver);
47 void connman_iface_unregister(struct connman_iface_driver *driver)
49 DBG("driver %p", driver);
51 drivers = g_slist_remove(drivers, driver);
54 static GSList *interfaces = NULL;
56 struct connman_iface *__connman_iface_find(int index)
60 for (list = interfaces; list; list = list->next) {
61 struct connman_iface *iface = list->data;
63 if (iface->index == index)
70 void __connman_iface_list(DBusMessageIter *iter)
76 for (list = interfaces; list; list = list->next) {
77 struct connman_iface *iface = list->data;
79 dbus_message_iter_append_basic(iter,
80 DBUS_TYPE_OBJECT_PATH, &iface->path);
84 int connman_iface_update(struct connman_iface *iface,
85 enum connman_iface_state state)
88 case CONNMAN_IFACE_STATE_ACTIVE:
89 if (iface->type == CONNMAN_IFACE_TYPE_80211) {
90 if (iface->driver->scan)
91 iface->driver->scan(iface);
93 if (iface->driver->connect)
94 iface->driver->connect(iface, NULL);
98 case CONNMAN_IFACE_STATE_CONNECTED:
99 __connman_dhcp_request(iface);
106 iface->state = state;
111 void connman_iface_indicate_carrier(struct connman_iface *iface, int carrier)
113 DBG("iface %p carrier %d", iface, carrier);
116 static DBusMessage *enable_iface(DBusConnection *conn,
117 DBusMessage *msg, void *data)
119 struct connman_iface *iface = data;
120 struct connman_iface_driver *driver = iface->driver;
123 DBG("conn %p", conn);
125 reply = dbus_message_new_method_return(msg);
129 if (driver->activate)
130 driver->activate(iface);
132 dbus_message_append_args(reply, DBUS_TYPE_INVALID);
137 static GDBusMethodTable iface_methods[] = {
138 { "Enable", "", "", enable_iface },
142 static dbus_bool_t get_type(DBusConnection *conn,
143 DBusMessageIter *iter, void *data)
145 struct connman_iface *iface = data;
148 DBG("iface %p", iface);
150 switch (iface->type) {
151 case CONNMAN_IFACE_TYPE_80203:
154 case CONNMAN_IFACE_TYPE_80211:
157 case CONNMAN_IFACE_TYPE_WIMAX:
160 case CONNMAN_IFACE_TYPE_BLUETOOTH:
168 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type);
173 static GDBusPropertyTable iface_properties[] = {
174 { "Type", "s", get_type },
178 static void device_free(void *data)
180 struct connman_iface *iface = data;
182 DBG("iface %p", iface);
184 if (iface->driver && iface->driver->remove)
185 iface->driver->remove(iface);
189 g_free(iface->sysfs);
193 static int probe_device(LibHalContext *ctx,
194 struct connman_iface_driver *driver, const char *udi)
196 DBusConnection *conn;
197 struct connman_iface *iface;
201 DBG("ctx %p driver %p udi %s", ctx, driver, udi);
206 iface = g_try_new0(struct connman_iface, 1);
210 temp = g_path_get_basename(udi);
211 iface->path = g_strdup_printf("%s/%s", CONNMAN_IFACE_BASEPATH, temp);
214 iface->udi = g_strdup(udi);
216 DBG("path %s", iface->path);
218 sysfs = libhal_device_get_property_string(ctx, udi,
219 "linux.sysfs_path", NULL);
221 iface->sysfs = g_strdup(sysfs);
225 if (g_str_has_prefix(driver->capability, "net") == TRUE)
226 iface->index = libhal_device_get_property_int(ctx, udi,
227 "net.linux.ifindex", NULL);
229 iface->type = CONNMAN_IFACE_TYPE_UNKNOWN;
231 iface->state = CONNMAN_IFACE_STATE_UNKNOWN;
233 DBG("iface %p", iface);
235 err = driver->probe(iface);
241 iface->driver = driver;
243 conn = libhal_ctx_get_dbus_connection(ctx);
245 g_dbus_register_object(conn, iface->path, iface, device_free);
247 interfaces = g_slist_append(interfaces, iface);
249 if ((iface->flags & CONNMAN_IFACE_FLAG_IPV4) &&
251 driver->get_ipv4(iface, &iface->ipv4);
253 DBG("address %s", inet_ntoa(iface->ipv4.address));
256 g_dbus_register_interface(conn, iface->path,
257 CONNMAN_IFACE_INTERFACE,
258 iface_methods, NULL, iface_properties);
260 g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
261 CONNMAN_MANAGER_INTERFACE,
263 DBUS_TYPE_OBJECT_PATH, &iface->path,
269 static void device_added(LibHalContext *ctx, const char *udi)
273 DBG("ctx %p udi %s", ctx, udi);
275 for (list = drivers; list; list = list->next) {
276 struct connman_iface_driver *driver = list->data;
278 if (driver->capability == NULL)
281 if (libhal_device_query_capability(ctx, udi,
282 driver->capability, NULL) == TRUE) {
283 if (probe_device(ctx, driver, udi) == 0)
289 static void device_removed(LibHalContext *ctx, const char *udi)
291 DBusConnection *conn;
294 DBG("ctx %p udi %s", ctx, udi);
296 conn = libhal_ctx_get_dbus_connection(ctx);
298 for (list = interfaces; list; list = list->next) {
299 struct connman_iface *iface = list->data;
301 if (strcmp(udi, iface->udi) == 0) {
302 g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
303 CONNMAN_MANAGER_INTERFACE,
305 DBUS_TYPE_OBJECT_PATH, &iface->path,
307 interfaces = g_slist_remove(interfaces, iface);
308 g_dbus_unregister_interface(conn, iface->path,
309 CONNMAN_IFACE_INTERFACE);
310 g_dbus_unregister_object(conn, iface->path);
316 static void probe_driver(LibHalContext *ctx,
317 struct connman_iface_driver *driver)
322 DBG("ctx %p driver %p", ctx, driver);
324 list = libhal_find_device_by_capability(ctx,
325 driver->capability, &num, NULL);
330 probe_device(ctx, driver, *tmp);
334 libhal_free_string_array(list);
338 static void find_devices(LibHalContext *ctx)
344 for (list = drivers; list; list = list->next) {
345 struct connman_iface_driver *driver = list->data;
347 DBG("driver %p", driver);
349 if (driver->capability == NULL)
352 probe_driver(ctx, driver);
356 static LibHalContext *hal_ctx = NULL;
358 static void hal_init(void *data)
360 DBusConnection *conn = data;
362 DBG("conn %p", conn);
367 hal_ctx = libhal_ctx_new();
371 if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) {
372 libhal_ctx_free(hal_ctx);
376 if (libhal_ctx_init(hal_ctx, NULL) == FALSE) {
377 libhal_ctx_free(hal_ctx);
381 libhal_ctx_set_device_added(hal_ctx, device_added);
382 libhal_ctx_set_device_removed(hal_ctx, device_removed);
384 //libhal_ctx_set_device_new_capability(hal_ctx, new_capability);
385 //libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability);
387 find_devices(hal_ctx);
390 static void hal_cleanup(void *data)
392 DBusConnection *conn = data;
395 DBG("conn %p", conn);
400 for (list = interfaces; list; list = list->next) {
401 struct connman_iface *iface = list->data;
403 DBG("path %s", iface->path);
405 g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
406 CONNMAN_MANAGER_INTERFACE,
408 DBUS_TYPE_OBJECT_PATH, &iface->path,
411 g_dbus_unregister_interface(conn, iface->path,
412 CONNMAN_IFACE_INTERFACE);
414 g_dbus_unregister_object(conn, iface->path);
417 g_slist_free(interfaces);
421 libhal_ctx_shutdown(hal_ctx, NULL);
423 libhal_ctx_free(hal_ctx);
428 static DBusConnection *connection = NULL;
429 static guint hal_watch = 0;
431 int __connman_iface_init(DBusConnection *conn)
433 DBG("conn %p", conn);
435 connection = dbus_connection_ref(conn);
436 if (connection == NULL)
439 hal_init(connection);
441 hal_watch = g_dbus_add_watch(connection, "org.freedesktop.Hal",
442 hal_init, hal_cleanup, connection, NULL);
447 void __connman_iface_cleanup(void)
449 DBG("conn %p", connection);
451 g_dbus_remove_watch(connection, hal_watch);
453 hal_cleanup(connection);
455 dbus_connection_unref(connection);