Linux USB driver probe() problem - linux

I'm currently work on kernel-mode USB driver for Seowon SWU-3220A WiMAX USB modem. It is a complex device (after plugging it appear in system as USB CDROM, and driver needs to switch it to modem mode). My problem is that the probe() function from my driver is never called. I think it because OS uses standard usb mass storage driver instead of my own.
I initialize driver as follow:
#define GDM7213_VENDOR_ID 0x1076
#define GDM7213_PRODUCT_ID 0x7f40
static struct usb_device_id gdm7213_table [] = {
{ USB_DEVICE(GDM7213_VENDOR_ID, GDM7213_PRODUCT_ID) },
{ }
};
MODULE_DEVICE_TABLE(usb, gdm7213_table);
static struct usb_driver gdm7213_driver = {
.name = "gdm7213",
.probe = gdm7213_probe,
.disconnect = gdm7213_disconnect,
.suspend = gdm7213_suspend,
.resume = gdm7213_resume,
.pre_reset = gdm7213_pre_reset,
.post_reset = gdm7213_post_reset,
.id_table = gdm7213_table,
};
static int gdm7213_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
printk(KERN_INFO "GDM7213 gdm7213_probe()\n");
return 0;
}
static int __init gdm7213_init_module(void)
{
int result;
printk(KERN_INFO "GDM7213 init_module()\n");
result = usb_register(&gdm7213_driver);
if (result)
err("usb_register failed. Error number %d", result);
return result;
}
static void __exit gdm7213_cleanup_module(void)
{
printk(KERN_INFO "GDM7213 cleanup_module()\n");
usb_deregister(&gdm7213_driver);
}
module_init(gdm7213_init_module);
module_exit(gdm7213_cleanup_module);
Can anybody say me where is a bug or suggest any workaround?

If it is the USB mass storage driver stealing it before you get a chance you might want to blacklist the VID/PID for the device with that driver.
Since you mentioned it's a USB WiMAX adapter I'm going to have a wild guess though that it's presenting a USB mass storage device that contains a driver for it on Windows. If that's the case you would be better off working with USB Modeswitch, which already handles this for 3G modems. Typically the devices expect some magic bytes (which often is actually a SCSI eject command) to persuade them to stop being mass storage devices and become the real modem. (That has a different PID normally too).
Even if your device can't be persuaded to show the real device instead of the driver with one of the existing USB Modeswitch rules it would be more appropriate to fix the problem with that than a kernel hack.
Doing it with USB Modeswitch has a number of advantages over what you proposed:
Keeps everything modular:
Your driver only has to care about WiMAX and one VID/PID for the device
The mass storage driver doesn't need to care about crazy devices - it just looks like plugging and unplugging a device. Teaching the mass storage driver about every single one of these sort of devices isn't appropriate, your device doesn't seem to be a special case.
The knowledge about the split personalities of the device is only relevant to USB Modeswitch, which only exists to solve this problem.
It doesn't break the USB mass storage aspects of the device - users might want to view the Windows driver under Linux for some reason, blacklisting this device would make that impossible. This might be important if you end up using some firmware shipped with the Windows driver under Linux too.
It follows the existing setup and keeps your changes local to your module. This might well be important if you want to get your driver in the mainline kernel ever.

Related

module init function does nothing but a print in linux device driver, is the driver initialized during device tree parsing?

