aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2021-03-06 19:39:51 +0100
committercbdev <cb@cbcdn.com>2021-03-06 19:39:51 +0100
commite2b1110bca5b2b208657a733a91fd713e5c38b71 (patch)
treeed2e392a705b8ac5be0e54c2b30601ad52fdad89
parentb199f019b47829f3745e8af8e62ed1ac4e65acf9 (diff)
downloadmidimonster-e2b1110bca5b2b208657a733a91fd713e5c38b71.tar.gz
midimonster-e2b1110bca5b2b208657a733a91fd713e5c38b71.tar.bz2
midimonster-e2b1110bca5b2b208657a733a91fd713e5c38b71.zip
Fix prefix-matching for evdev input names (#85)
-rw-r--r--backends/evdev.c27
-rw-r--r--backends/evdev.md3
2 files changed, 17 insertions, 13 deletions
diff --git a/backends/evdev.c b/backends/evdev.c
index 3dbf837..8f7c4f9 100644
--- a/backends/evdev.c
+++ b/backends/evdev.c
@@ -113,12 +113,14 @@ static int evdev_attach(instance* inst, evdev_instance_data* data, char* node){
static char* evdev_find(char* name){
int fd = -1;
struct dirent* file = NULL;
- char file_path[PATH_MAX * 2];
+ char file_path[PATH_MAX * 2], *result = calloc(PATH_MAX * 2, sizeof(char));
DIR* nodes = opendir(INPUT_NODES);
- char device_name[UINPUT_MAX_NAME_SIZE], *result = NULL;
+ char device_name[UINPUT_MAX_NAME_SIZE];
+ size_t min_distance = -1, distance = 0;
if(!nodes){
LOGPF("Failed to query input device nodes in %s: %s", INPUT_NODES, strerror(errno));
+ free(result);
return NULL;
}
@@ -141,20 +143,23 @@ static char* evdev_find(char* name){
close(fd);
if(!strncmp(device_name, name, strlen(name))){
- LOGPF("Matched name %s for %s: %s", device_name, name, file_path);
- break;
+ distance = strlen(device_name) - strlen(name);
+ LOGPF("Matched name %s as candidate (distance %" PRIsize_t ") for %s: %s", device_name, distance, name, file_path);
+ if(distance < min_distance){
+ strncpy(result, file_path, (PATH_MAX * 2) - 1);
+ min_distance = distance;
+ }
}
}
}
- if(file){
- result = calloc(strlen(file_path) + 1, sizeof(char));
- if(result){
- strncpy(result, file_path, strlen(file_path));
- }
- }
-
closedir(nodes);
+
+ if(!result[0]){
+ free(result);
+ return NULL;
+ }
+ LOGPF("Using %s for input name %s", result, name);
return result;
}
diff --git a/backends/evdev.md b/backends/evdev.md
index bf192b0..e7ba3cc 100644
--- a/backends/evdev.md
+++ b/backends/evdev.md
@@ -16,7 +16,7 @@ This functionality may require elevated privileges (such as special group member
| Option | Example value | Default value | Description |
|---------------|-----------------------|---------------|-------------------------------------------------------|
| `device` | `/dev/input/event1` | none | `evdev` device to use as input device |
-| `input` | `Xbox Wireless` | none | Presentation name of evdev device to use as input (prefix-matched), can be used instead of the `device` option |
+| `input` | `Xbox Wireless` | none | Presentation name of evdev device to use as input (most-specific prefix matched), can be used instead of the `device` option |
| `output` | `My Input Device` | none | Output device presentation name. Setting this option enables the instance for output |
| `exclusive` | `1` | `0` | Prevent other processes from using the device |
| `id` | `0x1 0x2 0x3` | none | Set output device bus identification (Vendor, Product and Version), optional |
@@ -49,7 +49,6 @@ If relative axes are used without specifying their extents, the channel will gen
of `0`, `0.5` and `1` for any input less than, equal to and greater than `0`, respectively. As for output, only
the values `-1`, `0` and `1` are generated for the same interval.
-
#### Channel specification
A channel is specified by its event type and event code, separated by `.`. For a complete list of event types and codes