2013-11-05 21:09:06

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 00/12] Implemented hid interfaces in daemon and HAL

v4: Fixed Johan's comments (length issue and single byte array)

v3: Wrong order of patches

v2: Fixed Johan's comments (splitting of patches, proper function and
struct names, update hal-msg.h and ipc document, alignment issues
removed pointer from ipc struct)

v1: This patch set implements get/set protocol and get/set report
interfaces and supported functionality in daemon. Sending notifications
and notification handling in hal. Few naming fixes and error handling.
And last handling of few uHID events.

Ravi kumar Veeramally (12):
android/hid: Implement hid get protocol in daemon
android/hid: Implement hid set protocol in daemon
android/hid: Handle protocol mode notification in HAL
android/hid: Add hid event get report structure to HAL msg headers
android/hid: Implement hid get report in daemon
android/hid: Add missing set report parameters to ipc document
android/hid: Implement hid set report in daemon
android/hid: Handle get report notification in HAL
android/hid: Replace header checking magic number with defines
android/hid: Handle invalid parameters in HAL
android/hid: Handle uhid events
android/hid: Align hal hid struct variables properly

android/hal-hidhost.c | 41 +++++-
android/hal-ipc-api.txt | 4 +-
android/hal-msg.h | 32 +++--
android/hid.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 372 insertions(+), 30 deletions(-)

--
1.8.1.2



2013-11-06 08:37:29

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH_v4 00/12] Implemented hid interfaces in daemon and HAL

Hi Ravi,

On Tue, Nov 05, 2013, Ravi kumar Veeramally wrote:
> v4: Fixed Johan's comments (length issue and single byte array)
>
> v3: Wrong order of patches
>
> v2: Fixed Johan's comments (splitting of patches, proper function and
> struct names, update hal-msg.h and ipc document, alignment issues
> removed pointer from ipc struct)
>
> v1: This patch set implements get/set protocol and get/set report
> interfaces and supported functionality in daemon. Sending notifications
> and notification handling in hal. Few naming fixes and error handling.
> And last handling of few uHID events.
>
> Ravi kumar Veeramally (12):
> android/hid: Implement hid get protocol in daemon
> android/hid: Implement hid set protocol in daemon
> android/hid: Handle protocol mode notification in HAL
> android/hid: Add hid event get report structure to HAL msg headers
> android/hid: Implement hid get report in daemon
> android/hid: Add missing set report parameters to ipc document
> android/hid: Implement hid set report in daemon
> android/hid: Handle get report notification in HAL
> android/hid: Replace header checking magic number with defines
> android/hid: Handle invalid parameters in HAL
> android/hid: Handle uhid events
> android/hid: Align hal hid struct variables properly
>
> android/hal-hidhost.c | 41 +++++-
> android/hal-ipc-api.txt | 4 +-
> android/hal-msg.h | 32 +++--
> android/hid.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++--
> 4 files changed, 372 insertions(+), 30 deletions(-)

I've applied all patches, but I also did some minor cleanups while
applying (e.g. to the documentation patch) and some bigger ones as
separate patches on top of this set.

Johan

2013-11-05 21:09:18

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 12/12] android/hid: Align hal hid struct variables properly

