libusb and poll / select - linux

I'm using a linux OS and was wondering if there were any file descriptors I could poll/select which would trigger when data was waiting to be read from a usb device. I am also using the libusb library and have yet to find file descriptors which I can use.

Use libusb's polling functions to hook its file descriptors into your event loop. select will wake up whenever there's activity that libusb will need to handle, which includes but probably is not limited to data being available for reading.

No, USB devices are not always "stream" devices, so reading from a file descriptor doesn't always make sense. However, if your USB device provides a serial port driver, you can listen for incoming data on the serial port device (just like any other serial port handled by your OS).

Related

YModem with I2C

I'm currently in a situation that my SoC will be connected via its I2C bus through a I2C-to-UART converter MAX3107 to the UART port of a microprocessor.
Although the communication between the two shouldn't be an issue, the part were the Soc should update the firmware of the microprocessor has to be done with the Y-Modem file transfer protocol.
Although a question is pending at the manufacturer, I still wanted to check here:
Would this even be possible
The SoC runs Linux, is this depending on the MAX3107 driver
Does this concern the I2C bus or is only the UART driver and bus interesting.
https://datasheets.maximintegrated.com/en/ds/MAX3107.pdf
I used the SC16IS750 instead with the Linux kernel driver.
Sending a file via Y-Modem doesn't seem to be a problem. I tried both Minicom and TeraTerm to send a file and it works. The receiver responds is just 1 character each time before sending a part of the file. If the responds would have been more than 64-byte at a time (instead of the one character) this would have been a problem, because the FIFO first needs to be read and cleared before another sting can be received.

Linux : how to transfer data through USB bulk endpoint of cdc-adm driver from userspace

I am a beginner to Linux drivers and I started with writing an application for a cdc-acm based USB device in linux. Therefore, I have used the cdc_acm driver. The USB device that I am using has 2 Bulk endpoints (read and write) and one interrupts endpoint.
Now, my question is whether all these endpoints operate on the same /dev/ttyACM0 file, and how does the write call on this tty file get convert into acm_write_bulk fops call?
If I write a data to trigger a USB functionality into the ttyACM0 file, will the data get sent through bulk out endpoint? Or how should I send the data to the bulk endpoint directly from user space. Should I write any supporting driver in kernel space?
Similarly, how do I read the data from interrupt endpoint in the userspace?
I appreciate your help in advance.
There is no need to write a kernel space driver. You can open /dev/ttyACM0 with the open system call, set parameters for it using termios (optional), and then use the read and write system calls to read and write bulk data from your device. These system calls are easiest to access from C and C++, but most languages have a library you can use to access serial ports.
I don't know of a great way to read data from the interrupt endpoint in Linux but you can at least look into the TIOCMGET, TIOCGICOUNT, and TIOCMIWAIT ioctls in you really need to do that.
The Linux serial port interface abstracts away all details about USB, endpoints, and bulk transfers, so you can use a simpler, more abstract API to communicate with the serial port. In fact, you can use the same code on any type of serial port, regardless of which kernel driver implements the serial port. It might help you to search the Internet for things like "linux serial port programming" or "posix serial port programming" to understand more about how to do this.
If you really are curious about how the Linux CDC ACM driver works, and how it converts a write system call into the corresponding USB transfer, you can read the source of the cdc-acm driver. However, that is way beyond what you need to do to simply use a serial port.

C++ Detecting USB serial device plugged/unplugged

I need to detect when a USB serial device is plugged or unplugged on my embedded system and know what is the tty associated with it.
My system runs over a 2.6 Linux Kernel.
Since I don't have write access to udev rules, nowadays I'm trying to get this information from the file system, looking for modifications in /sys/bus/usb/devices directory. However, I'm facing some problems with this approach.
I know what is the Id BUS of the USB port connected (e.g 1-1.3). So, I search for the associated tty (looking for a directory in /sys/bus/usb/devices/<Id BUS>:1.0/tty/ - e.g. /sys/bus/usb/devices/1-1.3:1.0/tty/ttyACM0). This way I know that I should use /dev/ttyACM0 to communicate with my device.
But, sometimes, this device (/dev/ttyACM0) does not exist.
Is there any better way to get this information?
I even thought trying to get this information from the syslog, but I don't know whether this is a pretty good idea.
Edit:
Only to clarify, my system needs to be able to detect state changes in the USB bus, i.e. detecting when a new device is plugged (and getting the tty name linked to it) or an existing one is unplugged.
The system is monitoring up to N USB/serial devices, which are plugged to it using an USB HUB. During its normal execution new devices can be plugged, existing devices can be removed (or rebooted by a remote command - out of this scope). When a device is rebooted, it could receive a different tty from the previous one used before (e.g. ttyACM0 -> ttyACM3), since the kernel designates to it a tty which is free at the moment, and it is a big problem to me.
Netlink is the preferred mechanism for communication between kernel and userspace.
You would create a Netlink socket with family NETLINK_KOBJECT_UEVENT, listen on that socket and filter out messages that contain SUBSYSTEM=usb and ACTION=add for USB plug events or ACTION=remove for USB unplug events.
I wrote a USB abstraction library called libusbp. You should look at its port_name example, which shows how to use libusbp to get the serial port name (e.g. /dev/ttyACM0) for a USB serial device. Behind the scenes, libusbp gets this information using libudev.
Check if the virtual file is deleted using stat.
#include <sys/statvfs.h>
...
struct stat sb;
return (stat("/dev/ttyUSB0", &sb) == 0); // true if open, false otherwise

How to detect when a usb cable is connected/disconnected on the device side in Linux 2.6.37?

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".

Does Linux serial port device support poll()?

I want to know whether Linux kernel device driver of serial port device, e.g. /dev/tty1, /dev/tty2, support poll() operation?
Or tell me where is the kernel source code of serial port device?
In my case, some sensors will send data to ARM CPU via serial port each second. And I think one way is to use a timer for periodically read from the serial port. Another way should use poll(), read it when data is ready.
Unless your serial port is a special case, using poll() or select() would seamlessly work.
If your serial port was controlled via USB, you would have to take care about what happens if the USB to serial is disconnected, but this does not seem to be the case for you.

Resources