Linux USB Mapping Question - python

I'm working on a utility that will auto mount an inserted USB stick on linux. I have tied into D-Bus to receive notification of when a device is inserted, and that works great. However, I need to determine which device in /dev is mapped to the inserted USB stick. I am getting the D-Bus notification and then scanning the USB system with pyUSB ( 0.4 ). I filter for USB_MASS_STORAGE_DEVICE classes, and I can see the device that's been added or removed. I need to mount this device so I can query it for available space and report that to our app so we can determine if enough free space exists so we can write our data.
I'm using python for this task. I'm not sure what our target distro will be, only that it will be at least 2.6
edit: My question is: How do I determine which device in /dev maps to the buss-device number I get from pyUSB.

You should probably ask HAL about that. You say you already get notifications from HAL by D-Bus... It maintains list of USB devices, together with their IDs and device names (block.device property).
Here's a nice example of how to get device file name together with the notification of new USB device: How can I listen for 'usb device inserted' events in Linux, in Python?

Why not use "os" module to mount the file system:
os.system ("mount ... ")
Or if you want to examine output use "popen":
l = op.popen ("mount ....").readlines()

what about using dmesg output to find out the device name (sdc1 etc...)
use it right after dbus tells you something is was inserted in USB. you could do tail dmesg for example

Related

How to distinguish identical USB-to-serial converter?

I have 2 identical USB-to-serial adapter cables (pretty much like this one) to connect a desktop PC under Ubuntu and some RS232 devices.
I develop a python software to pilot these devices.
I need to find a way to identify which one of the 2 adapters I am connected to.
I know about python's serial.tools.list_ports.comports() function, but all the settings are the exact same for both adapters (see capture below). Except the device, but it may change depending on the plugging order.
How can I change some settings' field to make both adapter pythonically distinguishable? Is it possible to write my own serial_number for example?
To solve this problem there are some alternative paths to serial devices in Linux.
There's either
/dev/serial/by-id/ and /dev/serial/by-path
variant to access your devices.
If this is always for a specific serial device, the normal way to do this is to use the udev program to create symlinks for you in /dev. There's a lot of different options for how to do this, either based on what physical port it's plugged into or based off of attributes of the device(e.g. serial number).
FTDI based devices all have a serial number associated with them, but since yours is a Prolific they don't have a serial number, so this becomes a bit harder. However, since we can use udev to create a symlink based on where it is plugged in, something like the following should work(put this in a file seen by udev, e.g. /etc/udev/rules.d/80-my-converter.rules):
SUBSYSTEM=="usb", KERNELS=="2-1.8.3", SYMLINK+="device_1"
SUBSYSTEM=="usb", KERNELS=="2-1.8.1.3", SYMLINK+="device_2"
The KERNELS parameter will have to change depending on where exactly you plug the serial device into and will be specific to your system. You can get a list of the udev parameters on your device by running the following:
udevadm info -a -n /dev/ttyUSB2
This page has more information on writing udev rules.

Python serial ports

I need to run both zigbee and SMS dongle on a raspberry pi, that means having to run both ports in a python script. Since xbee is always on ttyUSB0, is there a way I could set the dongle on ttyUSB1 or ttyUSB2 so that i dont have to configure it via gammu command everytime it is plugged in?
The best thing to do here is use a udev rule. This will allow you to symlink the device to a specific port, something like /dev/ttyXBEE and /dev/ttySMS in your case.
To accomplish this, you need to query the devices using udevadm to find some unique identifying information, then create a file /etc/udev/rules.d/99-usbserial.rules that will tell the Pi how to map the device.
This thread has an example.

Is it possible to find out which USB port a MIDI device is connected to in portmidi / pyportmidi

I'm connecting a several identical USB-MIDI devices and talking to them using Python and pyportmidi. I have noticed that when I run my code on Linux, occasionally the MIDI ports of the devices are enumerated in a different order, so I send messages to the wrong devices. As the devices do not have unique identifiers, I am told that I should identify them by which USB port they are connected to.
Is there any way to retrieve this information? My app will run on Linux, but Mac OS support is useful for development.
It's annoying because they usually enumerate in a sensible order - the first device in the hub is the first device in portmidi, but sometimes they don't - usually the first 2 devices are switched. I have to physically move the devices without unplugging to fix them.
lsusb should do the trick. All devices and their respective hubs are listed there.

Getting friendly device names in python

