sdbbs
sdbbs

Reputation: 5384

Is it possible to obtain USB device node (file) with Python (PyUSB)?

I am trying to find a way to iterate over all USB devices on a Raspberry Pi, and print out Vendor ID, Product ID, manufacturer name, and device node; via posts like:

... I understood I could use PyUSB - but I'm having lots of trouble, similar to:

... which that post does not answer.

So here is my test case - I have this on the Raspberry Pi Raspbian Stretch:

pi@raspberry:~ $ apt-show-versions -r libusb
libusb-0.1-4:armhf/stretch 2:0.1.12-30 uptodate
libusb-1.0-0:armhf/stretch 2:1.0.21-1 uptodate
libusbmuxd4:armhf/stretch 1.0.10-3 uptodate

I installed PyUSB with:

sudo pip3 install pyusb

As an example, I've connected an Arduino UNO to the Raspberry Pi; tail -f /var/log/syslog prints this upon USB connection:

...
Jun 23 09:35:01 raspberry kernel: [71431.582554] usb 1-1.2: new full-speed USB device number 7 using dwc_otg
Jun 23 09:35:01 raspberry kernel: [71431.726403] usb 1-1.2: New USB device found, idVendor=2341, idProduct=0043, bcdDevice= 0.01
Jun 23 09:35:01 raspberry kernel: [71431.726420] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=220
Jun 23 09:35:01 raspberry kernel: [71431.726431] usb 1-1.2: Manufacturer: Arduino (www.arduino.cc)
Jun 23 09:35:01 raspberry kernel: [71431.726440] usb 1-1.2: SerialNumber: 64131383231351C03272
Jun 23 09:35:01 raspberry mtp-probe: checking bus 1, device 7: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2"
Jun 23 09:35:01 raspberry mtp-probe: bus: 1, device: 7 was not an MTP device
Jun 23 09:35:01 raspberry kernel: [71431.778630] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device
Jun 23 09:35:01 raspberry kernel: [71431.779553] usbcore: registered new interface driver cdc_acm
Jun 23 09:35:01 raspberry kernel: [71431.779562] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
...

So, I know that Vendor ID is 0x2341 (apparently, hex), Product ID is 0x0043 (apparently, hex), manufacturer name is Arduino (www.arduino.cc), and device node/file is /dev/ttyACM0; and I simply want to print this out for all USB devices that are connected to the system via PyUSB.

Now, there is a bit of confusion online, since apparently, you can iterate over USB devices in PyUSB in two ways: the old "legacy" way, and the "new" way/API. So, I made a test script which tries them both, which I call test-usb.py:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import usb.core
import usb.util

print("This is 'old' PyUSB style iteration - uses legacy:")
busses = usb.busses()  # SO:8110310
for bus in busses:
  print(type(bus)) # <class 'usb.legacy.Bus'>
  devices = bus.devices
  for dev in devices:
    if dev != None:
      try:
        xdev = usb.core.find(idVendor=dev.idVendor, idProduct=dev.idProduct)
        if xdev._manufacturer is None:
          xdev._manufacturer = usb.util.get_string(xdev, xdev.iManufacturer)
        if xdev._product is None:
          xdev._product = usb.util.get_string(xdev, xdev.iProduct)
        stx = "USB VID: 0x{:04X} PID: 0x{:04X} Mfr name '{}' Product '{}'".format(dev.idVendor, dev.idProduct, str(xdev._manufacturer).strip(), str(xdev._product).strip(), dev.filename)
        print( stx )
        try:
          print("xdev.filename: '{}'".format(xdev.filename))
        except Exception as e:
          print("xdev.filename exception: {}".format(e))
        try:
          print("dev.filename: '{}'".format(dev.filename))
        except Exception as e:
          print("dev.filename exception: {}".format(e))
      except Exception as e:
        print("Exception: {}".format(e))

print()

def print_internals(dev): # SO: 18224189
  for attrib in dir(dev):
    if not attrib.startswith('_') and not attrib == 'configurations':
      try:
        x=getattr(dev, attrib)
        print( "  ", attrib, x)
      except Exception as e:
        print("Exception for attrib '{}': {}".format(attrib, e))
  try:
    for config in dev.configurations:
      for attrib in dir(config):
        if not attrib.startswith('_'):
          try:
            x=getattr(config, attrib)
            print( "  ", attrib, x)
          except Exception as e:
            print("Exception for attrib '{}': {}".format(attrib, e))
  except Exception as e:
    print("Exception config in dev.configurations: {}".format(e))