---
android/hal-msg.h | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 2c3067f..41ba649 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -282,9 +282,9 @@ struct hal_cmd_hid_set_protocol {

#define HAL_OP_HID_GET_REPORT 0x07
struct hal_cmd_hid_get_report {
- uint8_t bdaddr[6];
- uint8_t type;
- uint8_t id;
+ uint8_t bdaddr[6];
+ uint8_t type;
+ uint8_t id;
uint16_t buf;
} __attribute__((packed));

@@ -448,16 +448,16 @@ struct hal_ev_hid_conn_state {

#define HAL_EV_HID_INFO 0x82
struct hal_ev_hid_info {
- uint8_t bdaddr[6];
- uint8_t attr;
- uint8_t subclass;
- uint8_t app_id;
+ uint8_t bdaddr[6];
+ uint8_t attr;
+ uint8_t subclass;
+ uint8_t app_id;
uint16_t vendor;
uint16_t product;
uint16_t version;
- uint8_t country;
+ uint8_t country;
uint16_t descr_len;
- uint8_t descr[884];
+ uint8_t descr[884];
} __attribute__((packed));

#define HAL_EV_HID_PROTO_MODE 0x83
--
1.8.1.2


2013-11-05 21:09:14

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 08/12] android/hid: Handle get report notification in HAL

---
android/hal-hidhost.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index 29e3ee0..fe68fe7 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -68,6 +68,15 @@ static void handle_proto_mode(void *buf)
ev->status, ev->mode);
}

+static void handle_get_report(void *buf)
+{
+ struct hal_ev_hid_get_report *ev = buf;
+
+ if (bt_hh_cbacks->get_report_cb)
+ bt_hh_cbacks->get_report_cb((bt_bdaddr_t *) ev->bdaddr,
+ ev->status, ev->data, ev->len);
+}
+
/* will be called from notification thread context */
void bt_notify_hh(uint16_t opcode, void *buf, uint16_t len)
{
@@ -84,6 +93,9 @@ void bt_notify_hh(uint16_t opcode, void *buf, uint16_t len)
case HAL_EV_HID_PROTO_MODE:
handle_proto_mode(buf);
break;
+ case HAL_EV_HID_GET_REPORT:
+ handle_get_report(buf);
+ break;
default:
DBG("Unhandled callback opcode=0x%x", opcode);
break;
--
1.8.1.2


2013-11-05 21:09:15

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 09/12] android/hid: Replace header checking magic number with defines

---
android/hid.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/hid.c b/android/hid.c
index 5411922..999f5d6 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -200,7 +200,7 @@ static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
}

/* Discard non-data packets */
- if (bread == 0 || buf[0] != 0xA1)
+ if (bread == 0 || buf[0] != (HID_MSG_DATA | HID_DATA_TYPE_INPUT))
return TRUE;

/* send data to uHID device skipping HIDP header byte */
--
1.8.1.2


2013-11-05 21:09:13

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 07/12] android/hid: Implement hid set report in daemon

