Which drivers are used by usb mouse in linux kernel? - linux

I read from LDD3 chapter 14 about hotplug drivers.I need to write a usb mouse driver which load when I plug the hardware. Now, doing some experiment I come to know that there is a driver named "hid-generic" which is called when plug-unplug.
[ 6654.232046] usb 3-1: new low-speed USB device number 3 using uhci_hcd
[ 6654.462061] usb 3-1: New USB device found, idVendor=093a, idProduct=2510
[ 6654.462067] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 6654.462071] usb 3-1: Product: USB OPTICAL MOUSE
[ 6654.462074] usb 3-1: Manufacturer: PIXART
[ 6654.489316] input: PIXART USB OPTICAL MOUSE as /devices/pci0000:00/0000:00:1d.1/usb3/3-1/3-1:1.0/input/input12
[ 6654.489445] hid-generic 0003:093A:2510.0004: input,hidraw0: USB HID v1.10 Mouse [PIXART USB OPTICAL MOUSE] on usb-0000:00:1d.1-1/input0
Also lsmod shows,
Module Size Used by
hid_generic 12541 0
usbhid 47259 0
hid 105241 2 hid_generic,usbhid
psmouse 102541 0
My doubts are as follows,
1) To make my module load (hotplug) when this mouse plugs in, I have to disable these 3 drivers in kernel and build whole kernel with my driver with vendor and device ID in id_table. Right?
2) I also read about USB core drivers and USB device drivers. So these HID drivers are core drivers or device drivers?
3) Which are core drivers and device driver in case of USB mouse? And where can I find them in kernel source?
Thanks,
Sunil.

I'll try to answer your questions one by one :
1) To make my module load (hotplug) when this mouse plugs in, I have to disable these 3 drivers in kernel and build whole kernel with my driver with vendor and device ID in id_table. Right?
Yes, but there are some additional things you need to take care of. First understand how a particular module(driver) gets loaded. The key to this is MODULE_DEVICE_TABLE(usb, &my_id_table); Whenever a particular module is "installed" (using make modules_install), an entry, according to the id table passed in MODULE_DEVICE_TABLE gets created in /lib/modules/<your_kernel>/modules.usbmap and /lib/modules/<your_kernel>/modules.dep file(search for the string "usbhid" in the files). Whenever a new usb device is detected, the kernel reads these files to find the matching parameters. If it is found, the following module is loaded from the corresponding path found in /lib/modules/<your_kernel>/modules.dep which holds the info. about the path where the driver is located and also its dependencies.
So, now even if you unload(rmmod) usbhid from the kernel, it will be loaded again when you re-insert your mouse. To avoid this from happening you need to modify those files, i.e. remove the entries from the files. To do so, "move" the usbhid driver from its original path(generally located at /lib/modules/<your_kernel>/kernel/drivers/hid/usbhid/usbhid.ko to a safe place. Now rebuild the dependencies such that the entries would be removed from the dependency files.
Now you need to create entries of your driver. Just install your driver and you are good to go!
So, to summarize :
$ sudo rmmod usbhid # Unload the usb mouse driver
$ cd /lib/modules/$(uname -r)/ # Move to your current kernel
$ vim modules.usbmap # Check for the "usbhid" string
$ vim modules.dep # Check for "usbhid.ko:" string
$ sudo mv kernel/drivers/hid/usbhid/usbhid.ko ~/Desktop # Take backup of your current
usb mouse driver
$ sudo depmod -a # Rebuild the dependency files
Now check the dependency files for the string "usbhid" again. It shouldn't be there!
$ cd /path/to/your/driver
$ sudo make modules_install # Install your driver into /lib/modules/$(uname -r)/extra
$ sudo depmod -a # Rebuild the dependency files
After this step, search for the string corresponding to your module in the dependency files, and it should be there! From this moment on, whenever you insert the mouse(or from boot itself) your driver will be loaded, instead of the original.
Once your are done playing with your driver, you may copy back the original usbhid file to its original destination and rebuild the dependency files (sudo depmod -a)
Now I also see that you are trying to use vendor and device id to match your device, in which case, the driver would work only for your mouse. The recommended way is to use class ids, which makes your driver work for any usb mouse.
2) I also read about USB core drivers and USB device drivers. So these HID drivers are core drivers or device drivers?
usbhid is basically a "device driver". The classification of drivers could be briefed out as : core drivers, host controller drivers and device drivers :
Device Drivers : This is the software used to control the devices. For example usb mouse, pci based ethernet card, usb pendrive, i2c based accelerometer.
Host Controller Drivers : This is the software written to control the bus controller. For example USB Host Controllers(EHCI, UHCI, OHCI, etc.), PCI Host Controller, I2C Masters, etc.
Core Drivers : These actually glues up the above discussed drivers. Examples are USB core, PCI core, etc. Core drivers provides helper routines(APIs) such that the device and host-controller driver could make use of them(concept of module stacking!). These are the ones, which bind the correct device to its driver. There are many other services provided by the core drivers.
Example code for USB Device Driver :
http://lxr.free-electrons.com/source/drivers/hid/usbhid/usbmouse.c
You may find the USB Host Controller Drivers under :
http://lxr.free-electrons.com/source/drivers/usb/host/
USB Core resides here : http://lxr.free-electrons.com/source/drivers/usb/core/
I think this also answers your third question!
Hope this helped.

