Get access to USB device on Linux (libusb-1.0)? - linux

I am writing a small program to communicate with a specific USB HID product (identified by vendor and product IDs), using libusb-1.0 on Linux. Right now, I have to run the program as root because "libusb requires write access to USB device nodes". Is there a way to change the permissions on the device I need so that I don't need to run my program as root?

On modern Linux systems, udevd (man 7 udev) creates the device nodes for USB devices when they're plugged in. Add a udev rule that matches your device (eg. you could match by USB Vendor and Product IDs), and sets the OWNER / GROUP / MODE of the device node.
The best approach is probably to create a new group for users who should be able to access the device, then set that as the group owner in the udev rule. You may also need to use MODE to ensure that it has group read/write permissions. Eg. your rule will probably look something like:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="ffee", ATTRS{idProduct}=="5a5a", MODE="0660", GROUP="foobar"

Related

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

How can BeagleBone Black be used as Mass Storage Device?

Is it possible to use the BB as Mass Storage Device?
I want it to be connected to an audio player that can read files from USB connectivity (such as USB flash drive) and act as data storage device containing one specific folder (and its sub-folders) from the file system (if possible, on a flash drive connected to the board.).
As the device specs says, it has connectivity of:
USB client for power & communications
USB host
Operating system will probably be Ubuntu but can be changed.
What drivers or configurations needs to be done in order to achieve this?
The latest images have already the mass storage usb gadget active, so a mass storage peripheral should be recognized by your system upon connection.
A quick google search reveals this discussion about a user trying to disable the USB MS gadget:
From the discussion, the files where the magic happens are:
Debian: /opt/scripts/boot/am335x_evm.sh
Ubuntu: /opt/scripts/boot/am335*
Armstrong: /usr/bin/g-ether-load.sh
In my Debian image the line you want to modify is:
modprobe g_multi file=${gadget_partition} cdrom=0 stall=0 removable=1 nofua=1 iSerialNumber=${SERIAL_NUMBER} iManufacturer=Circuitco iProduct=BeagleBone${BLACK} host_addr=${cpsw_1_mac}
and the corresponding $gadget_partition variable that is set just before that in order to customize the folder you want to expose.
Note that the g_multi gadget in its standard configuration presents 3 different devices: an ethernet interface, a mass storage peripheral and a serial interface. If you want to customize the parameters you can refer to the g_multi documentation (kernel.org)

Is there a way to get the device node of a usb device using libusb APIs?

I am trying to get the device node (eg. /dev/sdb) of a usb device.
I was wondering if there is any libusb API that would give me the particular device node to which the USB device is associated with.
If there is no API, are there any other alternate means of achieving this? Any insight on this would prove REALLY helpful.
Thanks in advance.
On Linux, easiest method to explore attached USB devices and their properties is to simply scan directory /sys/bus/usb/devices. This virtual directory lists all attached devices. Each entry has very simple structure, and for every device that has slave connected (like device connected via hub) there is virtual subdirectory.
What is also nice that in general you do not need to be root to read a lot of device properties, like manufacturer or serial number.
Another very good property of this interface is that it is semi-stable. That is, every device has unique id like a-b.c.d.e:x.y (a - bus number, b,c - root hub, next hub, port, etc.., x,y - function, subfunction), and this device enumeration is not going to abruptly shift for all devices if one device is connected or disconnected.
You can also easily map these device ids into libusb-style bus/device numbers (but those are not stable).
Unfortunately, this is Linux specific, and does not seem to be available for other operating systems. I wish libusb had implemented something like this, but it does not.
Anyway, good luck!

How can I prevent all USB mass storages from mounting?

I want to prevent every kind of USB mass storage from mounting using udev rules.
Already I can detect all of USB mass storage devices connected to my system using the following rule:
SUBSYSTEMS=="scsi", SUBSYSTEM=="block" KERNEL=="sd[b-h]1"
But how can I prevent them from mounting?
I know I have to set the authorized file of its relevant USB device to zero! But how can I find the USB device path? The $DEVPATH gives me the path of storage device block for example sdb1!
I have an application which should give permission to some of USB mass storage devices. So the used method for blocking the USB mass storage devices should not be very static!
The following rule prevents all except the first partition from being auto-mounted:
# Rule: Only mount first partition found on /dev/sd* (USB) devices.
ACTION=="add|change", SUBSYSTEM=="block", KERNEL=="sd*[2-9]", ENV{UDISKS_PRESENTATION_NOPOLICY}="1"
Reason: In USB disks with multiple partitions, I only want to automount the first one. I manually mount the others, if I want them.
You should be able to substitute the partition matcher with KERNEL=="sd*", to get:
# Rule: Do not automount any partitions found on /dev/sd* (USB) devices.
ACTION=="add|change", SUBSYSTEM=="block", KERNEL=="sd*", ENV{UDISKS_PRESENTATION_NOPOLICY}="1"
This prevents auto-mounting, which you can then manually manage.
I have only tested this on Ubuntu 10.10
The easiest way to do this is to blacklist the usb-storage kernel module. This will only work if it has been compiled as a module however, rather than directly into the kernel. You can check with modprobe -n usb-storage.ko, or by looking for it in /lib/modules/$(uname -r)/kernel/drivers/usb/storage/
If it's compiled as a module, you can black list it by adding an entry to /etc/modprobe.d/blacklist(.conf) For Debian, see this guide

Resources