Python : PyUSB can't access usb device - python

I am trying to read an usb bar code reader from my python script, via the https://github.com/pyusb/pyusb library.
import usb.core
import usb.util
VENDOR_ID = 8208
PRODUCT_ID = 30264
dev = usb.core.find(idVendor=VENDOR_ID,
idProduct=PRODUCT_ID)
dev.set_configuration()
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
ep = usb.util.find_descriptor(
intf,
# match the first OUT endpoint
custom_match = \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_IN)
data = ep.read(ep.wMaxPacketSize, 8000000)
Unfortunately, this leads to a "USBError: [Errno 13] Access denied (insufficient permissions)" issue.
I tried to run the script as a sudo, but it didn't help. The script work fine on my Ubuntu laptop, but I am now trying to move it to Mac OS. One of the differences is that I do have a "detach_kernel" before hand on Linux, but this function make a fail with "not implemented on this OS" error with Mac Os...

Related

PyUsb: "insufficient permissions". macOS Big Sur

I'm following this tutorial for pyusb but when I get this far into the code, I get the error: raise USBError(_strerror(ret), ret, _libusb_errno[ret]) usb.core.USBError: [Errno 13] Access denied (insufficient permissions). Here is the code I wrote:
import usb.core
import usb.util
VID = 0x046d
PID = 0xc07e
dev = usb.core.find(idVendor=VID, idProduct=PID)
ep = dev[0].interfaces()[0].endpoints()[0]
i = dev[0].interfaces()[0].bInterfaceNumber
dev.reset()
if dev.is_kernel_driver_active(i):
dev.detach_kernel_driver(i)
r = dev.read(eaddr, 1024)
print(len(r))
As I said in the title, I'm on macOS Big Sur Version 11.4 and I'm trying to read from Bus 020 Device 029: ID 046d:c07e Logitech Inc. Gaming Mouse G402.
Thanks.
The error says "Access denied (insufficient permissions)". You have to run your code with sudo. Like: "sudo python3 <yourscript.py>".

No module named usb.core

How can I remove this error in the below mentioned program? The error iI'm getting is
ImportError: No module named usb.core
and my code is:
import usb.core
import usb.util
# find our device
dev = usb.core.find(idVendor=0xfffe, idProduct=0x0001)
# was it found?
if dev is None:
raise ValueError('Device not found')
# set the active configuration. With no arguments, the first
# configuration will be the active one
dev.set_configuration()
# get an endpoint instance
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
ep = usb.util.find_descriptor(
intf,
# match the first OUT endpoint
custom_match = \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_OUT)
assert ep is not None
# write the data
ep.write('test')
OS is windows 8 64-bit [...]
ValueError: No backend available
Allow me to translate: You forgot to install the correct USB driver.
USB devices need a driver to work in Windows. Look at PyUSB website for details, and use Zadig to generate and install the driver (e.g. LibUSB-Win32) for you. This program takes care of the certificate that Windows 8 wants to see for your drivers inf file.
Btw: The VID you should use for USB development is 0x4242.
For error:
C:\Users\RAHUL\Desktop\python progrms\USBsample.py, line 5, in <module>
dev = usb.core.find(idVendor=0xfffe, idProduct=0x0001) File "C:\Python27\lib\site-
packages\usb\core.py", line 864, in find raise ValueError('No backend available')
ValueError: No backend available
Download and install libusb-win32-devel-filter-1.2.6.0.exe. It should work.
python -m pip install pyusb libusb
Fixed this for me.

Executable out of script containing serial_for_url