The device driver is usbhid.
To prevent it from attaching to your device, add a HID_QUIRK_IGNORE entry to drivers/hid/usbhid/hid-quirks.c, or use the quirks parameter of the usbhid module.

Related

How to load and unload linux drivers that are built into kernel

I want to load and unload linux drivers in the device terminal,and I have two options but I do not want to do the first one
Build driver as a module
CONFIG_DRIVER = m
and I can use rmmod and modprobe to unload and load device driver.
Build device driver into kernel itself
CONFIG_DRIVER = Y
I want to follow the 2nd option but I do not know how to unload and load the device driver, can the open source community please help me out here !
It's easy as that. You find a device and driver which you want to unbind. For example, on my Intel Minnownboard (v1) I have PCH UDC controller (a PCI device):
% lspci -nk
...
02:02.4 0c03: 8086:8808 (rev 02)
Subsystem: 1cc8:0001
Kernel driver in use: pch_udc
Now I know necessary bits:
bus on which the device is located: PCI
device name: 0000:02:02.4 (note that lspci gives reduced PCI address, i.e. without domain or i.o.w. BDF, while driver expects domain:BDF)
driver name: pch_udc
Take altogether we can unbind the device:
% echo 0000:02:02.4 > /sys/bus/pci/drivers/pch_udc/unbind
[ 3042.531872] configfs-gadget 0000:02:02.4: unregistering UDC driver [g1]
[ 3042.540979] udc 0000:02:02.4: releasing '0000:02:02.4'
You may bind it again. Simple use bind node in the same folder.
The feature appeared more than 15 years ago and here is the article on LWN that explains it.

Raspberry Pi Zero USB device emulation

I know that the Raspberry Pi Zero supports OTG and USB Peripheral protocols, and there's a lot of cool built in peripherals shown here: https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget?view=all#other-modules
The problem is that I need to emulate a USB Peripheral device that does not appear on this list. I have a vendor ID and product ID for the device, and I'm trying to figure out how exactly to go about doing this. Do I need to modify the OTG USB drivers in the Raspbian kernel? Do I have to completely build my own kernel? Or is there a better option I don't even realize?
Thanks in advance!!
Do I need to modify the OTG USB drivers in the Raspbian kernel?
The answer to your first question is "it depends", but if your device
doesn't do anything too unusual this could be a No: you need not
modify source code for kernel modules nor the kernel.
You're fortunate that Raspbian supports a modern kernel with ConfigFS support. Once you are set up with dtoverlay=dwc2, you can open up a FunctionFS bulk endpoint as root like so:
modprobe libcomposite
modprobe usb_f_fs
cd /sys/kernel/config/usb_gadget
mkdir -p myperipheral; cd myperipheral
echo 0x1234 > idVendor # put actual vendor ID here
echo 0xabcd > idProduct # put actual product ID here
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "My Peripheral" > configs/c.1/strings/0x409/configuration
mkdir functions/ffs.my_func_name
ln -s functions/ffs.my_func_name configs/c.1/
mkdir -p /tmp/mount_point
mount my_func_name -t functionfs /tmp/mount_point
# compile ffs-test from source, then copy and run it from /tmp/mount_point
ls /sys/class/udc > UDC
If you need to emulate the other device more closely, it's up to you to set bcdDevice, bcdUSB, serial number, manufacturer, product string, max power, os_desc, and possibly other fields.
AFAIK FunctionFS does not support isochronous endpoints, interrupt transfers, nor out-of-the-ordinary control transfers. If you require this, you may need to start looking into extending existing gadget modules, with source code here.
Update: When I got home to test this, I encountered a severe caveat with Raspbian. It'll initially fail to create ffs.my_func_name because usb_f_fs is not enabled by default. Although you need not modify any kernel modules, you must recompile with an alternate configuration. make menuconfig -> Device Drivers -> USB support -> USB Gadget Support -> USB functions configurable through configfs / Function filesystem (FunctionFS) + some other modules to test. After uploading a new kernel/modules, I tested the above script on Raspbian 8. I would also recommend setting USB Gadget Drivers / Function Filesystem to (M) in case you resort to the simpler g_ffs legacy module in lieu of ConfigFS.