This patch requests hid device to set report.
---
android/hal-hidhost.c | 2 ++
android/hal-msg.h | 6 ++++--
android/hid.c | 40 ++++++++++++++++++++++++++++++++++++++--
3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index f554cb2..29e3ee0 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -284,6 +284,8 @@ static bt_status_t hh_set_report(bt_bdaddr_t *bd_addr,
return BT_STATUS_PARM_INVALID;

memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+ cmd.len = strlen(report);
+ memcpy(cmd.data, report, cmd.len);

switch (reportType) {
case BTHH_INPUT_REPORT:
diff --git a/android/hal-msg.h b/android/hal-msg.h
index bc7df6b..2c3067f 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -290,8 +290,10 @@ struct hal_cmd_hid_get_report {

#define HAL_OP_HID_SET_REPORT 0x08
struct hal_cmd_hid_set_report {
- uint8_t bdaddr[6];
- uint8_t type;
+ uint8_t bdaddr[6];
+ uint8_t type;
+ uint16_t len;
+ uint8_t data[670];
} __attribute__((packed));

#define HAL_OP_HID_SEND_DATA 0x09
diff --git a/android/hid.c b/android/hid.c
index fd58e6f..5411922 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -56,6 +56,7 @@

/* HID message types */
#define HID_MSG_GET_REPORT 0x40
+#define HID_MSG_SET_REPORT 0x50
#define HID_MSG_GET_PROTOCOL 0x60
#define HID_MSG_SET_PROTOCOL 0x70
#define HID_MSG_DATA 0xa0
@@ -842,9 +843,44 @@ static uint8_t bt_hid_get_report(struct hal_cmd_hid_get_report *cmd,
static uint8_t bt_hid_set_report(struct hal_cmd_hid_set_report *cmd,
uint16_t len)
{
- DBG("Not Implemented");
+ struct hid_device *dev;
+ GSList *l;
+ bdaddr_t dst;
+ int fd;
+ uint8_t *req;
+ uint8_t req_size;

- return HAL_STATUS_FAILED;
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(devices, &dst, device_cmp);
+ if (!l)
+ return HAL_STATUS_FAILED;
+
+ dev = l->data;
+ req_size = 1 + cmd->len;
+ req = g_try_malloc0(req_size);
+ if (!req)
+ return HAL_STATUS_NOMEM;
+
+ req[0] = HID_MSG_SET_REPORT | cmd->type;
+ memcpy(req + 1, cmd->data, req_size - 1);
+
+ fd = g_io_channel_unix_get_fd(dev->ctrl_io);
+
+ if (write(fd, req, req_size) < 0) {
+ error("error while querying device protocol");
+ g_free(req);
+ return HAL_STATUS_FAILED;
+ }
+
+ dev->last_hid_msg = HID_MSG_SET_REPORT;
+ g_free(req);
+ return HAL_STATUS_SUCCESS;
}

static uint8_t bt_hid_send_data(struct hal_cmd_hid_send_data *cmd,
--
1.8.1.2


2013-11-05 21:09:17

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 11/12] android/hid: Handle uhid events

Handling few uhid events and described scenarios. OUTPUT and
FEATURE events are not yet handled.
---
android/hid.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/android/hid.c b/android/hid.c
index 999f5d6..172a945 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -149,6 +149,11 @@ static void hid_device_free(struct hid_device *dev)
g_free(dev);
}

+static void handle_uhid_event(struct hid_device *dev, struct uhid_event *ev)
+{
+ DBG("UHID_OUTPUT UHID_FEATURE unsupported");
+}
+
static gboolean uhid_event_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
@@ -172,7 +177,40 @@ static gboolean uhid_event_cb(GIOChannel *io, GIOCondition cond,
}

DBG("uHID event type %d received", ev.type);
- /* TODO Handle events */
+
+ 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:
+ case UHID_FEATURE:
+ handle_uhid_event(dev, &ev);
+ 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;

--
1.8.1.2


2013-11-05 21:09:16

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 10/12] android/hid: Handle invalid parameters in HAL

---
android/hal-hidhost.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index fe68fe7..815902b 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -204,9 +204,8 @@ static bt_status_t hh_get_protocol(bt_bdaddr_t *bd_addr,
case BTHH_BOOT_MODE:
cmd.mode = HAL_HID_BOOT_PROTOCOL;
break;
- case BTHH_UNSUPPORTED_MODE:
- cmd.mode = HAL_HID_UNSUPPORTED_PROTOCOL;
- break;
+ default:
+ return BT_STATUS_PARM_INVALID;
}

return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST,
@@ -236,9 +235,8 @@ static bt_status_t hh_set_protocol(bt_bdaddr_t *bd_addr,
case BTHH_BOOT_MODE:
cmd.mode = HAL_HID_BOOT_PROTOCOL;
break;
- case BTHH_UNSUPPORTED_MODE:
- cmd.mode = HAL_HID_UNSUPPORTED_PROTOCOL;
- break;
+ default:
+ return BT_STATUS_PARM_INVALID;
}

return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST,
@@ -275,6 +273,8 @@ static bt_status_t hh_get_report(bt_bdaddr_t *bd_addr,
case BTHH_FEATURE_REPORT:
cmd.type = HAL_HID_FEATURE_REPORT;
break;
+ default:
+ return BT_STATUS_PARM_INVALID;
}

return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HID_GET_REPORT,
@@ -309,6 +309,8 @@ static bt_status_t hh_set_report(bt_bdaddr_t *bd_addr,
case BTHH_FEATURE_REPORT:
cmd.type = HAL_HID_FEATURE_REPORT;
break;
+ default:
+ return BT_STATUS_PARM_INVALID;
}

return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HID_SET_REPORT,
--
1.8.1.2


2013-11-05 21:09:12

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 06/12] android/hid: Add missing set report parameters to ipc document

---
android/hal-ipc-api.txt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
index 6b11684..48bcc45 100644
--- a/android/hal-ipc-api.txt
+++ b/android/hal-ipc-api.txt
@@ -552,7 +552,9 @@ Commands and responses:

Command parameters: Remote address (6 octets)
Report type (1 octet)
- ...
+ Report length (2 octet)
+ Report data (670 octet) L2CAP default MTU
+
Response parameters: <none>

Valid report types: 0x01 = Input
--
1.8.1.2


2013-11-05 21:09:10

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 04/12] android/hid: Add hid event get report structure to HAL msg headers

