4

I am writing a small simple driver module for a LED badge. I followed a couple of tutorials and references to do the job. All of them seem to imply that the module will be automatically loaded when the device is plugged in. However, when I run usb-devices the corresponding device has driver Driver=usbfs.

I have another terminal doing a follow on dmesg and it is at no point spitting out any of my debug messages. When I try to connect and disconnect this is what shows up:

[36078.726962] usb 1-2: USB disconnect, device number 24
[36080.925619] usb 1-2: new full-speed USB device number 25 using xhci_hcd
[36081.067062] usb 1-2: New USB device found, idVendor=0483, idProduct=5750
[36081.067067] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[36081.067071] usb 1-2: Product: CHW20160112 HID
[36081.067075] usb 1-2: Manufacturer: Chuanghongweitech1
[36081.068695] input: Chuanghongweitech1 CHW20160112 HID as /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/0003:0483:5750.0018/input/input40
[36081.069072] hid-generic 0003:0483:5750.0018: input,hidraw2: USB HID v1.10 Device [Chuanghongweitech1 CHW20160112 HID] on usb-0000:00:14.0-2/input0

My module does unload/load if I issue a sudo insmod ledbadge_drv.ko (rmmod for unload) with this output to the log:

[36216.554620] ledbadge:, Unloading module. Handler: ledbadge_exit
[36216.554620] ledbadge:, Attempting to deregister USB device.
[36216.554621] usbcore: deregistering interface driver ledbadge
[36216.554647] ledbadge:, Leaving module!
[36217.632615] ledbadge:, Loading module. Handler: ledbadge_init
[36217.632616] ledbadge:, Attempting to register USB device.
[36217.632636] usbcore: registered new interface driver ledbadge

The module's code is as follows:

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



#define LEDBADGE_VENDOR_ID  0x0483
#define LEDBADGE_PRODUCT_ID 0x5750
#define LEDBADGE_MOD_NAME   "ledbadge"
#define LEDBADGE_DRV_NAME   "ledbadge"


/************* usb operations *************/

/* 
    ledbadge_probe

        called when plugging the USB device */


static int ledbadge_probe(struct usb_interface *interface, const struct usb_device_id *id)
{   
    printk(KERN_NOTICE "Led Badge driver (%04X: %04X) plugged \n", id->idVendor, id->idProduct);
    return 0;
}


/* 
    ledbadge_disconnect

        called when unplugging the USB device */

static void ledbadge_disconnect(struct usb_interface *interface) 
{
    printk(KERN_NOTICE "%s:, ledbage USB device removed", LEDBADGE_DRV_NAME);
}




/************* usb driver *************/

// information required to recognize the device

static struct usb_device_id ledbadge_table [] = {
    {USB_DEVICE(LEDBADGE_VENDOR_ID, LEDBADGE_PRODUCT_ID)},
    { }, // terminating entry
};
MODULE_DEVICE_TABLE(usb, ledbadge_table);


static struct usb_driver ledbadge_driver = {
    .name = LEDBADGE_DRV_NAME,
    .id_table = ledbadge_table,
    .probe = ledbadge_probe,
    .disconnect = ledbadge_disconnect,
};








/************** module definition **************/

/* ledbadge_init

        caled on module loading */

static int __init ledbadge_init(void) 
{
    int ret = -1; 

    printk(KERN_NOTICE "%s:, Loading module. Handler: %s",
             LEDBADGE_MOD_NAME, __FUNCTION__); 

    printk(KERN_NOTICE "%s:, Attempting to register USB device.", LEDBADGE_MOD_NAME); 

    // attempt to register usb device
    ret = usb_register(&ledbadge_driver);

    // log dmesg of status
    if(ret == 0) printk(KERN_NOTICE "%s:, Device registered!", LEDBADGE_MOD_NAME);
    else         printk(KERN_ERR    "%s:, Device registration failed > %d", LEDBADGE_MOD_NAME, ret);

    return ret; 
}

/* ledbadge_exit

        caled on module unloading */

static void __exit ledbadge_exit(void) 
{
    printk(KERN_NOTICE "%s:, Unloading module. Handler: %s",
             LEDBADGE_MOD_NAME, __FUNCTION__); 

    printk(KERN_NOTICE "%s:, Attempting to deregister USB device.", LEDBADGE_MOD_NAME); 

    // attempt to deregister usb device
    usb_deregister(&ledbadge_driver);

    // log dmesg of status
    printk(KERN_NOTICE "%s:, Leaving module!", LEDBADGE_MOD_NAME);
}

module_init(ledbadge_init);
module_exit(ledbadge_exit); 

MODULE_LICENSE("GPL"); 
2
  • 1
    Maybe the other module is probably entering first (the dmesg shows something like a module handling your device)... Try to see how to blacklist them in your distro, so your module can assume the control of the hardware. Commented Apr 26, 2018 at 19:20
  • I haven't tried blacklisting the module, although read something about it. However, is it plausible to expect another solution? My distro might be using the blacklisted module to handle some other device.
    – dacabdi
    Commented Apr 26, 2018 at 19:22

1 Answer 1

5

Have you placed your module in the /lib/modules/<your kernel version> directory tree and run depmod after that?

If so, then in the /lib/modules/<your kernel version>/modules.alias file should be a line like this:

alias usb:v0483p5750d*dc*dsc*dp*ic*isc*ip*in* ledbadge

When the kernel sees a new USB device, it reads its vendor and product IDs and a number of other attributes, and uses those as components for a systematically-created module alias name like above. Then the kernel causes the modprobe command to be executed (actual mechanism for that has varied somewhat in the history of Linux 2.6 and above) with that alias name. If modprobe finds an alias definition that matches it, then the module listed in that alias definition gets loaded.

I think the matching happens in such a way that the most specific match will win. Currently it looks like the hid-generic module might be winning over your module (assuming that you've run depmod after installing your module), so your ledbadge device might be a USB HID class device. So you might need to also/instead declare a USB HID device alias. Something like this:

static const struct hid_device_id ledbadge_hid_table[] = {
        {HID_USB_DEVICE(LEDBADGE_VENDOR_ID,LEDBADGE_PRODUCT_ID)},
        { } // terminating entry
};

MODULE_DEVICE_TABLE(hid, ledbadge_hid_table);

The resulting line in the modules.alias file should be like:

alias hid:b0003g*v00000483p00005750 ledbadge
2
  • so a module's constructor is called after the containing device's probe method? if i am correct Commented Jul 16, 2020 at 4:17
  • 1
    A module's constructor is called when a module is loaded. It will only happen once, and should be independent of whether you have zero, one or more than one instaces of the hardware your driver module is supposed to handle. It is a side effect of loading the module, and not directly associated with device probing at all.
    – telcoM
    Commented Jul 16, 2020 at 6:12

You must log in to answer this question.

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