what does "usb start" command do exactly?

I am facing a problem when i try to read from usb device at u-boot.
When i do
fatls usb 0:1
it says bad device. But as soon as i do
usb start
fatls usb 0:1
then it shows me correcly the fat partition in USB.
I was looking to add both commands in the common/main.c so that whenever the board boots it looks for the fat partition of USB.
It is tough but i need to do it.
Anybody has a clue??
As has been said in the comments, "usb start" is what initializes the USB subsystem and scans attached devices for things U-Boot can deal with (USB sticks, ethernet, etc). Unlike some buses such as MMC that we will do an initial scan on prior to starting the shell, for USB you must run the start command first if you expect to use devices that are attached.
Now, you don't add things to common/main.c, you add things to the bootcmd environment variable (and this can be changed in the boards config.h file so that the default environment is changed, if you are working on a board where you cannot do 'saveenv' to save your changes in a persistent way). So what you would want to do is:
=> setenv bootcmd 'usb start;fatls usb 0:1'
or whatever commands you wish to do with the files present on the USB stick.

UART binding # runtime

When does the console and UART binding happen in Linux,is it possible to unbind the UART from console and bind it to other module(GPS) at runtime.
My board is having a single UART,can i switch between console and GPS at runtime.if yes how do i do it? if no what is the hack which I need to do?
Yes you can. At run time you can unbind/bind any driver. You can find more information here:
https://lwn.net/Articles/143397/
You can find the correct driver for your the UART (and GPS probably, but I'm not sure. Never played with it) here:
cd /sys/class/tty/<your-device>/device/driver/
Then in these directories you have the sysfs files bind and unbind. The device ID to use to unbind the device from the driver is typically show in the driver directory.
The platform_device is not special at all, it behaves like any other driver. Typically the device id of a platform device it's its name (there is not a bus enumeration behind). Here an example with platform_device with my PC:
# ls /sys/bus/platform/devices/
alarmtimer gpio_ich iTCO_wdt platform-framebuffer.0 PNP0800:00 PNP0C14:00
coretemp.0 hp-wmi microcode PNP0003:00 PNP0C04:00 serial8250
Fixed MDIO bus.0 i8042 pcspkr PNP0103:00 PNP0C0C:00
# cd /sys/bus/platform/drivers/serial8250/
# ls
bind serial8250 uevent unbind

How can I bind a driver with a USB device?

I am writing a USB device drive for linux. it's for a joystick.
every time plug it in, linux loads a hid driver. is there a way to tell Linux to load mine when I plug it in? or at least not load the default one?
I can echo the id in unbind of the default driver and echo it in bind of my driver; but I would like something more automatic..
thanks
Own USB driver taking precedence over usbhid
If you want to prevent binding to the usbhid driver, you can use its HID_QUIRK_IGNORE (= 4) setting. To stick with the example Karl Bielefeldt used, add
options usbhid quirks=0x15c2:0x0043:0x04
to some /etc/modprobe.d/*.conf file (and perhaps recreate your initramfs). That will tell hid-core to ignore that device. So usbhid will have a look at it but leave it for some other driver instead.
Own HID driver taking precedence over hid-generic
However, if your other driver is a HID driver not an USB driver, then you need usbhid to bind to the driver on the USB level, and you need your own HID driver to take precedence over hid-generic. This is the problem I'm facing my self, and for which I haven't found a solution yet, short of unbinding and rebinding the device later on.
Here's a thread with a fix for a similar problem. To summarize, you add something like the following to one of your /etc/udev/rules.d files:
SYSFS{idVendor}=="15c2", SYSFS{idProduct}=="0043", MODE="0666", PROGRAM="/bin/sh -c 'echo -n $id:1.0 >/sys/bus/usb/drivers/usbhid/unbind;\
echo -n $id:1.1 >/sys/bus/usb/drivers/usbhid/unbind'"
http://lwn.net/Articles/143397/ is very similar to the above answer, maybe some more details.

Resources