summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Szewczyk <p.szewczyk@samsung.com>2016-02-10 13:32:13 +0100
committerTaeyoung Kim <ty317.kim@samsung.com>2016-08-02 22:19:13 -0700
commit2d451eeaf595ed4ee38925b43b8acc036f639c17 (patch)
tree4119fe8937919085f4c073c9f1363e92e8b21cff
parent7a1eea1a0ce2fce63cc02725bf0290542eae6348 (diff)
downloaddeviced-2d451eeaf595ed4ee38925b43b8acc036f639c17.tar.gz
deviced-2d451eeaf595ed4ee38925b43b8acc036f639c17.tar.bz2
deviced-2d451eeaf595ed4ee38925b43b8acc036f639c17.zip
usbhost: Add API for handling device attach/detach
Change-Id: Ie333f7b403721f7b0611c57d172a930d1b1fc456 Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
-rw-r--r--src/deviced/dd-usbhost.h77
-rw-r--r--src/libdeviced/usbhost.c185
-rw-r--r--src/usbhost/usb-host.c12
3 files changed, 216 insertions, 58 deletions
diff --git a/src/deviced/dd-usbhost.h b/src/deviced/dd-usbhost.h
index eff38b0d..9bae8ae6 100644
--- a/src/deviced/dd-usbhost.h
+++ b/src/deviced/dd-usbhost.h
@@ -36,6 +36,24 @@ extern "C" {
* @{
*/
+#include <limits.h>
+struct usbhost_device {
+ char devpath[PATH_MAX]; /* unique info. */
+ int baseclass;
+ int subclass;
+ int protocol;
+ int vendorid;
+ int productid;
+ char *manufacturer;
+ char *product;
+ char *serial;
+};
+
+enum usbhost_state {
+ USB_HOST_REMOVED,
+ USB_HOST_ADDED,
+};
+
/**
* @par Description:
* This API is used to initialize usbhost signal \n
@@ -100,6 +118,37 @@ int register_usb_storage_change_handler(
/**
* @par Description:
+ * This API is used to register usbhost signal \n
+ * @param[in] device_changed callback function which is called when the device is connected/disconnected
+ * @param[in] data parameter of the callback function
+ * @return 0 on success, negative if failed
+ * @par Example
+ * @code
+ * ...
+ * if (init_usbhost_signal() < 0)
+ * printf("Failed to initialize usbhost signal\n");
+ *
+ * if (register_usb_device_change_handler(device_cb, data) < 0) {
+ * printf("Failed to register device handler\n");
+ * deinit_usbhost_signal();
+ * return;
+ * }
+ *
+ * // Do something
+ *
+ * if (unregister_usb_device_changed_handler() < 0)
+ * printf("Failed to unregister device changed signal\n");
+ *
+ * deinit_usbhost_signal();
+ * ...
+ * @endcode
+ */
+int register_usb_device_change_handler(
+ void (*device_changed)(struct usbhost_device *device, int state, void *data),
+ void *data);
+
+/**
+ * @par Description:
* This API is used to unregister usbhost signal \n
* @return 0 on success, negative if failed
* @par Example
@@ -127,6 +176,34 @@ int unregister_usb_storage_change_handler(void);
/**
* @par Description:
+ * This API is used to unregister usb connect/disconnect signal handler\n
+ * @return 0 on success, negative if failed
+ * @par Example
+ * @code
+ * ...
+ * if (init_usbhost_signal() < 0)
+ * printf("Failed to initialize usbhost signal\n");
+ *
+ * if (register_usb_device_change_handler(device_cb, data) < 0) {
+ * printf("Failed to register device signal\n");
+ * deinit_usbhost_signal();
+ * return;
+ * }
+ *
+ * // Do something
+ *
+ * if (unregister_usb_device_change_handler() < 0)
+ * printf("Failed to unregister storage signal\n");
+ *
+ * deinit_usbhost_signal();
+ * ...
+ * @endcode
+ */
+int unregister_usb_device_change_handler(
+ void (*device_changed)(struct usbhost_device *device, int state, void *data));
+
+/**
+ * @par Description:
* This API is used to request usb storage information \n
* @return 0 on success, negative if failed
* @par Example
diff --git a/src/libdeviced/usbhost.c b/src/libdeviced/usbhost.c
index 747be174..fae5d8a8 100644
--- a/src/libdeviced/usbhost.c
+++ b/src/libdeviced/usbhost.c
@@ -24,6 +24,8 @@
#include "log.h"
#include "common.h"
#include "dbus.h"
+#include "dd-usbhost.h"
+#include "core/list.h"
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
@@ -33,27 +35,32 @@
#define METHOD_REQUEST_STORAGE_UNMOUNT "StorageUnmount"
#define METHOD_REQUEST_STORAGE_FORMAT "StorageFormat"
#define SIGNAL_NAME_USB_STORAGE_CHANGED "usb_storage_changed"
+#define SIGNAL_NAME_USB_DEVICE_CHANGED "ChangedDevice"
#define RETRY_MAX 5
+union action {
+ void (*storage)(char *type, char *path, int mount, void *param);
+ void (*device)(struct usbhost_device *device, int state, void *data);
+};
+
struct signal_handler {
- char *name;
+ const char *name;
E_DBus_Signal_Handler *handler;
- void (*action)(char *type, char *path, int mount, void *param);
+ union action action;
void *data;
};
-static struct signal_handler handlers[] = {
- { SIGNAL_NAME_USB_STORAGE_CHANGED , NULL, NULL, NULL },
-};
+static dd_list *handlers;
static E_DBus_Connection *conn = NULL;
static int register_edbus_signal_handler(const char *path, const char *interface,
const char *name, E_DBus_Signal_Cb cb,
- void (*action)(char *type, char *path, int mount, void *param),
+ union action action,
void *data)
{
- int i, ret;
+ int ret;
+ struct signal_handler *handler = NULL;
if (!conn) {
_E("Use init_usbhost_signal() first to use this function");
@@ -61,45 +68,39 @@ static int register_edbus_signal_handler(const char *path, const char *interface
goto out;
}
- for (i = 0 ; i < ARRAY_SIZE(handlers) ; i++) {
- if (strncmp(handlers[i].name, name, strlen(name)))
- continue;
- break;
- }
- if (i >= ARRAY_SIZE(handlers)) {
- _E("Failed to find \"storage_changed\" signal");
- ret = -1;
- goto out;
- }
-
- if (handlers[i].handler) {
- _E("The handler is already registered");
- ret = -1;
+ handler = calloc(1, sizeof(*handler));
+ if (!handler) {
+ _E("No memory");
goto out;
}
-
- handlers[i].handler = e_dbus_signal_handler_add(conn, NULL, path,
+ handler->name = name;
+ handler->handler = e_dbus_signal_handler_add(conn, NULL, path,
interface, name, cb, NULL);
- if (!(handlers[i].handler)) {
+ if (!(handler->handler)) {
_E("fail to add edbus handler");
ret = -1;
goto out;
}
- handlers[i].action = action;
- handlers[i].data = data;
+
+ handler->action = action;
+ handler->data = data;
+
+ DD_LIST_APPEND(handlers, handler);
return 0;
out:
+ free(handler);
return ret;
}
static void storage_signal_handler(void *data, DBusMessage *msg)
{
- int i;
char *type, *path;
int mount;
DBusError err;
+ dd_list *elem;
+ struct signal_handler *handler;
if (dbus_message_is_signal(msg, DEVICED_INTERFACE_USBHOST, SIGNAL_NAME_USB_STORAGE_CHANGED) == 0) {
_E("The signal is not for storage changed");
@@ -117,18 +118,55 @@ static void storage_signal_handler(void *data, DBusMessage *msg)
return;
}
- for (i = 0 ; i < ARRAY_SIZE(handlers) ; i++) {
- if (strcmp(handlers[i].name, SIGNAL_NAME_USB_STORAGE_CHANGED))
+ DD_LIST_FOREACH(handlers, elem, handler) {
+ if (strcmp(handler->name, SIGNAL_NAME_USB_STORAGE_CHANGED))
continue;
- break;
+
+ if (handler->action.storage)
+ handler->action.storage(type, path, mount, handler->data);
}
- if (i >= ARRAY_SIZE(handlers)) {
- _E("Failed to find \"storage_changed\" signal");
+}
+
+static void device_signal_handler(void *data, DBusMessage *msg)
+{
+ char *path;
+ struct usbhost_device device;
+ int state;
+ DBusError err;
+ struct signal_handler *handler;
+ dd_list *element;
+
+ if (dbus_message_is_signal(msg, DEVICED_INTERFACE_USBHOST, SIGNAL_NAME_USB_DEVICE_CHANGED) == 0) {
+ _E("The signal is not ChangedDevice");
return;
}
- if (handlers[i].action)
- handlers[i].action(type, path, mount, handlers[i].data);
+ dbus_error_init(&err);
+ if (dbus_message_get_args(msg, &err,
+ DBUS_TYPE_INT32, &state,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_INT32, &device.baseclass,
+ DBUS_TYPE_INT32, &device.subclass,
+ DBUS_TYPE_INT32, &device.protocol,
+ DBUS_TYPE_INT32, &device.vendorid,
+ DBUS_TYPE_INT32, &device.productid,
+ DBUS_TYPE_STRING, &device.manufacturer,
+ DBUS_TYPE_STRING, &device.product,
+ DBUS_TYPE_STRING, &device.serial,
+ DBUS_TYPE_INVALID) == 0) {
+ _E("Failed to get device info");
+ return;
+ }
+
+ strncpy(device.devpath, path, PATH_MAX);
+
+ DD_LIST_FOREACH(handlers, element, handler) {
+ if (strcmp(handler->name, SIGNAL_NAME_USB_DEVICE_CHANGED))
+ continue;
+
+ if (handler->action.device)
+ handler->action.device(&device, state, handler->data);
+ }
}
API int init_usbhost_signal(void)
@@ -158,18 +196,20 @@ API int init_usbhost_signal(void)
API void deinit_usbhost_signal(void)
{
- int i;
+ dd_list *n, *next;
+ struct signal_handler *handler;
if (!conn)
return;
- for (i = 0 ; i < ARRAY_SIZE(handlers) ; i++) {
- if (handlers[i].handler) {
- e_dbus_signal_handler_del(conn, handlers[i].handler);
- handlers[i].handler = NULL;
+ DD_LIST_FOREACH_SAFE(handlers, n, next, handler) {
+ DD_LIST_REMOVE(handlers, handler);
+ if (handler->handler) {
+ e_dbus_signal_handler_del(conn, handler->handler);
+ handler->handler = NULL;
}
- handlers[i].action = NULL;
- handlers[i].data = NULL;
+
+ free(handler);
}
e_dbus_connection_close(conn);
@@ -185,36 +225,77 @@ API int request_usb_storage_info(void)
}
API int register_usb_storage_change_handler(
- void (*storage_changed)(char *type, char *path, int mount, void *),
+ void (*storage_changed)(char *type, char *path, int mount, void *param),
void *data)
{
+ union action action;
if (!storage_changed)
return -EINVAL;
+ action.storage = storage_changed;
return register_edbus_signal_handler(DEVICED_PATH_USBHOST,
DEVICED_INTERFACE_USBHOST,
SIGNAL_NAME_USB_STORAGE_CHANGED,
storage_signal_handler,
- storage_changed,
+ action,
+ data);
+}
+
+API int register_usb_device_change_handler(
+ void (*device_changed)(struct usbhost_device *device, int state, void *data),
+ void *data)
+{
+ union action action;
+ if (!device_changed)
+ return -EINVAL;
+
+ action.device = device_changed;
+ return register_edbus_signal_handler(DEVICED_PATH_USBHOST,
+ DEVICED_INTERFACE_USBHOST,
+ SIGNAL_NAME_USB_DEVICE_CHANGED,
+ device_signal_handler,
+ action,
data);
}
API int unregister_usb_storage_change_handler(void)
{
- int i;
+ dd_list *n, *next;
+ struct signal_handler *handler;
- for (i = 0 ; i < ARRAY_SIZE(handlers) ; i++) {
- if (strcmp(handlers[i].name, SIGNAL_NAME_USB_STORAGE_CHANGED))
+ DD_LIST_FOREACH_SAFE(handlers, n, next, handler) {
+ if (strcmp(handler->name, SIGNAL_NAME_USB_STORAGE_CHANGED))
continue;
- if (handlers[i].handler == NULL)
+ if (handler->handler == NULL)
continue;
- e_dbus_signal_handler_del(conn, handlers[i].handler);
- handlers[i].handler = NULL;
- handlers[i].action = NULL;
- handlers[i].data = NULL;
- return 0;
+ e_dbus_signal_handler_del(conn, handler->handler);
+ DD_LIST_REMOVE(handlers, handler);
+ free(handler);
}
+
+ return 0;
+}
+
+API int unregister_usb_device_change_handler(
+ void (*device_changed)(struct usbhost_device *device, int state, void *data))
+{
+ dd_list *n, *next;
+ struct signal_handler *handler;
+
+ DD_LIST_FOREACH_SAFE(handlers, n, next, handler) {
+ if (strcmp(handler->name, SIGNAL_NAME_USB_DEVICE_CHANGED))
+ continue;
+ if (handler->handler == NULL)
+ continue;
+ if (handler->action.device != device_changed)
+ continue;
+
+ e_dbus_signal_handler_del(conn, handler->handler);
+ DD_LIST_REMOVE(handlers, handler);
+ free(handler);
+ }
+
return -1;
}
diff --git a/src/usbhost/usb-host.c b/src/usbhost/usb-host.c
index 99c10685..e4a48b87 100644
--- a/src/usbhost/usb-host.c
+++ b/src/usbhost/usb-host.c
@@ -29,6 +29,7 @@
#include "core/device-notifier.h"
#include "core/udev.h"
#include "core/list.h"
+#include "core/device-idler.h"
#define USB_INTERFACE_CLASS "bInterfaceClass"
#define USB_INTERFACE_SUBCLASS "bInterfaceSubClass"
@@ -45,7 +46,7 @@
#define ROOTPATH tzplatform_getenv(TZ_SYS_VAR)
#define POLICY_FILENAME "usbhost-policy"
-const char *POLICY_FILEPATH;
+char *POLICY_FILEPATH;
/**
* Below usb host class is defined by www.usb.org.
@@ -582,7 +583,6 @@ static int read_policy(void)
FILE *fp;
struct policy_entry *entry;
char *line = NULL, value_str[256];
- char *p;
int ret = -1;
int count = 0;
size_t len;
@@ -608,7 +608,7 @@ static int read_policy(void)
goto out;
}
- ret = sscanf(line, "%d %s %04x %02x %02x %02x %04x %04x %04x %s\n",
+ ret = sscanf(line, "%d %s %04hx %02hhx %02hhx %02hhx %04hx %04hx %04hx %s\n",
&entry->creds.uid,
entry->creds.sec_label,
&entry->device.bcdUSB,
@@ -831,7 +831,7 @@ static int creds_read_label(DBusMessageIter *iter, char **dest)
static int get_caller_credentials(DBusMessage *msg, struct user_credentials *cred)
{
- char *cid;
+ const char *cid;
char *key;
char *arr[1];
DBusMessage *reply;
@@ -846,7 +846,7 @@ static int get_caller_credentials(DBusMessage *msg, struct user_credentials *cre
return -1;
}
- arr[0] = cid;
+ arr[0] = (char *)cid;
reply = dbus_method_sync_with_reply(DBUS_BUS_NAME,
DBUS_OBJECT_PATH,
DBUS_INTERFACE_NAME,
@@ -929,7 +929,7 @@ static DBusMessage *open_device(E_DBus_Object *obj, DBusMessage *msg)
DBusError err;
dbus_bool_t dbus_ret;
int ret = 0, fd = -1;
- const char *path;
+ char *path;
struct user_credentials cred;
dbus_error_init(&err);