summaryrefslogtreecommitdiff
path: root/android/hidhost.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2014-05-28 14:18:18 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2014-05-30 09:04:28 +0300
commit3452e079b4d1f13d04e05f9c6d4918d9276f808c (patch)
tree3bfec6c927b3829f6830cbb41570a33956f8aab2 /android/hidhost.c
parent8a2f6243438d2f88feaac652b5598bf2977946b0 (diff)
downloadbluez-3452e079b4d1f13d04e05f9c6d4918d9276f808c.tar.gz
android/hidhost: Rework uHID code to use bt_uhid
Diffstat (limited to 'android/hidhost.c')
-rw-r--r--android/hidhost.c143
1 files changed, 21 insertions, 122 deletions
diff --git a/android/hidhost.c b/android/hidhost.c
index 1758020e3..4a158c6b0 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,