1
0
forked from drath/libratbag

Use udev rules/hwdb to match mice to drivers and SVGs

This adds udev rules/hwdb that sets RATBAG_DRIVER and RATBAG_SVG
properties to the event devices. We then use this property to select
the correct driver instead of checking the hardcoded list in the
drivers. Having this in a hwdb makes it easier for users to test
if drivers match their mouse with a system installed libratbag.

Each driver now has an "id" which is used to match the driver set
in RATBAG_DRIVER. A SVG can optionally be set as well.

All entries in the hwdb are currently without a name as that
information was not available in the hardcoded lists.

Note that this patch breaks the test-driver.
This commit is contained in:
Thomas Hindoe Paaboel Andersen
2015-10-09 21:01:47 +02:00
parent 5278d43429
commit 3605bede48
12 changed files with 204 additions and 181 deletions

View File

@@ -763,15 +763,13 @@ etekcity_write_resolution_dpi(struct ratbag_resolution *resolution,
}
static int
etekcity_probe(struct ratbag_device *device, const struct ratbag_id id)
etekcity_probe(struct ratbag_device *device)
{
int rc;
struct ratbag_profile *profile;
struct etekcity_data *drv_data;
int active_idx;
log_raw(device->ratbag, "data: %d\n", id.data);
rc = ratbag_open_hidraw(device);
if (rc) {
log_error(device->ratbag,
@@ -835,22 +833,9 @@ etekcity_remove(struct ratbag_device *device)
free(ratbag_get_drv_data(device));
}
#define USB_VENDOR_ID_ETEKCITY 0x1ea7
static const struct ratbag_id etekcity_table[] = {
{.id = { .bustype = BUS_USB,
.vendor = USB_VENDOR_ID_ETEKCITY,
.product = 0x4011,
.version = VERSION_ANY },
.svg_filename = "etekcity.svg",
},
{ },
};
struct ratbag_driver etekcity_driver = {
.name = "EtekCity",
.table_ids = etekcity_table,
.id = "etekcity",
.probe = etekcity_probe,
.remove = etekcity_remove,
.read_profile = etekcity_read_profile,

View File

@@ -198,7 +198,7 @@ hidpp10drv_test_hidraw(struct ratbag_device *device)
}
static int
hidpp10drv_probe(struct ratbag_device *device, const struct ratbag_id id)
hidpp10drv_probe(struct ratbag_device *device)
{
int rc;
struct hidpp10drv_data *drv_data = NULL;
@@ -272,47 +272,9 @@ hidpp10drv_remove(struct ratbag_device *device)
free(drv_data);
}
#define LOGITECH_DEVICE(_bus, _pid) \
{ .bustype = (_bus), \
.vendor = USB_VENDOR_ID_LOGITECH, \
.product = (_pid), \
.version = VERSION_ANY }
static const struct ratbag_id hidpp10drv_table[] = {
/* M705 */
{ .id = LOGITECH_DEVICE(BUS_USB, 0x101b) },
/* M570 */
{ .id = LOGITECH_DEVICE(BUS_USB, 0x1028) },
/* G5 */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc041) },
/* G5 2007 */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc049) },
/* G9 */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc048) },
/* G9x [Original] */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc066) },
/* G9x [Call of Duty MW3 Edition] */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc249) },
/* G500 */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc068) },
/* G500s */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc24e),
.svg_filename = "logitech-g500s.svg" },
{ },
};
struct ratbag_driver hidpp10_driver = {
.name = "Logitech HID++1.0",
.table_ids = hidpp10drv_table,
.id = "hidpp10",
.probe = hidpp10drv_probe,
.remove = hidpp10drv_remove,
.read_profile = hidpp10drv_read_profile,

View File

@@ -406,7 +406,7 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
}
static int
hidpp20drv_20_probe(struct ratbag_device *device, const struct ratbag_id id)
hidpp20drv_20_probe(struct ratbag_device *device)
{
struct hidpp20_feature *feature_list;
int rc, i;
@@ -438,7 +438,7 @@ hidpp20drv_test_hidraw(struct ratbag_device *device)
}
static int
hidpp20drv_probe(struct ratbag_device *device, const struct ratbag_id id)
hidpp20drv_probe(struct ratbag_device *device)
{
int rc;
struct hidpp20drv_data *drv_data;
@@ -470,7 +470,7 @@ hidpp20drv_probe(struct ratbag_device *device, const struct ratbag_id id)
log_debug(device->ratbag, "'%s' is using protocol v%d.%d\n", ratbag_device_get_name(device), drv_data->proto_major, drv_data->proto_minor);
if (drv_data->proto_major >= 2) {
rc = hidpp20drv_20_probe(device, id);
rc = hidpp20drv_20_probe(device);
if (rc)
goto err;
}
@@ -497,40 +497,9 @@ hidpp20drv_remove(struct ratbag_device *device)
free(drv_data);
}
#define USB_VENDOR_ID_LOGITECH 0x046d
#define LOGITECH_DEVICE(_bus, _pid) \
{ .bustype = (_bus), \
.vendor = USB_VENDOR_ID_LOGITECH, \
.product = (_pid), \
.version = VERSION_ANY }
static const struct ratbag_id hidpp20drv_table[] = {
/* MX Master over unifying */
{ .id = LOGITECH_DEVICE(BUS_USB, 0x4041),
.svg_filename = "logitech-mx_master.svg" },
/* MX Master over bluetooth */
{ .id = LOGITECH_DEVICE(BUS_BLUETOOTH, 0xb012),
.svg_filename = "logitech-mx_master.svg" },
/* T650 over unifying */
{ .id = LOGITECH_DEVICE(BUS_USB, 0x4101) },
/* M325 over unifying */
{ .id = LOGITECH_DEVICE(BUS_USB, 0x400a) },
/* G502 over USB */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc07d) },
/* G303 over USB */
{ .id = LOGITECH_DEVICE(BUS_USB, 0xc080) },
{ },
};
struct ratbag_driver hidpp20_driver = {
.name = "Logitech HID++2.0",
.table_ids = hidpp20drv_table,
.id = "hidpp20",
.probe = hidpp20drv_probe,
.remove = hidpp20drv_remove,
.read_profile = hidpp20drv_read_profile,

View File

@@ -901,7 +901,7 @@ roccat_write_resolution_dpi(struct ratbag_resolution *resolution,
}
static int
roccat_probe(struct ratbag_device *device, const struct ratbag_id id)
roccat_probe(struct ratbag_device *device)
{
int rc;
struct ratbag_profile *profile;
@@ -965,20 +965,9 @@ roccat_remove(struct ratbag_device *device)
free(ratbag_get_drv_data(device));
}
static const struct ratbag_id roccat_table[] = {
{.id = { .bustype = BUS_USB,
.vendor = 0x1e7d,
.product = 0x2e22,
.version = VERSION_ANY },
.svg_filename = "roccat-kone-xtd.svg",
},
{ },
};
struct ratbag_driver roccat_driver = {
.name = "Roccat Kone XTD",
.table_ids = roccat_table,
.id = "roccat",
.probe = roccat_probe,
.remove = roccat_remove,
.read_profile = roccat_read_profile,

View File

@@ -26,17 +26,6 @@
#include "libratbag-private.h"
#include "libratbag-test.h"
static const struct ratbag_id test_table[] = {
{.id = { .bustype = 0x00,
.vendor = 0x00,
.product = 0x00,
.version = 0x00 },
.data = 1,
},
{ },
};
static int
test_has_capability(const struct ratbag_device *device,
enum ratbag_device_capability cap)
@@ -92,17 +81,12 @@ test_write_profile(struct ratbag_profile *profile)
}
static int
test_probe(struct ratbag_device *device, const struct ratbag_id id)
test_probe(struct ratbag_device *device)
{
struct ratbag_test_device *test_device;
assert(id.id.bustype == 0x00);
assert(id.id.vendor == 0x00);
assert(id.id.product == 0x00);
assert(id.id.version == 0x00);
assert(id.test_device != NULL);
test_device = id.test_device;
/* FIXME: after the move to hwdb the test_device is no
* longer passed in. */
ratbag_set_drv_data(device, test_device);
ratbag_device_init_profiles(device,
@@ -125,7 +109,6 @@ test_remove(struct ratbag_device *device)
struct ratbag_driver test_driver = {
.name = "Test driver",
.table_ids = test_table,
.probe = test_probe,
.remove = test_remove,
.read_profile = test_read_profile,

View File

@@ -59,7 +59,6 @@ struct ratbag {
struct ratbag_device {
char *name;
const char *svg_name;
void *userdata;
struct udev_device *udev_device;
@@ -79,25 +78,15 @@ struct ratbag_device {
struct list link;
};
struct ratbag_id {
struct input_id id;
const char *svg_filename;
unsigned long data;
struct ratbag_test_device *test_device; /**< Test suite only */
};
/**
* struct ratbag_driver - user space driver for a ratbag device
*/
struct ratbag_driver {
/** the name of the driver */
/** A human-readable name of the driver */
char *name;
/**
* A list of devices supported by this driver. The last element
* must be empty to mark the end.
*/
const struct ratbag_id *table_ids;
/** The id of the driver used to match with RATBAG_DRIVER in udev */
char *id;
/**
* Callback called while trying to open a device by libratbag.
@@ -107,7 +96,7 @@ struct ratbag_driver {
* Return -ENODEV to ignore the device and let other drivers
* probe the device. Any other error code will stop the probing.
*/
int (*probe)(struct ratbag_device *device, const struct ratbag_id id);
int (*probe)(struct ratbag_device *device);
/**
* Callback called right before the struct ratbag_device is

View File

@@ -284,15 +284,6 @@ out:
return rc;
}
static inline bool
ratbag_match_id(const struct input_id *dev_id, const struct input_id *match_id)
{
return (match_id->bustype == BUS_ANY || match_id->bustype == dev_id->bustype) &&
(match_id->vendor == VENDOR_ANY || match_id->vendor == dev_id->vendor) &&
(match_id->product == PRODUCT_ANY || match_id->product == dev_id->product) &&
(match_id->version == VERSION_ANY || match_id->version == dev_id->version);
}
struct ratbag_driver *
ratbag_find_driver(struct ratbag_device *device,
const struct input_id *dev_id,
@@ -300,44 +291,38 @@ ratbag_find_driver(struct ratbag_device *device,
{
struct ratbag *ratbag = device->ratbag;
struct ratbag_driver *driver;
const struct ratbag_id *matching_id;
struct ratbag_id matched_id;
int rc;
const char *driver_name;
matched_id.test_device = test_device;
driver_name = udev_prop_value(device->udev_device, "RATBAG_DRIVER");
if (!driver_name)
return NULL;
list_for_each(driver, &ratbag->drivers, link) {
log_debug(ratbag, "trying driver '%s'\n", driver->name);
matching_id = driver->table_ids;
do {
if (ratbag_match_id(dev_id, &matching_id->id)) {
matched_id.id = *dev_id;
matched_id.data = matching_id->data;
matched_id.svg_filename = matching_id->svg_filename;
device->driver = driver;
rc = driver->probe(device, matched_id);
if (rc == 0) {
if (!ratbag_sanity_check_device(device)) {
return NULL;
} else {
log_debug(ratbag, "driver match found\n");
device->svg_name = matching_id->svg_filename;
return driver;
}
}
if (!streq(driver->id, driver_name))
continue;
device->driver = NULL;
device->driver = driver;
if (rc != -ENODEV)
return NULL;
rc = driver->probe(device);
if (rc == 0) {
if (!ratbag_sanity_check_device(device)) {
return NULL;
} else {
log_debug(ratbag, "driver match found: %s\n", driver->name);
return driver;
}
matching_id++;
} while (matching_id->id.bustype != 0 ||
matching_id->id.vendor != 0 ||
matching_id->id.product != 0 ||
matching_id->id.version != 0);
}
device->driver = NULL;
if (rc != -ENODEV) {
log_error(ratbag, "%s: no hidraw device found", device->name);
return NULL;
}
}
log_error(ratbag, "%s: driver specified in hwdb not found: %s\n", device->name, driver_name);
return NULL;
}
@@ -456,7 +441,7 @@ ratbag_device_get_name(const struct ratbag_device* device)
LIBRATBAG_EXPORT const char *
ratbag_device_get_svg_name(const struct ratbag_device* device)
{
return device->svg_name;
return udev_prop_value(device->udev_device, "RATBAG_SVG");
}
void
@@ -467,7 +452,7 @@ ratbag_register_driver(struct ratbag *ratbag, struct ratbag_driver *driver)
return;
}
if (!driver->probe || !driver->remove || !driver->table_ids) {
if (!driver->probe || !driver->remove) {
log_bug_libratbag(ratbag, "Driver %s is incomplete.\n");
return;
}