[PATCH BlueZ 1/2] android/hidhost: Rework uHID code to use bt_uhid

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

---
 android/Android.mk  |   1 +
 android/Makefile.am |   1 +
 android/hidhost.c   | 143 ++++++++--------------------------------------------
 3 files changed, 23 insertions(+), 122 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index afd6e9c..de909d6 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -54,6 +54,7 @@ LOCAL_SRC_FILES := \
 	bluez/src/shared/gatt-db.c \
 	bluez/src/shared/io-glib.c \
 	bluez/src/shared/crypto.c \
+	bluez/src/shared/uhid.c \
 	bluez/src/sdpd-database.c \
 	bluez/src/sdpd-service.c \
 	bluez/src/sdpd-request.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 2d74505..bcaec4c 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -32,6 +32,7 @@ android_bluetoothd_SOURCES = android/main.c \
 				src/shared/hfp.h src/shared/hfp.c \
 				src/shared/gatt-db.h src/shared/gatt-db.c \
 				src/shared/crypto.h src/shared/crypto.c \
+				src/shared/uhid.h src/shared/uhid.c \
 				android/bluetooth.h android/bluetooth.c \
 				android/hidhost.h android/hidhost.c \
 				android/ipc-common.h \
diff --git a/android/hidhost.c b/android/hidhost.c
index 1758020..4a158c6 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -40,9 +40,9 @@
 #include "lib/sdp_lib.h"
 #include "src/shared/mgmt.h"
 #include "src/shared/util.h"
+#include "src/shared/uhid.h"
 #include "src/sdp-client.h"
 #include "src/uuid-helper.h"
-#include "profiles/input/uhid_copy.h"
 #include "src/log.h"
 
 #include "hal-msg.h"
@@ -53,7 +53,6 @@
 
 #define L2CAP_PSM_HIDP_CTRL	0x11
 #define L2CAP_PSM_HIDP_INTR	0x13
-#define UHID_DEVICE_FILE	"/dev/uhid"
 
 /* HID message types */
 #define HID_MSG_CONTROL		0x10
@@ -101,8 +100,7 @@ struct hid_device {
 	GIOChannel	*intr_io;
 	guint		ctrl_watch;
 	guint		intr_watch;
-	int		uhid_fd;
-	guint		uhid_watch_id;
+	struct bt_uhid	*uhid;
 	uint8_t		last_hid_msg;
 };
 
@@ -114,21 +112,6 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 	return bacmp(&dev->dst, dst);
 }
 
-static void uhid_destroy(int fd)
-{
-	struct uhid_event ev;
-
-	/* destroy uHID device */
-	memset(&ev, 0, sizeof(ev));
-	ev.type = UHID_DESTROY;
-
-	if (write(fd, &ev, sizeof(ev)) < 0)
-		error("hidhost: Failed to destroy uHID device: %s (%d)",
-						strerror(errno), errno);
-
-	close(fd);
-}
-
 static void hid_device_free(void *data)
 {
 	struct hid_device *dev = data;
@@ -145,13 +128,8 @@ static void hid_device_free(void *data)
 	if (dev->ctrl_io)
 		g_io_channel_unref(dev->ctrl_io);
 
-	if (dev->uhid_watch_id) {
-		g_source_remove(dev->uhid_watch_id);
-		dev->uhid_watch_id = 0;
-	}
-
-	if (dev->uhid_fd > 0)
-		uhid_destroy(dev->uhid_fd);
+	if (dev->uhid)
+		bt_uhid_unref(dev->uhid);
 
 	g_free(dev->rd_data);
 	g_free(dev);
@@ -196,9 +174,10 @@ static bool hex2buf(const uint8_t *hex, uint8_t *buf, int buf_size)
 	return true;
 }
 
