Udev tutorial 2
Published:
Automating USB Kernel Module Loading with Udev and MODALIAS in Linux
The first blog page defines udev rules to match a plugged-in device and trigger a shell script to insert a kernel module that enables ARM performance accounting. In this post, I’ll demonstrate how to embed USB device information directly into the kernel module so that when the USB stick is plugged in, the kernel module will automatically load. The general idea comes from this source.
Every device driver/kernel module carries a list of known aliases for devices it can handle. The list is contained in the kernel module file itself. The program depmod reads the ID lists and creates the file modules.alias in the kernel’s /lib/modules directory for all currently available modules. With this infrastructure, module loading is as easy as calling modprobe for every event that carries a MODALIAS key. If modprobe $MODALIAS is called, it matches the device alias composed for the device with the aliases provided by the modules. If a matching entry is found, that module is loaded. All this is automatically triggered by udev.
Drivers, Kernel Modules and Devices
Define device IDs in Kernel Module
You must define the specific USB device IDs that your custom kernel module will handle. This is done using a usb_device_id
table in your module.
#include <linux/usb.h>
#include <linux/module.h>
const uint16_t VENDOR_ID = 0x0951;
const uint16_t PRODUCT_ID = 0x1666;
/* Define USB device ID table */
static const struct usb_device_id my_usb_table[] = {
{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, // Replace VENDOR_ID and PRODUCT_ID with your device's values
{ } /* Terminating entry. this is the end of the array, so it doesn't try to process beyond this point*/
};
MODULE_DEVICE_TABLE(usb, my_usb_table);
VENDOR_ID
and PRODUCT_ID
are the hexadecimal values specific to your USB device. This can be found by lsusb. For more Data fields of usb_device_id, check mod_devicetable.h
Bus 002 Device 004: ID 0951:1666 Kingston Technology DataTraveler 100 G3/G4/SE9 G2
Register USB Driver
register your kernel module as a USB driver that will bind to devices matching the specified device IDs. You can do this by creating and registering a usb_driver
structure
/* Probe function: called when the device is connected */
static int my_usb_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
printk(KERN_INFO "My custom USB device is connected\n");
// Initialization code here
return 0;
}
/* Disconnect function: called when the device is disconnected */
static void my_usb_disconnect(struct usb_interface *interface)
{
printk(KERN_INFO "My custom USB device is disconnected\n");
// Cleanup code here
}
static struct usb_driver my_usb_driver = {
.name = "my_custom_usb_driver",
.id_table = my_usb_table, // Referencing the ID table defined earlier
.probe = my_usb_probe, // Function called when the device is plugged in
.disconnect = my_usb_disconnect, // Function called when the device is unplugged
};
/* Register the USB driver */
static int __init my_usb_init(void)
{
return usb_register(&my_usb_driver);
}
/* Deregister the USB driver */
static void __exit my_usb_exit(void)
{
usb_deregister(&my_usb_driver);
}
module_init(my_usb_init);
module_exit(my_usb_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Custom USB Driver Module");
This code sets up your module to handle the following:
- The
probe
function is executed when the USB device is connected. - The
disconnect
function is executed when the USB device is unplugged. usb_register()
andusb_deregister()
handle registering and deregistering your custom driver.
Build
Makefile
obj-m += my_usb_driver.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
make
sudo insmod my_usb_driver.ko
Update modules.alias
To automate the loading of your module using modprobe
. Firstly, ensure that your module is installed and properly located in
ls /lib/modules/$(uname -r)/kernel/drivers/usb/my_usb_driver.ko
Then
`sudo depmod -a`
- This updates the
/lib/modules/$(uname -r)/modules.alias
file to include the new device aliases. - When your USB device is connected,
udev
will trigger aMODALIAS
event, andmodprobe
will load your custom kernel module if the alias matches.
How do I know if modules.alias contains the new device aliases?
$ grep my_usb_driver /lib/modules/$(uname -r)/modules.alias
alias usb:v0951p1666d*dc*dsc*dp*ic*isc*ip*in* usb_mod
Once you plug your USB device. use lsmod
to find if the kernel module is loaded successfully.
$ lsmod
usb_mod 16384 0
Link to the code repo
https://github.com/lizeren/rasp-udev