[PATCH 21/21] hog: Handle HID devices operating in Boot Protocol Mode

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

 



From: Paulo Alcantara <paulo.alcantara@xxxxxxxxxxxxx>

BlueZ does not support HID devices operating in Boot Protocol Mode, so we
need to set it back to Report Protocol Mode through the Protocol Mode
characteristic.

This patch takes cares of changing from Boot Protocol Mode to Report
Protocol Mode by writing the Protocol Mode characteristic value to 1,
which is value for Report Protocol Mode on HID devices operating in
Boot Protocol Mode.
---
 input/hog_device.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/input/hog_device.c b/input/hog_device.c
index 7e6c4b1..18854b8 100644
--- a/input/hog_device.c
+++ b/input/hog_device.c
@@ -54,11 +54,15 @@
 #define HOG_INFO_UUID		0x2A4A
 #define HOG_REPORT_MAP_UUID	0x2A4B
 #define HOG_REPORT_UUID		0x2A4D
+#define HOG_PROTO_MODE_UUID	0x2A4E
 
 #define HOG_REPORT_TYPE_INPUT	1
 #define HOG_REPORT_TYPE_OUTPUT	2
 #define HOG_REPORT_TYPE_FEATURE	3
 
+#define HOG_PROTO_MODE_BOOT    0
+#define HOG_PROTO_MODE_REPORT  1
+
 #define UHID_DEVICE_FILE	"/dev/uhid"
 
 #define HOG_REPORT_MAP_MAX_SIZE        512
@@ -77,6 +81,7 @@ struct hog_device {
 	guint			uhid_watch_id;
 	uint16_t		bcdhid;
 	uint8_t			bcountrycode;
+	uint16_t		proto_mode_handle;
 	uint8_t			flags;
 };
 
@@ -328,13 +333,45 @@ static void info_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 			hogdev->bcdhid, hogdev->bcountrycode, hogdev->flags);
 }
 
+static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
+							gpointer user_data)
+{
+	struct hog_device *hogdev = user_data;
+	uint8_t value;
+	ssize_t vlen;
+
+	if (status != 0) {
+		error("Protocol Mode characteristic read failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	vlen = dec_read_resp(pdu, plen, &value, sizeof(value));
+	if (vlen < 0) {
+		error("ATT protocol error");
+		return;
+	}
+
+	if (value == HOG_PROTO_MODE_BOOT) {
+		uint8_t nval = HOG_PROTO_MODE_REPORT;
+
+		DBG("HoG device %s is operating in Boot Procotol Mode",
+								hogdev->path);
+
+		gatt_write_char(hogdev->attrib, hogdev->proto_mode_handle, &nval,
+						sizeof(nval), NULL, NULL);
+	} else if (value == HOG_PROTO_MODE_REPORT)
+		DBG("HoG device %s is operating in Report Protocol Mode",
+								hogdev->path);
+}
+
 static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 {
 	struct hog_device *hogdev = user_data;
-	bt_uuid_t report_uuid, report_map_uuid, info_uuid;
+	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid;
 	struct report *report;
 	GSList *l;
-	uint16_t map_handle = 0, info_handle = 0;
+	uint16_t map_handle = 0, info_handle = 0, proto_mode_handle = 0;
 
 	if (status != 0) {
 		const char *str = att_ecode2str(status);
@@ -345,6 +382,7 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 	bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
 	bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
 	bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
+	bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
 
 	for (l = chars; l; l = g_slist_next(l)) {
 		struct gatt_char *chr, *next;
@@ -369,6 +407,14 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 			map_handle = chr->value_handle;
 		else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
 			info_handle = chr->value_handle;
+		else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
+			proto_mode_handle = chr->value_handle;
+	}
+
+	if (proto_mode_handle) {
+		hogdev->proto_mode_handle = proto_mode_handle;
+		gatt_read_char(hogdev->attrib, proto_mode_handle, 0,
+						proto_mode_read_cb, hogdev);
 	}
 
 	if (info_handle)
-- 
1.7.10.4

--
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