in linux kernel 3.3, the drivers/mmc/host/dw-mmc.c file had this part.
static int __init dw_mci_init(void)
{
return platform_driver_probe(&dw_mci_driver, dw_mci_probe);
}
static void __exit dw_mci_exit(void)
{
platform_driver_unregister(&dw_mci_driver);
}
module_init(dw_mci_init);
module_exit(dw_mci_exit);
at some point during the kernel booting (actually in start_kernel(), in init_call loop), the dw_mci_init is called(because it's with __init tag) and the probe function probes the device and installs the driver. Some years ago I have modified this driver to implement our own SD card controller driver.
Now, when I look at linux kernel 5.4.21, above part of the same file has changed like this :
static int __init dw_mci_init(void)
{
pr_info("Synopsys Designware Multimedia Card Interface Driver\n");
return 0;
}
static void __exit dw_mci_exit(void)
{
}
module_init(dw_mci_init);
module_exit(dw_mci_exit);
The driver init function does nothing but a print. What happened? I guess somewhere in the kernel initialization, the kernel parses the "device tree" (flattend device tree, .dtb file) and the matching platform drivers are found and called to initialize the deivce and driver. Is this correct? and if so, where in the kernel source can I find the device tree (flattend device tree) parsing and device driver installation operation?
What happened?
The driver has been split into separate modules to handle devices from different bus types. The platform driver is in the "dw_mmc-pltfrm" module. (This also handles devices configured by device tree nodes.) There is also a PCI driver in the "dw_mmc-pci" module. The old "dw_mmc" module exports functions in common to the bus type-specific driver modules.
In "dw_mmc-pltfrm.c", the module init and exit functions are defined by the helper macro call:
module_platform_driver(dw_mci_pltfm_driver);

Linux - Is it necessary to register (instantiate) i2c devices before using them?

I'm confused on how userspace programs using Linux's i2c dev interface is able to register (instantiate?) i2c devices.
From my understanding by reading this: https://www.kernel.org/doc/Documentation/i2c/instantiating-devices, it seems we need to either:
Define a i2c_board_info struct with name and address of the i2c
device, do a i2c_register_board_info()
Have a devicetree entry such as this:
i2c1: i2c#400a0000 {
/* ... master properties skipped ... */
clock-frequency = <100000>;
flash#50 {
compatible = "atmel,24c256";
reg = <0x50>;
};
pca9532: gpio#60 {
compatible = "nxp,pca9532";
gpio-controller;
#gpio-cells = <2>;
reg = <0x60>;
};
};
Instantiate devies explicitly by defining a i2c_board_info struct, then call i2c_new_device() in the init of the i2c device driver
But how is this done for user space programs using the i2c-dev interface described here https://www.kernel.org/doc/Documentation/i2c/dev-interface?
I don't have a devicetree entry, and when I grep the code for i2c_board_info, i2c_register_board_info(), or i2c_new_device() I don't find anything. But the code below still works, how?
#include <linux/i2c-dev.h>
void read_from_device(uint8_t *read_data)
{
int result;
file_desc = open("/dev/i2c-2", O_RDWR);
ioctl(file_desc, I2C_SLAVE, device_address);
i2c_smbus_write_byte_data(file_desc, DEVICE_PAGE_ADDRESS, page_number);
result = i2c_smbus_read_byte_data(file_desc, device_register_address);
*read_data = result;
close(file_desc);
}
Does this mean we don't necessarily have to register (instantiate) i2c devices in order to use them? Does that apply to both i2c drivers as well as userspace programs using i2c-dev interface?
The i2c-dev driver binds to the bus (i2c_adapter), not a specific i2c device (i2c_client). So you only need to create the bus device to use i2c-dev and adding devices for the clients isn't necessary. In fact, you'll find i2c-dev will not let you use an I2C address bound to another driver unless you use the I2C_SLAVE_FORCE ioctl.
This is the opposite to the spidev driver, which binds to a specific spi slave device and not the bus as a whole. I2C predates the modern Linux device model and some things are different than is done in other places.
If you want a kernel driver to control the I2C device then there needs to be a device for the driver to bind to. The exception would be so-called "old style" I2C drivers which probe a set of addresses and bind to devices if any are found that appear to be the correct kind.

Need to find and open a USB serial device on linux

I'm writing a small C application to run on my (Linux) QNAP NAS that will talk to an Arduino (I have no difficulty with any of the USB code for the arduino). (The arduino has a trusted application on it that accepts text commands via USB serial.)
My wish was to find it using the USB vendor/product IDs (only half implemented at the moment). What I have so far (see below) works quite nicely in that it does find the device.
// runs on NAS
#include <stdio.h>
#include <usb.h>
main () {
struct usb_bus *bus;
struct usb_device *dev;
usb_init();
usb_find_busses();
usb_find_devices();
for (bus = usb_busses; bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
printf("Trying %s/%s\n", bus->dirname, dev->filename);
printf("\tVendor = 0x%04x\n", dev->descriptor.idVendor);
printf("\tBus = 0x%03x\n", bus->location);
printf("\tFile = %s\n", dev->filename);
if (dev->descriptor.idVendor==0x403) {
printf("\t HEY, THIS IS MINE!\n");
usb_dev_handle *handle = usb_open(dev);
printf("\t HANDLE 0x%08x\n", (int) handle);
//printf(handle, "1,5,62,75\n");
usb_close(handle);
}
}
}
}
The trouble is that now I want to send/receive a little bit of text with the device and I don't know how to do that.
I have expected I should be generating a device name from something in the usb_device struct and then open it like a file (like one would do on Windows).
If that's correct, I need to know the correct way to find out the device name...
I believe I'm using libusb.
I happen to know that -- as currently configured/connected -- it's ttyUSB0 but I'd like to know that using code.
thank you!
I suggest using libusbp. It is a C library with a C++ wrapper, and there is example code showing how to get the name of a serial port based on the vendor ID and product ID of the USB device:
https://github.com/pololu/libusbp/blob/master/examples/port_name/port_name.cpp
libusb is a library used for low level communication with USB devices. But when your communication is limited just to reading device's USB descriptor - libusb is not the best tool.
Linux systems use udev subsystem to manage hot-plug devices. udev reads descriptors of all plugged USB devices and stores them in its database. libudev is the library that you should use to get such info like device names of enumerated devices. In your case you need to remember that usb_device and usb_interface are separate things - only the latter would have the tty device file assigned to it.
Alternatively you could just use udev config to assign a constant device name to your specific device. So you would not have to be looking for it.