---
android/hal-msg.h | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 5faf852..bc7df6b 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -465,6 +465,14 @@ struct hal_ev_hid_proto_mode {
uint8_t mode;
} __attribute__((packed));

+#define HAL_EV_HID_GET_REPORT 0x85
+struct hal_ev_hid_get_report {
+ uint8_t bdaddr[6];
+ uint8_t status;
+ uint16_t len;
+ uint8_t data[0];
+} __attribute__((packed));
+
#define HAL_EV_AV_CONNECTION_STATE 0x81
struct hal_ev_av_connection_state {
uint8_t state;
--
1.8.1.2


2013-11-05 21:09:11

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 05/12] android/hid: Implement hid get report in daemon

This patch requests hid device report and reads reply
message and sends notification to HAL.
---
android/hal-hidhost.c | 1 +
android/hid.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index 13928e6..f554cb2 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -251,6 +251,7 @@ static bt_status_t hh_get_report(bt_bdaddr_t *bd_addr,

memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
cmd.id = reportId;
+ cmd.buf = bufferSize;

switch (reportType) {
case BTHH_INPUT_REPORT:
diff --git a/android/hid.c b/android/hid.c
index dc44159..fd58e6f 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -55,14 +55,23 @@
#define UHID_DEVICE_FILE "/dev/uhid"

/* HID message types */
+#define HID_MSG_GET_REPORT 0x40
#define HID_MSG_GET_PROTOCOL 0x60
#define HID_MSG_SET_PROTOCOL 0x70
#define HID_MSG_DATA 0xa0

+/* HID data types */
+#define HID_DATA_TYPE_INPUT 0x01
+#define HID_DATA_TYPE_OUTPUT 0x02
+#define HID_DATA_TYPE_FEATURE 0x03
+
/* HID protocol header parameters */
#define HID_PROTO_BOOT 0x00
#define HID_PROTO_REPORT 0x01

+/* HID GET REPORT Size Field */
+#define HID_GET_REPORT_SIZE_FIELD 0x08
+
static GIOChannel *notification_io = NULL;
static GIOChannel *ctrl_io = NULL;
static GIOChannel *intr_io = NULL;
@@ -283,6 +292,50 @@ static void bt_hid_notify_proto_mode(struct hid_device *dev, uint8_t *buf,
HAL_EV_HID_PROTO_MODE, sizeof(ev), &ev, -1);
}

+static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf,
+ int len)
+{
+ struct hal_ev_hid_get_report *ev;
+ int ev_len;
+ char address[18];
+
+ ba2str(&dev->dst, address);
+ DBG("device %s", address);
+
+ ev_len = sizeof(*ev) + sizeof(struct hal_ev_hid_get_report) + 1;
+
+ if (!((buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_INPUT)) ||
+ (buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_OUTPUT)) ||
+ (buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_FEATURE)))) {
+ ev = g_malloc0(ev_len);
+ ev->status = buf[0];
+ bdaddr2android(&dev->dst, ev->bdaddr);
+ goto send;
+ }
+
+ /* Report porotocol mode reply contains id after hdr, in boot
+ * protocol mode id doesn't exist */
+ ev_len += (dev->boot_dev) ? (len - 1) : (len - 2);
+ ev = g_malloc0(ev_len);
+ ev->status = HAL_HID_STATUS_OK;
+ bdaddr2android(&dev->dst, ev->bdaddr);
+
+ /* Report porotocol mode reply contains id after hdr, in boot
+ * protocol mode id doesn't exist */
+ if (dev->boot_dev) {
+ ev->len = len - 1;
+ memcpy(ev->data, buf + 1, ev->len);
+ } else {
+ ev->len = len - 2;
+ memcpy(ev->data, buf + 2, ev->len);
+ }
+
+send:
+ ipc_send(notification_io, HAL_SERVICE_ID_HIDHOST, HAL_EV_HID_GET_REPORT,
+ ev_len, ev, -1);
+ g_free(ev);
+}
+
static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
{
struct hid_device *dev = data;
@@ -303,6 +356,9 @@ static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
case HID_MSG_SET_PROTOCOL:
bt_hid_notify_proto_mode(dev, buf, bread);
break;
+ case HID_MSG_GET_REPORT:
+ bt_hid_notify_get_report(dev, buf, bread);
+ break;
}