-static void handle_uhid_output(struct hid_device *dev,
-						struct uhid_output_req *output)
+static void handle_uhid_output(struct uhid_event *event, void *user_data)
 {
+	struct uhid_output_req *output = &event->u.output;
+	struct hid_device *dev = user_data;
 	int fd, req_size;
 	uint8_t *req;
 
@@ -222,87 +201,15 @@ static void handle_uhid_output(struct hid_device *dev,
 	free(req);
 }
 
-static gboolean uhid_event_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
-{
-	struct hid_device *dev = user_data;
-	struct uhid_event ev;
-	ssize_t bread;
-	int fd;
-
-	DBG("");
-
-	if (cond & (G_IO_ERR | G_IO_NVAL))
-		goto failed;
-
-	fd = g_io_channel_unix_get_fd(io);
-	memset(&ev, 0, sizeof(ev));
-
-	bread = read(fd, &ev, sizeof(ev));
-	if (bread < 0) {
-		DBG("read: %s (%d)", strerror(errno), errno);
-		goto failed;
-	}
-
-	DBG("uHID event type %d received", ev.type);
-
-	switch (ev.type) {
-	case UHID_START:
-	case UHID_STOP:
-		/*
-		 * These are called to start and stop the underlying hardware.
-		 * We open the channels before creating the device so the
-		 * hardware is always ready. No need to handle these.
-		 * The kernel never destroys a device itself! Only an explicit
-		 * UHID_DESTROY request can remove a device.
-		 */
-		break;
-	case UHID_OPEN:
-	case UHID_CLOSE:
-		/*
-		 * OPEN/CLOSE are sent whenever user-space opens any interface
-		 * provided by the kernel HID device. Whenever the open-count
-		 * is non-zero we must be ready for I/O. As long as it is zero,
-		 * we can decide to drop all I/O and put the device
-		 * asleep This is optional, though.
-		 */
-		break;
-	case UHID_OUTPUT:
-		handle_uhid_output(dev, &ev.u.output);
-		break;
-	case UHID_FEATURE:
-		/* TODO */
-		break;
-	case UHID_OUTPUT_EV:
-		/*
-		 * This is only sent by kernels prior to linux-3.11. It
-		 * requires us to parse HID-descriptors in user-space to
-		 * properly handle it. This is redundant as the kernel
-		 * does it already. That's why newer kernels assemble
-		 * the output-reports and send it to us via UHID_OUTPUT.
-		 */
-		DBG("UHID_OUTPUT_EV unsupported");
-		break;
-	default:
-		warn("unexpected uHID event");
-	}
-
-	return TRUE;
-
-failed:
-	dev->uhid_watch_id = 0;
-	return FALSE;
-}
-
 static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
 {
 	struct hid_device *dev = data;
 	uint8_t buf[UHID_DATA_MAX];
 	struct uhid_event ev;
-	int fd, bread;
+	int fd, bread, err;
 
 	/* Wait uHID if not ready */
-	if (dev->uhid_fd < 0)
+	if (!dev->uhid)
 		return TRUE;
 
 	fd = g_io_channel_unix_get_fd(chan);
@@ -323,8 +230,9 @@ static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
 	ev.u.input.size = bread - 1;
 	memcpy(ev.u.input.data, &buf[1], ev.u.input.size);
 
-	if (write(dev->uhid_fd, &ev, sizeof(ev)) < 0)
-		DBG("uhid write: %s (%d)", strerror(errno), errno);
+	err = bt_uhid_send(dev->uhid, &ev);
+	if (err < 0)
+		DBG("bt_uhid_send: %s (%d)", strerror(-err), -err);
 
 	return TRUE;
 }
@@ -571,16 +479,13 @@ static void bt_hid_set_info(struct hid_device *dev)
 
 static int uhid_create(struct hid_device *dev)
 {
-	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_NVAL;
 	struct uhid_event ev;
-	GIOChannel *io;
 	int err;
 
-	dev->uhid_fd = open(UHID_DEVICE_FILE, O_RDWR | O_CLOEXEC);
-	if (dev->uhid_fd < 0) {
+	dev->uhid = bt_uhid_new_default();
+	if (!dev->uhid) {
 		err = -errno;
-		error("hidhost: Failed to open uHID device: %s",
-							strerror(errno));
+		error("hidhost: Failed to create bt_uhid instance");
 		return err;
 	}
 
@@ -595,20 +500,16 @@ static int uhid_create(struct hid_device *dev)
 	ev.u.create.rd_size = dev->rd_size;
 	ev.u.create.rd_data = dev->rd_data;
 
-	if (write(dev->uhid_fd, &ev, sizeof(ev)) < 0) {
-		err = -errno;
+	err = bt_uhid_send(dev->uhid, &ev);
+	if (err < 0) {
 		error("hidhost: Failed to create uHID device: %s",
-							strerror(errno));
-		close(dev->uhid_fd);
-		dev->uhid_fd = -1;
+							strerror(-err));
+		bt_uhid_unref(dev->uhid);
+		dev->uhid = NULL;
 		return err;
 	}
 
-	io = g_io_channel_unix_new(dev->uhid_fd);
-	g_io_channel_set_encoding(io, NULL, NULL);
-	dev->uhid_watch_id = g_io_add_watch(io, cond, uhid_event_cb, dev);
-	g_io_channel_unref(io);
-
+	bt_uhid_register(dev->uhid, UHID_OUTPUT, handle_uhid_output, dev);
 	bt_hid_set_info(dev);
 
 	return 0;
@@ -843,7 +744,6 @@ static void bt_hid_connect(const void *buf, uint16_t len)
 
 	dev = g_new0(struct hid_device, 1);
 	bacpy(&dev->dst, &dst);
-	dev->uhid_fd = -1;
 
 	ba2str(&dev->dst, addr);
 	DBG("connecting to %s", addr);
@@ -1361,7 +1261,6 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 		dev = g_new0(struct hid_device, 1);
 		bacpy(&dev->dst, &dst);
 		dev->ctrl_io = g_io_channel_ref(chan);
-		dev->uhid_fd = -1;
 
 		sdp_uuid16_create(&uuid, PNP_INFO_SVCLASS_ID);
 		if (bt_search_service(&adapter_addr, &dev->dst, &uuid,
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux