eb14655c205484db8fc3b91ba13e93b88a8ce4b7
[connman] / src / udev.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  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 <sys/types.h>
27
28 #define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
29 #include <libudev.h>
30
31 #include <glib.h>
32
33 #include "connman.h"
34
35 #ifdef NEED_UDEV_DEVICE_GET_PARENT_WITH_DEVTYPE
36 static struct udev_device *udev_device_get_parent_with_devtype(struct udev_device *device,
37                                                                 const char *devtype)
38 {
39         return NULL;
40 }
41 #endif
42
43 #ifdef NEED_UDEV_ENUMERATE_ADD_MATCH_PROPERTY
44 static int udev_enumerate_add_match_property(struct udev_enumerate *enumerate,
45                                         const char *property, const char *value)
46 {
47         return 0;
48 }
49 #endif
50
51 static void print_properties(struct udev_device *device, const char *prefix)
52 {
53         struct udev_list_entry *entry;
54
55         entry = udev_device_get_properties_list_entry(device);
56         while (entry) {
57                 const char *name = udev_list_entry_get_name(entry);
58                 const char *value = udev_list_entry_get_value(entry);
59
60                 if (g_str_has_prefix(name, "CONNMAN") == TRUE ||
61                                 g_str_equal(name, "DEVNAME") == TRUE ||
62                                         g_str_equal(name, "DEVPATH") == TRUE)
63                         connman_debug("%s%s = %s", prefix, name, value);
64
65                 entry = udev_list_entry_get_next(entry);
66         }
67 }
68
69 static void print_device(struct udev_device *device, const char *action)
70 {
71         struct udev_device *parent;
72
73         connman_debug("=== %s ===", action);
74         print_properties(device, "");
75
76         parent = udev_device_get_parent_with_devtype(device, "usb_device");
77         print_properties(parent, "    ");
78 }
79
80 static void enumerate_devices(struct udev *context)
81 {
82         struct udev_enumerate *enumerate;
83         struct udev_list_entry *entry;
84
85         enumerate = udev_enumerate_new(context);
86         if (enumerate == NULL)
87                 return;
88
89         udev_enumerate_add_match_property(enumerate, "CONNMAN_TYPE", "?*");
90
91         udev_enumerate_scan_devices(enumerate);
92
93         entry = udev_enumerate_get_list_entry(enumerate);
94         while (entry) {
95                 const char *syspath = udev_list_entry_get_name(entry);
96                 struct udev_device *device;
97
98                 device = udev_device_new_from_syspath(context, syspath);
99
100                 print_device(device, "coldplug");
101
102                 udev_device_unref(device);
103
104                 entry = udev_list_entry_get_next(entry);
105         }
106
107         udev_enumerate_unref(enumerate);
108 }
109
110 static gboolean udev_event(GIOChannel *channel,
111                                 GIOCondition condition, gpointer user_data)
112 {
113         struct udev_monitor *monitor = user_data;
114         struct udev_device *device;
115         const char *action;
116
117         device = udev_monitor_receive_device(monitor);
118         if (device == NULL)
119                 return TRUE;
120
121         action = udev_device_get_action(device);
122         if (action == NULL)
123                 goto done;
124
125         print_device(device, action);
126
127 done:
128         udev_device_unref(device);
129
130         return TRUE;
131 }
132
133 static struct udev *udev_ctx;
134 static struct udev_monitor *udev_mon;
135 static guint udev_watch = 0;
136
137 int __connman_udev_init(void)
138 {
139         GIOChannel *channel;
140         int fd;
141
142         DBG("");
143
144         udev_ctx = udev_new();
145         if (udev_ctx == NULL) {
146                 connman_error("Failed to create udev context");
147                 return -1;
148         }
149
150         udev_mon = udev_monitor_new_from_socket(udev_ctx,
151                                                 "@/org/moblin/connman/udev");
152         if (udev_mon == NULL) {
153                 connman_error("Failed to create udev monitor");
154                 udev_unref(udev_ctx);
155                 udev_ctx = NULL;
156                 return -1;
157         }
158
159         if (udev_monitor_enable_receiving(udev_mon) < 0) {
160                 connman_error("Failed to enable udev monitor");
161                 udev_unref(udev_ctx);
162                 udev_ctx = NULL;
163                 udev_monitor_unref(udev_mon);
164                 return -1;
165         }
166
167         enumerate_devices(udev_ctx);
168
169         fd = udev_monitor_get_fd(udev_mon);
170
171         channel = g_io_channel_unix_new(fd);
172         if (channel == NULL)
173                 return 0;
174
175         udev_watch = g_io_add_watch(channel, G_IO_IN, udev_event, udev_mon);
176
177         g_io_channel_unref(channel);
178
179         return 0;
180 }
181
182 void __connman_udev_cleanup(void)
183 {
184         DBG("");
185
186         if (udev_watch > 0)
187                 g_source_remove(udev_watch);
188
189         if (udev_ctx == NULL)
190                 return;
191
192         udev_monitor_unref(udev_mon);
193         udev_unref(udev_ctx);
194 }