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
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
36 #include <net/route.h>
38 #include <linux/netlink.h>
39 #include <linux/rtnetlink.h>
44 #include <hal/libhal.h>
48 static DBusConnection *connection = NULL;
50 static GSList *drivers = NULL;
52 int connman_iface_register(struct connman_iface_driver *driver)
54 DBG("driver %p", driver);
56 drivers = g_slist_append(drivers, driver);
61 void connman_iface_unregister(struct connman_iface_driver *driver)
63 DBG("driver %p", driver);
65 drivers = g_slist_remove(drivers, driver);
68 static GSList *interfaces = NULL;
70 struct connman_iface *__connman_iface_find(int index)
74 for (list = interfaces; list; list = list->next) {
75 struct connman_iface *iface = list->data;
77 if (iface->index == index)
84 void __connman_iface_list(DBusMessageIter *iter)
90 for (list = interfaces; list; list = list->next) {
91 struct connman_iface *iface = list->data;
93 dbus_message_iter_append_basic(iter,
94 DBUS_TYPE_OBJECT_PATH, &iface->path);
98 int connman_iface_update(struct connman_iface *iface,
99 enum connman_iface_state state)
101 const char *str = NULL;
104 case CONNMAN_IFACE_STATE_ENABLED:
106 if (iface->type == CONNMAN_IFACE_TYPE_80211) {
107 if (iface->driver->connect)
108 iface->driver->connect(iface, NULL);
112 case CONNMAN_IFACE_STATE_CARRIER:
114 __connman_dhcp_request(iface);
117 case CONNMAN_IFACE_STATE_READY:
121 case CONNMAN_IFACE_STATE_SHUTDOWN:
128 iface->state = state;
131 g_dbus_emit_signal(connection, iface->path,
132 CONNMAN_IFACE_INTERFACE, "StateChanged",
133 DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
139 void connman_iface_indicate_carrier(struct connman_iface *iface, int carrier)
141 DBG("iface %p carrier %d", iface, carrier);
144 int connman_iface_get_ipv4(struct connman_iface *iface,
145 struct connman_ipv4 *ipv4)
152 if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
155 DBG("iface %p ipv4 %p", iface, ipv4);
157 memset(&req, 0, sizeof(req));
158 req.hdr.nlmsg_len = sizeof(req.hdr) + sizeof(req.msg);
159 req.hdr.nlmsg_type = RTM_GETADDR;
160 req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
161 req.hdr.nlmsg_pid = 0;
162 req.hdr.nlmsg_seq = 4711;
163 req.msg.rtgen_family = AF_INET;
165 __connman_rtnl_send(&req, sizeof(req));
170 int connman_iface_set_ipv4(struct connman_iface *iface,
171 struct connman_ipv4 *ipv4)
175 struct sockaddr_in *addr;
179 if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
182 DBG("iface %p ipv4 %p", iface, ipv4);
184 sk = socket(PF_INET, SOCK_DGRAM, 0);
188 memset(&ifr, 0, sizeof(ifr));
189 ifr.ifr_ifindex = iface->index;
191 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
196 DBG("ifname %s", ifr.ifr_name);
198 addr = (struct sockaddr_in *) &ifr.ifr_addr;
199 addr->sin_family = AF_INET;
200 addr->sin_addr = ipv4->address;
202 err = ioctl(sk, SIOCSIFADDR, &ifr);
205 DBG("address setting failed (%s)", strerror(errno));
207 addr = (struct sockaddr_in *) &ifr.ifr_netmask;
208 addr->sin_family = AF_INET;
209 addr->sin_addr = ipv4->netmask;
211 err = ioctl(sk, SIOCSIFNETMASK, &ifr);
214 DBG("netmask setting failed (%s)", strerror(errno));
216 addr = (struct sockaddr_in *) &ifr.ifr_broadaddr;
217 addr->sin_family = AF_INET;
218 addr->sin_addr = ipv4->broadcast;
220 err = ioctl(sk, SIOCSIFBRDADDR, &ifr);
223 DBG("broadcast setting failed (%s)", strerror(errno));
225 memset(&rt, 0, sizeof(rt));
226 rt.rt_flags = RTF_UP | RTF_GATEWAY;
228 addr = (struct sockaddr_in *) &rt.rt_dst;
229 addr->sin_family = AF_INET;
230 addr->sin_addr.s_addr = INADDR_ANY;
232 addr = (struct sockaddr_in *) &rt.rt_gateway;
233 addr->sin_family = AF_INET;
234 addr->sin_addr = ipv4->gateway;
236 addr = (struct sockaddr_in *) &rt.rt_genmask;
237 addr->sin_family = AF_INET;
238 addr->sin_addr.s_addr = INADDR_ANY;
240 err = ioctl(sk, SIOCADDRT, &rt);
245 DBG("default route failed (%s)", strerror(errno));
249 sprintf(cmd, "echo \"nameserver %s\" | resolvconf -a %s",
250 inet_ntoa(ipv4->nameserver), ifr.ifr_name);
259 int connman_iface_clear_ipv4(struct connman_iface *iface)
262 struct sockaddr_in *addr;
266 if ((iface->flags & CONNMAN_IFACE_FLAG_RTNL) == 0)
269 DBG("iface %p", iface);
271 sk = socket(PF_INET, SOCK_DGRAM, 0);
275 memset(&ifr, 0, sizeof(ifr));
276 ifr.ifr_ifindex = iface->index;
278 if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
283 DBG("ifname %s", ifr.ifr_name);
285 addr = (struct sockaddr_in *) &ifr.ifr_addr;
286 addr->sin_family = AF_INET;
287 addr->sin_addr.s_addr = INADDR_ANY;
289 //err = ioctl(sk, SIOCDIFADDR, &ifr);
290 err = ioctl(sk, SIOCSIFADDR, &ifr);
294 if (err < 0 && errno != EADDRNOTAVAIL) {
295 DBG("address removal failed (%s)", strerror(errno));
299 sprintf(cmd, "resolvconf -d %s", ifr.ifr_name);
308 static DBusMessage *scan_iface(DBusConnection *conn,
309 DBusMessage *msg, void *data)
311 struct connman_iface *iface = data;
312 struct connman_iface_driver *driver = iface->driver;
315 DBG("conn %p", conn);
317 reply = dbus_message_new_method_return(msg);
324 dbus_message_append_args(reply, DBUS_TYPE_INVALID);
329 static void append_entry(DBusMessageIter *dict,
330 const char *key, int type, void *val)
332 DBusMessageIter entry, value;
333 const char *signature;
335 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
338 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
341 case DBUS_TYPE_STRING:
342 signature = DBUS_TYPE_STRING_AS_STRING;
344 case DBUS_TYPE_UINT16:
345 signature = DBUS_TYPE_UINT16_AS_STRING;
348 signature = DBUS_TYPE_VARIANT_AS_STRING;
352 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
354 dbus_message_iter_append_basic(&value, type, val);
355 dbus_message_iter_close_container(&entry, &value);
357 dbus_message_iter_close_container(dict, &entry);
360 static DBusMessage *get_properties(DBusConnection *conn,
361 DBusMessage *msg, void *data)
363 struct connman_iface *iface = data;
365 DBusMessageIter array, dict;
368 DBG("conn %p", conn);
370 reply = dbus_message_new_method_return(msg);
374 dbus_message_iter_init_append(reply, &array);
376 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
377 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
378 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
379 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
381 str = __connman_iface_type2string(iface->type);
382 append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
384 str = __connman_iface_state2string(iface->state);
385 append_entry(&dict, "State", DBUS_TYPE_STRING, &str);
387 if (iface->type == CONNMAN_IFACE_TYPE_80211) {
388 dbus_uint16_t signal = 75;
389 append_entry(&dict, "Signal", DBUS_TYPE_UINT16, &signal);
392 str = __connman_iface_policy2string(iface->policy);
393 append_entry(&dict, "Policy", DBUS_TYPE_STRING, &str);
395 if (iface->device.driver != NULL)
396 append_entry(&dict, "Driver",
397 DBUS_TYPE_STRING, &iface->device.driver);
399 if (iface->device.vendor != NULL)
400 append_entry(&dict, "Vendor",
401 DBUS_TYPE_STRING, &iface->device.vendor);
403 if (iface->device.product != NULL)
404 append_entry(&dict, "Product",
405 DBUS_TYPE_STRING, &iface->device.product);
407 dbus_message_iter_close_container(&array, &dict);
412 static DBusMessage *get_state(DBusConnection *conn,
413 DBusMessage *msg, void *data)
415 struct connman_iface *iface = data;
419 DBG("conn %p", conn);
421 reply = dbus_message_new_method_return(msg);
425 state = __connman_iface_state2string(iface->state);
427 dbus_message_append_args(reply, DBUS_TYPE_STRING, &state,
433 static DBusMessage *get_signal(DBusConnection *conn,
434 DBusMessage *msg, void *data)
436 struct connman_iface *iface = data;
438 dbus_uint16_t signal;
440 DBG("conn %p", conn);
442 reply = dbus_message_new_method_return(msg);
446 if (iface->type == CONNMAN_IFACE_TYPE_80211)
451 dbus_message_append_args(reply, DBUS_TYPE_UINT16, &signal,
457 static DBusMessage *get_policy(DBusConnection *conn,
458 DBusMessage *msg, void *data)
460 struct connman_iface *iface = data;
464 DBG("conn %p", conn);
466 reply = dbus_message_new_method_return(msg);
470 policy = __connman_iface_policy2string(iface->policy);
472 dbus_message_append_args(reply, DBUS_TYPE_STRING, &policy,
478 static DBusMessage *set_policy(DBusConnection *conn,
479 DBusMessage *msg, void *data)
481 struct connman_iface *iface = data;
483 enum connman_iface_policy new_policy;
484 const char *path, *policy;
486 DBG("conn %p", conn);
488 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &policy,
491 new_policy = __connman_iface_string2policy(policy);
493 reply = dbus_message_new_method_return(msg);
497 dbus_message_append_args(reply, DBUS_TYPE_INVALID);
499 if (iface->policy != new_policy) {
500 path = dbus_message_get_path(msg);
502 iface->policy = new_policy;
504 if (new_policy == CONNMAN_IFACE_POLICY_AUTO) {
505 if (iface->driver->activate)
506 iface->driver->activate(iface);
508 if (iface->driver->shutdown)
509 iface->driver->shutdown(iface);
512 g_dbus_emit_signal(conn, path, CONNMAN_IFACE_INTERFACE,
513 "PolicyChanged", DBUS_TYPE_STRING, &policy,
520 static void append_ipv4(DBusMessage *reply, struct connman_iface *iface)
522 DBusMessageIter array, dict;
525 dbus_message_iter_init_append(reply, &array);
527 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
528 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
529 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
530 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
532 str = __connman_ipv4_method2string(iface->ipv4.method);
533 append_entry(&dict, "Method", DBUS_TYPE_STRING, &str);
535 if (iface->ipv4.address.s_addr != INADDR_ANY) {
536 str = inet_ntoa(iface->ipv4.address);
537 append_entry(&dict, "Address", DBUS_TYPE_STRING, &str);
540 if (iface->ipv4.netmask.s_addr != INADDR_ANY) {
541 str = inet_ntoa(iface->ipv4.netmask);
542 append_entry(&dict, "Netmask", DBUS_TYPE_STRING, &str);
545 if (iface->ipv4.gateway.s_addr != INADDR_ANY) {
546 str = inet_ntoa(iface->ipv4.gateway);
547 append_entry(&dict, "Gateway", DBUS_TYPE_STRING, &str);
550 dbus_message_iter_close_container(&array, &dict);
553 static DBusMessage *get_ipv4(DBusConnection *conn,
554 DBusMessage *msg, void *data)
556 struct connman_iface *iface = data;
559 DBG("conn %p", conn);
561 reply = dbus_message_new_method_return(msg);
565 append_ipv4(reply, iface);
570 static DBusMessage *set_ipv4(DBusConnection *conn,
571 DBusMessage *msg, void *data)
573 struct connman_iface *iface = data;
574 DBusMessage *reply, *signal;
575 DBusMessageIter array, dict;
577 gboolean changed = FALSE;
579 DBG("conn %p", conn);
581 dbus_message_iter_init(msg, &array);
583 dbus_message_iter_recurse(&array, &dict);
585 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
586 DBusMessageIter entry, value;
587 const char *key, *val;
588 enum connman_ipv4_method method;
591 dbus_message_iter_recurse(&dict, &entry);
592 dbus_message_iter_get_basic(&entry, &key);
594 dbus_message_iter_next(&entry);
596 dbus_message_iter_recurse(&entry, &value);
598 //type = dbus_message_iter_get_arg_type(&value);
599 dbus_message_iter_get_basic(&value, &val);
601 if (g_strcasecmp(key, "Method") == 0) {
602 method = __connman_ipv4_string2method(val);
603 if (iface->ipv4.method != method) {
604 iface->ipv4.method = method;
609 if (g_strcasecmp(key, "Address") == 0) {
610 addr = inet_addr(val);
611 if (iface->ipv4.address.s_addr != addr) {
612 iface->ipv4.address.s_addr = addr;
617 if (g_strcasecmp(key, "Netmask") == 0) {
618 addr = inet_addr(val);
619 if (iface->ipv4.netmask.s_addr != addr) {
620 iface->ipv4.netmask.s_addr = addr;
625 if (g_strcasecmp(key, "Gateway") == 0) {
626 addr = inet_addr(val);
627 if (iface->ipv4.gateway.s_addr != addr) {
628 iface->ipv4.gateway.s_addr = addr;
633 dbus_message_iter_next(&dict);
636 reply = dbus_message_new_method_return(msg);
640 dbus_message_append_args(reply, DBUS_TYPE_INVALID);
642 path = dbus_message_get_path(msg);
644 if (changed == TRUE) {
645 signal = dbus_message_new_signal(path,
646 CONNMAN_IFACE_INTERFACE, "IPv4Changed");
647 if (signal != NULL) {
648 append_ipv4(signal, iface);
649 dbus_connection_send(conn, signal, NULL);
650 dbus_message_unref(signal);
657 static DBusMessage *set_network(DBusConnection *conn,
658 DBusMessage *msg, void *data)
660 struct connman_iface *iface = data;
662 DBusMessageIter array, dict;
664 DBG("conn %p", conn);
666 dbus_message_iter_init(msg, &array);
668 dbus_message_iter_recurse(&array, &dict);
670 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
671 DBusMessageIter entry, value;
672 const char *key, *val;
674 dbus_message_iter_recurse(&dict, &entry);
675 dbus_message_iter_get_basic(&entry, &key);
677 dbus_message_iter_next(&entry);
679 dbus_message_iter_recurse(&entry, &value);
681 //type = dbus_message_iter_get_arg_type(&value);
682 dbus_message_iter_get_basic(&value, &val);
684 if (g_strcasecmp(key, "ESSID") == 0) {
685 if (iface->driver->set_network)
686 iface->driver->set_network(iface, val);
689 if (g_strcasecmp(key, "PSK") == 0) {
690 if (iface->driver->set_network)
691 iface->driver->set_passphrase(iface, val);
694 dbus_message_iter_next(&dict);
697 reply = dbus_message_new_method_return(msg);
701 dbus_message_append_args(reply, DBUS_TYPE_INVALID);
706 static GDBusMethodTable iface_methods[] = {
707 { "Scan", "", "", scan_iface },
708 { "GetProperties", "", "a{sv}", get_properties },
709 { "GetState", "", "s", get_state },
710 { "GetSignal", "", "q", get_signal },
711 { "GetPolicy", "", "s", get_policy },
712 { "SetPolicy", "s", "", set_policy },
713 { "GetIPv4", "", "a{sv}", get_ipv4 },
714 { "SetIPv4", "a{sv}", "", set_ipv4 },
715 { "SetNetwork", "a{sv}", "", set_network },
719 static GDBusSignalTable iface_signals[] = {
720 { "StateChanged", "s" },
721 { "SignalChanged", "q" },
722 { "PolicyChanged", "s" },
723 { "IPv4Changed", "a{sv}" },
724 { "NetworkChanged", "a{sv}" },
728 static void device_free(void *data)
730 struct connman_iface *iface = data;
732 DBG("iface %p", iface);
734 connman_iface_clear_ipv4(iface);
736 if (iface->driver && iface->driver->remove)
737 iface->driver->remove(iface);
741 g_free(iface->sysfs);
742 g_free(iface->identifier);
743 g_free(iface->device.driver);
744 g_free(iface->device.vendor);
745 g_free(iface->device.product);
749 static void detect_device_info(LibHalContext *ctx, struct connman_iface *iface)
751 char *parent, *subsys, *value;
753 parent = libhal_device_get_property_string(ctx, iface->udi,
754 "info.parent", NULL);
756 subsys = libhal_device_get_property_string(ctx, iface->udi,
757 "linux.subsystem", NULL);
759 value = libhal_device_get_property_string(ctx, iface->udi,
760 "info.linux.driver", NULL);
762 value = libhal_device_get_property_string(ctx, parent,
763 "info.linux.driver", NULL);
765 iface->device.driver = g_strdup(value);
768 if (strcmp(subsys, "net") == 0) {
769 value = libhal_device_get_property_string(ctx, parent,
770 "info.vendor", NULL);
772 iface->device.vendor = g_strdup(value);
774 value = libhal_device_get_property_string(ctx, parent,
775 "info.product", NULL);
777 iface->device.product = g_strdup(value);
781 static int probe_device(LibHalContext *ctx,
782 struct connman_iface_driver *driver, const char *udi)
784 DBusConnection *conn;
785 struct connman_iface *iface;
789 DBG("ctx %p driver %p udi %s", ctx, driver, udi);
794 iface = g_try_new0(struct connman_iface, 1);
798 temp = g_path_get_basename(udi);
799 iface->path = g_strdup_printf("%s/%s", CONNMAN_IFACE_BASEPATH, temp);
802 iface->udi = g_strdup(udi);
804 DBG("iface %p path %s", iface, iface->path);
806 sysfs = libhal_device_get_property_string(ctx, udi,
807 "linux.sysfs_path", NULL);
809 iface->sysfs = g_strdup(sysfs);
811 detect_device_info(ctx, iface);
815 if (g_str_has_prefix(driver->capability, "net") == TRUE)
816 iface->index = libhal_device_get_property_int(ctx, udi,
817 "net.linux.ifindex", NULL);
819 iface->type = CONNMAN_IFACE_TYPE_UNKNOWN;
821 iface->state = CONNMAN_IFACE_STATE_UNKNOWN;
822 iface->policy = CONNMAN_IFACE_POLICY_UNKNOWN;
824 err = driver->probe(iface);
830 __connman_iface_create_identifier(iface);
832 __connman_iface_init_via_inet(iface);
834 iface->driver = driver;
836 conn = libhal_ctx_get_dbus_connection(ctx);
838 g_dbus_register_object(conn, iface->path, iface, device_free);
840 interfaces = g_slist_append(interfaces, iface);
842 if (iface->flags & CONNMAN_IFACE_FLAG_IPV4) {
843 if (driver->get_ipv4)
844 driver->get_ipv4(iface, &iface->ipv4);
846 connman_iface_get_ipv4(iface, &iface->ipv4);
848 DBG("address %s", inet_ntoa(iface->ipv4.address));
851 g_dbus_register_interface(conn, iface->path,
852 CONNMAN_IFACE_INTERFACE,
853 iface_methods, iface_signals, NULL);
855 DBG("iface %p identifier %s", iface, iface->identifier);
857 g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
858 CONNMAN_MANAGER_INTERFACE,
860 DBUS_TYPE_OBJECT_PATH, &iface->path,
863 if (iface->policy == CONNMAN_IFACE_POLICY_AUTO) {
864 if (driver->activate)
865 driver->activate(iface);
871 static void device_added(LibHalContext *ctx, const char *udi)
875 DBG("ctx %p udi %s", ctx, udi);
877 for (list = drivers; list; list = list->next) {
878 struct connman_iface_driver *driver = list->data;
880 if (driver->capability == NULL)
883 if (libhal_device_query_capability(ctx, udi,
884 driver->capability, NULL) == TRUE) {
885 if (probe_device(ctx, driver, udi) == 0)
891 static void device_removed(LibHalContext *ctx, const char *udi)
893 DBusConnection *conn;
896 DBG("ctx %p udi %s", ctx, udi);
898 conn = libhal_ctx_get_dbus_connection(ctx);
900 for (list = interfaces; list; list = list->next) {
901 struct connman_iface *iface = list->data;
903 if (strcmp(udi, iface->udi) == 0) {
904 g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
905 CONNMAN_MANAGER_INTERFACE,
907 DBUS_TYPE_OBJECT_PATH, &iface->path,
909 interfaces = g_slist_remove(interfaces, iface);
910 g_dbus_unregister_interface(conn, iface->path,
911 CONNMAN_IFACE_INTERFACE);
912 g_dbus_unregister_object(conn, iface->path);
918 static void probe_driver(LibHalContext *ctx,
919 struct connman_iface_driver *driver)
924 DBG("ctx %p driver %p", ctx, driver);
926 list = libhal_find_device_by_capability(ctx,
927 driver->capability, &num, NULL);
932 probe_device(ctx, driver, *tmp);
936 libhal_free_string_array(list);
940 static void find_devices(LibHalContext *ctx)
946 for (list = drivers; list; list = list->next) {
947 struct connman_iface_driver *driver = list->data;
949 DBG("driver %p", driver);
951 if (driver->capability == NULL)
954 probe_driver(ctx, driver);
958 static LibHalContext *hal_ctx = NULL;
960 static void hal_init(void *data)
962 DBusConnection *conn = data;
964 DBG("conn %p", conn);
969 hal_ctx = libhal_ctx_new();
973 if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) {
974 libhal_ctx_free(hal_ctx);
978 if (libhal_ctx_init(hal_ctx, NULL) == FALSE) {
979 libhal_ctx_free(hal_ctx);
983 libhal_ctx_set_device_added(hal_ctx, device_added);
984 libhal_ctx_set_device_removed(hal_ctx, device_removed);
986 //libhal_ctx_set_device_new_capability(hal_ctx, new_capability);
987 //libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability);
989 find_devices(hal_ctx);
992 static void hal_cleanup(void *data)
994 DBusConnection *conn = data;
997 DBG("conn %p", conn);
1002 for (list = interfaces; list; list = list->next) {
1003 struct connman_iface *iface = list->data;
1005 DBG("path %s", iface->path);
1007 g_dbus_emit_signal(conn, CONNMAN_MANAGER_PATH,
1008 CONNMAN_MANAGER_INTERFACE,
1010 DBUS_TYPE_OBJECT_PATH, &iface->path,
1013 g_dbus_unregister_interface(conn, iface->path,
1014 CONNMAN_IFACE_INTERFACE);
1016 g_dbus_unregister_object(conn, iface->path);
1019 g_slist_free(interfaces);
1023 libhal_ctx_shutdown(hal_ctx, NULL);
1025 libhal_ctx_free(hal_ctx);
1030 static guint hal_watch = 0;
1032 int __connman_iface_init(DBusConnection *conn)
1034 DBG("conn %p", conn);
1036 connection = dbus_connection_ref(conn);
1037 if (connection == NULL)
1040 hal_init(connection);
1042 hal_watch = g_dbus_add_watch(connection, "org.freedesktop.Hal",
1043 hal_init, hal_cleanup, connection, NULL);
1048 void __connman_iface_cleanup(void)
1050 DBG("conn %p", connection);
1052 g_dbus_remove_watch(connection, hal_watch);
1054 hal_cleanup(connection);
1056 dbus_connection_unref(connection);