4 * Copyright (c) 2012 - 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.
23 #include <libsyscommon/libgdbus.h>
24 #include <libsyscommon/list.h>
27 #include "shared/device-notifier.h"
28 #include "shared/devices.h"
31 #define KERNEL "kernel"
34 #define UDEV_MONITOR_BUFFER_SIZE (128*1024)
37 struct udev_monitor *mon;
43 static struct udev *udev;
45 static struct uevent_info kevent = {.mon = NULL, .fdh = 0, .event_list = 0}; /* kernel */
46 static struct uevent_info uevent = {.mon = NULL, .fdh = 0, .event_list = 0}; /* udev */
48 static gboolean uevent_control_cb(gint fd, GIOCondition cond, void *data)
50 struct uevent_info *info = data;
51 struct udev_device *dev;
52 struct uevent_handler *l;
54 const char *subsystem;
59 dev = udev_monitor_receive_device(info->mon);
61 return G_SOURCE_CONTINUE;
63 subsystem = udev_device_get_subsystem(dev);
67 len = strlen(subsystem);
68 SYS_G_LIST_FOREACH(info->event_list, elem, l) {
69 if (!strncmp(l->subsystem, subsystem, len) &&
75 udev_device_unref(dev);
76 return G_SOURCE_CONTINUE;
79 static int uevent_control_stop(struct uevent_info *info)
81 struct udev_device *dev;
87 g_source_remove(info->fdh);
91 dev = udev_monitor_receive_device(info->mon);
93 udev_device_unref(dev);
94 udev_monitor_unref(info->mon);
98 udev = udev_unref(udev);
102 static int uevent_control_start(const char *type,
103 struct uevent_info *info)
105 struct uevent_handler *l;
114 _E("%s Uevent control routine is alreay started.", type);
121 _E("Failed to create udev.");
125 udev = udev_ref(udev);
127 info->mon = udev_monitor_new_from_netlink(udev, type);
128 if (info->mon == NULL) {
129 _E("Failed to create udev_monitor.");
133 _I("Set udev monitor buffer size(%d).", UDEV_MONITOR_BUFFER_SIZE);
134 ret = udev_monitor_set_receive_buffer_size(info->mon,
135 UDEV_MONITOR_BUFFER_SIZE);
137 _E("Failed to set receive buffer size.");
141 SYS_G_LIST_FOREACH(info->event_list, elem, l) {
142 ret = udev_monitor_filter_add_match_subsystem_devtype(
146 _E("Failed to apply subsystem filter.");
151 ret = udev_monitor_filter_update(info->mon);
153 _E("Failed to call 'udev_monitor_filter_update'.");
155 fd = udev_monitor_get_fd(info->mon);
157 _E("Failed to call 'udev_monitor_get_fd'.");
161 info->fdh = g_unix_fd_add(fd, G_IO_IN,
162 uevent_control_cb, info);
164 _E("Failed to call 'error g_unix_fd_add'.");
168 if (udev_monitor_enable_receiving(info->mon) < 0) {
169 _E("Failed to call 'udev_monitor_enable_receiving'.");
175 uevent_control_stop(info);
179 static int register_uevent_control(struct uevent_info *info,
180 const struct uevent_handler *uh)
182 struct uevent_handler *l;
185 bool matched = false;
188 if (!info || !uh || !uh->subsystem)
191 /* if udev is not initialized, it just will be added list */
192 if (!udev || !info->mon)
195 len = strlen(uh->subsystem);
196 /* check if the same subsystem is already added */
197 SYS_G_LIST_FOREACH(info->event_list, elem, l) {
198 if (!strncmp(l->subsystem, uh->subsystem, len)) {
204 /* the first request to add subsystem */
206 r = udev_monitor_filter_add_match_subsystem_devtype(info->mon,
207 uh->subsystem, NULL);
209 _E("Failed to add subsystem(%s): %d", uh->subsystem, r);
214 r = udev_monitor_filter_update(info->mon);
216 _E("Failed to update udev monitor filter: %d", r);
219 SYS_G_LIST_APPEND(info->event_list, uh);
223 static int unregister_uevent_control(struct uevent_info *info,
224 const struct uevent_handler *uh)
226 struct uevent_handler *l;
230 if (!info || !uh || !uh->subsystem)
233 len = strlen(uh->subsystem);
234 SYS_G_LIST_FOREACH_SAFE(info->event_list, n, next, l) {
235 if (!strncmp(l->subsystem, uh->subsystem, len) &&
236 l->uevent_func == uh->uevent_func) {
237 SYS_G_LIST_REMOVE(info->event_list, l);
245 int register_kernel_uevent_control(const struct uevent_handler *uh)
247 return register_uevent_control(&kevent, uh);
250 int unregister_kernel_uevent_control(const struct uevent_handler *uh)
252 return unregister_uevent_control(&kevent, uh);
255 int register_udev_uevent_control(const struct uevent_handler *uh)
257 return register_uevent_control(&uevent, uh);
260 int unregister_udev_uevent_control(const struct uevent_handler *uh)
262 return unregister_uevent_control(&uevent, uh);
265 static int device_event_handler(void *data)
267 device_notifier_state_e state = *(device_notifier_state_e *)data;
269 if (state == DEVICED_NOTIFIER_STATE_START) {
270 uevent_control_start(KERNEL, &kevent);
271 uevent_control_start(UDEV, &uevent);
272 } else if (state == DEVICED_NOTIFIER_STATE_STOP) {
273 uevent_control_stop(&kevent);
274 uevent_control_stop(&uevent);
280 static int device_change_poweroff(void *data)
282 uevent_control_stop(&kevent);
283 uevent_control_stop(&uevent);
287 static void udev_init(void *data)
289 syscommon_notifier_subscribe_notify(DEVICED_NOTIFIER_POWEROFF, device_change_poweroff);
290 syscommon_notifier_subscribe_notify(DEVICED_NOTIFIER_EVENT_HANDLER, device_event_handler);
292 if (uevent_control_start(KERNEL, &kevent) != 0)
293 _E("Failed to init uevent kernel control.");
295 if (uevent_control_start(UDEV, &uevent) != 0)
296 _E("Failed to init uevent udev control.");
299 static void udev_exit(void *data)
301 syscommon_notifier_unsubscribe_notify(DEVICED_NOTIFIER_EVENT_HANDLER, device_event_handler);
302 syscommon_notifier_unsubscribe_notify(DEVICED_NOTIFIER_POWEROFF, device_change_poweroff);
305 static const struct device_ops udev_device_ops = {
306 .priority = DEVICE_PRIORITY_NORMAL,
307 DECLARE_NAME_LEN("udev"),
312 DEVICE_OPS_REGISTER(&udev_device_ops)