ratbagd: pick the ID from a list of preselected names

We don't want anyone to rely on a specific content of the ID, e.g. by
hardcoding hidraw/event node numbers. So let's make this an opaque list with
no meaning other than "this is a rodent".

This is solely for the benefit of ratbagctl which uses these IDs as access
identifier.

This doesn't affect ratbag-command which still uses device paths. It also does
not affect the object path. And piper shows the device name anyway.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer
2019-02-21 09:58:19 +10:00
parent b568963b14
commit 12ac8b17f0
4 changed files with 81 additions and 3 deletions

View File

@@ -44,6 +44,7 @@ struct ratbagd_device {
struct ratbagd *ctx;
RBNode node;
char *sysname;
char *id;
char *path;
struct ratbag_device *lib_device;
@@ -274,7 +275,7 @@ ratbagd_device_get_capabilities(sd_bus *bus,
const sd_bus_vtable ratbagd_device_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Id", "s", NULL, offsetof(struct ratbagd_device, sysname), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Id", "s", NULL, offsetof(struct ratbagd_device, id), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Capabilities", "au", ratbagd_device_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Name", "s", ratbagd_device_get_device_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Profiles", "ao", ratbagd_device_get_profiles, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -287,6 +288,7 @@ const sd_bus_vtable ratbagd_device_vtable[] = {
int ratbagd_device_new(struct ratbagd_device **out,
struct ratbagd *ctx,
const char *sysname,
const char *id,
struct ratbag_device *lib_device)
{
_cleanup_(ratbagd_device_freep) struct ratbagd_device *device = NULL;
@@ -297,6 +299,7 @@ int ratbagd_device_new(struct ratbagd_device **out,
assert(out);
assert(ctx);
assert(sysname);
assert(id);
device = zalloc(sizeof(*device));
device->ctx = ctx;
@@ -304,6 +307,7 @@ int ratbagd_device_new(struct ratbagd_device **out,
device->lib_device = ratbag_device_ref(lib_device);
device->sysname = strdup_safe(sysname);
device->id = strdup_safe(id);
r = sd_bus_path_encode(RATBAGD_OBJ_ROOT "/device",
device->sysname,
@@ -357,12 +361,19 @@ struct ratbagd_device *ratbagd_device_free(struct ratbagd_device *device)
device->lib_device = ratbag_device_unref(device->lib_device);
device->path = mfree(device->path);
device->sysname = mfree(device->sysname);
device->id = mfree(device->id);
assert(!device->lib_device); /* ratbag yields !NULL if still pinned */
return mfree(device);
}
const char *ratbagd_device_get_id(struct ratbagd_device *device)
{
assert(device);
return device->sysname;
}
const char *ratbagd_device_get_sysname(struct ratbagd_device *device)
{
assert(device);

View File

@@ -190,7 +190,7 @@ int ratbagd_reset_test_device(sd_bus_message *m,
device = ratbag_device_new_test_device(ctx->lib_ctx, &ratbagd_test_device_descr);
r = ratbagd_device_new(&ratbagd_test_device, ctx, "test_device", device);
r = ratbagd_device_new(&ratbagd_test_device, ctx, "test_device", "test_device", device);
/* the ratbagd_device takes its own reference, drop ours */
ratbag_device_unref(device);

View File

@@ -204,6 +204,67 @@ static const sd_bus_vtable ratbagd_vtable[] = {
SD_BUS_VTABLE_END,
};
/* 32 pre-picked names. If you have more than 32 devices connected and need
* ratbag to control them all, congratulations, you are official a niche
* use-case.
*/
static const char *device_ids[] = {
"mara", "capybara", "porcupine", "paca",
"vole", "woodrat", "gerbil", "shrew",
"hare", "beaver", "gopher", "chinchilla",
"mouse", "rat", "rabbit", "guineapig",
"hutia", "degu", "gundi", "acouchy",
"nutria", "tuco-tuco", "paca", "hamster",
"zokor", "chipmunk", "squirrel", "marmot",
"groundhog", "suslik", "agouti", "blesmol",
};
/* bitmask telling us which ones of the above are free. */
static uint32_t device_ids_free = (1UL << ARRAY_LENGTH(device_ids)) - 1;
static inline const char *
pick_device_id(const char *sysname)
{
int index;
/* search for the first number in the sysname and where we find it,
* use that as lookup index. This way we get some sort of
* consistency, hidraw2 is always "rat", etc.
* Totally not necessary but we might as well have some fun here.
* Where this fails or picks an id already chosen, we fall back to
* "choose the first one free".
*/
if (sscanf(sysname, "%*[^0-9]%d", &index) == 1 &&
index >= 0 && (unsigned)index < sizeof(device_ids_free) * 8 &&
!!(device_ids_free & (1 << index)))
goto assign;
index = ffs(device_ids_free);
/* This can only happen if you have >32 devices, so let's not worry
* about this too much */
if (index == 0)
return sysname;
index -= 1; /* ffs is 1-based */
assign:
device_ids_free &= ~(1 << index);
return device_ids[index];
}
static inline void
release_device_id(const char *id)
{
for (size_t i = 0; i < ARRAY_LENGTH(device_ids); i++) {
if (streq(id, device_ids[i])) {
device_ids_free |= (1 << i);
break;
}
}
}
static void ratbagd_process_device(struct ratbagd *ctx,
struct udev_device *udevice)
{
@@ -230,9 +291,11 @@ static void ratbagd_process_device(struct ratbagd *ctx,
if (streq_ptr("remove", udev_device_get_action(udevice))) {
/* device was removed, unlink it and destroy our context */
if (device) {
release_device_id(ratbagd_device_get_id(device));
ratbagd_device_unlink(device);
ratbagd_device_free(device);
(void) sd_bus_emit_properties_changed(ctx->bus,
RATBAGD_OBJ_ROOT,
RATBAGD_NAME_ROOT ".Manager",
@@ -242,6 +305,7 @@ static void ratbagd_process_device(struct ratbagd *ctx,
} else if (device) {
/* device already known, refresh our view of the device */
} else {
const char *id;
enum ratbag_error_code error;
/* device unknown, create new one and link it */
@@ -251,7 +315,8 @@ static void ratbagd_process_device(struct ratbagd *ctx,
if (error != RATBAG_SUCCESS)
return; /* unsupported device */
r = ratbagd_device_new(&device, ctx, sysname, lib_device);
id = pick_device_id(sysname);
r = ratbagd_device_new(&device, ctx, sysname, id, lib_device);
/* the ratbagd_device takes its own reference, drop ours */
ratbag_device_unref(lib_device);

View File

@@ -169,8 +169,10 @@ extern const sd_bus_vtable ratbagd_device_vtable[];
int ratbagd_device_new(struct ratbagd_device **out,
struct ratbagd *ctx,
const char *sysname,
const char *id,
struct ratbag_device *lib_device);
struct ratbagd_device *ratbagd_device_free(struct ratbagd_device *device);
const char *ratbagd_device_get_id(struct ratbagd_device *device);
const char *ratbagd_device_get_sysname(struct ratbagd_device *device);
const char *ratbagd_device_get_path(struct ratbagd_device *device);
unsigned int ratbagd_device_get_num_buttons(struct ratbagd_device *device);