mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-08 07:33:53 +01:00
ibratbag-hidraw: add optional filter to hidraw read
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 <lains@riseup.net> Signed-off-by: Rafael Silva <perigoso@riseup.net>
This commit is contained in:
committed by
Peter Hutterer
parent
6dbaeaf506
commit
ae53f6123b
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user