Get unique serial number of USB device mounted to /dev folder - linux

I attach 2 webcam to computer and it was listed in /dev folder: /dev/video0; /dev/video1.
Can you help me write C code to get serial number of webcam with input: /dev/video[0;1]

Just ran into this same problem and it took a bit to find the solution. Any solution which starts with "just use lsusb" is incorrect. You can figure out the devices serial, but none of the extra information it provides help you determine which /dev/video it links to.
Solution:
/bin/udevadm info --name=/dev/video1 | grep SERIAL_SHORT
Output:
E: ID_SERIAL_SHORT=256DEC57

Based on the hint of using udevadm and the tutorial from http://www.signal11.us/oss/udev/ I got below code to get the serial info of my webcam.
#include "stdio.h"
#include <libudev.h>
int main(int argc, char **argv)
{
struct udev *udev;
struct udev_device *dev;
struct udev_enumerate *enumerate;
struct udev_list_entry *list, *node;
const char *path;
udev = udev_new();
if (!udev) {
printf("can not create udev");
return 0;
}
enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "video4linux");
udev_enumerate_scan_devices(enumerate);
list = udev_enumerate_get_list_entry(enumerate);
udev_list_entry_foreach(node, list) {
path = udev_list_entry_get_name(node);
dev = udev_device_new_from_syspath(udev, path);
printf("Printing serial for %s\n", path);
printf("ID_SERIAL=%s\n",
udev_device_get_property_value(dev, "ID_SERIAL"));
printf("ID_SERIAL_SHORT=%s\n",
udev_device_get_property_value(dev, "ID_SERIAL_SHORT"));
udev_device_unref(dev);
}
return 0;
}

You can use lsusb, but you need to add verbose flag and make sure you use sudo with it, otherwise the serial will be incorrect.
sudo lsusb -v
If that is too verbose, then run lsusb to get the device id:
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 012: ID 1ab1:0e11 Rigol Technologies
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Then run lsusb with device flag and grep the serial number.
So for the serial number of Rigol device:
$ sudo lsusb -s 012 -v|grep -i iserial
iSerial 3 DP8C221100000

Playing around with libusb, it looks like there's a standard getSerialNumber() method. Unfortunately, not all USB devices implement this. I have a couple cheap $4 webcams that return None for it. These interfaces expose other metadata, like VendorID and ProductID, which I've seen some code try and use as a unique identifier, but it's not guaranteed to be unique, especially if you have multiple devices of the same make and model.
But assuming you get a serial number for your device, the next problem is figuring out which /dev/videoN file it corresponds to. I have an old version of libusb installed, so I couldn't get the method working that returned the full sysfs path of the USB device, so instead I scrapped the output from hwinfo. I extracted all the chunks corresponding to cameras, and then from those I extracted the piece that looked like:
SysFS BusID: 1-1.2:1.0
USB devices actually form a complicated tree, and that BusID encodes where the device is located in that tree.
You can then take that BusID to find where the device lives in the filesystem as well as the video path, which should be at:
/sys/bus/usb/devices/<BusID>/video4linux/
That's a directory, and inside it you'll find a videoN file matching one in /dev.

Looking at lsusb you find out that it uses libusb, it has many functions, notably for usb device handling and enumeration. libudev might be relevant too.
Alternatively, popen the lsusb command...

Related

Using Findstr to find a serial number in a line

I am using devcon to query a verifone device to get the serial number and I a trying to find the serial number below "123-552-666" and output that to a text file. I have been playing around with various commands but just cant seem to get it.
I have used this:
findstr /RC:"[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9]" "verifone1.txt"
But just got this lie returned
USB\VID_11CA&PID_0300\123-552-666_____
Below is the full data I am searching. Would appreciate any assistance
USB\VID_11CA&PID_0300\123-552-666_____
Name: Verifone V,P Family USB UART device (COM7)
Driver is running.

How to identify identical USB dongles connected at the same time to an USBhub

I have an USBhub (D-Link DUB-H7) connected to my laptop with Windows 10. Connected to the hub are 4 identical PEAK dongles to talk to a CANbus. Now, my problem is to programmatically identify these 4 seperate dongles and knowing which one is which. The dongles are fixed in the hub.
To start I downloaded and installed USBDeview to view my devices. In the program I can see my 4 PCAN-USB dongles and I can see that their Instance ID are different. That's good, now I have my identifier. However, once I try to get the ID's with Python things aren't looking good. This is my following test program:
import win32com.client
wmi = win32com.client.GetObject("winmgmts:")
input("Connect the hub")
dongle_list = [(usb.name, usb.DeviceID) for usb in wmi.InstancesOf("Win32_USBHub")]
input("Disconnect the hub")
nod_list = [(usb.name, usb.DeviceID) for usb in wmi.InstancesOf("Win32_USBHub")]
diff = list(set(dongle_list) - set(nod_list))
for d in diff:
print(d)
Running this gives me only 2 new usb devices and the ID's point to the USBhub rather than the dongles connected to the hub. I also tried with wmi.InstancesOf("CIM_USBDevice") but the result stays the same.
('Generic USB Hub', 'USB\\VID_05E3&PID_0608\\5&4A43CD6&0&4')
('Generic USB Hub', 'USB\\VID_05E3&PID_0608\\6&9EBFB9C&0&4')
So how can I retrieve the usb information of the devices connected to the USBhub using Python or powershell/cmd invoked by Python?
Another route I was thinking I could take is by using port identifiers. If I disconnect a dongle I can see that it was connected to Port_#0001.Hub_#000x, where is x is a positive integer. So maybe I could poll the port to see if the dongle is connected and then I too know which one is which (dongles are fixed in the hub). Although I think that using the Instance ID is more foolproof.
I ended up creating a powershell command and invoke that using Python. I noticed however that the InstanceID's are hardware addresses of the the USBhub and not the dongles.
I also noticed that the dongles sometimes switch their addresses related on how they were connected. So I also needed to disable them and enable them again in the order I want.
This is what I have now:
poll_cmd = """
$ret = (Get-PnpDevice | ? {($_.description -like "*pcan*") -and ($_.status -eq "ok")} | sort instanceid).instanceid;
$ret | % {Disable-PnpDevice $_ -Confirm:$False};
$ret | % {Start-Sleep -Seconds 1; Enable-PnpDevice $_ -Confirm:$False};
$ret
"""
usbs = (
subprocess.check_output(["powershell.exe", poll_cmd])
.decode()
.strip()
.split("\r\n")
)
usbs holds the list of usb dongles I'm interested in.
However this gave me one more problem: UAC. I need admin rights to enable the usbs. And used the top answer from Request UAC elevation from within a Python script? to give my program admin rights.

