vpelletier / python-libusb1

Python ctype-based wrapper around libusb1
GNU Lesser General Public License v2.1
174 stars 67 forks source link

usb1.USBErrorAccess: LIBUSB_ERROR_ACCESS [-3] #34

Closed bernardoaraujor closed 6 years ago

bernardoaraujor commented 6 years ago

Source:

import usb1

# Bus 003 Device 012: ID 1d57:fa20 Xenta
VENDOR_ID = 0x1D57
PRODUCT_ID = 0xFA20

with usb1.USBContext() as context:
    handle = context.openByVendorIDAndProductID(
        VENDOR_ID,
        PRODUCT_ID,
        skip_on_error=True,
    )
    if handle is None:
        print('Device not present, or user is not allowed to access device.')
    else:
        print(handle)

Error:

/usr/bin/python2.7 /home/bernardo/dev/psumon/psumon/tmp.py
Traceback (most recent call last):
  File "/home/bernardo/dev/psumon/psumon/tmp.py", line 12, in <module>
    skip_on_error=True,
  File "/usr/lib/python2.7/site-packages/usb1/__init__.py", line 2298, in openByVendorIDAndProductID
    return result.open()
  File "/usr/lib/python2.7/site-packages/usb1/__init__.py", line 2067, in open
    mayRaiseUSBError(libusb1.libusb_open(self.device_p, byref(handle)))
  File "/usr/lib/python2.7/site-packages/usb1/__init__.py", line 133, in mayRaiseUSBError
    __raiseUSBError(value)
  File "/usr/lib/python2.7/site-packages/usb1/__init__.py", line 125, in raiseUSBError
    raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
usb1.USBErrorAccess: LIBUSB_ERROR_ACCESS [-3]

Process finished with exit code 1

Works fine when I invoke it with sudo:

$ sudo python tmp.py 
<usb1.USBDeviceHandle object at 0x7f3d2e170fd0>

I reckon from looking at python-libusb1/usb1/libusb1.py that LIBUSB_ERROR_ACCESS [-3] means Access denied (insufficient permissions). Do I need to set any kinds of permission in my system before I can use this package?

Also, which value should INTERFACE hold in the following code?

    with handle.claimInterface(INTERFACE):
        # Do stuff with endpoints on claimed interface.
vpelletier commented 6 years ago

LIBUSB_ERROR_ACCESS [-3] means Access denied (insufficient permissions).

Correct.

Do I need to set any kinds of permission in my system before I can use this package?

Yes. The way I personally do is using udev rules to tag the device with uaccess so that current session can access the device:

$ cat /etc/udev/rules.d/60-edison.rules
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="8087", ATTR{idProduct}=="0a99", TAG+="uaccess"

Or I directly set device's group to plugdev and make the user member of that group (old fashion). In the case of this device I have an extra rule to trigger a firmware load when default device id appears, and then it reappears as another idProduct and I finally grant access, but I could just as well have used uaccess here:

$ cat /etc/udev/rules.d/ITI1480A.rules
ACTION!="add", GOTO="ITI_rules_end"
SUBSYSTEM!="usb", GOTO="ITI_rules_end"
ATTR{idVendor}!="16c0", GOTO="ITI_rules_end"

ATTR{idProduct}=="07a8", GROUP="plugdev"
ATTR{idProduct}=="07a8", RUN+="ITI1480A.sh '$attr{busnum}' '$attr{devnum}' '/lib/firmware/ITI1480A.ihx'"
ATTR{idProduct}=="07a9", SYMLINK="ITI1480A%n", GROUP="plugdev"

LABEL="ITI_rules_end"

Also, which value should INTERFACE hold in the following code?

This depends on the device you want to control. Typically, there is a single interface, numbered 0, like in the following case (bInterfaceNumber):

$ lsusb -vd 1d6b:0002

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Couldn't open device, some information will be missing
Device Descriptor:
[...]
  Configuration Descriptor:
[...]
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         9 Hub
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0 Full speed (or root) hub
      iInterface              0
      Endpoint Descriptor:
[...]
bernardoaraujor commented 6 years ago

Thanks for the response @vpelletier !

Why do you have GOTO="ITI_rules_end" in every line of /etc/udev/rules.d/ITI1480A.rules?

Also, In case of the rule RUN+="ITI1480A.sh '$attr{busnum}' '$attr{devnum}' '/lib/firmware/ITI1480A.ihx'", where is ITI1480A.sh placed in your system?

I'm writing a similar script (not necessarily to load firmware), but I don't know where to place it, and I'm a bit insecure about udev scripting rules.

vpelletier commented 6 years ago

Why do you have GOTO="ITI_rules_end" in every line of /etc/udev/rules.d/ITI1480A.rules?

Not really on every line, only the first ones, which are narrowing down the event types. Non-interesting events are skipped by telling udev to go to the end of script, hence skipping the event. Maybe not the simplest way. I believe I just mimicked how it was done in another file, which had more rules.

where is ITI1480A.sh placed in your system?

It's at /lib/udev/ITI1480A.sh. I expect this to be part of the udev doc for RUN.

romainjouin commented 3 years ago

How do we do that in Mac OS ?

xingheng commented 5 months ago

How do we do that in Mac OS ?

Any new findings on this? @romainjouin

vpelletier commented 5 months ago

I do not have direct experience with Mac OS. Such need should be independent from the present project (python wrapper), so I guess you should have more chance checking libusb.info directly - including C-implemented projects to see how they achieve that.