diff --git a/README.md b/README.md index ad58b64..1cf2fe9 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,17 @@ Manage the settings of your keyboard, mouse, ... with a simple GUI. This is for the internal settings of your devices, not for the OS settings. For example, you can change the mouse DPI, polling rate, rgb, ... +## Driver interface + +Drivers **must** expose the following symbols: +```c +void driver_init(); // Initialization +uint32_t driver_getkey(); // Calls to this function must return USB keys that this driver registers, until 0 +char* driver_get_name(); // Returns peripheral name +char* driver_get_image(); // Returns peripheral image +device_type_t driver_get_type(); // Returns device type + +// Mouse drivers + +``` + diff --git a/src/device/usb/usb.c b/src/device/usb/usb.c index fc98aef..80fcfc4 100644 --- a/src/device/usb/usb.c +++ b/src/device/usb/usb.c @@ -1,20 +1,84 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "device/device.h" +#include "utils/hashmap.h" + +hashmap_t* usb_drivers; + +void usb_drivers_init() +{ + // Initialize hashmap + usb_drivers = hashmap_alloc(); + + // Obtain current executable path + char exe_path[PATH_MAX]; + readlink("/proc/self/exe", exe_path, PATH_MAX); + + char* path = dirname(exe_path); + size_t path_len = strlen(path); + + char driver_path[PATH_MAX]; + memcpy(driver_path, path, path_len); + memcpy(driver_path + path_len, "/drivers/", 10); + + // Open driver directory and load all symbols + DIR* directory = opendir(driver_path); + if(!directory) + { + fprintf(stderr, "Error: Could not open '%s' directory\n", driver_path); + return; + } + + printf("Opened drivers directory: %s\n", driver_path); + + struct dirent* entry; + while((entry = readdir(directory))) + { + if(entry->d_type & DT_DIR) continue; + + size_t entry_name_len = strlen(entry->d_name); + + char fullpath[PATH_MAX]; + memcpy(fullpath, driver_path, path_len + 9); + memcpy(fullpath + path_len + 9, entry->d_name, entry_name_len); + *(fullpath + path_len + 9 + entry_name_len) = 0; + + void* driver = dlopen(fullpath, RTLD_LAZY | RTLD_LOCAL); + void (*init_fn)(void) = dlsym(driver, "driver_init"); + init_fn(); + + uint32_t (*getkey_fn)(void) = dlsym(driver, "driver_getkey"); + uint32_t key; + while((key = getkey_fn())) + hashmap_put(usb_drivers, key, driver); + } + + closedir(directory); +} void usb_init() { - // List all usb devices obtaining 'vendor:product' - // Call corresponding driver if it exists, so - // that we get a peripheral handle + // Init drivers + usb_drivers_init(); + + // Init libusb if(libusb_init(NULL)) { fprintf(stderr, "Error: Could not initialize libusb\n"); return; } + // List all usb devices obtaining 'vendor:product' + // Call corresponding driver if it exists, so + // that we get a peripheral handle libusb_device** list; ssize_t device_count = libusb_get_device_list(NULL, &list); if(device_count <= 0) return; @@ -28,5 +92,13 @@ void usb_init() printf("Found usb device %04x:%04x\n", desc.idVendor, desc.idProduct); array_t* array = device_get_array(); array_add(array, 0); + + libusb_device_handle* handle; + libusb_open(current, &handle); + char buf[4096] = {0}; + libusb_get_string_descriptor_ascii(handle, 1, buf, 4096); + printf("Device desc (1): %s\n", buf); + libusb_get_string_descriptor_ascii(handle, 2, buf, 4096); + printf("Device desc (2): %s\n", buf); } } diff --git a/src/utils/hashmap.c b/src/utils/hashmap.c new file mode 100644 index 0000000..57035a1 --- /dev/null +++ b/src/utils/hashmap.c @@ -0,0 +1,76 @@ +#include "hashmap.h" +#include + +#define HASHMAP_ARRAY_SIZE 512 + +struct HASHMAP_ENTRY +{ + uint32_t key; + void* elem; + struct HASHMAP_ENTRY* next; +}; + +struct HASHMAP +{ + struct HASHMAP_ENTRY** array; +}; + +size_t _hashmap_hash(uint32_t key) +{ + return key % HASHMAP_ARRAY_SIZE; +} + +hashmap_t* hashmap_alloc() +{ + hashmap_t* tr = malloc(sizeof(hashmap_t)); + tr->array = calloc(sizeof(struct HASHMAP_ENTRY*), HASHMAP_ARRAY_SIZE); + return tr; +} + +void hashmap_free(hashmap_t* hashmap) +{ + for(size_t i = 0; i < HASHMAP_ARRAY_SIZE; i++) + { + struct HASHMAP_ENTRY* current = hashmap->array[i]; + + while(current) + { + struct HASHMAP_ENTRY* old = current; + current = current->next; + free(old); + } + } + + free(hashmap->array); + free(hashmap); +} + +void hashmap_put(hashmap_t* hashmap, uint32_t key, void* elem) +{ + size_t index = _hashmap_hash(key); + struct HASHMAP_ENTRY** current = &hashmap->array[index]; + + while(*current) + { + current = &(*current)->next; + } + + (*current) = malloc(sizeof(struct HASHMAP_ENTRY)); + (*current)->key = key; + (*current)->elem = elem; + (*current)->next = 0; +} + +void* hashmap_get(hashmap_t* hashmap, uint32_t key) +{ + size_t index = _hashmap_hash(key); + struct HASHMAP_ENTRY* current = hashmap->array[index]; + + while(current) + { + if(current->key == key) return current->elem; + current = current->next; + } + + return 0; +} diff --git a/src/utils/hashmap.h b/src/utils/hashmap.h new file mode 100644 index 0000000..133cdd4 --- /dev/null +++ b/src/utils/hashmap.h @@ -0,0 +1,15 @@ +#ifndef HASHMAP_H +#define HASHMAP_H + +#include +#include + +typedef struct HASHMAP hashmap_t; + +hashmap_t* hashmap_alloc(); +void hashmap_free(hashmap_t* hashmap); + +void hashmap_put(hashmap_t* hashmap, uint32_t key, void* elem); +void* hashmap_get(hashmap_t* hashmap, uint32_t key); + +#endif