when Linux calls PCI driver's probe function?

Before registering a PCI driver, we have to initialize struct pci_driver and pass it to pci_register_driver. One of fields of the structure is a pointer to driver's probe function.
My question is - when the kernel calls driver's probe routine. Is it guaranteed to be right after the call to pci_register_driver or may happen any other time? What is determining this behaviour?
UPDATE
pci_register_driver is a macro expanded into __pci_register_driver, which in turn calls driver_register, and driver_register calls bus_add_driver.
There's a following code in bus_add_driver:
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv);
if (error)
goto out_unregister;
}
driver_attach will call bus_for_each_dev with argument __driver_attach, which will invoke driver_probe_device
And driver_probe_device ultimately calls really_probe:
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
The one thing I'm not sure about, is if the flag drivers_autoprobe gets set for pci_bus.
After the PCI core within your linux kernel has enumerated your device during the link training phase (this occurs by default at boot), it will gather information about the End Point devices connected to it, this includes the Vendor id, and the device id. The PCI core will then iterate through all of the drivers that have been registered to it with the function `pci_register_driver' and see if the driver supports this vendor/device combination.
A driver identifies that it supports that vendor/device combination using the struct pci_device_id id_table field of the pci_driver structure.
A typical implementation would look something like this:
#define VENDOR 0xBEEF // vendor of EP device
#define DEVICE 0x1111 // device id of EP
static struct pci_device_id module_dev_table[] = {
{ PCI_DEVICE(VENDOR, DEVICE)},
{0, },
};
// PCI driver structure used to register this driver with the kernel
static struct pci_driver fpga_driver = {
.id_table = module_dev_table,
.probe = module_probe,
.remove = module_remove,
.suspend = module_suspend,
.resume = module_resume,
};
When the PCI core identifies your driver as a driver that supports a device on the bus, your probe function will then be called.
So to answer your question, NO, your probe function is not guaranteed to be called immediately after you register your driver, and almost certainly will not be. Your probe function will be called immediately after PCI core enumeration/Link training identifies a device which your driver supports.
When kernel detects a PCI device on PCI bus, kernel gets the device name based on the device tree. After this kernel scans through list of registered drivers if any of the drivers handle this device. If yes, then kernel will call probe of that particular driver.

how to get 'device struct' from 'dev_t' in linux kernel programming?

I am quite new to kernel programming and I am following the tutorial given at :
USB boot authentication
I want to get a 'device struct' of a USB drive. I have 'dev_t' instance of the USB device. Further, I want to check whether the device struct is a USB device or not. I am not able to figure out how to start...
Thanks
As hiteshradia said dev_t is a device number (a major number and minor number). You can however use this along with the knowledge that it is for a block device to get access to the struct device associated with it. To do so, use struct block_device *bdget(dev_t) from linux/fs.h. From this you can use block_device->bd_part to get a struct hd_struct * for the device and finally use struct device *part_to_dev(struct hd_struct *) defined as a macro in linux/genhd.h.
dev_t is only a device number which represents a /dev/sdb1 partition as seen from your link. It is not possible to get the underlying usb drive details using it.
In the link you provided there is section
if(udev->serial != NULL)
{
if((strcmp(udev->serial, "3513001D97827E69")) == 0) /* Hard coded usb device serial here*/
{
key_dev_found = 1;
}
}
where you can get usb device details and struct usb_device *udev

Resources