print("This is 'new' PyUSB style iteration - does not use legacy:")
for xdev in usb.core.find(find_all=True): # SO:9577601
  print(type(xdev)) # <class 'usb.core.Device'>
  try:
    if xdev._manufacturer is None:
      xdev._manufacturer = usb.util.get_string(xdev, xdev.iManufacturer)
  except Exception as e:
    print("Exception: {}".format(e))
  try:
    if xdev._product is None:
      xdev._product = usb.util.get_string(xdev, xdev.iProduct)
  except Exception as e:
    print("Exception: {}".format(e))
  stx = "USB VID: 0x{:04X} PID: 0x{:04X} Mfr name '{}' Product '{}'".format(xdev.idVendor, xdev.idProduct, str(xdev._manufacturer).strip(), str(xdev._product).strip())
  print( stx )
  try:
    print("xdev.filename: '{}'".format(xdev.filename))
  except Exception as e:
    print("xdev.filename exception: {}".format(e))
  print_internals(xdev)

The above script outputs:

pi@raspberry:~ $ python3 test-usb.py
This is 'old' PyUSB style iteration - uses legacy:
<class 'usb.legacy.Bus'>
Exception: The device has no langid
USB VID: 0x0424 PID: 0x7800 Mfr name 'None' Product 'None'
xdev.filename exception: 'Device' object has no attribute 'filename'
dev.filename: ''
USB VID: 0x0424 PID: 0x2514 Mfr name 'None' Product 'None'
xdev.filename exception: 'Device' object has no attribute 'filename'
dev.filename: ''
USB VID: 0x0424 PID: 0x2514 Mfr name 'None' Product 'None'
xdev.filename exception: 'Device' object has no attribute 'filename'
dev.filename: ''
Exception: The device has no langid

This is 'new' PyUSB style iteration - does not use legacy:
<class 'usb.core.Device'>
Exception: The device has no langid
Exception: The device has no langid
USB VID: 0x2341 PID: 0x0043 Mfr name 'None' Product 'None'
xdev.filename exception: 'Device' object has no attribute 'filename'
   address 7
   attach_kernel_driver <bound method Device.attach_kernel_driver of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   bDescriptorType 1
   bDeviceClass 2
   bDeviceProtocol 0
   bDeviceSubClass 0
   bLength 18
   bMaxPacketSize0 8
   bNumConfigurations 1
   backend <usb.backend.libusb1._LibUSB object at 0x7680f510>
   bcdDevice 1
   bcdUSB 272
   bus 1
   clear_halt <bound method Device.clear_halt of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   ctrl_transfer <bound method Device.ctrl_transfer of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   default_timeout 1000
   detach_kernel_driver <bound method Device.detach_kernel_driver of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   finalize <bound method AutoFinalizedObject.finalize of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   get_active_configuration <bound method Device.get_active_configuration of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   iManufacturer 1
   iProduct 2
   iSerialNumber 220
   idProduct 67
   idVendor 9025
   is_kernel_driver_active <bound method Device.is_kernel_driver_active of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   langids ()
Exception for attrib 'manufacturer': The device has no langid
   port_number 2
   port_numbers (1, 2)
Exception for attrib 'product': The device has no langid
   read <bound method Device.read of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   reset <bound method Device.reset of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
Exception for attrib 'serial_number': The device has no langid
   set_configuration <bound method Device.set_configuration of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   set_interface_altsetting <bound method Device.set_interface_altsetting of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
   speed 2
   write <bound method Device.write of <DEVICE ID 2341:0043 on Bus 001 Address 007>>
Exception config in dev.configurations: 'method' object is not iterable
<class 'usb.core.Device'>
USB VID: 0x0424 PID: 0x7800 Mfr name 'None' Product 'None'
xdev.filename exception: 'Device' object has no attribute 'filename'
   address 4
   attach_kernel_driver <bound method Device.attach_kernel_driver of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   bDescriptorType 1
   bDeviceClass 255
   bDeviceProtocol 255
   bDeviceSubClass 0
   bLength 18
   bMaxPacketSize0 64
   bNumConfigurations 1
   backend <usb.backend.libusb1._LibUSB object at 0x7680f510>
   bcdDevice 768
   bcdUSB 528
   bus 1
   clear_halt <bound method Device.clear_halt of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   ctrl_transfer <bound method Device.ctrl_transfer of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   default_timeout 1000
   detach_kernel_driver <bound method Device.detach_kernel_driver of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   finalize <bound method AutoFinalizedObject.finalize of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   get_active_configuration <bound method Device.get_active_configuration of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   iManufacturer 0
   iProduct 0
   iSerialNumber 0
   idProduct 30720
   idVendor 1060
   is_kernel_driver_active <bound method Device.is_kernel_driver_active of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   langids ()
   manufacturer None
   port_number 1
   port_numbers (1, 1, 1)
   product None
   read <bound method Device.read of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   reset <bound method Device.reset of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   serial_number None
   set_configuration <bound method Device.set_configuration of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   set_interface_altsetting <bound method Device.set_interface_altsetting of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
   speed 3
   write <bound method Device.write of <DEVICE ID 0424:7800 on Bus 001 Address 004>>
