5 * Copyright (C) 2007-2009 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
26 #include <sys/types.h>
28 #define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
35 #ifdef NEED_UDEV_ENUMERATE_ADD_MATCH_PROPERTY
36 static int udev_enumerate_add_match_property(struct udev_enumerate *enumerate,
37 const char *property, const char *value)
43 #ifdef NEED_UDEV_DEVICE_GET_PARENT_WITH_SUBSYSTEM_DEVTYPE
44 static struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *device,
45 const char *subsystem, const char *devtype)
51 static GSList *device_list = NULL;
53 static struct connman_device *find_device(const char *interface)
57 if (interface == NULL)
60 for (list = device_list; list; list = list->next) {
61 struct connman_device *device = list->data;
62 const char *device_interface;
64 device_interface = connman_device_get_interface(device);
65 if (device_interface == NULL)
68 if (g_str_equal(device_interface, interface) == TRUE)
75 static void add_device(struct udev_device *udev_device)
77 enum connman_device_type devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
78 struct connman_device *device;
79 struct udev_list_entry *entry;
80 const char *type = NULL, *interface = NULL;
84 entry = udev_device_get_properties_list_entry(udev_device);
86 const char *name = udev_list_entry_get_name(entry);
88 if (g_str_has_prefix(name, "CONNMAN_TYPE") == TRUE)
89 type = udev_list_entry_get_value(entry);
90 else if (g_str_has_prefix(name, "CONNMAN_INTERFACE") == TRUE)
91 interface = udev_list_entry_get_value(entry);
93 entry = udev_list_entry_get_next(entry);
96 device = find_device(interface);
100 if (type == NULL || interface == NULL)
103 if (g_str_equal(interface, "ttyUSB0") == FALSE &&
104 g_str_equal(interface, "noz0") == FALSE)
107 if (g_str_equal(type, "nozomi") == TRUE)
108 devtype = CONNMAN_DEVICE_TYPE_NOZOMI;
109 else if (g_str_equal(type, "huawei") == TRUE)
110 devtype = CONNMAN_DEVICE_TYPE_HUAWEI;
111 else if (g_str_equal(type, "novatel") == TRUE)
112 devtype = CONNMAN_DEVICE_TYPE_NOVATEL;
116 device = connman_device_create(interface, devtype);
120 connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_SINGLE);
121 connman_device_set_policy(device, CONNMAN_DEVICE_POLICY_MANUAL);
123 connman_device_set_interface(device, interface);
125 if (connman_device_register(device) < 0) {
126 connman_device_unref(device);
130 device_list = g_slist_append(device_list, device);
133 static void remove_device(struct udev_device *udev_device)
135 struct connman_device *device;
136 struct udev_list_entry *entry;
137 const char *interface = NULL;
141 entry = udev_device_get_properties_list_entry(udev_device);
143 const char *name = udev_list_entry_get_name(entry);
145 if (g_str_has_prefix(name, "CONNMAN_INTERFACE") == TRUE)
146 interface = udev_list_entry_get_value(entry);
148 entry = udev_list_entry_get_next(entry);
151 device = find_device(interface);
155 device_list = g_slist_remove(device_list, device);
157 connman_device_unregister(device);
158 connman_device_unref(device);
161 static void print_properties(struct udev_device *device, const char *prefix)
163 struct udev_list_entry *entry;
165 entry = udev_device_get_properties_list_entry(device);
167 const char *name = udev_list_entry_get_name(entry);
168 const char *value = udev_list_entry_get_value(entry);
170 if (g_str_has_prefix(name, "CONNMAN") == TRUE ||
171 g_str_has_prefix(name, "ID_MODEM") == TRUE ||
172 g_str_equal(name, "DEVNAME") == TRUE ||
173 g_str_equal(name, "DEVPATH") == TRUE)
174 connman_debug("%s%s = %s", prefix, name, value);
176 entry = udev_list_entry_get_next(entry);
180 static void print_device(struct udev_device *device, const char *action)
182 const char *subsystem = udev_device_get_subsystem(device);
183 const char *devtype = NULL;
184 struct udev_device *parent;
186 connman_debug("=== %s ===", action);
187 print_properties(device, "");
189 if (subsystem != NULL && g_str_equal(subsystem, "usb") == TRUE)
190 devtype = "usb_device";
192 parent = udev_device_get_parent_with_subsystem_devtype(device,
194 print_properties(parent, " ");
197 static void enumerate_devices(struct udev *context)
199 struct udev_enumerate *enumerate;
200 struct udev_list_entry *entry;
202 enumerate = udev_enumerate_new(context);
203 if (enumerate == NULL)
206 udev_enumerate_add_match_property(enumerate, "CONNMAN_TYPE", "?*");
208 udev_enumerate_scan_devices(enumerate);
210 entry = udev_enumerate_get_list_entry(enumerate);
212 const char *syspath = udev_list_entry_get_name(entry);
213 struct udev_device *device;
215 device = udev_device_new_from_syspath(context, syspath);
217 print_device(device, "coldplug");
221 udev_device_unref(device);
223 entry = udev_list_entry_get_next(entry);
226 udev_enumerate_unref(enumerate);
229 static gboolean udev_event(GIOChannel *channel,
230 GIOCondition condition, gpointer user_data)
232 struct udev_monitor *monitor = user_data;
233 struct udev_device *device;
236 device = udev_monitor_receive_device(monitor);
240 action = udev_device_get_action(device);
244 print_device(device, action);
246 if (g_str_equal(action, "add") == TRUE)
248 else if (g_str_equal(action, "remove") == TRUE)
249 remove_device(device);
252 udev_device_unref(device);
257 static struct udev *udev_ctx;
258 static struct udev_monitor *udev_mon;
259 static guint udev_watch = 0;
261 int __connman_udev_init(void)
268 udev_ctx = udev_new();
269 if (udev_ctx == NULL) {
270 connman_error("Failed to create udev context");
274 udev_mon = udev_monitor_new_from_socket(udev_ctx,
275 "@/org/moblin/connman/udev");
276 if (udev_mon == NULL) {
277 connman_error("Failed to create udev monitor");
278 udev_unref(udev_ctx);
283 if (udev_monitor_enable_receiving(udev_mon) < 0) {
284 connman_error("Failed to enable udev monitor");
285 udev_unref(udev_ctx);
287 udev_monitor_unref(udev_mon);
291 enumerate_devices(udev_ctx);
293 fd = udev_monitor_get_fd(udev_mon);
295 channel = g_io_channel_unix_new(fd);
299 udev_watch = g_io_add_watch(channel, G_IO_IN, udev_event, udev_mon);
301 g_io_channel_unref(channel);
306 void __connman_udev_cleanup(void)
313 g_source_remove(udev_watch);
315 for (list = device_list; list; list = list->next) {
316 struct connman_device *device = list->data;
318 connman_device_unregister(device);
319 connman_device_unref(device);
322 g_slist_free(device_list);
325 if (udev_ctx == NULL)
328 udev_monitor_unref(udev_mon);
329 udev_unref(udev_ctx);