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
27 #include <sys/types.h>
29 #define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
36 static GSList *device_list = NULL;
38 static struct connman_device *find_device(const char *interface)
42 if (interface == NULL)
45 for (list = device_list; list; list = list->next) {
46 struct connman_device *device = list->data;
47 const char *device_interface;
49 device_interface = connman_device_get_interface(device);
50 if (device_interface == NULL)
53 if (g_str_equal(device_interface, interface) == TRUE)
60 static void add_device(struct udev_device *udev_device)
62 enum connman_device_type devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
63 struct connman_device *device;
64 struct udev_list_entry *entry;
65 const char *type = NULL, *interface = NULL;
69 entry = udev_device_get_properties_list_entry(udev_device);
71 const char *name = udev_list_entry_get_name(entry);
73 if (g_str_has_prefix(name, "CONNMAN_TYPE") == TRUE)
74 type = udev_list_entry_get_value(entry);
75 else if (g_str_has_prefix(name, "CONNMAN_INTERFACE") == TRUE)
76 interface = udev_list_entry_get_value(entry);
78 entry = udev_list_entry_get_next(entry);
81 device = find_device(interface);
85 if (type == NULL || interface == NULL)
88 if (g_str_equal(interface, "ttyUSB0") == FALSE &&
89 g_str_equal(interface, "noz0") == FALSE)
92 if (g_str_equal(type, "nozomi") == TRUE)
93 devtype = CONNMAN_DEVICE_TYPE_NOZOMI;
94 else if (g_str_equal(type, "huawei") == TRUE)
95 devtype = CONNMAN_DEVICE_TYPE_HUAWEI;
96 else if (g_str_equal(type, "novatel") == TRUE)
97 devtype = CONNMAN_DEVICE_TYPE_NOVATEL;
101 device = connman_device_create(interface, devtype);
105 connman_device_set_mode(device, CONNMAN_DEVICE_MODE_NETWORK_SINGLE);
107 connman_device_set_interface(device, interface);
109 if (connman_device_register(device) < 0) {
110 connman_device_unref(device);
114 device_list = g_slist_append(device_list, device);
117 static void remove_device(struct udev_device *udev_device)
119 struct connman_device *device;
120 struct udev_list_entry *entry;
121 const char *interface = NULL;
125 entry = udev_device_get_properties_list_entry(udev_device);
127 const char *name = udev_list_entry_get_name(entry);
129 if (g_str_has_prefix(name, "CONNMAN_INTERFACE") == TRUE)
130 interface = udev_list_entry_get_value(entry);
132 entry = udev_list_entry_get_next(entry);
135 device = find_device(interface);
139 device_list = g_slist_remove(device_list, device);
141 connman_device_unregister(device);
142 connman_device_unref(device);
145 static void print_properties(struct udev_device *device, const char *prefix)
147 struct udev_list_entry *entry;
149 entry = udev_device_get_properties_list_entry(device);
151 const char *name = udev_list_entry_get_name(entry);
152 const char *value = udev_list_entry_get_value(entry);
154 if (g_str_has_prefix(name, "CONNMAN") == TRUE ||
155 g_str_has_prefix(name, "RFKILL") == TRUE ||
156 g_str_has_prefix(name, "ID_MODEM") == TRUE ||
157 g_str_equal(name, "ID_VENDOR") == TRUE ||
158 g_str_equal(name, "ID_MODEL") == TRUE ||
159 g_str_equal(name, "INTERFACE") == TRUE ||
160 g_str_equal(name, "IFINDEX") == TRUE ||
161 g_str_equal(name, "DEVNAME") == TRUE ||
162 g_str_equal(name, "DEVPATH") == TRUE)
163 connman_debug("%s%s = %s", prefix, name, value);
165 entry = udev_list_entry_get_next(entry);
169 static void print_device(struct udev_device *device, const char *action)
171 const char *subsystem, *devtype = NULL;
172 struct udev_device *parent;
174 connman_debug("=== %s ===", action);
175 print_properties(device, "");
177 parent = udev_device_get_parent(device);
181 subsystem = udev_device_get_subsystem(parent);
183 if (subsystem != NULL &&
184 g_str_equal(subsystem, "usb-serial") == TRUE) {
186 devtype = "usb_device";
189 parent = udev_device_get_parent_with_subsystem_devtype(device,
191 print_properties(parent, " ");
194 static void enumerate_devices(struct udev *context)
196 struct udev_enumerate *enumerate;
197 struct udev_list_entry *entry;
199 enumerate = udev_enumerate_new(context);
200 if (enumerate == NULL)
203 udev_enumerate_add_match_property(enumerate, "CONNMAN_TYPE", "?*");
205 udev_enumerate_scan_devices(enumerate);
207 entry = udev_enumerate_get_list_entry(enumerate);
209 const char *syspath = udev_list_entry_get_name(entry);
210 struct udev_device *device;
212 device = udev_device_new_from_syspath(context, syspath);
214 print_device(device, "coldplug");
218 udev_device_unref(device);
220 entry = udev_list_entry_get_next(entry);
223 udev_enumerate_unref(enumerate);
226 static gboolean udev_event(GIOChannel *channel,
227 GIOCondition condition, gpointer user_data)
229 struct udev_monitor *monitor = user_data;
230 struct udev_device *device;
233 device = udev_monitor_receive_device(monitor);
237 action = udev_device_get_action(device);
241 print_device(device, action);
243 if (g_str_equal(action, "add") == TRUE)
245 else if (g_str_equal(action, "remove") == TRUE)
246 remove_device(device);
249 udev_device_unref(device);
254 static struct udev *udev_ctx;
255 static struct udev_monitor *udev_mon;
256 static guint udev_watch = 0;
258 char *__connman_udev_get_devtype(const char *ifname)
260 struct udev_device *device;
264 snprintf(syspath, sizeof(syspath) - 1, "/sys/class/net/%s", ifname);
266 device = udev_device_new_from_syspath(udev_ctx, syspath);
270 devtype = udev_device_get_devtype(device);
274 connman_info("%s ==> %s", ifname, devtype);
277 udev_device_unref(device);
282 int __connman_udev_init(void)
289 udev_ctx = udev_new();
290 if (udev_ctx == NULL) {
291 connman_error("Failed to create udev context");
295 udev_mon = udev_monitor_new_from_netlink(udev_ctx, "udev");
296 if (udev_mon == NULL) {
297 connman_error("Failed to create udev monitor");
298 udev_unref(udev_ctx);
303 if (udev_monitor_enable_receiving(udev_mon) < 0) {
304 connman_error("Failed to enable udev monitor");
305 udev_unref(udev_ctx);
307 udev_monitor_unref(udev_mon);
311 enumerate_devices(udev_ctx);
313 fd = udev_monitor_get_fd(udev_mon);
315 channel = g_io_channel_unix_new(fd);
319 udev_watch = g_io_add_watch(channel, G_IO_IN, udev_event, udev_mon);
321 g_io_channel_unref(channel);
326 void __connman_udev_cleanup(void)
333 g_source_remove(udev_watch);
335 for (list = device_list; list; list = list->next) {
336 struct connman_device *device = list->data;
338 connman_device_unregister(device);
339 connman_device_unref(device);
342 g_slist_free(device_list);
345 if (udev_ctx == NULL)
348 udev_monitor_unref(udev_mon);
349 udev_unref(udev_ctx);