Exception config in dev.configurations: 'method' object is not iterable
<class 'usb.core.Device'>
USB VID: 0x0424 PID: 0x2514 Mfr name 'None' Product 'None'
xdev.filename exception: 'Device' object has no attribute 'filename'
   address 3
   attach_kernel_driver <bound method Device.attach_kernel_driver of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   bDescriptorType 1
   bDeviceClass 9
   bDeviceProtocol 2
   bDeviceSubClass 0
   bLength 18
   bMaxPacketSize0 64
   bNumConfigurations 1
   backend <usb.backend.libusb1._LibUSB object at 0x7680f510>
   bcdDevice 2995
   bcdUSB 512
   bus 1
   clear_halt <bound method Device.clear_halt of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   ctrl_transfer <bound method Device.ctrl_transfer of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   default_timeout 1000
   detach_kernel_driver <bound method Device.detach_kernel_driver of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   finalize <bound method AutoFinalizedObject.finalize of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   get_active_configuration <bound method Device.get_active_configuration of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   iManufacturer 0
   iProduct 0
   iSerialNumber 0
   idProduct 9492
   idVendor 1060
   is_kernel_driver_active <bound method Device.is_kernel_driver_active of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   langids ()
   manufacturer None
   port_number 1
   port_numbers (1, 1)
   product None
   read <bound method Device.read of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   reset <bound method Device.reset of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   serial_number None
   set_configuration <bound method Device.set_configuration of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   set_interface_altsetting <bound method Device.set_interface_altsetting of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
   speed 3
   write <bound method Device.write of <DEVICE ID 0424:2514 on Bus 001 Address 003>>
Exception config in dev.configurations: 'method' object is not iterable
<class 'usb.core.Device'>
USB VID: 0x0424 PID: 0x2514 Mfr name 'None' Product 'None'
xdev.filename exception: 'Device' object has no attribute 'filename'
   address 2
   attach_kernel_driver <bound method Device.attach_kernel_driver of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   bDescriptorType 1
   bDeviceClass 9
   bDeviceProtocol 2
   bDeviceSubClass 0
   bLength 18
   bMaxPacketSize0 64
   bNumConfigurations 1
   backend <usb.backend.libusb1._LibUSB object at 0x7680f510>
   bcdDevice 2995
   bcdUSB 512
   bus 1
   clear_halt <bound method Device.clear_halt of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   ctrl_transfer <bound method Device.ctrl_transfer of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   default_timeout 1000
   detach_kernel_driver <bound method Device.detach_kernel_driver of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   finalize <bound method AutoFinalizedObject.finalize of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   get_active_configuration <bound method Device.get_active_configuration of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   iManufacturer 0
   iProduct 0
   iSerialNumber 0
   idProduct 9492
   idVendor 1060
   is_kernel_driver_active <bound method Device.is_kernel_driver_active of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   langids ()
   manufacturer None
   port_number 1
   port_numbers (1,)
   product None
   read <bound method Device.read of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   reset <bound method Device.reset of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   serial_number None
   set_configuration <bound method Device.set_configuration of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   set_interface_altsetting <bound method Device.set_interface_altsetting of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
   speed 3
   write <bound method Device.write of <DEVICE ID 0424:2514 on Bus 001 Address 002>>
Exception config in dev.configurations: 'method' object is not iterable
<class 'usb.core.Device'>
Exception: The device has no langid
Exception: The device has no langid
USB VID: 0x1D6B PID: 0x0002 Mfr name 'None' Product 'None'
xdev.filename exception: 'Device' object has no attribute 'filename'
   address 1
   attach_kernel_driver <bound method Device.attach_kernel_driver of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   bDescriptorType 1
   bDeviceClass 9
   bDeviceProtocol 1
   bDeviceSubClass 0
   bLength 18
   bMaxPacketSize0 64
   bNumConfigurations 1
   backend <usb.backend.libusb1._LibUSB object at 0x7680f510>
   bcdDevice 1049
   bcdUSB 512
   bus 1
   clear_halt <bound method Device.clear_halt of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   ctrl_transfer <bound method Device.ctrl_transfer of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   default_timeout 1000
   detach_kernel_driver <bound method Device.detach_kernel_driver of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   finalize <bound method AutoFinalizedObject.finalize of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   get_active_configuration <bound method Device.get_active_configuration of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   iManufacturer 3
   iProduct 2
   iSerialNumber 1
   idProduct 2
   idVendor 7531
   is_kernel_driver_active <bound method Device.is_kernel_driver_active of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   langids ()
