Problem reading from a device with libusb - linux

The situation is this: I have a USB device (a custom device I'm trying to talk to) with two endpoints, one writing to the device, one reading from the device. Both are bulk transfers. Every communication transaction takes the form of (1) Write a command to the device (2) Read the response. I'm using libusb (version 0.1 rather than the 1.0 beta) to actually perform the communications.
On Windows, all is well. I can connect the device, claim the interface and communicate happily. However, in Ubuntu (a standard Hardy desktop install), whilst I can connect to the device and write to it, all read operations fail with the error "error submitting URB: Invalid argument" reported from libusb (error code -22).
If I check /var/log/messages I see a warning message logged for the same time as the read was attempted: "sysfs: duplicate filename 'usbdev4.3_ep81' can not be created" - which tallies with the device (it is indeed on that bus and it's endpoint 81 I'm trying to read from).
So... anyone seen a similar problem using libusb, or have any idea how to fix it?

Turns out it was a misconfiguration in the descriptors on the device itself. lsusb -v showed an extra interface which was never used, which had a single isochronous endpoint 0x81. Since this was never used (and had never been tested as far as I could see, so quite possibly not even defined correctly) I removed it from the device descriptors completely (in the firmware).
And now I have a fully working device. Why linux refused to read from the device but Windows worked fine I don't know, but it definitely sent me on a wild goose chase.

I haven't used libusb in quite some time -- but the sysfs error indicates that this is likely to be a kernel problem rather than a libusb one, so I'd start by trying to track that one down. (Not much point in trying to work with libusb until you're sure your kernel is talking to the device correctly).
Does the patch at http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/17/345922 apply to your kernel? (If so, does it fix the issue?)

I had to do some hacking to udev rules to get the device created with the right permissions for libusb to work. Like so:
SUBSYSTEM=="usb" ATTRS{idVendor}=="0a81", ATTRS{idProduct}=="0701", \
MODE="0666" SYMLINK+="missile_launcher"
(This was an usb missile launcher I was writing a driver for.
Also this snippet was required to not clash with the kernel.
if(LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP)
{
// Detach kernel driver (usbhid) from device interface. (Linux hack)
usb_detach_kernel_driver_np(launcher, 0);
usb_detach_kernel_driver_np(launcher, 1);
}
I'm not sure how this relates to your problem, but atleast there are two possible points of failure that might be involved.

You can try WinDriver it's a commercial tool but have free full function evaluation (somehow time limited). You can check with WinDriver and if problem is reproducible it's might be device or your protocol fault. You did not give enough information to determine or analyze.

Related

debugging Device driver using GDB

I'm new to device drivers in Linux. And my first day task is to debug driver using GDB in Linux.
I need to debug some XYZ (PCIe device driver supports ethernet) device driver to know about the flow and what is going on device's registers and all.
I have installed the driver with patch file and insmod command.
The device is working properly. But am not getting any solution to debug the device driver.
All I know is that how to debug C program using GDB in Linux(fedora20). I got one link similar to my Problem but from that also I have not got any knowledge.
Can anybody please share your thoughts that how can I start from scratch.
I am very specific to learn about Debugging device drivers in Linux. Especially that init or probe function inside my driver I need to know the flow.
The gdb debugger is useful to debug user-space application level programs (since it uses ptrace(2)).
For kernel code, things are different. Consider using kgdb (I don't know the details). You might also add debug prints ....
I recommend at least reading more about operating systems, e.g. Operating Systems: Three Easy Pieces (freely downloadable), and reading something about Linux programming (perhaps the old ALP, and also intro(2), syscalls(2) and related stuff). Don't dare coding Linux loadable kernel modules without good familiarity with Linux programming (in user-land). See also kernelnewbies.
BTW, you should prefer writing user-land code than kernel modules. A very simple rule of thumb is to avoid writing kernel code when possible.
To begin with, you may need to understand basics of device driver and kernel in linux. Subsequently focus as per the type of driver in-hand. You also need to understand the functionality (specification / manual / datasheet) of the device you are working on.
The very basic approach for debugging can be using printk. Normally there will be debug logs that can be enabled through compilation flags. If it is present, enable it so that it can give important pointers else you might need to add it on your own.
Start with verification of driver registration and verification of loading of your driver (static or loadable module as per your requirement). Check whether it is getting listed as part of sysfs or proc as applicable. Check whether probe is successful and subsequently the appropriate read/write/open/close/other calls as per your driver / device functionality.
The dmesg shall be very helpfull for viewing the kernel messages. There are also tools like kdb, LTT, strace that can be useful as per the scenario.

Device mapper, boot with virtual device

I have a task to make a virtual device under a real one with the help of device mapper kernel module. Virtual device must transfer any request to a real device, so both devices must be equal.
In prospective I should be able to control requests, so I wrote kernel module, representing device mapper target, using this article.
After making module and inserting it (insmod command) I setup my device (dmsetup create). Then do mount and can work with a real device through just created virtual.
But the question is how to repeat above mentioned instructions in boot time? I'd like to use my virtual device as a general one (by changing fstab, I guess).
Thanks in advance!
If you are going to use your device as the root filesystem, you need to create an initramfs that sets it up. Basically a shell script that issues dmsetup commands, followed by a mount and finally pivot_root to the new filesystem.
There was a discussion on the dm-devel mailing list last year on how to do this in the Linux kernel without an initramfs, by specifying mapper lines on the kernel command line. This is they way Chrome OS does it, because they can't/won't use an initramfs. See here for documentation of this feature. The functionality was never merged though.
The patch series was updated and resubmitted in May 2017. Hopefully we will eventually see it merged in some form or other.
If you are not going to use your device as the root filesystem, you can still use the same approach if you want, but there might be easier ways.

What causes Linux to issue a CLEAR_TT_BUFFER command?

I'm writing a library that interfaces to a Full Speed USB device using libusb. It seens to be working fine, but when I run the code inside GDB or Valgrind, I see in Wireshark that there are CLEAR_TT_BUFFER commands being send to the USB hub (I presume it's the internal one, since I have the device directly attached to the PC), and some packets seem to be lost (this shouldn't happen, as I'm using bulk transfer).
So the question is, what (under which conditions) is issuing those commands, and how do I prevent/detect them?

Linux scsi command queue

I'm a newbie here at this forum. I'm currently stuck with a problem.
I'm a beginner to Linux kernel drivers, and currently involved in developing a Linux SCSI device driver for a block mass storage device. The development platform is on a high-end machine with Fedora 14. The setup is 1 host to one LU/device. To make the long story short, the driver is working in the sense that it initializes without problems, it can detect the device and send scsi frames to it, it can read and write to the device, and I can do stable Iometer read and write tests through the driver. All of that when there is only 1 outstanding command at a time (no queueing).
The problem is, I couldn't get queuing to work. The upper SCSI layers doesn't send me (LLD) more than one commands to be outstanding unless I scsi_done() the first command. I expect that the upper layer can call queuecommand() more than once before I send the commands to the device for processing, then for the device to interrupt me for the response and for LLD to close the command with scsi_done(). Without queuing, our speed is very slow.
I've already tweaked values I thought are connected to queuing, like setting .can_queue and .cmd_per_lun to my target queue_depth in both scsi_host and scsi_host_template. Basically I've played with various values including 1, but to no avail. I also did disable and enable tagging if this has any effect, but still no change. So far I don't remember doing much with scsi_device in the driver, except in slave_configure. Is there anything I'm missing and can still do in driver level? I can't believe Linux would have no support for command queuing. I'm missing something here.

Is there a way to ask the Linux Kernel to re-run its PCI initialization code?

I'm looking for either a kernel mode call that I can make from a driver, a userland utility, or a system call that will ask the Kernel to look at the PCI bus and either completely re-run its initialization, or initialize a specific device. Specifically, I need the Kernel to recognize a device that was added to the bus after boot and then configure its address space, interrupt, and other configuration parameters, and finally enable the device so that I can load the driver for it (unless this all happens as part of the driver load).
I'm stuck on the 2.4.x series Kernel for this, and am currently working with 2.4.20, but will be moving to 2.4.37 if it matters. The distro is a stripped down Red Hat 7.3 running in a ram disk, but I can add in whatever tools are needed to get this working (as long as they play nice with 2.4 series).
If some background would help clarify what I'm trying to do: From a cold boot, once in Linux I use GPIO to program an FPGA. Part of the FPGA, once programmed, implements a simple PCI device. Currently, after programming the FPGA, I reboot the system and Linux recognizes the device after coming up and loads the driver for it.
Instead of needing that reboot, I'd like to simply ask the Kernel to do whatever it does during boot up to find PCI devices (I have the Kernel configured to find PCI devices on its own, instead of asking the BIOS for that information, so the BIOS won't need to know about this device (I hope)).
I believe that Linux is capable of seeing the device after it is programmed but before a reboot, because scanpci will show the device after I program it, as will lspci -H 1. I just need a way to get it into /proc/pci, configured and enabled.
This below command will help the user to rescan it complete root hub.
echo "1" > /sys/class/pci_bus/0000\:00/rescan
You could speed up the reboot with kexec, if you don't figure out how to get the PCI scan redone. You could ask this on the LKML, if you haven't already.
unloading/reloading the module doesn't help, does it?
http://www.linuxjournal.com/article/5633 suggests you should be able to do it with 2.4 kernels using pcihpfs.
If that isn't working, maybe the driver doesn't support hotplug?
It would probably crash the system if you reconfigured the addresses of other PCI devices while they are in use.
A better way would be to just configure the new card. If your kernel has support for Cardus devices, it already knows how to configure a newly-inserted PCI device (which is what Cardbus is). You just need to figure out how to get the kernel to do it...
It should be possible for a kernel module to do this. Even if you can't get built-in hotplug code, you should be able to set the pci resources using calls to pci_bus_write_config_dword() and friends. There is probably some IRQ routing setup to do as well.

Resources