From ae53f6123b7924ee1a649243d77ba251c949d6fe Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Wed, 10 Nov 2021 21:08:00 +0000 Subject: [PATCH] ibratbag-hidraw: add optional filter to hidraw read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, these functions will read and timeout after 1s if no packets were received. The issue with this is that a lot of times we may catch unrelated packets, such as mouse or keyboard changes. To solve this, this patch adds a new optional filter argument, when a filter is passed the functions now will keep reading packets until a valid packet is found. The filter argument is user written function that returns true or false. Co-authored-by: Filipe LaĆ­ns Signed-off-by: Rafael Silva --- src/driver-openinput.c | 18 +++++++++++++++- src/driver-steelseries.c | 4 ++-- src/libratbag-hidraw.c | 44 ++++++++++++++++++++++++++++------------ src/libratbag-hidraw.h | 15 ++++++++++---- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/driver-openinput.c b/src/driver-openinput.c index bd509cc7..ad002866 100644 --- a/src/driver-openinput.c +++ b/src/driver-openinput.c @@ -159,6 +159,22 @@ openinput_get_report_size(unsigned int report) } } +static bool +openinput_report_filter(uint8_t *buf, size_t len) +{ + if (len < 1) + return false; + + switch(buf[0]) { + case OI_REPORT_SHORT: + return len == OI_REPORT_SHORT_SIZE; + case OI_REPORT_LONG: + return len == OI_REPORT_LONG_SIZE; + default: + return false; + } +} + static int openinput_send_report(struct ratbag_device *device, struct oi_report_t *report) { @@ -175,7 +191,7 @@ openinput_send_report(struct ratbag_device *device, struct oi_report_t *report) return ret; } - ret = ratbag_hidraw_read_input_report(device, buffer, OI_REPORT_MAX_SIZE); + ret = ratbag_hidraw_read_input_report(device, buffer, OI_REPORT_MAX_SIZE, openinput_report_filter); if (ret < 0) { log_error(device->ratbag, "openinput: failed to read data from device (%s)\n", strerror(-ret)); diff --git a/src/driver-steelseries.c b/src/driver-steelseries.c index f5b10fc0..e467d0de 100644 --- a/src/driver-steelseries.c +++ b/src/driver-steelseries.c @@ -234,7 +234,7 @@ steelseries_get_firmware_version(struct ratbag_device *device) if (ret < 0) return ret; - ret = ratbag_hidraw_read_input_report_index(device, buf, sizeof(buf), STEELSERIES_INPUT_HIDRAW); + ret = ratbag_hidraw_read_input_report_index(device, buf, sizeof(buf), STEELSERIES_INPUT_HIDRAW, NULL); if (ret < 0) return ret; @@ -278,7 +278,7 @@ steelseries_read_settings(struct ratbag_device *device) if (ret < 0) return ret; - ret = ratbag_hidraw_read_input_report_index(device, buf, STEELSERIES_REPORT_SIZE, STEELSERIES_INPUT_HIDRAW); + ret = ratbag_hidraw_read_input_report_index(device, buf, STEELSERIES_REPORT_SIZE, STEELSERIES_INPUT_HIDRAW, NULL); if (ret < 0) return ret; diff --git a/src/libratbag-hidraw.c b/src/libratbag-hidraw.c index 7dc324fe..781e326f 100644 --- a/src/libratbag-hidraw.c +++ b/src/libratbag-hidraw.c @@ -1642,16 +1642,19 @@ ratbag_hidraw_output_report(struct ratbag_device *device, uint8_t *buf, size_t l } int -ratbag_hidraw_read_input_report(struct ratbag_device *device, uint8_t *buf, size_t len) +ratbag_hidraw_read_input_report(struct ratbag_device *device, uint8_t *buf, size_t len, + ratbagd_hidraw_filter_t filter) { - return ratbag_hidraw_read_input_report_index(device, buf, len, 0); + return ratbag_hidraw_read_input_report_index(device, buf, len, 0, filter); } int -ratbag_hidraw_read_input_report_index(struct ratbag_device *device, uint8_t *buf, size_t len, int hidrawno) +ratbag_hidraw_read_input_report_index(struct ratbag_device *device, uint8_t *buf, size_t len, int hidrawno, + ratbagd_hidraw_filter_t filter) { - int rc; + int rc, nfds; struct pollfd fds; + int ts, ts_end; assert(hidrawno >= 0 && hidrawno < MAX_HIDRAW); @@ -1661,17 +1664,32 @@ ratbag_hidraw_read_input_report_index(struct ratbag_device *device, uint8_t *buf fds.fd = device->hidraw[hidrawno].fd; fds.events = POLLIN; - rc = poll(&fds, 1, 1000); - if (rc == -1) - return -errno; + /* convert to ms */ + ts = now(CLOCK_MONOTONIC_RAW) / 1000 / 1000; + ts_end = ts + 1000; /* end in now + 1000ms */ - if (rc == 0) - return -ETIMEDOUT; + while (ts < ts_end) { + nfds = poll(&fds, 1, ts_end - ts); /* poll for the remainder of timeout */ - rc = read(device->hidraw[hidrawno].fd, buf, len); + if (nfds < 0) + return -errno; - if (rc > 0) - log_buf_raw(device->ratbag, "input report: ", buf, rc); + if (nfds > 0) { + rc = read(device->hidraw[hidrawno].fd, buf, len); - return rc >= 0 ? rc : -errno; + if (rc < 0) + return -errno; + + if (rc > 0) { + if(!filter || (filter && filter(buf, rc))) { + log_buf_raw(device->ratbag, "input report: ", buf, rc); + return rc; + } + } + } + + ts = now(CLOCK_MONOTONIC_RAW) / 1000 / 1000; + } + + return -ETIMEDOUT; } diff --git a/src/libratbag-hidraw.h b/src/libratbag-hidraw.h index 8ca56d08..0f6756c6 100644 --- a/src/libratbag-hidraw.h +++ b/src/libratbag-hidraw.h @@ -47,6 +47,8 @@ struct ratbag_hidraw { char *sysname; }; +typedef bool (*ratbagd_hidraw_filter_t)(uint8_t *buf, size_t len); + /** * Open the hidraw device associated with the device. * @@ -162,27 +164,32 @@ int ratbag_hidraw_output_report(struct ratbag_device *device, uint8_t *buf, size /** * Read an input report from the device + * Optional filter function can be provided, when the filter returns false the packet is ignored * * @param device the ratbag device * @param[out] buf resulting raw data * @param len length of buf + * @param filter filter function * * @return count of data transfered, or a negative errno on error */ -int ratbag_hidraw_read_input_report(struct ratbag_device *device, uint8_t *buf, size_t len); +int ratbag_hidraw_read_input_report(struct ratbag_device *device, uint8_t *buf, size_t len, + ratbagd_hidraw_filter_t filter); /** * Read an input report from the device from a specific hidraw index + * Optional filter function can be provided, when the filter returns false the packet is ignored * * @param device the ratbag device * @param[out] buf resulting raw data * @param len length of buf - * @param interal index of hidraw array + * @param hidrawno index of hidraw array + * @param filter filter function * * @return count of data transfered, or a negative errno on error */ -int ratbag_hidraw_read_input_report_index(struct ratbag_device *device, uint8_t *buf, size_t len, int hidrawno); - +int ratbag_hidraw_read_input_report_index(struct ratbag_device *device, uint8_t *buf, size_t len, int hidrawno, + ratbagd_hidraw_filter_t filter); /** * Tells if a given device has the specified report ID.