/* reset msg type request */
@@ -736,9 +792,51 @@ static uint8_t bt_hid_set_protocol(struct hal_cmd_hid_set_protocol *cmd,
static uint8_t bt_hid_get_report(struct hal_cmd_hid_get_report *cmd,
uint16_t len)
{
- DBG("Not Implemented");
+ struct hid_device *dev;
+ GSList *l;
+ bdaddr_t dst;
+ int fd;
+ uint8_t *req;
+ uint8_t req_size;

- return HAL_STATUS_FAILED;
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(devices, &dst, device_cmp);
+ if (!l)
+ return HAL_STATUS_FAILED;
+
+ dev = l->data;
+ req_size = (cmd->buf > 0) ? 4 : 2;
+ req = g_try_malloc0(req_size);
+ if (!req)
+ return HAL_STATUS_NOMEM;
+
+ req[0] = HID_MSG_GET_REPORT | cmd->type;
+
+ if (cmd->buf > 0)
+ req[0] = req[0] | HID_GET_REPORT_SIZE_FIELD;
+
+ req[1] = cmd->id;
+
+ if (cmd->buf > 0)
+ bt_put_le16(cmd->buf, (req + 2));
+
+ fd = g_io_channel_unix_get_fd(dev->ctrl_io);
+
+ if (write(fd, req, req_size) < 0) {
+ error("error while querying device protocol");
+ g_free(req);
+ return HAL_STATUS_FAILED;
+ }
+
+ dev->last_hid_msg = HID_MSG_GET_REPORT;
+ g_free(req);
+ return HAL_STATUS_SUCCESS;
}

static uint8_t bt_hid_set_report(struct hal_cmd_hid_set_report *cmd,
--
1.8.1.2


2013-11-05 21:09:07

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 01/12] android/hid: Implement hid get protocol in daemon

This patch requests hid device protocol mode and reads reply
message and sends notification to HAL.
---
android/hid.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 102 insertions(+), 4 deletions(-)

diff --git a/android/hid.c b/android/hid.c
index 8f5ba88..9bfa018 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -54,6 +54,14 @@
#define L2CAP_PSM_HIDP_INTR 0x13
#define UHID_DEVICE_FILE "/dev/uhid"

+/* HID message types */
+#define HID_MSG_GET_PROTOCOL 0x60
+#define HID_MSG_DATA 0xa0
+
+/* HID protocol header parameters */
+#define HID_PROTO_BOOT 0x00
+#define HID_PROTO_REPORT 0x01
+
static GIOChannel *notification_io = NULL;
static GIOChannel *ctrl_io = NULL;
static GIOChannel *intr_io = NULL;
@@ -76,6 +84,7 @@ struct hid_device {
guint intr_watch;
int uhid_fd;
guint uhid_watch_id;
+ uint8_t last_hid_msg;
};

static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -243,12 +252,72 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;
}