I have developed a python script for making a serial communication to a digital pump. I now need to make an executable out of it. However even though it works perfectly well when running it with python and py2exe does produce the .exe properly when I run the executable the following error occurs:
File: pump_model.pyc in line 96 in connect_new
File: serial\__init__.pyc in line 71 in serial_for_url
ValueError: invalid URL protocol 'loop' not known
The relevant piece of my code is the following:
# New serial connection
def connect_new(self, port_name):
"""Function for configuring a new serial connection."""
try:
self.ser = serial.Serial(port = port_name,\
baudrate = 9600,\
parity = 'N',\
stopbits = 1,\
bytesize = 8,\
timeout = self.timeout_time)
except serial.SerialException:
self.ser = serial.serial_for_url('loop://',\
timeout = self.timeout_time) # This line BLOWS!
except:
print sys.exc_info()[0]
finally:
self.initialize_pump()
I should note that the application was written in OSX and was tested on Windows with the Canopy Python Distribution.
I had the exact same problem with "socket://" rather than "loop://"
I wasn't able to get the accepted answer to work however the following seems to succeed:
1) Add an explicit import of the offending urlhandler.* module
import serial
# explicit import for py2exe - to fix "socket://" url issue
import serial.urlhandler.protocol_socket
# explicit import for py2exe - to fix "loop://" url issue (OP's particular prob)
import serial.urlhandler.protocol_loop
# use serial_for_url in normal manner
self._serial = serial.serial_for_url('socket://192.168.1.99:12000')
2) Generate a setup script for py2exe (see https://pypi.python.org/pypi/py2exe/) -- I've installed py2exe to a virtualenv:
path\to\env\Scripts\python.exe -m py2exe myscript.py -W mysetup.py
3) edit mysetup.py to include option
zipfile="library.zip" # default generated value is None
(see also http://www.py2exe.org/index.cgi/ListOfOptions)
3) build it:
path\to\env\Scripts\python.exe mysetup.py py2exe
4) run it
dist\myscript.exe
Found it!
It seems that for some reason the 'loop://' arguement can't be recognised after the .exe production.
I figured out by studying the pyserial/init.py script that when issuing the command serial.serial_for_url(‘loop://') you essentially call:
sys.modules['serial.urlhandler.protocol_loop’].Serial(“loop://“)
So you have to first import the serial.urlhandler.protocol_loop
and then issue that command in place of the one malfunctioning.
So you can now type:
__import__('serial.urlhandler.protocol_loop')
sys.modules[‘serial.urlhandler.protocol_loop’].Serial("loop://")
After this minor workaround it worked fine.

Problems with pyUSB

I have been trying to make a program with Python which sends commands to a DYMO labelmanager PnP usb device. I tried installing pyUSB and tried the code provided in pyUSB tutorial to figure out a bit how the USB communicating works, but it doesn't work. Code from pyUSB tutorial:
(I have changed the idVendor and idProduct to cope with my device. It finds the device but writing fails)
import usb.core
import usb.util
# find our device
dev = usb.core.find(idVendor=0x0922, idProduct=0x1001)
# was it found?
if dev is None:
raise ValueError('Device not found')
# set the active configuration. With no arguments, the first
# configuration will be the active one
dev.set_configuration()
# get an endpoint instance
cfg = dev.get_active_configuration()
interface_number = cfg[(0,0)].bInterfaceNumber
alternate_setting = usb.control.get_interface(interface_number)
intf = usb.util.find_descriptor(
cfg, bInterfaceNumber = interface_number,
bAlternateSetting = alternate_setting
)
ep = usb.util.find_descriptor(
intf,
# match the first OUT endpoint
custom_match = \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_OUT
)
assert ep is not None
# write the data
ep.write('test')
and it gives an error:
Traceback (most recent call last):
File "C:\Python27\proc\labelprinttest.py", line 18, in <module>
alternate_setting = usb.control.get_interface(interface_number)
TypeError: get_interface() takes exactly 2 arguments (1 given)
where is the problem?
(well of course there reads that the function takes 2 arguments and only 1 is given, but I have tried to investigate and I have no idea what the other needed argument is)
The definition of get_interface() is as follows:
def get_interface(dev, bInterfaceNumber):
r"""Get the current alternate setting of the interface.
dev is the Device object to which the request will be
sent to.
"""
So, try to call it using usb.control.get_interface(dev, interface_number)

Communication with the USB device in Python

I want to communicate with and send data to a USB device. I am able to find the device but while attaching the device with the kernel driver it is giving USB Error: Resource Busy. The following is my code:
import usb
dev = usb.core.find(idVendor=0x0403, idProduct=0x6001)
dev.set_configuration()
cfg = dev.get_active_configuration()
dev.attach_kernel_driver(interface)
interface_number = cfg[(0, 0)].bInterfaceNumber
alternate_settting = usb.control.get_interface(interface_number)
intf = usb.util.find_descriptor(
cfg, bInterfaceNumber=interface_number,
bAlternateSetting=alternate_setting)
ep = usb.util.find_descriptor(
intf, custom_match=lambda e:
usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
dev.detach_kernel_driver(interface)
ep.write("\r" + linea1[:19] + "\n\r" + " " * (20 - len(linea2)) + linea2)
Assuming your using Linux and libusb-1.0 as a PyUSB's backend library.
According to the libusb documentation:
// Detach a kernel driver from an interface.
// If successful, you will then be able to claim the interface and perform I/O.
int libusb_detach_kernel_driver (libusb_device_handle *dev,
int interface_number)
// Re-attach an interface's kernel driver, which was previously
// detached using libusb_detach_kernel_driver().
int libusb_attach_kernel_driver(libusb_device_handle *dev,
int interface_number)
So basically, you need to call detach_kernel_driver first to detach already attached kernel driver (if any) from the device's interface, so you can communicate with it in your code (it's either your code or some kernel driver talking to the device's interface). When you're done, you may want to call attach_kernel_driver to re-attach the kernel driver again.
I believe there's no need to call any of those C functions/Python methods if you can ensure that no kernel driver is loaded for a given device (or manually unload it before running your code).
Edit:
I just got this piece of code (based on your sample) working. Note: for simplicity I've hardcoded 0 as interface number for detach_kernel_driver and attach_kernel_driver - you should make it smarter, I suppose.
import usb
dev = usb.core.find(idVendor=0x0403, idProduct=0x6001)
reattach = False
if dev.is_kernel_driver_active(0):
reattach = True
dev.detach_kernel_driver(0)
dev.set_configuration()
cfg = dev.get_active_configuration()
interface_number = cfg[(0,0)].bInterfaceNumber
alternate_settting = usb.control.get_interface(dev, interface_number)
intf = usb.util.find_descriptor(cfg, bInterfaceNumber = interface_number,
bAlternateSetting = alternate_settting)
ep = usb.util.find_descriptor(intf,custom_match = \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_OUT)
ep.write("test\n\r")
# This is needed to release interface, otherwise attach_kernel_driver fails
# due to "Resource busy"
usb.util.dispose_resources(dev)
# It may raise USBError if there's e.g. no kernel driver loaded at all
if reattach:
dev.attach_kernel_driver(0)

Categories