summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArkadiusz Miśkiewicz <arekm@maven.pl>2013-03-22 19:46:47 +0100
committerRichard Hughes <richard@hughsie.com>2013-03-22 19:46:23 +0000
commitfadca8ad7706c15b5fabee2f7be599961fe33240 (patch)
tree5ff8c33c4bb0575a925f61bb0dfc635f6510963d
parent32daed2dfa22196bd4c51fdabad3d333d4839903 (diff)
downloadupower-fadca8ad7706c15b5fabee2f7be599961fe33240.tar.gz
Better method of figuring out v1 vs v2 protocol version.
Protocol version detection isn't very reliable (especially for hid++ v1). Version 1 checking was potentially happening in every hidpp_device_cmd() call and not only when requested. Improve that to do version checking and priv->version manipulation only when requested by using HIDPP_REFRESH_FLAGS_VERSION. When doing version checking first try v2 protocol command and if it succeeds assume version 2 device. Otherwise try v1 protocol query and if that successds assume version 1 device. v2 devices in unreachable/sleep mode seem to do not respond to v2 queries but they respond to v1 queries! Still we want best protocol possible. To do that we are rechecking version when current protocol version is below 2 and we are doing up_device_unifying_refresh() and if recheck succeeds we upgrade protocol to v2. Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl> Signed-off-by: Richard Hughes <richard@hughsie.com>
-rw-r--r--src/linux/hidpp-device.c36
-rw-r--r--src/linux/up-device-unifying.c16
2 files changed, 42 insertions, 10 deletions
diff --git a/src/linux/hidpp-device.c b/src/linux/hidpp-device.c
index bfc1b5c..5398a38 100644
--- a/src/linux/hidpp-device.c
+++ b/src/linux/hidpp-device.c
@@ -46,6 +46,7 @@
/* HID++ 1.0 */
#define HIDPP_READ_SHORT_REGISTER 0x81
#define HIDPP_READ_SHORT_REGISTER_BATTERY 0x0d
+#define HIDPP_READ_SHORT_REGISTER_CONNECTION_STATE 0x02
#define HIDPP_READ_LONG_REGISTER 0x83
#define HIDPP_READ_LONG_REGISTER_DEVICE_TYPE 11
@@ -314,11 +315,6 @@ hidpp_device_cmd (HidppDevice *device,
buf[2] == HIDPP_ERR_INVALID_SUBID &&
buf[3] == 0x00 &&
buf[4] == HIDPP_FEATURE_ROOT_FN_PING) {
- /* HID++ 1.0 ping reply, so fake success with version 1 */
- if (buf[5] == HIDPP_ERROR_CODE_UNKNOWN) {
- response_data[0] = 1;
- goto out;
- }
if (buf[5] == HIDPP_ERROR_CODE_UNSUPPORTED) {
/* device offline / unreachable */
g_set_error_literal (error, 1, 0,
@@ -533,6 +529,7 @@ hidpp_device_refresh (HidppDevice *device,
/* get version */
if ((refresh_flags & HIDPP_REFRESH_FLAGS_VERSION) > 0) {
+ /* first try v2 packet */
buf[0] = 0x00;
buf[1] = 0x00;
buf[2] = HIDPP_PING_DATA;
@@ -543,9 +540,32 @@ hidpp_device_refresh (HidppDevice *device,
buf, 3,
buf, 4,
error);
- if (!ret)
- goto out;
- priv->version = buf[0];
+ if (ret)
+ priv->version = buf[0];
+ /* then try v1 packet */
+ else {
+ /* discard potential v1 error */
+ g_clear_error (error);
+
+ /* checking hid++ v1 packet */
+ buf[0] = 0x00;
+ buf[1] = 0x00;
+ buf[2] = 0x00;
+
+ ret = hidpp_device_cmd (device,
+ HIDPP_RECEIVER_ADDRESS,
+ HIDPP_READ_SHORT_REGISTER,
+ HIDPP_READ_SHORT_REGISTER_CONNECTION_STATE,
+ buf, 3,
+ buf, 2,
+ error);
+
+ if (!ret)
+ goto out;
+
+ priv->version = 1;
+ }
+
}
/* get device kind */
diff --git a/src/linux/up-device-unifying.c b/src/linux/up-device-unifying.c
index f6636e6..ea8b0b3 100644
--- a/src/linux/up-device-unifying.c
+++ b/src/linux/up-device-unifying.c
@@ -52,13 +52,25 @@ up_device_unifying_refresh (UpDevice *device)
gboolean ret;
GError *error = NULL;
GTimeVal timeval;
+ HidppRefreshFlags refresh_flags;
UpDeviceState state = UP_DEVICE_STATE_UNKNOWN;
UpDeviceUnifying *unifying = UP_DEVICE_UNIFYING (device);
UpDeviceUnifyingPrivate *priv = unifying->priv;
- /* refresh just the battery stats */
+ /* refresh the battery stats */
+ refresh_flags = HIDPP_REFRESH_FLAGS_BATTERY;
+
+ /*
+ * Device hid++ v2 when in unreachable mode seems to be able
+ * to respond to hid++ v1 queries (but fails to respond to v2
+ * queries). When it gets waken up it starts responding
+ * to v2 queries, so always try to upgrade protocol to v2
+ */
+ if (hidpp_device_get_version (priv->hidpp_device) < 2)
+ refresh_flags |= HIDPP_REFRESH_FLAGS_VERSION;
+
ret = hidpp_device_refresh (priv->hidpp_device,
- HIDPP_REFRESH_FLAGS_BATTERY,
+ refresh_flags,
&error);
if (!ret) {
g_warning ("failed to coldplug unifying device: %s",