+static void bt_hid_notify_proto_mode(struct hid_device *dev, uint8_t *buf,
+ int len)
+{
+ struct hal_ev_hid_proto_mode ev;
+ char address[18];
+
+ ba2str(&dev->dst, address);
+ DBG("device %s", address);
+
+ memset(&ev, 0, sizeof(ev));
+ bdaddr2android(&dev->dst, ev.bdaddr);
+
+ if (buf[0] == HID_MSG_DATA) {
+ ev.status = HAL_HID_STATUS_OK;
+ if (buf[1] == HID_PROTO_REPORT)
+ ev.mode = HAL_HID_REPORT_PROTOCOL;
+ else if (buf[1] == HID_PROTO_BOOT)
+ ev.mode = HAL_HID_BOOT_PROTOCOL;
+ else
+ ev.mode = HAL_HID_UNSUPPORTED_PROTOCOL;
+
+ } else {
+ ev.status = buf[0];
+ ev.mode = HAL_HID_UNSUPPORTED_PROTOCOL;
+ }
+
+ ipc_send(notification_io, HAL_SERVICE_ID_HIDHOST,
+ HAL_EV_HID_PROTO_MODE, sizeof(ev), &ev, -1);
+}
+
+static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
+{
+ struct hid_device *dev = data;
+ int fd, bread;
+ uint8_t buf[UHID_DATA_MAX];
+
+ DBG("");
+
+ fd = g_io_channel_unix_get_fd(chan);
+ bread = read(fd, buf, sizeof(buf));
+ if (bread < 0) {
+ error("read: %s(%d)", strerror(errno), -errno);
+ return TRUE;
+ }
+
+ switch (dev->last_hid_msg) {
+ case HID_MSG_GET_PROTOCOL:
+ bt_hid_notify_proto_mode(dev, buf, bread);
+ break;
+ }
+
+ /* reset msg type request */
+ dev->last_hid_msg = 0;
+
+ return TRUE;
+}
+
static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond,
gpointer data)
{
struct hid_device *dev = data;
char address[18];

+ if (cond & G_IO_IN)
+ return ctrl_io_watch_cb(chan, data);
+
ba2str(&dev->dst, address);
bt_hid_notify_state(dev, HAL_HID_STATE_DISCONNECTED);

@@ -395,8 +464,8 @@ static void control_connect_cb(GIOChannel *chan, GError *conn_err,
}

dev->ctrl_watch = g_io_add_watch(dev->ctrl_io,
- G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- ctrl_watch_cb, dev);
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ ctrl_watch_cb, dev);

return;

@@ -591,9 +660,38 @@ static uint8_t bt_hid_info(struct hal_cmd_hid_set_info *cmd, uint16_t len)
static uint8_t bt_hid_get_protocol(struct hal_cmd_hid_get_protocol *cmd,
uint16_t len)
{
- DBG("Not Implemented");
+ struct hid_device *dev;
+ GSList *l;
+ bdaddr_t dst;
+ int fd;
+ uint8_t hdr;

- return HAL_STATUS_FAILED;
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(devices, &dst, device_cmp);
+ if (!l)
+ return HAL_STATUS_FAILED;
+
+ dev = l->data;
+
+ if (dev->boot_dev)
+ return HAL_STATUS_UNSUPPORTED;
+
+ hdr = HID_MSG_GET_PROTOCOL | cmd->mode;
+ fd = g_io_channel_unix_get_fd(dev->ctrl_io);
+
+ if (write(fd, &hdr, sizeof(hdr)) < 0) {
+ error("error while querying device protocol");
+ return HAL_STATUS_FAILED;
+ }
+
+ dev->last_hid_msg = HID_MSG_GET_PROTOCOL;
+ return HAL_STATUS_SUCCESS;
}

