USB driver for LINUX operating systems using LKM
First part displays info about the pen drive on the kernel log. The second part will read and write to the USB device via the device file.
I have used Loadable kernel module (LKM). LKMs are pieces of kernel code which are not complied into in the kernel, but they are instead linked to the kernel once they are loaded. When the module is loaded it prints to log file letting you know that the model was either successfully or unsuccessfully loaded into the kernel. Once successfully loaded the module then registers a device driver and a listener to tell if a USB device is plugged into a USB port. When a device is plugged in to the port, the module registers the device, also giving the device its ID, and prints to the log file that a device has been plugged in. After the device is removed from the port, the module attempts to unregister the device, then writes to log file if the device was unregistered successfully or not. The log file is located in var/log/message folder.
The most basic form of USB communication is through something called an endpoint. The below figure shows a typical snippet of USB device specifications for devices connected on a system. To be specific, the “E: ” lines in the figure shows example of an interrupt endpoint of a UHCI Host Controller and two bulk endpoints of the pen drive under consideration. Also, the endpoint numbers (in hex) are respectively 0x81, 0x02. The MSB of the first and third being 1 indicating “in” endpoints, represented by “(I)” in the figure. Second one is an “(O)” for the “out” endpoint.
<linux/usb.h>
):int usb_register(struct usb_driver *driver);
void usb_deregister(struct usb_driver *);
int (*probe)(struct usb_interface *interface, const struct usb_device_id *id);
void (*disconnect)(struct usb_interface *interface);
struct usb_device device = interface_to_usbdev(interface);
pen_info.c
pen_write()
and pen_read()
below shows the possible calls to usb_bulk_msg()
(prototyped in <linux/usb.h>
) to do the transfers over the pen drive’s bulk end points 0x81 and 0x02, respectively.
make
The module is compiled to .ko file
The driver was loaded using insmod pen_driver.ko
. The pen drive was plugged in (after making sure that the usb-storage driver is not already loaded). Checking for the dynamic creation of /dev/pen0
(0 being the minor number obtained – check dmesg logs for the value on your system) was implemented. write/read
operations were performed on /dev/pen0
. The desired output was seen. And hence, the pen drive was plugged out and the driver was unloaded using rmmod pen_driver
.
lsmod
show the kernel log
dmesg
show info about module
modinfo pen_driver.ko
Through out this project we learned that loading LKMs while the kernel is running is more efficient for modules that are not used on a normal basis. This way the module does not have to be manually loaded every power up. Depending on the functionality and the number of times it may be needed should determine whether to compile the module with the kernel or to load it.
The significant advantages of LKMs have proven itself to be desired and many operating systems support them, although may be called something different depending on the system. Although they may not be the best solution in every case, it is a very popular technic. Most device driver use LKMs to tell the controller how to communicate and interact with the device.
This project was done as a learning excercise
The project is based on :
https://sysplay.github.io/books/LinuxDrivers/book/index.html