0

I am trying to write a simple Linux USB mouse driver, and I've run into a problem with actually getting the information from the mouse to the module.

Right now I have a kernel module that can be successfully loaded into the kernel. The module is a character device, and I can access this device via the /dev/mymodule file, writing and reading from it calls the functions I implemented.

However, I don't understand how to feed the data coming from my mouse to this character driver. The mouse has a separate file in /dev/input that I can read from, and, when looking at the mouse's entry at /sys/bus/hid/devices/ I can see that the mouse uses the hid-generic driver (and works like an actual mouse).

How can I make the mouse use the character device driver? (preferably this exact mouse and not any others connected to my PC). I feel like I'm misunderstanding something fundamental.

Things I've tried that didn't work:

  • Adding MODULE_ALIAS(<content of /sys/bus/hid/devices/<mouse>/modalias>) to the module source.
  • Adding MODULE_DEVICE_TABLE as follows:
static struct hid_device_id mod_table [] = {
        {HID_USB_DEVICE(1532, 0043)},
        {}
};

MODULE_DEVICE_TABLE(hid, mod_table);

In both cases aliases appeared in the module.alias after depmod, but they don't seem to do anything.

Another thing I tried is unbinding the generic driver, but I don't know what to bind the mouse to for my character driver. Do I need to implement something else for this case?

Any help would be appreciated.

1 Answer 1

0

I recently encountered this issue as well. I assume you registered a struct usb_driver driver in your module, and not an hid_driver? Edit: Oops I somehow missed that you were writing a char driver.

If you look at the source code of linux/drivers/hid/hid-generic.c (the driver that is being checked for compatibility before any custom drivers), you can see that it calls the bus_for_each_drv macro in its match function. It loops through every driver registered for the given bus (hid_bus_type in this case), and checks whether the hid_device struct instance representing the recently plugged-in device matches the ids in the driver's id table (its hid_device_id table).

The important part here is that if your driver is not registered as an hid_driver, it will not be included in this loop, even if you supply an hid_device_id table in addition and create a module alias. You can easily check this yourself by writing a simple kernel module that calls the same bus_for_each_drv macro and passing a callback function that simply prints the drv->name string for each driver it loops through. Here is a simple example:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/hid.h>

MODULE_LICENSE("GPL");

static int __print_driver_name(struct device_driver *drv, void *data)
{
        printk("%s", drv->name);
        return 0;
}

static int __init init_list_hid_drivers(void)
{
        printk("list_hid_drivers module loaded. Drivers:\n");
        bus_for_each_drv(&hid_bus_type, NULL, NULL, __print_driver_name);

        return 0;
}

static void __exit exit_list_hid_drivers(void)
{
        printk("list_hid_drivers module unloaded");
}

module_init(init_list_hid_drivers);
module_exit(exit_list_hid_drivers);                                         

You can use the hid-generic.c driver as a template for a very simple hid_driver implementation.

As far as I can see from a quick glance at the hid_device_probe function in linux/drivers/hid/hid-core.c, the only way to assign some non-HID driver, e.g. a usb_driver to an HID device is to bind a specific driver to your device, which should avoid having to go through any of these matching procedures, but I might be wrong about this.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .