Users can add or remove functionalities to the Linux kernel while the system is running. These “programs” that can be added to the kernel at runtime are called “module” and built into individual files with .ko (Kernel object) extension. A kernel module can be modified without need of recompiling the full kernel.
Linux driver modules can be found in: /lib/modules/<version>/kernel/drivers/ where <version> would be the output of the command uname -r on the system.
lsmod - List the available loaded modules.cat /proc/modules - List the available loaded modules.lsmod | egrep -v “\s0” - List loaded modules.insmod module - Load the module specified by module.modprobe module - Load the module along with its dependencies.rmmod module - Remove/Unload the module.modprobe module - Install kernel module.modprobe -rv module - Remove the module.modinfo module - Gives information about the module.modinfo -n module - Gives the path were the module files are located.
depmod command generates modules.dep and map files.
Linux kernel modules can provide services (called “symbols”) for other modules to useusing one of the EXPORT_SYMBOL variants in the code). If a second module uses thissymbol, that second module clearly depends on the first module. These dependencies can getquite complex.
depmod creates a list of module dependencies by reading each module underlib/modules/version and determining what symbols it exports and what symbols it needs. By default, this list is written to modules.dep, and a binary hashed version namedmodules.dep.bin, in the same directory.
A device driver contains at least two functions:
These are specified as the init and exit functions, respectively, by the macros module_init() and module_exit(), which are defined in the kernel header module.h.
# include <linux/module .h >
# include <linux/version .h >
# include <linux/kernel .h >
static int __init init_mod ( void ) /* Constructor */
{
printk ( KERN_INFO " Module1 started ...\ n ");
return 0;
}
static void __exit end_mod ( void ) /* Destructor */
{
printk ( KERN_INFO " Module1 ended ...\ n ");
}
module_init ( init_mod );
module_exit ( end_mod );
MODULE_LICENSE (" GPL ");
MODULE_AUTHOR (" Uppsala University ");
MODULE _DESCRIPTION (" Test Driver Module ");
It's required that the MODULE_LICENSE macro receives a GPL license.
To build a module or driver, you need to have the kernel source (or, at least, the kernel headers) installed on your system. The kernel source is assumed to be installed at /usr/src/linux. If it’s at any other location on your system, specify the location in the KERNEL_SOURCE variable in the Makefile.
Example of Makefile:
MOD_NAME := veikk BUILD_DIR := /lib/modules/$(shell uname -r)/build obj-m := $(MOD_NAME).o all: make -C $(BUILD_DIR) M=$(CURDIR) modules chmod +x ./config.sh clean: make -C $(BUILD_DIR) M=$(CURDIR) clean install: make -C $(BUILD_DIR) M=$(CURDIR) modules_install depmod modprobe veikk uninstall: modprobe -r $(MOD_NAME) rm $(shell modinfo -n veikk) depmod
With this Makefile the commands would be:
For install:
make sudo make install clean
For uninstall:
sudo make uninstall
printk() is the equivalent of printf() for kernel modules.
pr_*() functions are the same as plain printk(), but with the KERN_xxx log level already included.
dev_*() functions (like dev_alert or dev_info) are the same as the corresponding pr_*() functions, but also print identifying information about the struct device.
dev_info(&hdev->dev, "VEIKK A15 has been attached\n"); dev_alert(&hdev->dev, "It failed on allockating memory for the VEIKK A15\n");
kzalloc() allocates kernel memory like kmalloc(), but it also zero-initializes the allocated memory. devm_kzalloc() is managed kzalloc(). The memory allocated with managed functions is associated with the device. When the device is detached from the system or the driver for the device is unloaded, that memory is freed automatically.
The memory allocated with kzalloc() should be freed with kfree(). The memory allocated with devm_kzalloc() is freed automatically. It can be freed with devm_kfree().
hid_set_drvdata
Will set on the data property from the hdev the passed value.
hid_parse(hdev)
Required to be called after setting up the device. It parses a report description of the device and populate fields of the HID device struct (necessary for hid_hw_start()).
For device memory allocations there is also a “group” concept. Groups can be thought of as markers in the stream of allocations associated with a given device. The allocations performed within a specific group can be rolled back without affecting any others. In brief, the group API is:
void *devres_open_group(struct device *dev, void *id, gfp_t gfp);
void devres_close_group(struct device *dev, void *id);
void devres_remove_group(struct device *dev, void *id);
int devres_release_group(struct device *dev, void *id);
Cuando enchufamos un dispositivo USB lo que nos aparece por pantall en la salida de dmesg es algo parecido a esto:
[24343.392476] input: VEIKK.INC A15 as /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/0003:2FEB:0004.0007/input/input23 [24343.392675] hid-generic 0003:2FEB:0004.0007: input,hidraw3: USB HID v1.00 Mouse [VEIKK.INC A15] on usb-0000:00:14.0-2/input0 [24343.393665] input: VEIKK.INC A15 as /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.1/0003:2FEB:0004.0008/input/input24 [24343.453812] hid-generic 0003:2FEB:0004.0008: input,hidraw4: USB HID v1.00 Keyboard [VEIKK.INC A15] on usb-0000:00:14.0-2/input1 [24343.454684] hid-generic 0003:2FEB:0004.0009: hiddev1,hidraw5: USB HID v1.00 Device [VEIKK.INC A15] on usb-0000:00:14.0-2/input2
Para desvincular el driver por defecto para este dispositivo, por ejemplo, escogeremos el “mouse” escribiendo en unbind:
echo -n "0003:2FEB:0004.0007" > /sys/bus/hid/drivers/hid-generic/unbind
Para vincularlo:
echo -n "0003:2FEB:0004.0007" > /sys/bus/hid/drivers/veikk/bind
Reference: https://lwn.net/Articles/143397/
Tutorial for creating a driver for a virtual char device. It creates that device using mknod command and accesses it using the driver.
https://s3.wasabisys.com/my-files/public/tutorial-DD.pdf
To see all registered inputs:
xinput
To map a xinput with a display (xrandr will give you the display id):
xinput map-to-output <registered input id> <display id> xinput map-to-output 22 HDMI-1-1
To detect your USB device, in a terminal, you can try:
lsusb , example: $ lsusb Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 001 Device 002: ID 046d:0809 Logitech, Inc. Webcam Pro 9000 Bus 003 Device 002: ID 046d:c016 Logitech, Inc. Optical Wheel Mouse
or this powerful tool, lsinput , 1st install it, and then try it, it lists all input devices including your USB device :
$ sudo apt-get install input-utils $ lsinput /dev/input/event0 ... /dev/input/event1 ... /dev/input/event2 ... /dev/input/event3 bustype : BUS_USB vendor : 0x46d product : 0xc016 version : 272 name : "Logitech Optical USB Mouse" phys : "usb-0000:00:1d.1-2/input0" uniq : "" bits ev : EV_SYN EV_KEY EV_REL EV_MSC
udevadm , with this command line, you need to unplug the device before using the command and then plug it to see it:
$ udevadm monitor --udev monitor will print the received events for: UDEV - the event which udev sends out after rule processing UDEV [1915.787445] add /devices/pci0000:00/0000:00:1d.3/usb5/5-2 (usb) UDEV [1915.796226] add /devices/pci0000:00/0000:00:1d.3/usb5/5-2/5-2:1.0 (usb)