diff --git a/src/libratbag-private.h b/src/libratbag-private.h index d7eeb08e..255f9843 100644 --- a/src/libratbag-private.h +++ b/src/libratbag-private.h @@ -24,11 +24,36 @@ #ifndef LIBRATBAG_PRIVATE_H #define LIBRATBAG_PRIVATE_H +#include + #include "libratbag.h" +#include "libratbag-util.h" + + +#define BUS_ANY 0xffff +#define VENDOR_ANY 0xffff +#define PRODUCT_ANY 0xffff +#define VERSION_ANY 0xffff + +struct ratbag_driver; struct ratbag { int evdev_fd; int refcount; + struct ratbag_driver *driver; +}; + +struct ratbag_id { + struct input_id id; + unsigned long data; +}; + +struct ratbag_driver { + char *name; + const struct ratbag_id *table_ids; + + /* private */ + struct list link; }; void ratbag_device_init(struct ratbag *rb, int fd); diff --git a/src/libratbag.c b/src/libratbag.c index 10e2a336..d5b57a3f 100644 --- a/src/libratbag.c +++ b/src/libratbag.c @@ -24,7 +24,7 @@ #include "config.h" #include #include -#include +#include #include #include #include @@ -33,6 +33,8 @@ #include "libratbag-util.h" struct libratbag { + struct list drivers; + int refcount; libratbag_log_handler log_handler; enum libratbag_log_priority log_priority; @@ -86,12 +88,45 @@ ratbag_device_init(struct ratbag *rb, int fd) rb->refcount = 1; } +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); +} + +static struct ratbag_driver * +ratbag_find_driver(struct libratbag *libratbag, const struct input_id *dev_id) +{ + struct ratbag_driver *driver; + const struct ratbag_id *matching_id; + + list_for_each(driver, &libratbag->drivers, link) { + log_debug(libratbag, "testing against %s\n", driver->name); + matching_id = driver->table_ids; + do { + if (ratbag_match_id(dev_id, &matching_id->id)) { + 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); + } + + return NULL; +} + LIBRATBAG_EXPORT struct ratbag* ratbag_new_from_fd(struct libratbag *libratbag, int fd) { int rc; struct input_id ids; struct ratbag *ratbag = NULL; + struct ratbag_driver *driver; if (!libratbag) { fprintf(stderr, "libratbag is NULL\n"); @@ -108,6 +143,14 @@ ratbag_new_from_fd(struct libratbag *libratbag, int fd) ratbag_device_init(ratbag, fd); + driver = ratbag_find_driver(libratbag, &ids); + if (!driver) { + errno = ENOTSUP; + goto out_err; + } + + ratbag->driver = driver; + return ratbag; out_err: @@ -130,6 +173,12 @@ ratbag_unref(struct ratbag *ratbag) return NULL; } +static void +ratbag_register_driver(struct libratbag *libratbag, struct ratbag_driver *driver) +{ + list_insert(&libratbag->drivers, &driver->link); +} + LIBRATBAG_EXPORT struct libratbag * libratbag_create_context(void) { @@ -141,6 +190,7 @@ libratbag_create_context(void) libratbag->refcount = 1; + list_init(&libratbag->drivers); libratbag->log_handler = libratbag_default_log_func; libratbag->log_priority = LIBRATBAG_LOG_PRIORITY_DEBUG;