summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2013-08-06 19:57:09 +0200
committerPeter Wu <lekensteyn@gmail.com>2013-08-22 22:58:16 +0200
commita375524c52e75079236127f9a89bd335cd37b3c9 (patch)
tree411e61896cb1220fea49b4d8f03b19782b10d734
parent79643504344c1df5bdc3cfb18fd4eb75a9b6de66 (diff)
downloadupower-a375524c52e75079236127f9a89bd335cd37b3c9.tar.gz
hidpp: clear message queue before initiating new requests (v2)
This prevents the use of responses from other HID++ applications (such as Solaar and ltunify). - v2: do not hang in a loop when read() fails, e.g. when it returns EIO because the device was unplugged. Signed-off-by: Peter Wu <lekensteyn@gmail.com>
-rw-r--r--src/linux/hidpp-device.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/linux/hidpp-device.c b/src/linux/hidpp-device.c
index 6d02bf1..6943920 100644
--- a/src/linux/hidpp-device.c
+++ b/src/linux/hidpp-device.c
@@ -29,6 +29,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <errno.h>
#include "hidpp-device.h"
@@ -271,6 +272,27 @@ hidpp_device_print_buffer (HidppDevice *device, const HidppMessage *msg)
g_print ("param[0]=%02x\n\n", msg->s.params[0]);
}
+static void
+hidpp_discard_messages (HidppDevice *device)
+{
+ HidppDevicePrivate *priv = device->priv;
+ GPollFD poll[] = {
+ {
+ .fd = priv->fd,
+ .events = G_IO_IN | G_IO_OUT | G_IO_ERR,
+ },
+ };
+ char c;
+ int r;
+
+ while (g_poll (poll, G_N_ELEMENTS(poll), 0) > 0) {
+ /* kernel discards remainder of packet */
+ r = read (priv->fd, &c, 1);
+ if (r < 0 && errno != EINTR)
+ break;
+ }
+}
+
/**
* hidpp_device_cmd:
**/
@@ -302,6 +324,9 @@ hidpp_device_cmd (HidppDevice *device,
msg_len = HIDPP_MSG_LENGTH(request);
+ /* ignore all unrelated queued messages */
+ hidpp_discard_messages(device);
+
/* write to the device */
wrote = write (priv->fd, (const char *)request, msg_len);
if ((gsize) wrote != msg_len) {