-diff -urN upower-0.9.20.org/src/linux/up-device-unifying.c upower-0.9.20/src/linux/up-device-unifying.c
---- upower-0.9.20.org/src/linux/up-device-unifying.c 2013-01-10 13:08:46.000000000 +0100
-+++ upower-0.9.20/src/linux/up-device-unifying.c 2013-03-20 16:55:41.757576712 +0100
-@@ -165,7 +165,7 @@
+commit 232d70155c45d24afabe47ed37954cc000678295
+Author: Arkadiusz Miśkiewicz <arekm@maven.pl>
+Date: Wed Mar 20 17:51:14 2013 +0100
+
+ Find hidraw devices correctly with systemd udev >= v196.
+
+ udev v196 libraries changed behaviour of g_udev_device_get_sysfs_attr()
+ by stopping following symlinks for "device" attribute [1]. That change
+ broke hiddev finding for unifying devices. Fix that by getting sysfs
+ path from parent hiddev device.
+
+ 1. http://cgit.freedesktop.org/systemd/systemd/commit/?id=5ae18ddc0d86673520c0dd6b59ccac8afc8aa605
+
+ Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl>
+ Signed-off-by: Richard Hughes <richard@hughsie.com>
+
+diff --git a/src/linux/up-device-unifying.c b/src/linux/up-device-unifying.c
+index c7f0103..4b659c3 100644
+--- a/src/linux/up-device-unifying.c
++++ b/src/linux/up-device-unifying.c
+@@ -165,7 +165,7 @@ up_device_unifying_coldplug (UpDevice *device)
hidraw_list = g_udev_client_query_by_subsystem (client, "hidraw");
for (l = hidraw_list; l != NULL; l = l->next) {
if (g_strcmp0 (g_udev_device_get_sysfs_path (parent),
receiver = g_object_ref (l->data);
break;
}
+
+commit 28f396496a90705b0d8823707396731fe60d85bc
+Author: Arkadiusz Miśkiewicz <arekm@maven.pl>
+Date: Wed Mar 20 22:22:54 2013 +0100
+
+ Detection of version 1 hid++ is not returned to the caller
+
+ HID++ version 1 was properly detected but that information wasn't
+ reaching caller.
+
+ Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl>
+ Signed-off-by: Richard Hughes <richard@hughsie.com>
+
+diff --git a/src/linux/hidpp-device.c b/src/linux/hidpp-device.c
+index 0a27dbf..1bcefab 100644
+--- a/src/linux/hidpp-device.c
++++ b/src/linux/hidpp-device.c
+@@ -314,9 +314,9 @@ 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 */
++ /* HID++ 1.0 ping reply, so fake success with version 1 */
+ if (buf[5] == HIDPP_ERROR_CODE_UNKNOWN) {
+- buf[0] = 1;
++ response_data[0] = 1;
+ goto out;
+ }
+ if (buf[5] == HIDPP_ERROR_CODE_UNSUPPORTED) {
+
+commit 972acff14532aa1a495b2ee20f24505cb581291a
+Author: Arkadiusz Miśkiewicz <arekm@maven.pl>
+Date: Wed Mar 20 22:28:11 2013 +0100
+
+ Buffer for HIDPP_REFRESH_FLAGS_KIND not big enough
+
+ HIDPP_REFRESH_FLAGS_KIND action puts result into 7 bytes buffer and
+ later tries to access 8th element (with index 7). Make buffer bigger,
+ so 8th element will fit.
+
+ Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl>
+ Signed-off-by: Richard Hughes <richard@hughsie.com>
+
+diff --git a/src/linux/hidpp-device.c b/src/linux/hidpp-device.c
+index 1bcefab..58c6e6d 100644
+--- a/src/linux/hidpp-device.c
++++ b/src/linux/hidpp-device.c
+@@ -560,7 +560,7 @@ hidpp_device_refresh (HidppDevice *device,
+ HIDPP_READ_LONG_REGISTER,
+ 0xb5,
+ buf, 3,
+- buf, 7,
++ buf, 8,
+ error);
+ if (!ret)
+ goto out;
+
+commit af24f55c7925c8ea990cb36078b63c17cd671a95
+Author: Arkadiusz Miśkiewicz <arekm@maven.pl>
+Date: Wed Mar 20 22:35:59 2013 +0100
+
+ Invalid request/response for HIDPP_REFRESH_FLAGS_BATTERY in hid++1
+
+ Version 1 hid++ HIDPP_REFRESH_FLAGS_BATTERY packets were incorrect.
+
+ Response packets were incorrectly thrown away as invalid. These
+ packets have HIDPP_HEADER_REQUEST (and not HIDPP_HEADER_RESPONSE as code
+ expexted). Fix that by allowing both types.
+
+ Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl>
+ Signed-off-by: Richard Hughes <richard@hughsie.com>
+
+diff --git a/src/linux/hidpp-device.c b/src/linux/hidpp-device.c
+index 58c6e6d..8e861c5 100644
+--- a/src/linux/hidpp-device.c
++++ b/src/linux/hidpp-device.c
+@@ -327,7 +327,7 @@ hidpp_device_cmd (HidppDevice *device,
+ goto out;
+ }
+ }
+- if (buf[0] != HIDPP_HEADER_RESPONSE ||
++ if ((buf[0] != HIDPP_HEADER_REQUEST && buf[0] != HIDPP_HEADER_RESPONSE) ||
+ buf[1] != device_idx ||
+ buf[2] != feature_idx ||
+ buf[3] != function_idx) {
+@@ -662,16 +662,14 @@ hidpp_device_refresh (HidppDevice *device,
+ /* get battery status */
+ if ((refresh_flags & HIDPP_REFRESH_FLAGS_BATTERY) > 0) {
+ if (priv->version == 1) {
+- buf[0] = HIDPP_READ_SHORT_REGISTER;
+- buf[1] = HIDPP_READ_SHORT_REGISTER_BATTERY;
++ buf[0] = 0x00;
++ buf[1] = 0x00;
+ buf[2] = 0x00;
+- buf[3] = 0x00;
+- buf[4] = 0x00;
+ ret = hidpp_device_cmd (device,
+ priv->device_idx,
+- HIDPP_FEATURE_ROOT_INDEX,
+- HIDPP_FEATURE_ROOT_FN_PING,
+- buf, 5,
++ HIDPP_READ_SHORT_REGISTER,
++ HIDPP_READ_SHORT_REGISTER_BATTERY,
++ buf, 3,
+ buf, 1,
+ error);
+ if (!ret)
+
+commit e571f840e9fd945c94bc1c5fa494fde9d23fa2ad
+Author: Arkadiusz Miśkiewicz <arekm@maven.pl>
+Date: Thu Mar 21 19:57:26 2013 +0100
+
+ Add support for HIDPP_REFRESH_FLAGS_MODEL in hid++ v1
+
+ Add support for checking device model name for hid++ v1 protocol
+ version.
+
+ Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl>
+ Signed-off-by: Richard Hughes <richard@hughsie.com>
+
+diff --git a/src/linux/hidpp-device.c b/src/linux/hidpp-device.c
+index 8e861c5..bfc1b5c 100644
+--- a/src/linux/hidpp-device.c
++++ b/src/linux/hidpp-device.c
+@@ -624,39 +624,60 @@ hidpp_device_refresh (HidppDevice *device,
+
+ /* get device model string */
+ if ((refresh_flags & HIDPP_REFRESH_FLAGS_MODEL) > 0) {
+- buf[0] = 0x00;
+- buf[1] = 0x00;
+- buf[2] = 0x00;
+- map = hidpp_device_map_get_by_feature (device, HIDPP_FEATURE_GET_DEVICE_NAME_TYPE);
+- if (map != NULL) {
++ if (priv->version == 1) {
++ buf[0] = 0x40 | (priv->device_idx - 1);
++ buf[1] = 0x00;
++ buf[2] = 0x00;
++
+ ret = hidpp_device_cmd (device,
++ HIDPP_RECEIVER_ADDRESS,
++ HIDPP_READ_LONG_REGISTER,
++ 0xb5,
++ buf, 3,
++ buf, HIDPP_RESPONSE_LONG_LENGTH,
++ error);
++ if (!ret)
++ goto out;
++
++ len = buf[1];
++ name = g_string_new ("");
++ g_string_append_len (name, (gchar *) buf+2, len);
++ priv->model = g_strdup (name->str);
++ } else if (priv->version == 2) {
++ buf[0] = 0x00;
++ buf[1] = 0x00;
++ buf[2] = 0x00;
++ map = hidpp_device_map_get_by_feature (device, HIDPP_FEATURE_GET_DEVICE_NAME_TYPE);
++ if (map != NULL) {
++ ret = hidpp_device_cmd (device,
+ priv->device_idx,
+ map->idx,
+ HIDPP_FEATURE_GET_DEVICE_NAME_TYPE_FN_GET_COUNT,
+ buf, 3,
+ buf, 1,
+ error);
+- if (!ret)
+- goto out;
+- }
+- len = buf[0];
+- name = g_string_new ("");
+- for (i = 0; i < len; i +=4 ) {
+- buf[0] = i;
+- buf[1] = 0x00;
+- buf[2] = 0x00;
+- ret = hidpp_device_cmd (device,
++ if (!ret)
++ goto out;
++ }
++ len = buf[0];
++ name = g_string_new ("");
++ for (i = 0; i < len; i +=4 ) {
++ buf[0] = i;
++ buf[1] = 0x00;
++ buf[2] = 0x00;
++ ret = hidpp_device_cmd (device,
+ priv->device_idx,
+ map->idx,
+ HIDPP_FEATURE_GET_DEVICE_NAME_TYPE_FN_GET_NAME,
+ buf, 3,
+ buf, 4,
+ error);
+- if (!ret)
+- goto out;
+- g_string_append_len (name, (gchar *) &buf[0], 4);
++ if (!ret)
++ goto out;
++ g_string_append_len (name, (gchar *) &buf[0], 4);
++ }
++ priv->model = g_strdup (name->str);
+ }
+- priv->model = g_strdup (name->str);
+ }
+
+ /* get battery status */
+
+commit fd0286e871bcf67d29aa622b66ecf362fe2d6ec0
+Author: Arkadiusz Miśkiewicz <arekm@maven.pl>
+Date: Thu Mar 21 20:40:26 2013 +0100
+
+ Repair vendor handling for Logitech Unifying devices
+
+ Set proper vendor via udev rules for unifying devices and handle
+ that in code.
+
+ Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl>
+ Signed-off-by: Richard Hughes <richard@hughsie.com>
+
+diff --git a/rules/95-upower-csr.rules b/rules/95-upower-csr.rules
+index bd171b2..b8d92fe 100644
+--- a/rules/95-upower-csr.rules
++++ b/rules/95-upower-csr.rules
+@@ -22,6 +22,7 @@ LABEL="up_csr_end"
+
+ # Unifying HID++ devices
+ SUBSYSTEM!="hid", GOTO="up_unifying_end"
++ATTRS{idVendor}=="046d", ENV{UPOWER_VENDOR}="Logitech, Inc."
+ ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", DRIVER=="logitech-djdevice", ENV{UPOWER_BATTERY_TYPE}="unifying"
+ ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c532", DRIVER=="logitech-djdevice", ENV{UPOWER_BATTERY_TYPE}="unifying"
+ LABEL="up_unifying_end"
+diff --git a/src/linux/up-device-unifying.c b/src/linux/up-device-unifying.c
+index 4b659c3..633909f 100644
+--- a/src/linux/up-device-unifying.c
++++ b/src/linux/up-device-unifying.c
+@@ -123,6 +123,7 @@ up_device_unifying_coldplug (UpDevice *device)
+ const gchar *bus_address;
+ const gchar *device_file;
+ const gchar *type;
++ const gchar *vendor;
+ gboolean ret = FALSE;
+ gchar *endptr = NULL;
+ gchar *tmp;
+@@ -198,9 +199,13 @@ up_device_unifying_coldplug (UpDevice *device)
+ goto out;
+ }
+
++ vendor = g_udev_device_get_property (native, "UPOWER_VENDOR");
++ if (vendor == NULL)
++ vendor = g_udev_device_get_property (native, "ID_VENDOR");
++
+ /* set some default values */
+ g_object_set (device,
+- "vendor", g_udev_device_get_property (native, "ID_VENDOR"),
++ "vendor", vendor,
+ "type", up_device_unifying_get_device_kind (unifying),
+ "model", hidpp_device_get_model (unifying->priv->hidpp_device),
+ "has-history", TRUE,
+
+commit 32daed2dfa22196bd4c51fdabad3d333d4839903
+Author: Arkadiusz Miśkiewicz <arekm@maven.pl>
+Date: Fri Mar 22 15:28:11 2013 +0100
+
+ Add support for Logitech Wireless (NonUnifying) devices
+
+ There are Logitech Wireless devices similar to Unifying ones with the
+ difference that device is paired with single dongle and dongle doesn't
+ support pairing multiple devices.
+
+ Add support for these. Tested with Wireless Mouse M187 and M185/M225.
+
+ Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl>
+ Signed-off-by: Richard Hughes <richard@hughsie.com>
+
+diff --git a/rules/95-upower-csr.rules b/rules/95-upower-csr.rules
+index b8d92fe..b476660 100644
+--- a/rules/95-upower-csr.rules
++++ b/rules/95-upower-csr.rules
+@@ -25,4 +25,5 @@ SUBSYSTEM!="hid", GOTO="up_unifying_end"
+ ATTRS{idVendor}=="046d", ENV{UPOWER_VENDOR}="Logitech, Inc."
+ ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", DRIVER=="logitech-djdevice", ENV{UPOWER_BATTERY_TYPE}="unifying"
+ ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c532", DRIVER=="logitech-djdevice", ENV{UPOWER_BATTERY_TYPE}="unifying"
++ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52f", ENV{UPOWER_BATTERY_TYPE}="lg-wireless"
+ LABEL="up_unifying_end"
+diff --git a/src/linux/up-device-unifying.c b/src/linux/up-device-unifying.c
+index 633909f..f6636e6 100644
+--- a/src/linux/up-device-unifying.c
++++ b/src/linux/up-device-unifying.c
+@@ -142,7 +142,7 @@ up_device_unifying_coldplug (UpDevice *device)
+ type = g_udev_device_get_property (native, "UPOWER_BATTERY_TYPE");
+ if (type == NULL)
+ goto out;
+- if (g_strcmp0 (type, "unifying") != 0)
++ if ((g_strcmp0 (type, "unifying") != 0) && (g_strcmp0 (type, "lg-wireless") != 0))
+ goto out;
+
+ /* get the device index */
+@@ -153,23 +153,37 @@ up_device_unifying_coldplug (UpDevice *device)
+ g_debug ("Could not get physical device index");
+ goto out;
+ }
+- hidpp_device_set_index (unifying->priv->hidpp_device,
++
++ if (g_strcmp0 (type, "lg-wireless") == 0)
++ hidpp_device_set_index (unifying->priv->hidpp_device, 1);
++ else {
++ hidpp_device_set_index (unifying->priv->hidpp_device,
+ g_ascii_strtoull (tmp + 1, &endptr, 10));
+- if (endptr != NULL && endptr[0] != '\0') {
+- g_debug ("HID_PHYS malformed: '%s'", bus_address);
+- goto out;
++ if (endptr != NULL && endptr[0] != '\0') {
++ g_debug ("HID_PHYS malformed: '%s'", bus_address);
++ goto out;
++ }
+ }
+
+- /* find the hidraw device that matches the parent */
++ /* find the hidraw device that matches */
+ parent = g_udev_device_get_parent (native);
+ client = g_udev_client_new (NULL);
+ hidraw_list = g_udev_client_query_by_subsystem (client, "hidraw");
+ for (l = hidraw_list; l != NULL; l = l->next) {
+- if (g_strcmp0 (g_udev_device_get_sysfs_path (parent),
+- g_udev_device_get_sysfs_path(g_udev_device_get_parent(l->data))) == 0) {
+- receiver = g_object_ref (l->data);
+- break;
++ if (g_strcmp0 (type, "lg-wireless") == 0) {
++ if (g_strcmp0 (g_udev_device_get_sysfs_path (native),
++ g_udev_device_get_sysfs_path(g_udev_device_get_parent(l->data))) != 0)
++ continue;
++ // Ugly way to distinguish receiver itself from mouse/keyboard etc for non-unifying dongles
++ if (g_strcmp0(g_udev_device_get_property(g_udev_device_get_parent (native), "INTERFACE"), "3/0/0") != 0)
++ continue;
++ } else {
++ if (g_strcmp0 (g_udev_device_get_sysfs_path (parent),
++ g_udev_device_get_sysfs_path(g_udev_device_get_parent(l->data))) != 0)
++ continue;
+ }
++ receiver = g_object_ref (l->data);
++ break;
+ }
+ if (receiver == NULL) {
+ g_debug ("Unable to find an hidraw device for Unifying receiver");
+
+commit fadca8ad7706c15b5fabee2f7be599961fe33240
+Author: Arkadiusz Miśkiewicz <arekm@maven.pl>
+Date: Fri Mar 22 19:46:47 2013 +0100
+
+ 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>
+
+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",