Exception for attrib 'manufacturer': The device has no langid
   port_number 0
   port_numbers None
Exception for attrib 'product': The device has no langid
   read <bound method Device.read of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   reset <bound method Device.reset of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
Exception for attrib 'serial_number': The device has no langid
   set_configuration <bound method Device.set_configuration of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   set_interface_altsetting <bound method Device.set_interface_altsetting of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
   speed 3
   write <bound method Device.write of <DEVICE ID 1d6b:0002 on Bus 001 Address 001>>
Exception config in dev.configurations: 'method' object is not iterable

So, the only thing I could get to, is USB VID: 0x2341 PID: 0x0043; the exception The device has no langid prevents retrieval of manufacturer and product name (and there are a ton of other exceptions, too)

And no one knows where the device node/path is: apparently, there used to be a dev.filename in the "legacy" mode, which maybe at a certain point in the past, maybe did contain the device node/file /dev/ttyACM0 - but now seemingly does not anymore, as it is empty; and I couldn't find a mention of where that information resides in the "new" API (if it's there).

So - how can I iterate over all USB devices in Python 3 in Linux, and print out Vendor ID, Product ID, manufacturer name, and device node filename? If this is not possible with PyUSB - what other options do I have in terms of Python libraries (I'd like to avoid parsing /var/log/syslog or /dev/bus manually)?

Upvotes: 1

Views: 3357

Answers (1)

sdbbs
sdbbs

Reputation: 5384

Ok, I think I got somewhere.

First, it is no longer possible to obtain device node (file) via PyUSB:

filename not work and not list all device attach with usb · Issue #165 · pyusb/pyusb · GitHub

Filenames are no longer supported: the legacy API returns empty strings (and libusb-compat fakes them with the address number).

Second, a device node like for the Arduino UNO only exists for a USB devices that expose a USB serial port (or in other words, for devices for which the OS loads a USB-serial kernel driver); a different USB class (I guess, like mass storage device), would probably not expose a similar device node.

Third, as far as the problem with "langid" goes:

ValueError: The device has no langid · Issue #139 · pyusb/pyusb · GitHub

However in some of the other comments it is a question of permissions: If you don't have permissions you cannot retrieve the langid nor the serial number/manufacturer/product strings.

...

The most common cause for ValueError: The device has no langid is simply lack of permission to access the device. Try running your program with sudo and, if that works, consider using a udev rule to grant access to the device to the unprivileged users.

So, since I don't want to run my script as sudo, and I don't want to write a udev rule - the only way to retrieve this info I found, was to use PyUSB to just iterate over VendorIDs and ProductIDs; then pass this over to pyudev, from where we can find the device node, if it is a USB serial device - and in that case, we can also retrieve Manufacturer and Product strings.

Here is the script - again called test-usb.py:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import usb.core # sudo pip3 install pyusb
import usb.util
import pyudev # sudo pip3 install pyudev
import inspect

pyudev_context = pyudev.Context() # SO:8110310 -> github.com/dhylands/usb-ser-mon (find_port.py)

#for device in pyudev_context.list_devices(subsystem='tty'):
#  print( device.device_node )
#  # note: device.properties['ID_VENDOR_ID'] is a string, hex representation of the ID number, without "0x" prefix
#  try:
#    print( type( device.properties['ID_VENDOR_ID'] ) )
#  except Exception as e:
#    print( e )
#  try:
#    print( device.properties['ID_MODEL_ID'] )
#  except Exception as e:
#    print( e )


for xdev in usb.core.find(find_all=True):
  langids_str = ""
  try:
    langids_str = usb.util.get_langids(xdev)
  except Exception as e:
    langids_str = e

  ## trying to set _langids without sudo, will get rid of the 'ValueError: The device has no langid',
  ## however, mostly we'll just get '[Errno 13] Access denied (insufficient permissions)' instead
  #if xdev._langids is None:
  #  xdev._langids = (1033,)

  try:
    mfr_str = usb.util.get_string(xdev, xdev.iManufacturer)
  except Exception as e:
    mfr_str = e

  try:
    prod_str = usb.util.get_string(xdev, xdev.iProduct)
  except Exception as e:
    prod_str = e

  # check if it is USB serial device, with a device node/filename
  devnode_str = "No device node"
  vidhex_str = "{:04X}".format(xdev.idVendor)
  pidhex_str = "{:04X}".format(xdev.idProduct)
  for device in pyudev_context.list_devices(subsystem='tty'):
    try:
      if ( (vidhex_str.lower() == device.properties['ID_VENDOR_ID'].lower() ) and (pidhex_str.lower() == device.properties['ID_MODEL_ID'].lower()) ):
        devnode_str = "{} ({} ; {})".format(device.device_node, device.properties['ID_VENDOR'], device.properties['ID_MODEL_FROM_DATABASE'] )
        #for ikey in device.properties.keys(): print(ikey)
    except:
      pass

  out_str = "VID: 0x{}, PID: 0x{}, devnode: {}, langids: '{}', Mfr: '{}', Prod: '{}'".format(
    vidhex_str, pidhex_str, devnode_str, langids_str, mfr_str, prod_str
  )
  print(out_str)

## for ikey in device.properties.keys(): print(ikey):
# DEVLINKS
# DEVNAME
# DEVPATH
# ID_BUS
# ID_MODEL
# ID_MODEL_ENC
# ID_MODEL_FROM_DATABASE
# ID_MODEL_ID
# ID_PATH
# ID_PATH_TAG
# ID_REVISION
# ID_SERIAL
# ID_SERIAL_SHORT
# ID_TYPE
# ID_USB_CLASS_FROM_DATABASE
# ID_USB_DRIVER
# ID_USB_INTERFACES
# ID_USB_INTERFACE_NUM
# ID_VENDOR
# ID_VENDOR_ENC
# ID_VENDOR_FROM_DATABASE
# ID_VENDOR_ID
# MAJOR
# MINOR
# SUBSYSTEM
# TAGS
# USEC_INITIALIZED

Here is what the script outputs on a Raspberry Pi/Stretch with Arduino UNO connected - with sudo:

pi@raspberry:~ $ sudo python3 test-usb.py
VID: 0x2341, PID: 0x0043, devnode: /dev/ttyACM0 (Arduino__www.arduino.cc_ ; Uno R3 (CDC ACM)), langids: '(1033,)', Mfr: 'Arduino (www.arduino.cc)', Prod: '[Errno 32] Pipe error'
VID: 0x0424, PID: 0x7800, devnode: No device node, langids: '[Errno 32] Pipe error', Mfr: 'None', Prod: 'None'
VID: 0x0424, PID: 0x2514, devnode: No device node, langids: '[Errno 32] Pipe error', Mfr: 'None', Prod: 'None'
VID: 0x0424, PID: 0x2514, devnode: No device node, langids: '[Errno 32] Pipe error', Mfr: 'None', Prod: 'None'
VID: 0x1D6B, PID: 0x0002, devnode: No device node, langids: '(1033,)', Mfr: 'Linux 4.19.66-v7+ dwc_otg_hcd', Prod: 'DWC OTG Controller'

Here is what it outputs without sudo:

pi@raspberry:~ $ python3 test-usb.py
VID: 0x2341, PID: 0x0043, devnode: /dev/ttyACM0 (Arduino__www.arduino.cc_ ; Uno R3 (CDC ACM)), langids: '[Errno 13] Access denied (insufficient permissions)', Mfr: 'The device has no langid', Prod: 'The device has no langid'
VID: 0x0424, PID: 0x7800, devnode: No device node, langids: '[Errno 13] Access denied (insufficient permissions)', Mfr: 'None', Prod: 'None'
VID: 0x0424, PID: 0x2514, devnode: No device node, langids: '[Errno 13] Access denied (insufficient permissions)', Mfr: 'None', Prod: 'None'
VID: 0x0424, PID: 0x2514, devnode: No device node, langids: '[Errno 13] Access denied (insufficient permissions)', Mfr: 'None', Prod: 'None'
VID: 0x1D6B, PID: 0x0002, devnode: No device node, langids: '[Errno 13] Access denied (insufficient permissions)', Mfr: 'The device has no langid', Prod: 'The device has no langid'

Note that the Arduino Uno, seemingly, does not have a product string description exposed via USB - and correspondingly, in pyudev, device.properties['ID_MODEL'] for it prints just 0043 - but device.properties['ID_MODEL_FROM_DATABASE'] prints the actual model name.

Upvotes: 1

Related Questions