aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <paulo.alcantara@openbossa.org>2012-06-21 21:02:34 -0300
committerPaulo Alcantara <paulo.alcantara@openbossa.org>2012-06-21 21:36:42 -0300
commitb5a39842f1fd900909d685bdfd36bd46210f8bae (patch)
tree2715c832dd52944cc7bbb571b1ad445566670020
parent2b51e4b7348b4635e59d02775d43efbb4b7724f6 (diff)
downloadbluez-b5a39842f1fd900909d685bdfd36bd46210f8bae.tar.gz
bluez-b5a39842f1fd900909d685bdfd36bd46210f8bae.tar.xz
bluez-b5a39842f1fd900909d685bdfd36bd46210f8bae.zip
HoG: Handle HID devices operating in Boot Protocol Modefor-upstream
HID devices like keyboards, as well as mices, support boot protocol. It was designed to be used by the PC BIOS during POST setup. Thus, BlueZ does not have to support HID devices operating in this mode, so we need to change from Boot Procotol Mode to Report Protocol Mode since we're running out of BIOSes. As the default Protocol Mode for all HID devices is the Report Protocol Mode, we set the Protocol Mode characteristic value to 1 (Report Protocol Mode) when necessary. This patches 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.
-rw-r--r--input/hog_device.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/input/hog_device.c b/input/hog_device.c
index dfa23128..7b88dbb6 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
@@ -99,6 +103,8 @@ struct report {
static GSList *devices = NULL;
+static uint16_t proto_mode_handle = 0;
+
static gint report_handle_cmp(gconstpointer a, gconstpointer b)
{
const struct report *report = a;
@@ -338,10 +344,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;
+ uint16_t handle = proto_mode_handle;
+
+ proto_mode_handle = 0;
+
+ 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, 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;
@@ -355,6 +396,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;
@@ -379,8 +421,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)
+ gatt_read_char(hogdev->attrib, proto_mode_handle, 0,
+ proto_mode_read_cb, hogdev);
+
if (info_handle)
gatt_read_char(hogdev->attrib, info_handle, 0,
info_read_cb, hogdev);