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 #include </hal/include/device/hal-backend-common.h>
31 #define EVENT_KERNEL "kernel"
32 #define EVENT_UDEV "udev"
34 #define UDEV_MONITOR_SIZE (128*1024)
37 struct udev_monitor *mon;
45 static struct udev *udev;
46 static struct uevent_info kevent; /* kernel */
47 static struct uevent_info uevent; /* udev */
49 static gboolean uevent_control_cb(GIOChannel *channel,
50 GIOCondition cond, void *data)
52 struct uevent_info *info = data;
53 struct udev_device *dev;
54 struct uevent_handler *l;
56 const char *subsystem;
60 _E("data is invalid");
64 dev = udev_monitor_receive_device(info->mon);
68 subsystem = udev_device_get_subsystem(dev);
72 len = strlen(subsystem);
74 for (elem = info->event_list ; elem ; elem = g_list_next(elem)) {
78 if (!strncmp(l->subsystem, subsystem, len) &&
84 udev_device_unref(dev);
88 static int uevent_control_stop(struct uevent_info *info)
90 struct udev_device *dev;
96 g_source_remove(info->eventid);
100 g_io_channel_unref(info->ch);
104 dev = udev_monitor_receive_device(info->mon);
106 udev_device_unref(dev);
107 udev_monitor_unref(info->mon);
111 udev = udev_unref(udev);
115 static int uevent_control_start(const char *type,
116 struct uevent_info *info)
118 struct uevent_handler *l;
127 _E("%s uevent control routine is alreay started", type);
134 _E("error create udev");
138 udev = udev_ref(udev);
140 info->mon = udev_monitor_new_from_netlink(udev, type);
141 if (info->mon == NULL) {
142 _E("error udev_monitor create");
146 _I("Set udev monitor buffer size %d", UDEV_MONITOR_SIZE);
147 ret = udev_monitor_set_receive_buffer_size(info->mon,
150 _E("fail to set receive buffer size");
154 for (elem = info->event_list ; elem ; elem = g_list_next(elem)) {
156 ret = udev_monitor_filter_add_match_subsystem_devtype(
160 _E("error apply subsystem filter");
165 ret = udev_monitor_filter_update(info->mon);
167 _E("error udev_monitor_filter_update");
169 fd = udev_monitor_get_fd(info->mon);
171 _E("error udev_monitor_get_fd");
175 info->ch = g_io_channel_unix_new(fd);
176 info->eventid = g_io_add_watch(info->ch,
177 G_IO_IN, uevent_control_cb, info);
178 if (info->eventid == 0) {
179 _E("Failed to add channel watch");
183 if (udev_monitor_enable_receiving(info->mon) < 0) {
184 _E("error unable to subscribe to udev events");
190 uevent_control_stop(info);
194 int uevent_control_kernel_start(void)
196 return uevent_control_start(EVENT_KERNEL, &kevent);
199 void uevent_control_kernel_stop(void)
201 uevent_control_stop(&kevent);
204 int uevent_control_udev_start(void)
206 return uevent_control_start(EVENT_UDEV, &uevent);
209 void uevent_control_udev_stop(void)
211 uevent_control_stop(&uevent);
214 static int register_uevent_control(struct uevent_info *info,
215 struct uevent_handler *uh)
217 struct uevent_handler *l;
220 bool matched = false;
223 if (!info || !uh || !uh->subsystem)
226 /* if udev is not initialized, it just will be added list */
227 if (!udev || !info->mon)
230 len = strlen(uh->subsystem);
231 /* check if the same subsystem is already added */
232 for (elem = info->event_list; elem ; elem = g_list_next(elem)) {
234 if (!strncmp(l->subsystem, uh->subsystem, len)) {
240 /* the first request to add subsystem */
242 r = udev_monitor_filter_add_match_subsystem_devtype(info->mon,
243 uh->subsystem, NULL);
245 _E("fail to add %s subsystem : %d", uh->subsystem, r);
250 r = udev_monitor_filter_update(info->mon);
252 _E("fail to update udev monitor filter : %d", r);
255 info->event_list = g_list_append(info->event_list, uh);
259 static int unregister_uevent_control(struct uevent_info *info,
260 const struct uevent_handler *uh)
262 struct uevent_handler *l;
266 if (!info || !uh || !uh->subsystem)
269 len = strlen(uh->subsystem);
270 for (n = info->event_list, next = g_list_next(n) ;
271 n ; n = next, next = g_list_next(n)) {
273 if (!strncmp(l->subsystem, uh->subsystem, len) &&
274 l->uevent_func == uh->uevent_func) {
275 info->event_list = g_list_delete_link(info->event_list, n);
283 int register_kernel_event_control(struct uevent_handler *uh)
285 return register_uevent_control(&kevent, uh);
288 void unregister_kernel_event_control(struct uevent_handler *uh)
290 unregister_uevent_control(&kevent, uh);
293 int register_udev_event_control(struct uevent_handler *uh)
295 return register_uevent_control(&uevent, uh);
298 void unregister_udev_event_control(struct uevent_handler *uh)
300 unregister_uevent_control(&uevent, uh);