I have an 2-port signal relay connected to my computer via a USB serial interface. Using the pyserial module I can control these relays with ease. However, this is based on the assumption that I know beforehand which COM-port (or /dev-node) the device is assigned to.
For the project I'm doing that's not enough since I don't want to assume that the device always gets assigned to for example COM7 in Windows. I need to be able to identify the device programatically across the possible platforms (Win, Linux, OSX (which I imagine would be similar to the Linux approach)), using python. Perhaps by, as the title suggests, enumerate USB-devices on the system and somehow get more friendly names for them. Windows and Linux being the most important platforms to support.
Any help would be greatly appreciated!
EDIT:
Seems like the pyudev-module would be a good fit for Linux-systems. Has anyone had any experience with that?
Regarding Linux, if all you need is to enumerate devices, you can even skip pyudev dependency for your project, and simply parse the output of /sbin/udevadm info --export-db command (does not require root privileges). It will dump all information about present devices and classes, including USB product IDs for USB devices, which should be more then enough to identify your USB-to-serial adapters. Of course, you can also do this with pyudev.
I know this is an older post, but I was struggling with it today.
Ultimately I used the wmi library for python as I'm on a Windows machine (sorry, I know my answer only applies to Windows, but maybe it'll help someone).
Install the package using pip first:
pip install wmi
then
import wmi
c = wmi.WMI()
wql = "Select * From Win32_USBControllerDevice"
for item in c.query(wql):
print item.Dependent.Caption
Should result with something like:
USB Root Hub
USB Root Hub
Prolific USB-to-Serial Comm Port (COM9)
USB Root Hub
USB Root Hub
USB Composite Device
USB Video Device
USB Audio Device
USB Root Hub
...snip...
In this case, you'd have to string parse the Caption to find the COM port. You can also take a look at just the item. Dependent object to see other attributes of the USB device beside Caption that you may find relevant:
instance of Win32_PnPEntity
{
Caption = "USB Root Hub";
ClassGuid = "{36fc9e60-c465-11cf-8056-444553540000}";
ConfigManagerErrorCode = 0;
ConfigManagerUserConfig = FALSE;
CreationClassName = "Win32_PnPEntity";
Description = "USB Root Hub";
DeviceID = "USB\\ROOT_HUB\\4&32F13EF0&1";
HardwareID = {"USB\\ROOT_HUB&VID8086&PID3A36&REV0000",
"USB\\ROOT_HUB&VID8086&PID3A36", "USB\\ROOT_HUB"};
Manufacturer = "(Standard USB Host Controller)";
Name = "USB Root Hub";
PNPDeviceID = "USB\\ROOT_HUB\\4&32F13EF0&1";
Service = "usbhub";
Status = "OK";
SystemCreationClassName = "Win32_ComputerSystem";
SystemName = "001fbc0934d1";
};
At least for linux, you can use some dummy hacks to determine your /dev node, by inspecting for example the output of "ls /dev | grep ttyUSB" before and after you attach your device. This somehow must apply as well for the OSX case. A good idea is to inspect those commands using something like the subprocess.Popen() command. As for windows, this might be helpful.
Windows: you can pull USB information from WMI, but you need to be administrator. The examples are in .NET, but you should be able to use the Python WMI module. This will give you access to USB identification strings, which may contain useful information. For FTDI serial devices there is a short cut using FTDI's DLL, which does not require privileged access.
Linux: all the available information is under /sys/bus/usb, and also available through udev. This looks like a good answer.
As far as Windows goes, you could scan the registry:
import _winreg as reg
from itertools import count
key = reg.OpenKey(reg.HKEY_LOCAL_MACHINE, 'HARDWARE\\DEVICEMAP\\SERIALCOMM')
try:
for i in count():
device, port = reg.EnumValue(key, i)[:2]
print device, port
except WindowsError:
pass
It will be great if this is possible, but in my experience with commercial equipments using COM ports this is not the case. Most of the times you need to set manually in the software the COM port. This is a mess, specially in windows (at least XP) that tends to change the number of the com ports in certain cases. In some equipment there is an autodiscovery feature in the software that sends a small message to every COM port and waits for the right answer. This of course only works if the instrument implements some kind of identification command. Good luck.

RS232 Serial - USB Converter device path (/dev/ttyUSB*) not getting listed

I am using an RS232 Serial - USB Converter to connect to a controller. I am trying to connect to this port programmatically.
The device is getting listed as below when I give lsusb
Bus 003 Device 003: ID 05ad:0fba Y.C. Cable U.S.A., Inc.
But I am not able to see it's device path (something like /dev/ttyUSB*).
I would like to know the way to get the path from device id (or) a way to create / find the path which can be used to open the port from a program (Ruby, Python, C)
Centos has a fairly old kernel. It may be lacking in support for your device.
Are you able to try with a newer distribution (Fedora, Ubuntu, etc) to test whether it works or not? Failing that, do you have a different dongle you can use?
You can Google for "Centos 05ad:0fba" or similar combinations to find out whether it's supported.

Categories