What types of bluetooth devices exist?

I'm using bluetoothctl to check for device type (I need it to choose the right icon for the bluetooth device). I have found that so far exists phone and audio-card. Do you know where to find a list of all those types of bluetooth devices?
This is the output from bluetoothctl, and there is a field with Icon. All posible types from that field is what I'm interested in.
Device XX:XX:XX:XX:XX:XX (public)
Name: XXXXX
Alias: XXXXX
Class: 0x00240408
Icon: audio-card
The answer to this can be found by browsing the source of the bluez bluetooth stack in src/dbus-common.c.
At the time of writing this answer, the complete list is:
"audio-card"
"audio-headphones"
"audio-headset"
"camera-photo"
"camera-video"
"computer"
"input-gaming"
"input-keyboard"
"input-mouse"
"input-tablet"
"modem"
"multimedia-player"
"network-wireless"
"phone"
"printer"
"scanner"
"unknown"
"video-display"
With the help of gtk3-icon-browser I noticed that the Icon type from bluetoothctl corresponds with the theme-default icons.

alsa: How to programmatically find if a device is busy/in use using it name and without opening it

We have a Linux device which has a speaker and MIC devices. These devices are shared among different modules - example a VOIP call can use speaker, a hazard Warning system can use speaker, a Voice prompt can use a speaker etc:
There seems to be a function in ALSA which uses pcm to provide the status.
int snd_pcm_status (snd_pcm_t * pcm, snd_pcm_status_t * status)
However the *pcm is returned by snd_pcm_open. We do not want to open the device as we would like to know the status of the device using its "name"
Alsa API is here
How can we check if a resource/device is busy without opening it and using its name?
The same information for playback stream X of device Y on card Z is available in the file /proc/asound/cardZ/pcmYp/subX/status; when the device is not open, it just says "closed".
Please note that you cannot use this information to decide if you can open the device, because some other process could have openend it just after you've read this information. The only way to check if you can open it is to actually try.
Though it requires /dev/dsp, this seems to work:
#!/bin/dash
## If the speaker is not used by any, returns 0, and prints "free"
## Otherwise, returns 1 and prints "not free"
iExit (){
trap '' 0
exit $1
}
iCatch (){
# The speaker is already in use
echo not free
iExit 1
}
trap iCatch 0
{
exec 3>&1 1>/dev/dsp
# If the execution reaches here, the speaker is not used by any
# Otherwise, it's catched by iCatch
exec 1>&3
echo free
iExit 0
} 2>/dev/null
Without PulseAudio, it seems on some PC only one output is accepted at one time; on others simultaneous playbacks are allowed. But even in the latter case, the above code works.
NB: The above code does not work with bash; for bash, simply use if/else rather than trap.
NB 2: /dev/dsp may be lacking depending on the kernel configuration.

Reading USB input stream on linux

I'm working on an embedded linux machine and trying to read a USB devices input stream, but for some reason I don't have any such thing in my /dev directory. I would assume it would be something like /dev/ttyUSB01 or /dev/input/usb or something similar, but it's not there. dmesg returns the following
[ 195.863911] input: GIT GIT USB READER as /class/input/input2
[ 195.864259] generic-usb 0003:1234:5678.0001: input: USB HID v1.00 Keyboard [GIT GIT USB READER] on usb-0000:00:0f.4-1/input0
I've scanned through /sys/class/input/input2 and I am not really sure what I'm looking for. Maybe someone could point me in the right direction?
Had the same problem a few days ago and we discovered this workaround.
You could do the following command at the terminal:
cat /proc/bus/input/devices
This will list your devices connected, and your devices should be on the list. For instance, one item on there appears this way for me:
I: Bus=0011 Vendor=0002 Product=000a Version=0000
N: Name="TPPS/2 IBM TrackPoint"
P: Phys=synaptics-pt/serio0/input0
S: Sysfs=/devices/platform/i8042/serio4/serio5/input/input15
U: Uniq=
H: Handlers=mouse1 event15
B: PROP=0
B: EV=7
B: KEY=70000 0 0 0 0
B: REL=3
Under Handlers, you'll notice that event15 shows up. You can access the data stream by referencing /dev/input/event15 in my case. You'll have to figure out what it is in your case
Check out /dev/input/by-path and look for your usb-0000:00:0f.4-1. On my Ubuntu box that's a symbolic link to the device.
Have you tried using mdev? It's a lightweight alternative to udev and it populates /dev. If hotplugging is not enabled you might need to run it manually.
To scan /sys and create devices, try:
mdev -s

Resources