3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "um_usb_uevent_handler.h"
20 #define UEVENT_BUF_MAX (128*1024*1024)
21 #define UDEV_MON_UDEV "udev"
22 #define UDEV_ENTRY_NAME_SUBSYSTEM "SUBSYSTEM"
23 #define UDEV_ENTRY_NAME_ACTION "ACTION"
24 #define UDEV_ENTRY_NAME_DEVTYPE "DEVTYPE"
25 #define UDEV_ENTRY_NAME_DEVNAME "DEVNAME"
26 #define UDEV_ENTRY_NAME_NPARTS "NPARTS"
27 #define UDEV_ENTRY_NAME_ACCESSORY "ACCESSORY"
29 #define UDEV_SUBSYSTEM_BLOCK "block"
30 #define UDEV_SUBSYSTEM_USB_DEVICE "usb_device"
31 #define UDEV_SUBSYSTEM_USB "usb"
32 #define UDEV_SUBSYSTEM_MISC "misc"
33 #define UDEV_ACTION_ADD "add"
34 #define UDEV_ACTION_REMOVE "remove"
35 #define UDEV_ACTION_CHANGE "change"
36 #define UDEV_DEVTYPE_DISK "disk"
37 #define UDEV_DEVTYPE_PARTITION "partition"
38 #define UDEV_ACCESSORY_START "START"
40 static int um_event_control_get_value_by_name(struct udev_list_entry *list_entry,
41 char *name, char **value)
48 const char *localValue = NULL;
49 struct udev_list_entry *entry_found = NULL;
50 entry_found = udev_list_entry_get_by_name(list_entry, name);
52 USB_LOG("FAIL: udev_list_entry_get_by_name(%s)", name);
55 localValue = udev_list_entry_get_value(entry_found);
57 USB_LOG("FAIL: udev_list_entry_get_value(%s)", name);
60 USB_LOG("%s: %s", name, localValue);
62 *value = strdup(localValue);
64 USB_LOG("FAIL: strdup()");
72 static int um_uevent_control_usb_storage_action(UmMainData *ad,
83 if (!strcmp(action, UDEV_ACTION_ADD)) {
84 USB_LOG("Mass storage is added");
85 um_uevent_mass_storage_added(ad, (char *)devname, fstype);
91 if (!strcmp(action, UDEV_ACTION_REMOVE)) {
92 USB_LOG("Mass storage is removed");
93 um_uevent_mass_storage_removed(ad, (char *)devname);
98 USB_LOG("ERROR: Action (%s) is improper", action);
103 static int um_uevent_control_subsystem_block(UmMainData *ad, struct udev_list_entry *list_entry)
110 char *action = NULL; /* add, remove, ... */
111 char *devname = NULL; /* /dev/sda, /dev/sda1, ... */
112 char *fstype = NULL; /* vfat, ... */
113 char *fsversion = NULL; /* fat, fat32, ntfs, ... */
115 ret = um_event_control_get_value_by_name(list_entry, "ID_FS_TYPE", &fstype);
116 if (ret != 0 || !fstype) {
117 USB_LOG("ERROR: This block device cannot be mounted");
121 ret = um_event_control_get_value_by_name(list_entry, "ID_FS_VERSION", &fsversion);
122 if (ret != 0 || !fsversion) {
123 USB_LOG("ERROR: This block device cannot be mounted");
128 /* Getting device name */
129 ret = um_event_control_get_value_by_name(list_entry, UDEV_ENTRY_NAME_DEVNAME, &devname);
130 if (ret != 0 || !devname) {
131 USB_LOG("FAIL: um_event_control_get_value_by_name()");
134 USB_LOG("The device name is %s", devname);
135 if (!strstr(devname, "sd")) {
136 USB_LOG("ERROR: devname is improper");
140 /* Getting device action */
141 ret = um_event_control_get_value_by_name(list_entry, UDEV_ENTRY_NAME_ACTION, &action);
142 if (ret != 0 || !action) {
143 USB_LOG("FAIL: um_event_control_get_value_by_name()");
146 USB_LOG("The action is %s", action);
148 ret = um_uevent_control_usb_storage_action(ad, action, devname, fstype);
150 USB_LOG("FAIL: um_uevent_control_usb_storage_action()");
172 static int um_uevent_control_subsystem_usb_device(UmMainData *ad, struct udev_list_entry *list_entry)
179 char *action = NULL; /* add, remove, ... */
181 /* Getting device action */
182 ret = um_event_control_get_value_by_name(list_entry, UDEV_ENTRY_NAME_ACTION, &action);
183 if (ret < 0 || !action) {
184 USB_LOG("FAIL: um_event_control_get_value_by_name()");
188 USB_LOG("The action is %s", action);
190 if (!strcmp(action, UDEV_ACTION_ADD)) {
191 um_uevent_usb_host_added(ad);
197 if (!strcmp(action, UDEV_ACTION_REMOVE)) {
198 um_uevent_usb_host_removed(ad);
204 USB_LOG("ERROR: action (%s) is improper", action);
210 static int um_uevent_control_subsystem_misc(UmMainData *ad, struct udev_list_entry *list_entry)
217 char *action = NULL; /* add, remove, change ... */
218 char *accessory = NULL; /* START, ... */
220 /* Getting device action */
221 ret = um_event_control_get_value_by_name(list_entry, UDEV_ENTRY_NAME_ACTION, &action);
222 if (ret < 0 || !action) {
223 USB_LOG("FAIL: um_event_control_get_value_by_name()");
227 USB_LOG("The action is %s", action);
229 ret = um_event_control_get_value_by_name(list_entry, UDEV_ENTRY_NAME_ACCESSORY, &accessory);
230 if (ret < 0 || !accessory) {
231 USB_LOG("FAIL: um_event_control_get_value_by_name()");
235 USB_LOG("The accessory is %s", accessory);
237 if (!strcmp(action, UDEV_ACTION_CHANGE) && !strcmp(accessory, UDEV_ACCESSORY_START)) {
238 um_uevent_usb_accessory_added(ad);
251 static void um_uevent_control_subsystem(UmMainData *ad,
252 struct udev_list_entry *list_entry,
260 if (!strcmp(subsystem, UDEV_SUBSYSTEM_BLOCK)) {
261 if (um_uevent_control_subsystem_block(ad, list_entry) < 0)
262 USB_LOG("FAIL: um_uevent_control_subsystem_block()");
267 if (!strcmp(subsystem, UDEV_SUBSYSTEM_USB_DEVICE)) {
268 if (um_uevent_control_subsystem_usb_device(ad, list_entry) < 0)
269 USB_LOG("FAIL: um_uevent_control_subsystem_usb_device()");
274 if (!strcmp(subsystem, UDEV_SUBSYSTEM_MISC)) {
275 if (um_uevent_control_subsystem_misc(ad, list_entry) < 0)
276 USB_LOG("FAIL: um_uevent_control_subsystem_usb_device()");
281 USB_LOG("ERROR: subsystem (%s) is improper", subsystem);
285 static Eina_Bool uevent_control_cb(void *data, Ecore_Fd_Handler *fd_handler)
288 if (!data) return ECORE_CALLBACK_RENEW;
289 if (!fd_handler) return ECORE_CALLBACK_RENEW;
290 UmMainData *ad = (UmMainData *)data;
293 struct udev_device *dev = NULL;
294 struct udev_list_entry *list_entry = NULL;
295 struct udev_list_entry *entry_found = NULL;
296 char *subsystem = NULL;
298 if (!ecore_main_fd_handler_active_get(ad->udevFdHandler, ECORE_FD_READ)) {
299 USB_LOG("FAIL: ecore_main_fd_handler_active_get()");
300 return ECORE_CALLBACK_RENEW;
302 dev = udev_monitor_receive_device(ad->udevMon);
304 USB_LOG("FAIL: udev_monitor_receive_device()");
305 return ECORE_CALLBACK_RENEW;
308 /* Getting the First element of the device entry list */
309 list_entry = udev_device_get_properties_list_entry(dev);
311 USB_LOG("FAIL: udev_device_get_properties_list_entry()");
312 udev_device_unref(dev);
313 return ECORE_CALLBACK_RENEW;
316 ret = um_event_control_get_value_by_name(list_entry, UDEV_ENTRY_NAME_SUBSYSTEM, &subsystem);
317 if (ret < 0 || !subsystem) {
318 USB_LOG("FAIL: um_event_control_get_value_by_name()");
319 udev_device_unref(dev);
320 return ECORE_CALLBACK_RENEW;
323 udev_list_entry_foreach(entry_found, list_entry) {
324 USB_LOG("::::::::::::::::::::::::::::::::");
325 USB_LOG("::: Number: %d", i);
326 USB_LOG("::: Name : %s", udev_list_entry_get_name(entry_found));
327 USB_LOG("::: value : %s", udev_list_entry_get_value(entry_found));
329 USB_LOG(":::::::::::::::::::::::::::::");
331 um_uevent_control_subsystem(ad, list_entry, subsystem);
333 udev_device_unref(dev);
336 return ECORE_CALLBACK_RENEW;
339 void um_uevent_control_stop(UmMainData *ad)
344 if (ad->udevFdHandler) {
345 ecore_main_fd_handler_del(ad->udevFdHandler);
346 ad->udevFdHandler = NULL;
349 if (ad->udevFd >= 0) {
355 udev_monitor_unref(ad->udevMon);
360 udev_unref(ad->udev);
367 int um_uevent_control_start(UmMainData *ad, int mode)
374 ad->udev = udev_new();
376 USB_LOG("FAIL: udev_new()");
380 ad->udevMon = udev_monitor_new_from_netlink(ad->udev, UDEV_MON_UDEV);
381 if (ad->udevMon == NULL) {
382 USB_LOG("FAIL: udev_monitor_new_from_netlink()");
383 um_uevent_control_stop(ad);
387 /* The buffer size should be 128 * 1024 * 1024
388 * according to the buffer size of udev daemon */
389 ret = udev_monitor_set_receive_buffer_size(ad->udevMon, UEVENT_BUF_MAX);
391 USB_LOG("FAIL: udev_monitor_set_receive_buffer_size()");
392 um_uevent_control_stop(ad);
397 case USB_DEVICE_HOST:
398 if (udev_monitor_filter_add_match_subsystem_devtype(ad->udevMon,
399 UDEV_SUBSYSTEM_BLOCK, NULL) < 0
400 || udev_monitor_filter_add_match_subsystem_devtype(ad->udevMon,
401 UDEV_SUBSYSTEM_USB, NULL) < 0
402 || udev_monitor_filter_add_match_subsystem_devtype(ad->udevMon,
403 UDEV_SUBSYSTEM_USB_DEVICE, NULL) < 0) {
404 USB_LOG("FAIL: udev_monitor_filter_add_match_subsystem_devtype()");
405 um_uevent_control_stop(ad);
410 case USB_DEVICE_CLIENT:
411 if (udev_monitor_filter_add_match_subsystem_devtype(ad->udevMon,
412 UDEV_SUBSYSTEM_MISC, NULL) < 0) {
413 USB_LOG("FAIL: udev_monitor_filter_add_match_subsystem_devtype()");
414 um_uevent_control_stop(ad);
421 USB_LOG("ERROR: mode (%d) is improper", mode);
422 um_uevent_control_stop(ad);
426 ad->udevFd = udev_monitor_get_fd(ad->udevMon);
427 if (ad->udevFd < 0) {
428 USB_LOG("FAIL: udev_monitor_get_fd()");
429 um_uevent_control_stop(ad);
433 ad->udevFdHandler = ecore_main_fd_handler_add(ad->udevFd, ECORE_FD_READ,
434 uevent_control_cb, ad, NULL, NULL);
435 if (ad->udevFdHandler == NULL) {
436 USB_LOG("FAIL: ecore_main_fd_handler_add()");
437 um_uevent_control_stop(ad);
441 ret = udev_monitor_enable_receiving(ad->udevMon);
443 USB_LOG("FAIL: udev_monitor_enable_receiving()");
444 um_uevent_control_stop(ad);