I'm researching ways to communicate with a USB device in Linux and would prefer to not write a Linux Kernel driver. I understand that libusb exists and is a user-land library that would work, but our embedded device doesn't support usbfs ( and would be really a pain to change kernels to add the support ).
So my question is basically this: Is it possible / advisable to communicate with a USB device by directly reading and writing to the /dev/USB or the udev file corresponding to the USB device thus bypassing the need for a custom Linux Driver and usbfs?
I'm hoping it's possible to communicate using the USB devices protocol just by reading / writing protocol packets directly through file-type read/write commands once the /dev/USB or udev device file is open.
Thoughts and suggestions please.
FOLLOW UP:
Since the USB device I needed to talk to is a USB HID class device, I was able to use libudev and the standard Linux USB HID RAW driver by reading / writing directly to /dev/hidraw0 ( or the appropriate /dev/hidraw device ). It wasn't necessary to write a custom driver for a simple USB HID device.
Jim, I don't think you can escape the need to write a driver and just manage to read the USB file in /dev. Because who defines as to what should happen when you do a read() on the USB device file? And who defines what action should be initiated when you invoke sysioctl()? Your driver! In other words, the device files are themselves incapable of anything until they are supported by the underlying drivers. In fact, you can treat the device files to be an abstraction of the underlying driver! So, no driver, no use of device file :(
I suggest you go through the following articles about how to write a driver and also understand the USB internals-
http://www.linux-usb.org/USB-guide/c15.html
http://www.linuxjournal.com/article/4786 ( Slightly outdated )
Related
I have developed a kernel driver for a USB device. Such a device has some pins that can provide functionality both as CDC ACM serial port or as input buttons. So to implement that I had to use two different USB configuration descriptors.
The driver works as expected, but I have to hardcode the chosen setup before compiling and loading the firmware to the micro-controller. I am searching a mechanism to change that device configuration from userspace.
I read about a SET_CONFIGURATION message on USB documentation, but coudn't find any Linux tool to send such kind of standard USB messages from userspace to the USB bus.
Does some of you (with more experience on this topic) know some userspace Linux tool to send a SET_CONFIGURATION message to a device connected to the USB bus?
Thanks in advance! :)
The function libusb_set_configuration() in LibUSB could do that in theory, but there is no need.
One can simply put both HID (for the button) and CDC (serial port) into one configuration using an "Interface association descriptor" (IAD).
This github repo resolves my issue:
https://github.com/avtolstoy/usbtool
No need for any special tools. You can simply do it via sysfs:
Find your device cd /sys/bus/usb/devices/X-Y/ where X is the bus number and Y is the device number.
Edit bConfigurationValue e.g., using sudoedit
Set the file contents to the desired configuration number and save it
That’s it!
I would like to implement a USB device driver in user space by means of libusb. I'm using a Linux machine supporting a USB OTG controller which is switched to device mode. The USB host is another machine which needs to communicate with my Linux machine by means of a USB vendor specific interface with a bulk in/out interface.
I would like to know if it is possible to use libusb to communicate with the USB host on the other side. Or, if libusb could be used only for host side functionalities.
If libusb can't be used is there any other way to implement the device driver in user space?
Thank you.
As of my knowledge this is not possible. (Vanilla) libusb is only for host usage because the whole process of how to use libusb can only provide this mode.
You can find an answer in the FAQ of the old libusb (before libusbx, the abandoning of the old libusb and the rename of libusbx to the new libusb):
libusb FAQ
Also there is a question on SO to this topic with some suggestions:
How to communicate with the USB Host from a Linux USB Client
I have a embedded device that runs linux 2.6.37.
I want my application to know when the USB is connected.
Currently I can achieve this by pooling
/sys/devices/platform/musb/musb-hdrc.0/vbus.
However this approach does not distinguish between a USB charger or a USB host.
I found this udev approach but I don't think it's available in my version of the kernel. because I did not find any USB related nodes in my /dev. This discussing also shows that it might not be feasible, ether.
I also found linux hotplug and tried the netlink example, but I didn't see any output running the example when I connect/disconnect the USB cable.
What I want to do is to detect connection type on the device, when USB is connected, and prepare (unmount file system) and switch to g_file_storage if device is connected to a host, and do nothing if device is connect to a charger.
How shall I achieve this?
To achieve that, you can use the inotify(7) feature, available in all linux kernels to be awaken as soon as some device node gets created in /sys.
To know what type of device you have, you have to read the usb info from proper usb ioctl call (or if you are not a kernel interface expert, using the libusb interface) to get the device vendor, device id and device class fields coming from the device. Normally, the hotplug software gets informed on these clase of events (via a special socket). The most probably reason you don't get the device properly initialized is some misconfiguration in the config files for udev system, which normally has one entry for each possible device vendor/device id pair and allows it to load the appropiate device driver to control it. The process continues with the device driver module creating dynamically the actual devices, and they'll appear in the /dev/ filesystem as a consequence of some other kernel event to udevd.
Read apropiate documents in <linux_src>/Documentation (this directory directory belongs to the linux kernel source code, so you'll probably need to install it), and udevd(8) man pages to be able to add a new usb.
On 2.6.37 kernel, this could be done by polling
/sys/devices/platform/musb-omap2430.0/musb-hdrc.0/mode
If handshake with host is successful then it will read as "peripheral", if fail it'll be "idle".
I am trying to find out a high-level overview of how the USB storage driver works in Linux. I'm looking for a simple article or even a picture/flowchart describing how it works.
Basically, I'm looking to get these questions answered:
When you plug the device into your computer, what happens? Is there a daemon that picks up on it, or does the event trigger an interrupt somewhere? Does the core USB driver read information about the device before passing control over to the USB storage driver? How does it decide what type of device it is? How does the device get mounted, and what allows it to communicate with the computer's filesystem? When I copy a file, what does the data flow look like in the kernel?
I hope the question isn't too vague - I tried Google to no avail, so I'm wondering if anyone knows any articles or diagrams that can explain this, or perhaps if they can explain it themselves without too much effort. Thanks.
No, it is a very good question.
The block writing is going in linux with the block device layer. The filesystems are working with this block dev layer.
If this layer wants to write something out, says it to the driver of the usb master device. This driver is talking with the usb controller chip of the motherboard.
This chip is very simple: the usb is practically a serial port, with a lot of extensions, mainly targeting the autoconfiguration and the power management. But basically, you can write out bytes, and read in bytes.
Your questions:
When you plug the device into your computer, what happens? Is there a daemon that picks up on it, or does the event trigger an interrupt somewhere?
The device (usb slave) says the master (in the motherboard): "I am here". The usb controller chip gets the message and says it to the kernel (normally) with an interrupt. The kernel reinitializes and rescans the usb bus, and says the udev: "here is a new 1234:5678 usb device on the usb tree 1.3.5"
"How does it decide what type of device it is?"
Usb devices have a vendor and model id, and they can say this on ask. Google for "usb ids".
"How does the device get mounted, and what allows it to communicate with the computer's filesystem?"
The kernel only loads the driver and says the udev (which is in userspace): "Here is a new block device on device number 22:16". From this, udev tries to mount this with some userspace daemon, it is already distribution-dependant.
I am wondering, do you need a specific device driver to read a usb device in Linux, or should it just be able to be read. If I connect my cell phone or iPod touch to my linux box, it is not found is /proc/partitions and thus is not a mountable device by fdisks standards, though gnomes nautilus does in fact mount the iPod but not the windows mobile touch pro cell phone.
So I am interested, If I just wanted to read a device(iPod touch) in linux, how can I do so. How can I get a hold of a descriptor of a set usb device so I can read it.
Thanks all.
You can access raw USB endpoints under /dev/usbdev. There is user-space libusb that makes it easier.
Unfortunately there is no simple concept of "just read it" for USB devices (I am assuming that you are not referring to reading and writing the data on the USB bus that make up the USB protocol). In short, you always need a device driver for accessing a USB device and it is up to the driver to implement "the abstraction" of the device used by the system (disk, serial device, etc).