4 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
29 #define EVENT_KERNEL "kernel"
30 #define EVENT_UDEV "udev"
32 #define UDEV_MONITOR_SIZE (128*1024)
35 struct udev_monitor *mon;
43 static struct udev *udev;
44 static struct uevent_info kevent; /* kernel */
45 static struct uevent_info uevent; /* udev */
47 static gboolean uevent_control_cb(GIOChannel *channel,
48 GIOCondition cond, void *data)
50 struct uevent_info *info = data;
51 struct udev_device *dev;
52 struct uevent_handler *l;
54 const char *subsystem;
58 _E("data is invalid");
62 _I("Set udev monitor buffer size %d", UDEV_MONITOR_SIZE);
63 dev = udev_monitor_receive_device(info->mon);
67 subsystem = udev_device_get_subsystem(dev);
71 len = strlen(subsystem);
73 for (elem = info->event_list ; elem ; elem = g_list_next(elem)) {
77 if (!strncmp(l->subsystem, subsystem, len) &&
83 udev_device_unref(dev);
87 static int uevent_control_stop(struct uevent_info *info)
89 struct udev_device *dev;
95 g_source_remove(info->eventid);
99 g_io_channel_unref(info->ch);
103 dev = udev_monitor_receive_device(info->mon);
105 udev_device_unref(dev);
106 udev_monitor_unref(info->mon);
110 udev = udev_unref(udev);
114 static int uevent_control_start(const char *type,
115 struct uevent_info *info)
117 struct uevent_handler *l;
126 _E("%s uevent control routine is alreay started", type);
133 _E("error create udev");
137 udev = udev_ref(udev);
139 info->mon = udev_monitor_new_from_netlink(udev, type);
140 if (info->mon == NULL) {
141 _E("error udev_monitor create");
145 ret = udev_monitor_set_receive_buffer_size(info->mon,
148 _E("fail to set receive buffer size");
152 for (elem = info->event_list ; elem ; elem = g_list_next(elem)) {
154 ret = udev_monitor_filter_add_match_subsystem_devtype(
158 _E("error apply subsystem filter");
163 ret = udev_monitor_filter_update(info->mon);
165 _E("error udev_monitor_filter_update");
167 fd = udev_monitor_get_fd(info->mon);
169 _E("error udev_monitor_get_fd");
173 info->ch = g_io_channel_unix_new(fd);
174 info->eventid = g_io_add_watch(info->ch,
175 G_IO_IN, uevent_control_cb, info);
176 if (info->eventid == 0) {
177 _E("Failed to add channel watch");
181 if (udev_monitor_enable_receiving(info->mon) < 0) {
182 _E("error unable to subscribe to udev events");
188 uevent_control_stop(info);
192 int uevent_control_kernel_start(void)
194 return uevent_control_start(EVENT_KERNEL, &kevent);
197 void uevent_control_kernel_stop(void)
199 uevent_control_stop(&kevent);
202 int uevent_control_udev_start(void)
204 return uevent_control_start(EVENT_UDEV, &uevent);
207 void uevent_control_udev_stop(void)
209 uevent_control_stop(&uevent);
212 static int register_uevent_control(struct uevent_info *info,
213 struct uevent_handler *uh)
215 struct uevent_handler *l;
218 bool matched = false;
221 if (!info || !uh || !uh->subsystem)
224 /* if udev is not initialized, it just will be added list */
225 if (!udev || !info->mon)
228 len = strlen(uh->subsystem);
229 /* check if the same subsystem is already added */
230 for (elem = info->event_list; elem ; elem = g_list_next(elem)) {
232 if (!strncmp(l->subsystem, uh->subsystem, len)) {
238 /* the first request to add subsystem */
240 r = udev_monitor_filter_add_match_subsystem_devtype(info->mon,
241 uh->subsystem, NULL);
243 _E("fail to add %s subsystem : %d", uh->subsystem, r);
248 r = udev_monitor_filter_update(info->mon);
250 _E("fail to update udev monitor filter : %d", r);
253 info->event_list = g_list_append(info->event_list, uh);
257 static int unregister_uevent_control(struct uevent_info *info,
258 const struct uevent_handler *uh)
260 struct uevent_handler *l;
264 if (!info || !uh || !uh->subsystem)
267 len = strlen(uh->subsystem);
268 for (n = info->event_list, next = g_list_next(n) ;
269 n ; n = next, next = g_list_next(n)) {
271 if (!strncmp(l->subsystem, uh->subsystem, len) &&
272 l->uevent_func == uh->uevent_func) {
273 info->event_list = g_list_delete_link(info->event_list, n);
281 int register_kernel_event_control(struct uevent_handler *uh)
283 return register_uevent_control(&kevent, uh);
286 void unregister_kernel_event_control(struct uevent_handler *uh)
288 unregister_uevent_control(&kevent, uh);
291 int register_udev_event_control(struct uevent_handler *uh)
293 return register_uevent_control(&uevent, uh);
296 void unregister_udev_event_control(struct uevent_handler *uh)
298 unregister_uevent_control(&uevent, uh);