static uint8_t bt_hid_set_protocol(struct hal_cmd_hid_set_protocol *cmd,
--
1.8.1.2


2013-11-05 21:09:09

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 03/12] android/hid: Handle protocol mode notification in HAL

---
android/hal-hidhost.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index c20c785..13928e6 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -59,6 +59,15 @@ static void handle_info(void *buf)
bt_hh_cbacks->hid_info_cb((bt_bdaddr_t *) ev->bdaddr, info);
}

+static void handle_proto_mode(void *buf)
+{
+ struct hal_ev_hid_proto_mode *ev = buf;
+
+ if (bt_hh_cbacks->protocol_mode_cb)
+ bt_hh_cbacks->protocol_mode_cb((bt_bdaddr_t *) ev->bdaddr,
+ ev->status, ev->mode);
+}
+
/* will be called from notification thread context */
void bt_notify_hh(uint16_t opcode, void *buf, uint16_t len)
{
@@ -72,6 +81,9 @@ void bt_notify_hh(uint16_t opcode, void *buf, uint16_t len)
case HAL_EV_HID_INFO:
handle_info(buf);
break;
+ case HAL_EV_HID_PROTO_MODE:
+ handle_proto_mode(buf);
+ break;
default:
DBG("Unhandled callback opcode=0x%x", opcode);
break;
--
1.8.1.2


2013-11-05 21:09:08

by Ravi kumar Veeramally

[permalink] [raw]
Subject: [PATCH_v4 02/12] android/hid: Implement hid set protocol in daemon

This patch requests hid device to set protocol mode and reads
reply message and sends notification to HAL.
---
android/hid.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/android/hid.c b/android/hid.c
index 9bfa018..dc44159 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -56,6 +56,7 @@

/* HID message types */
#define HID_MSG_GET_PROTOCOL 0x60
+#define HID_MSG_SET_PROTOCOL 0x70
#define HID_MSG_DATA 0xa0

/* HID protocol header parameters */
@@ -299,6 +300,7 @@ static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)

switch (dev->last_hid_msg) {
case HID_MSG_GET_PROTOCOL:
+ case HID_MSG_SET_PROTOCOL:
bt_hid_notify_proto_mode(dev, buf, bread);
break;
}
@@ -697,9 +699,38 @@ static uint8_t bt_hid_get_protocol(struct hal_cmd_hid_get_protocol *cmd,
static uint8_t bt_hid_set_protocol(struct hal_cmd_hid_set_protocol *cmd,
uint16_t len)
{
- DBG("Not Implemented");
+ struct hid_device *dev;
+ GSList *l;
+ bdaddr_t dst;
+ int fd;
+ uint8_t hdr;

- return HAL_STATUS_FAILED;
+ DBG("");
+
+ if (len < sizeof(*cmd))
+ return HAL_STATUS_INVALID;
+
+ android2bdaddr(&cmd->bdaddr, &dst);
+
+ l = g_slist_find_custom(devices, &dst, device_cmp);
+ if (!l)
+ return HAL_STATUS_FAILED;
+
+ dev = l->data;
+
+ if (dev->boot_dev)
+ return HAL_STATUS_UNSUPPORTED;
+
+ hdr = HID_MSG_SET_PROTOCOL | cmd->mode;
+ fd = g_io_channel_unix_get_fd(dev->ctrl_io);
+
+ if (write(fd, &hdr, sizeof(hdr)) < 0) {
+ error("error while setting device protocol");
+ return HAL_STATUS_FAILED;
+ }
+
+ dev->last_hid_msg = HID_MSG_SET_PROTOCOL;
+ return HAL_STATUS_SUCCESS;
}

static uint8_t bt_hid_get_report(struct hal_cmd_hid_get_report *cmd,
--
1.8.1.2