Hard time in understanding MODULE_DEVICE_TABLE(usb, id_table) usage
It is usually used to support hot-plugging, by loading/inserting the driver for a device if not already loaded.
There is a similar question here: Detect the presence of a device when it's hot plugged in Linux
(From my ans)
It works as follows:
Each driver in the code exposes its vendor/device id using:
MODULE_DEVICE_TABLE(of, omap_mcspi_of_match);
At compilation time the build process extracts this infomation from all the drivers and prepares a device table.
When you insert the device, the device table is referred by the kernel and if an entry is found matching the device/vendor id of the added device, then its module is loaded and initialized.
Usb device id table understanding
You should have Linux
kernel source at hand to really understand this.
- Why
pen_table
is an array?
It wil be necessary in MODULE_DEVICE_TABLE
(see Hard time in understanding MODULE_DEVICE_TABLE(usb, id_table) usage) and in defining instance of usb_driver
struct, see http://opensourceforu.efytimes.com/2011/11/usb-drivers-in-linux-2/.
- what type of array initialization is this?
USB_DEVICE
is a macro defined in include/linux/usb.h:
#define USB_DEVICE(vend, prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
.idVendor = (vend), \
.idProduct = (prod)
- how this terminates?
C standard says:
The initialization shall occur in initializer list order, each
initializer provided for a particular subobject overriding any
previously listed initializer for the same subobject; all subobjects
that are not initialized explicitly shall be initialized implicitly
the same as objects that have static storage duration.
and:
If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate. If an object that has static
storage duration is not initialized explicitly, then:
- if it has pointer type, it is initialized to a null pointer;
- if it has arithmetic type, it is initialized to (positive or
unsigned) zero;- if it is an aggregate, every member is initialized (recursively)
according to these rules;- if it is a union, the first named member is initialized
(recursively) according to these rules.
Thanks to this, id_table
is defined as a pointer and not as an array inside usb_driver
:
const struct usb_device_id *id_table;
Instead of passing an array size independently a function that uses id_table
will increment pointer to id_table
until one of its elements is NULL. See this short example that represents this technique:
#include <stdio.h>
#include <stdlib.h>
struct small
{
int a;
int b;
};
struct big
{
struct small *s;
};
struct small table[] =
{
{1, 1},
{2, 2},
{3, 3},
{}
};
int main(void)
{
struct big b = {
.s = table
};
const struct small *s;
/* traverse through table using pointer arithmetic */
for (s = b.s; s->a; s++)
{
printf("%d\n", s->a);
printf("%d\n", s->b);
}
exit(0);
}
- I tried to initialize device id table in this way, but I am getting
errors as near initialization
I don't, are you sure you're not trying to redefine pen_table
? What's an error message?
How to insert my driver automatically on the insertion of USB mouse in Linux System?
Thanks all for your help.
I follow the udev approach to load module automatically on the USB insertion
Below is the procedure to load your Driver automatically on the Insertion of Hot plug-gable device (I experiment with the USB mouse and below procedure is working fine for it)
Run Following command
cmd > udevadm info -a -p $(udevadm info -q path -n /dev/input/mouse)
In place of ?? in the above command user need to add the device ID based on its entry in /dev (e.g.for USB flash drive: sdb1 or sda1 etc. based on the device identity)
Get the Value of the below parameters from the output of above command
KERNEL, ATTRS{idVendor}, ATTRS{idProduct}, ATTRS{serial}Go to /etc/dev/rule.d directory and Add your rule
cmd > sudo vim 40-usbmouse.rules
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd?1", ATTRS{idVendor}=="058f", ATTRS{idProduct}=="6387", ATTRS{serial} =="4EPLXAXE", SYMLINK+="usbpd", RUN+="/usr/local/bin/InsertModule.sh"Save this file.
Above rule is defined for the USB Mouse.
Parameter SYMLINK creates a link of your device in the /dev directory and In RUN+ you can give your script location which is going to execute on your device insertion.For more info on How to write a rule refer below link
http://hackaday.com/2009/09/18/how-to-write-udev-rules/
Now after you define your rule user need to restart the udev to take your rule in notice by kernel.
cmd > sudo stop udevcmd > sudo start udev
Insert your USB and validate that your script which you define in your rule shows its effact.
For Mouse user can use below commandcmd > udevadm info -a -p $(udevadm info -q path -n /dev/input/mouse)
P.S.: cmd stands for the command shell (Terminal).The above procedure is working with any USB device.
Minimal Linux kernel options to enable hid input
It turns out OHCI driver is needed to handle low speed peripherals even if they're connected to USB2 (EHCI) controller.
Actually MT7628 has a "secondary" OHCI controller not even advertised in Data Sheet.
This means that, on top of selecting CONFIG_USB_OHCI_HCD=m
and CONFIG_USB_OHCI_HCD_PLATFORM=m
also the following patch is needed:
diff --git a/arch/mips/boot/dts/ralink/mt7628a.dtsi b/arch/mips/boot/dts/ralink/mt7628a.dtsi
index bf6b6a459bd6..b4ac008fdfdf 100644
--- a/arch/mips/boot/dts/ralink/mt7628a.dtsi
+++ b/arch/mips/boot/dts/ralink/mt7628a.dtsi
@@ -323,6 +323,17 @@ ehci@101c0000 {
interrupts = <18>;
};
+ ohci@101c1000 {
+ compatible = "generic-ohci";
+ reg = <0x101c1000 0x1000>;
+
+ phys = <&usb_phy>;
+ phy-names = "usb";
+
+ interrupt-parent = <&intc>;
+ interrupts = <18>;
+ };
+
ethernet: ethernet@10100000 {
compatible = "ralink,rt5350-eth";
reg = <0x10100000 0x10000>;
Note address 101c1000 is nowhere mentioned in MT7628 programming manual and it's "one cell away" (0x1000) from standard (and documented) EHCI controller cell (at 101c0000).
I assume similar situation is also true for other SoCs because USB standard mandates to "hand over" low speed devices to a legacy USB1 controller.
I hope this will spare a lot of headache to whoever will stumble in the same problem.
PyVISA not listing USB instrument on Linux
I managed to find a solution which I share for the sake of future generations to come. I had just to add a line to the file /etc/udev/rules.d/99-com.rules
with the content SUBSYSTEM=="usb", MODE="0666", GROUP="usbusers"
(or append this line in case the file already exists) and then restart the computer. In summary:
- Enter into the sudo environment:
sudo su
- Now add the required line into the respective file:
echo 'SUBSYSTEM=="usb", MODE="0666", GROUP="usbusers"' >> /etc/udev/rules.d/99-com.rules
Restart the computer.
Enjoy.
$ python3
Python 3.7.3 (default, Dec 20 2019, 18:57:59)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyvisa
>>> pyvisa.ResourceManager().list_resources()
('ASRL/dev/ttyAMA0::INSTR', 'USB0::bla::bla::bla::INSTR')
>>> osc = pyvisa.ResourceManager().open_resource('USB0::bla::bla::bla::INSTR')
>>> osc.query('*IDN?')
'*IDN LECROY,WR640ZI,LCRY28blablabla,7.7.1\n'
Related Topics
Removing Sensitive Data from Git. "Fatal: Ambiguous Argument 'Rm'"
Size() VS Ls -La VS Du -H Which One Is Correct Size
How to Build Msi Package on a Linux Server
Keep the Window's Name Fixed in Tmux
What Does "Make Oldconfig" Do Exactly in the Linux Kernel Makefile
Add Text to File at Certain Line in Linux
What's the Meaning of a ! Before a Command in the Shell
Trace of Executed Programs Called by a Bash Script
Convert an Iso Date to Seconds Since Epoch in Linux Bash
Hosting Two Website Under One Web App - Azure Services
How to Free Up Space on Docker Devmapper and Centos7
How to Append the Output to a File
What Is the Command to Match Brackets in Emacs
How to Find the Tomcat 7 Installation Folder on Linux Ami in Elastic Beanstalk
What Is the Use of _Iomem in Linux While Writing Device Drivers