forked from drath/libratbag
asus: add support for the Omni receiver and new data layouts
Mice behind an ASUS Omni receiver all enumerate with the same usb id (0b05:1ace), so the regular bus:vid:pid DeviceMatch cannot tell models apart. Identify the model during probe instead: - asus-rog-omni-receiver.device is a minimal bootstrap file that only declares Quirks=OMNI_RECEIVER, so the asus driver gets probed on the receiver's hidraw nodes - the probe queries the serial number signature (03 12 12 02) and matches its prefix against the OmniSignature field of the .device files, then re-resolves the device data for the identified usb id - an unknown signature fails the probe with -ENODEV, which also drops the receiver's keyboard and media control nodes The Strix Impact III family answers with data two bytes earlier than the original protocol (code plus params echo instead of code plus pad), so two quirks cover the new layouts: - LED_V2: per-zone LED responses with data at offset 4, brightness in 0-100 - SETTINGS_V2: settings and DPI responses with data at offset 4, rate/debounce/snapping as single bytes Also write DPI values with two bytes so presets above 12850 dpi work. Verified on a ROG Strix Impact III Wireless: identification on hidraw4, all 5 profiles with 8 buttons, 1 LED and DPI presets 400/800/1600/3200, report rate 1000 Hz, debounce 12 ms, LED brightness 127 (50%). Writes round-trip and survive a ratbagd restart.
This commit is contained in:
committed by
staticssleever668
parent
1f4efda955
commit
d93a8bc474
12
data/devices/asus-rog-omni-receiver.device
Normal file
12
data/devices/asus-rog-omni-receiver.device
Normal file
@@ -0,0 +1,12 @@
|
||||
[Device]
|
||||
Name=ASUS ROG Omni Receiver
|
||||
DeviceMatch=usb:0b05:1ace
|
||||
DeviceType=mouse
|
||||
Driver=asus
|
||||
|
||||
# The Omni receiver is a shared USB device for multiple mice (all of them
|
||||
# enumerate with the same usb id), so the actual model is identified during
|
||||
# probe and resolved to the model-specific .device data. This file only
|
||||
# exists to get the asus driver probed on the receiver's hidraw nodes.
|
||||
[Driver/asus]
|
||||
Quirks=OMNI_RECEIVER
|
||||
138
src/asus.c
138
src/asus.c
@@ -26,6 +26,7 @@
|
||||
#include "asus.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libratbag-data.h"
|
||||
#include "libratbag-private.h"
|
||||
@@ -138,15 +139,37 @@ asus_query(struct ratbag_device *device,
|
||||
union asus_request *request, union asus_response *response)
|
||||
{
|
||||
int rc;
|
||||
uint32_t quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
uint8_t omni_tx_buf[ASUS_PACKET_SIZE];
|
||||
uint8_t omni_rx_buf[ASUS_PACKET_SIZE];
|
||||
|
||||
rc = ratbag_hidraw_output_report(device, request->raw, ASUS_PACKET_SIZE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (quirks & ASUS_QUIRK_OMNI_RECEIVER) {
|
||||
/* devices behind the Omni receiver use report ID 0x03 and a
|
||||
* 64-byte report, the payload is shifted by one byte */
|
||||
memset(omni_tx_buf, 0, sizeof(omni_tx_buf));
|
||||
omni_tx_buf[0] = 0x03;
|
||||
memcpy(omni_tx_buf + 1, request->raw, ASUS_PACKET_SIZE - 1);
|
||||
|
||||
memset(response, 0, sizeof(union asus_response));
|
||||
rc = ratbag_hidraw_read_input_report(device, response->raw, ASUS_PACKET_SIZE, NULL);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
rc = ratbag_hidraw_output_report(device, omni_tx_buf, ASUS_PACKET_SIZE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
memset(response, 0, sizeof(union asus_response));
|
||||
rc = ratbag_hidraw_read_input_report(device, omni_rx_buf, ASUS_PACKET_SIZE, NULL);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
memcpy(response->raw, omni_rx_buf + 1, ASUS_PACKET_SIZE - 1);
|
||||
} else {
|
||||
rc = ratbag_hidraw_output_report(device, request->raw, ASUS_PACKET_SIZE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
memset(response, 0, sizeof(union asus_response));
|
||||
rc = ratbag_hidraw_read_input_report(device, response->raw, ASUS_PACKET_SIZE, NULL);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* invalid state, disconnected or sleeping */
|
||||
if (response->data.code == ASUS_STATUS_ERROR) {
|
||||
@@ -339,22 +362,49 @@ asus_get_resolution_data(struct ratbag_device *device, union asus_resolution_dat
|
||||
|
||||
case 4: /* 4 DPI presets */
|
||||
if (sep_xy_dpi) { /* separate X & Y values */
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
data->data_xy.dpi[i].x = data->data_xy.dpi[i].x * 50 + 50;
|
||||
data->data_xy.dpi[i].y = data->data_xy.dpi[i].y * 50 + 50;
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI) {
|
||||
data->data_xy.dpi[i].x *= 2;
|
||||
data->data_xy.dpi[i].y *= 2;
|
||||
if (quirks & ASUS_QUIRK_SETTINGS_V2) {
|
||||
/* new layout: data starts at offset 4, each preset
|
||||
* is x lo/hi, y lo/hi */
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
uint16_t x = data->raw[4 + i * 4] |
|
||||
(data->raw[5 + i * 4] << 8);
|
||||
uint16_t y = data->raw[6 + i * 4] |
|
||||
(data->raw[7 + i * 4] << 8);
|
||||
data->data_xy.dpi[i].x = x * 50 + 50;
|
||||
data->data_xy.dpi[i].y = y * 50 + 50;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
data->data_xy.dpi[i].x = data->data_xy.dpi[i].x * 50 + 50;
|
||||
data->data_xy.dpi[i].y = data->data_xy.dpi[i].y * 50 + 50;
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI) {
|
||||
data->data_xy.dpi[i].x *= 2;
|
||||
data->data_xy.dpi[i].y *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
data->data4.dpi[i] = data->data4.dpi[i] * 50 + 50;
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI)
|
||||
data->data4.dpi[i] *= 2;
|
||||
if (quirks & ASUS_QUIRK_SETTINGS_V2) {
|
||||
/* new layout: data starts at offset 4, dpi presets
|
||||
* are 2 bytes each, rate/debounce/snapping are
|
||||
* single bytes at offset 12/14/16 */
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
uint16_t dpi = data->raw[4 + i * 2] |
|
||||
(data->raw[5 + i * 2] << 8);
|
||||
data->data4.dpi[i] = dpi * 50 + 50;
|
||||
}
|
||||
data->data4.rate = ASUS_POLLING_RATES[data->raw[12] & 0x07];
|
||||
data->data4.response = ASUS_DEBOUNCE_TIMES[data->raw[14]];
|
||||
data->data4.snapping = data->raw[16];
|
||||
} else {
|
||||
for (i = 0; i < dpi_count; i++) {
|
||||
data->data4.dpi[i] = data->data4.dpi[i] * 50 + 50;
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI)
|
||||
data->data4.dpi[i] *= 2;
|
||||
}
|
||||
data->data4.rate = ASUS_POLLING_RATES[data->data4.rate];
|
||||
data->data4.response = ASUS_DEBOUNCE_TIMES[data->data4.response];
|
||||
}
|
||||
data->data4.rate = ASUS_POLLING_RATES[data->data4.rate];
|
||||
data->data4.response = ASUS_DEBOUNCE_TIMES[data->data4.response];
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -378,10 +428,12 @@ asus_set_dpi(struct ratbag_device *device, unsigned int index, unsigned int dpi)
|
||||
if (quirks & ASUS_QUIRK_DOUBLE_DPI)
|
||||
idpi /= 2;
|
||||
|
||||
idpi = (idpi - 50) / 50;
|
||||
union asus_request request = {
|
||||
.data.cmd = ASUS_CMD_SET_SETTING,
|
||||
.data.params[0] = index,
|
||||
.data.params[2] = (idpi - 50) / 50,
|
||||
.data.params[2] = idpi & 0xff,
|
||||
.data.params[3] = (idpi >> 8) & 0xff,
|
||||
};
|
||||
|
||||
rc = asus_query(device, &request, &response);
|
||||
@@ -511,3 +563,49 @@ asus_set_led(struct ratbag_device *device,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ASUS Omni receiver: identify the mouse behind the shared receiver.
|
||||
*
|
||||
* All mice connected to an Omni receiver share the same USB id
|
||||
* (0b05:1ace), so the model is queried with a signature request
|
||||
* (03 12 12 02). The response carries a 12 byte ASCII serial number at
|
||||
* offset 5 and the model is derived from its prefix.
|
||||
*
|
||||
* The serial number is matched against the OmniSignature field of the
|
||||
* .device files, so supporting a new model does not require any code
|
||||
* changes. On success the usb id of the identified model is returned in
|
||||
* id, so that the caller can resolve the mouse-specific .device data.
|
||||
*/
|
||||
int
|
||||
asus_omni_identify(struct ratbag_device *device, struct input_id *id)
|
||||
{
|
||||
int rc;
|
||||
union asus_request request = {
|
||||
.data.cmd = 0x1212,
|
||||
.data.params[0] = 0x02,
|
||||
};
|
||||
union asus_response response;
|
||||
char signature[13];
|
||||
|
||||
rc = asus_query(device, &request, &response);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* signature is 12 ASCII bytes at offset 5 of the raw report,
|
||||
* which is offset 4 after the report id is stripped */
|
||||
memcpy(signature, response.raw + 4, 12);
|
||||
signature[12] = '\0';
|
||||
|
||||
rc = ratbag_device_data_omni_signature_match(device->ratbag, signature, id);
|
||||
if (rc) {
|
||||
log_debug(device->ratbag,
|
||||
"Unknown ASUS Omni device serial '%s'. Please add an "
|
||||
"OmniSignature entry to the .device file of the model.\n",
|
||||
signature);
|
||||
return rc;
|
||||
}
|
||||
|
||||
log_info(device->ratbag,
|
||||
"ASUS Omni device identified (serial %s)\n", signature);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#define ASUS_QUIRK_SEPARATE_XY_DPI 1 << 4
|
||||
#define ASUS_QUIRK_SEPARATE_LEDS 1 << 5
|
||||
#define ASUS_QUIRK_BUTTONS_SECONDARY 1 << 6
|
||||
#define ASUS_QUIRK_OMNI_RECEIVER 1 << 7 /* device is behind an ASUS Omni receiver, transport uses report ID 0x03 */
|
||||
#define ASUS_QUIRK_LED_V2 1 << 8 /* LED response is per-zone with data at offset 4, brightness is 0-100 */
|
||||
#define ASUS_QUIRK_SETTINGS_V2 1 << 9 /* settings/DPI response data starts at offset 4, rate/debounce/snapping are single bytes */
|
||||
|
||||
#define ASUS_PACKET_SIZE 64
|
||||
#define ASUS_BUTTON_ACTION_TYPE_KEY 0 /* keyboard key */
|
||||
@@ -222,6 +225,11 @@ asus_setup_led(struct ratbag_device *device, struct ratbag_led *led);
|
||||
int
|
||||
asus_query(struct ratbag_device *device, union asus_request *request, union asus_response *response);
|
||||
|
||||
/* ASUS Omni receiver: identify the mouse behind the shared receiver and
|
||||
* return the usb id that matches its own .device file. */
|
||||
int
|
||||
asus_omni_identify(struct ratbag_device *device, struct input_id *id);
|
||||
|
||||
/* commit */
|
||||
|
||||
int
|
||||
|
||||
@@ -212,7 +212,7 @@ asus_driver_load_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
|
||||
/* get LEDs */
|
||||
|
||||
if (!(quirks & ASUS_QUIRK_SEPARATE_LEDS) && led_count) {
|
||||
if (!(quirks & (ASUS_QUIRK_SEPARATE_LEDS | ASUS_QUIRK_LED_V2)) && led_count) {
|
||||
log_debug(device->ratbag, "Loading LEDs data\n");
|
||||
rc = asus_get_led_data(device, &led_data, 0);
|
||||
if (rc)
|
||||
@@ -220,16 +220,29 @@ asus_driver_load_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
}
|
||||
|
||||
ratbag_profile_for_each_led(profile, led) {
|
||||
if (quirks & ASUS_QUIRK_SEPARATE_LEDS) {
|
||||
if (quirks & (ASUS_QUIRK_SEPARATE_LEDS | ASUS_QUIRK_LED_V2)) {
|
||||
log_debug(device->ratbag, "Loading LED %d data\n", led->index);
|
||||
rc = asus_get_led_data(device, &led_data, led->index);
|
||||
if (rc)
|
||||
return rc;
|
||||
asus_led = &led_data.data.led[0];
|
||||
} else {
|
||||
asus_led = &led_data.data.led[led->index];
|
||||
}
|
||||
|
||||
if (quirks & ASUS_QUIRK_LED_V2) {
|
||||
/* new layout: a single zone per response with data at
|
||||
* offset 4, brightness is 0-100 percent */
|
||||
led->mode = drv_data->led_modes[led_data.raw[4]];
|
||||
led->brightness = led_data.raw[5] * 255 / 100;
|
||||
led->color.red = led_data.raw[6];
|
||||
led->color.green = led_data.raw[7];
|
||||
led->color.blue = led_data.raw[8];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (quirks & ASUS_QUIRK_SEPARATE_LEDS)
|
||||
asus_led = &led_data.data.led[0];
|
||||
else
|
||||
asus_led = &led_data.data.led[led->index];
|
||||
|
||||
led->mode = drv_data->led_modes[asus_led->mode];
|
||||
if (quirks & ASUS_QUIRK_RAW_BRIGHTNESS) {
|
||||
led->brightness = asus_led->brightness;
|
||||
@@ -379,6 +392,9 @@ asus_driver_save_profile(struct ratbag_device *device, struct ratbag_profile *pr
|
||||
uint8_t led_brightness;
|
||||
if (quirks & ASUS_QUIRK_RAW_BRIGHTNESS) {
|
||||
led_brightness = led->brightness;
|
||||
} else if (quirks & ASUS_QUIRK_LED_V2) {
|
||||
/* convert brightness from 0-255 to 0-100 percent */
|
||||
led_brightness = (uint8_t)round((double)led->brightness * 100.0 / 255.0);
|
||||
} else {
|
||||
/* convert brightness from 0-256 to 0-4 */
|
||||
led_brightness = (uint8_t)round((double)led->brightness / 64.0);
|
||||
@@ -515,17 +531,51 @@ asus_driver_probe(struct ratbag_device *device)
|
||||
struct ratbag_button *button;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct ratbag_led *led;
|
||||
uint32_t quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
|
||||
rc = ratbag_open_hidraw(device);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = asus_get_profile_data(device, &profile_data);
|
||||
if (rc) {
|
||||
ratbag_close_hidraw(device);
|
||||
return -ENODEV;
|
||||
/* The Omni receiver is a shared USB device for multiple mice, so the
|
||||
* actual model has to be identified and resolved to its own .device
|
||||
* data before anything else. Wrong hidraw nodes (keyboard, media
|
||||
* control, etc.) fail the identification and are rejected here. */
|
||||
if (quirks & ASUS_QUIRK_OMNI_RECEIVER) {
|
||||
struct ratbag_device_data *data;
|
||||
struct input_id id = device->ids;
|
||||
|
||||
rc = asus_omni_identify(device, &id);
|
||||
if (rc) {
|
||||
log_debug(device->ratbag,
|
||||
"Omni device is not a supported mouse\n");
|
||||
ratbag_close_hidraw(device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = ratbag_device_data_new_for_id(device->ratbag, &id);
|
||||
if (!data) {
|
||||
log_error(device->ratbag,
|
||||
"No device data for Omni mouse %04x:%04x\n",
|
||||
id.vendor, id.product);
|
||||
ratbag_close_hidraw(device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ratbag_device_data_unref(device->data);
|
||||
device->data = data;
|
||||
device->devicetype = ratbag_device_data_get_device_type(device->data);
|
||||
free(device->name);
|
||||
device->name = strdup_safe(ratbag_device_data_get_name(device->data));
|
||||
log_info(device->ratbag,
|
||||
"ASUS Omni receiver identified device: %s\n",
|
||||
device->name);
|
||||
|
||||
quirks = ratbag_device_data_asus_get_quirks(device->data);
|
||||
}
|
||||
|
||||
rc = asus_get_profile_data(device, &profile_data);
|
||||
|
||||
/* create device state data */
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
ratbag_set_drv_data(device, drv_data);
|
||||
|
||||
@@ -107,6 +107,7 @@ struct data_asus {
|
||||
struct dpi_range *dpi_range;
|
||||
uint32_t quirks;
|
||||
int led_modes[ASUS_MAX_NUM_LED_MODES];
|
||||
char *omni_signature; /* serial number prefix of mice behind an Omni receiver */
|
||||
};
|
||||
|
||||
struct ratbag_device_data {
|
||||
@@ -441,6 +442,9 @@ init_data_asus(struct ratbag *ratbag,
|
||||
data->asus.is_wireless = wireless;
|
||||
g_clear_error(&error);
|
||||
|
||||
data->asus.omni_signature = g_key_file_get_string(keyfile, group, "OmniSignature", &error);
|
||||
g_clear_error(&error);
|
||||
|
||||
gsize quirks_count = 0;
|
||||
_cleanup_(g_strfreevp) char **quirks = g_key_file_get_string_list(keyfile, group, "Quirks", &quirks_count, &error);
|
||||
if (!error && quirks) {
|
||||
@@ -457,6 +461,12 @@ init_data_asus(struct ratbag *ratbag,
|
||||
data->asus.quirks |= ASUS_QUIRK_SEPARATE_LEDS;
|
||||
} else if (streq(quirks[i], "BUTTONS_SECONDARY")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_BUTTONS_SECONDARY;
|
||||
} else if (streq(quirks[i], "OMNI_RECEIVER")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_OMNI_RECEIVER;
|
||||
} else if (streq(quirks[i], "LED_V2")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_LED_V2;
|
||||
} else if (streq(quirks[i], "SETTINGS_V2")) {
|
||||
data->asus.quirks |= ASUS_QUIRK_SETTINGS_V2;
|
||||
} else {
|
||||
log_error(ratbag, "%s is invalid quirk. Ignoring...\n", quirks[i]);
|
||||
}
|
||||
@@ -753,7 +763,79 @@ out:
|
||||
return data;
|
||||
}
|
||||
|
||||
int
|
||||
ratbag_device_data_omni_signature_match(struct ratbag *ratbag,
|
||||
const char *signature,
|
||||
struct input_id *id)
|
||||
{
|
||||
struct dirent **files;
|
||||
const char *datadir;
|
||||
int n, nfiles;
|
||||
size_t best_len = 0;
|
||||
int rc = -ENODEV;
|
||||
|
||||
datadir = getenv("LIBRATBAG_DATA_DIR");
|
||||
if (!datadir)
|
||||
datadir = LIBRATBAG_DATA_DIR;
|
||||
|
||||
n = scandir(datadir, &files, filter_device_files, alphasort);
|
||||
if (n <= 0) {
|
||||
log_error(ratbag, "Unable to locate device files in %s: %s\n",
|
||||
datadir, n == 0 ? "No files found" : strerror(errno));
|
||||
return rc;
|
||||
}
|
||||
|
||||
nfiles = n;
|
||||
while (n--) {
|
||||
_cleanup_(g_key_file_freep) GKeyFile *keyfile = NULL;
|
||||
_cleanup_(g_error_freep) GError *error = NULL;
|
||||
_cleanup_(g_strfreevp) char **match_strv = NULL;
|
||||
_cleanup_free_ char *omni_signature = NULL;
|
||||
_cleanup_(freep) char *file = NULL;
|
||||
size_t len;
|
||||
unsigned int vendor, product;
|
||||
|
||||
if (xasprintf(&file, "%s/%s", datadir, files[n]->d_name) == -1)
|
||||
goto out;
|
||||
|
||||
keyfile = g_key_file_new();
|
||||
if (!g_key_file_load_from_file(keyfile, file, G_KEY_FILE_NONE, &error)) {
|
||||
log_error(ratbag, "Failed to parse keyfile %s: %s\n",
|
||||
file, error->message);
|
||||
continue;
|
||||
}
|
||||
|
||||
omni_signature = g_key_file_get_string(keyfile, "Driver/asus",
|
||||
"OmniSignature", NULL);
|
||||
if (!omni_signature)
|
||||
continue;
|
||||
|
||||
len = strlen(omni_signature);
|
||||
if (len <= best_len || strncmp(signature, omni_signature, len) != 0)
|
||||
continue;
|
||||
|
||||
match_strv = g_key_file_get_string_list(keyfile, GROUP_DEVICE,
|
||||
"DeviceMatch", NULL, NULL);
|
||||
if (!match_strv)
|
||||
continue;
|
||||
|
||||
/* the device must have a usb id to be resolvable */
|
||||
if (sscanf(match_strv[0], "usb:%x:%x", &vendor, &product) != 2)
|
||||
continue;
|
||||
|
||||
id->vendor = vendor;
|
||||
id->product = product;
|
||||
best_len = len;
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
while (nfiles--)
|
||||
free(files[nfiles]);
|
||||
free(files);
|
||||
|
||||
return rc;
|
||||
}
|
||||
/* HID++ 1.0 */
|
||||
|
||||
int
|
||||
|
||||
@@ -140,6 +140,19 @@ ratbag_device_data_steelseries_get_quirk(const struct ratbag_device_data *data);
|
||||
|
||||
/* ASUS */
|
||||
|
||||
/**
|
||||
* Find the usb id of the device whose OmniSignature matches the serial
|
||||
* number of a mouse behind an Omni receiver. The longest matching prefix
|
||||
* wins. The bustype of id is left untouched, only vendor and product are
|
||||
* set.
|
||||
*
|
||||
* @return 0 on success or -ENODEV if no .device file matches
|
||||
*/
|
||||
int
|
||||
ratbag_device_data_omni_signature_match(struct ratbag *ratbag,
|
||||
const char *signature,
|
||||
struct input_id *id);
|
||||
|
||||
/**
|
||||
* @return Number of profiles
|
||||
*/
|
||||
|
||||
@@ -115,6 +115,7 @@ def check_section_asus(section: configparser.SectionProxy):
|
||||
"Leds",
|
||||
"LedModes",
|
||||
"Profiles",
|
||||
"OmniSignature",
|
||||
"Quirks",
|
||||
"Wireless",
|
||||
)
|
||||
@@ -135,6 +136,9 @@ def check_section_asus(section: configparser.SectionProxy):
|
||||
"SEPARATE_XY_DPI",
|
||||
"SEPARATE_LEDS",
|
||||
"BUTTONS_SECONDARY",
|
||||
"OMNI_RECEIVER",
|
||||
"LED_V2",
|
||||
"SETTINGS_V2",
|
||||
)
|
||||
for quirk in section["Quirks"].split(";"):
|
||||
assert quirk in quirks
|
||||
|
||||
Reference in New Issue
Block a user