pyusb: cannot set configuration - python

I am trying to make a script (on linux) that can turn a light in my mouse on or off.
This is the code I have so far:
import usb.core
import usb.util
import sys
interface = 0
dev = usb.core.find(idVendor=0x1532, idProduct=0x0017)
def main():
if dev is None:
print "device not found"
else:
print "device found"
if dev.is_kernel_driver_active(interface) is True:
print "but we need to detach kernel driver"
dev.detach_kernel_driver(interface)
print "claiming device"
usb.util.claim_interface(dev, interface)
print "release claimed interface"
usb.util.release_interface(dev, interface)
print "now attaching the kernel driver again"
dev.attach_kernel_driver(interface)
print "all done"
return 0
if __name__ == '__main__':
main()
This works fine but if I try to do a: dev.set_configuration()
after the claim_interface(dev, interface)
the script returns the error: usb.core.USBError: Resource busy
Why is it still busy after I have detached its kernel driver?

Not sure if this will solve, but are the udev rules for your mouse being set up correctly? I had a similar problem with a custom device a friend did for me and I solved by adding a rule like:
SUBSYSTEM !="usb_device", ACTION !="add", GOTO="device_rules_end"
SYSFS{idVendor} =="1532", SYSFS{idProduct} =="0017", SYMLINK+="mydevice"
MODE="0666", OWNER="<your-username-here>", GROUP="root"
LABEL="device_rules_end"
in my /etc/udev/rules.d folder.
HTH!
EDIT: Before adding the rule, try running your script with sudo. If it will work that way it's almost certainly a permission setting that will be fixed by the above rule.

I had this problem too. Your code works well if you "set_configuration" first and only then claim the interface. This is also the order suggested here: http://libusb.sourceforge.net/api-1.0/caveats.html

Related

How do I start a COM server? Code is in Python

I want to run Python code as a COM server. Eventually I want to run an RTD server available here. But first I want to know what exactly you have to do to getting any COM server running. So let's focus on this example.
class HelloWorld:
_reg_clsid_ = "{7CC9F362-486D-11D1-BB48-0000E838A65F}"
_reg_desc_ = "Python Test COM Server"
_reg_progid_ = "Python.TestServer"
_public_methods_ = ['Hello']
_public_attrs_ = ['softspace', 'noCalls']
_readonly_attrs_ = ['noCalls']
def __init__(self):
self.softspace = 1
self.noCalls = 0
def Hello(self, who):
self.noCalls = self.noCalls + 1
# insert "softspace" number of spaces
return "Hello" + " " * self.softspace + who
if __name__=='__main__':
import win32com.server.register
win32com.server.register.UseCommandLine(HelloWorld)
Ok, this works in the way that there were no errors and server is registered, hence it is available in the HKEY_CLASSES_ROOT registry. But what can I do with this? Some say you have to compile a instance and have a .dll or .exe file. WHat else do I have to do?
Well, I ran your example. The registry key for the server is at:
HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{7CC9F362-486D-11D1-BB48-0000E838A65F}
It has two subkeys... one for LocalServer32 and one for InProcServer32
I created a simple VBA macro in Excel:
Sub d()
Set obj = CreateObject("Python.TestServer")
MsgBox obj.Hello("joe")
End Sub
Macro ran just fine. My version of Excel is 64-bit. I ran the macro and then fired up Task Manager while the message box was being displayed. I could see pythonw.exe running in the background.
The only difference between my python script and yours is probably the name and also that I added a line to print to make sure I was executing the function:
if __name__=='__main__':
import win32com.server.register
print("Going to register...")
win32com.server.register.UseCommandLine(HelloWorld)
When I ran the 64-bit csript.exe test, it worked... as expected... when I ran the 32-bit version it failed.
I know why...sort of...
The registry entry for InProcServer32 is pythoncom36.dll
That's no good. It is an incomplete path. I tried modifying the path variable on my shell to add to one of the 3 places where the DLL existed on my system, but it didn't work. Also, tried coding the path in the InProcServer32. That didn't work.. kept saying it couldn't find the file.
I ran procmon, and then I observerved that it couldn't load vcruntime140.dll. Found the directory under python where those files were, and added to my path. It got further along. If I cared enough, I might try more. Eventually using procmon, I could find all the problems. But you can do that.
My simple solution was to rename the key InProcServer32 for the CLSID to be _InProcServer32. How does that work? Well, the system can't find InProcServer32 so it always uses LocalServer32--for 32-bit and 64-bit processes. If you need the speed of in process then you'd need to fix the problem by using procmon and being relentless until you solved all the File Not Found errors and such. But, if you don't need the speed of in process, then just using the LocalServer32 might solve the problem.
Caveats I'm using an Anaconda distro that my employer limits access to and I can only install it from the employee store. YMMV.

When using text() with python-escpos I get [Errno None] and key error = 1 (windows 10)

I am trying to print to a TM-T20II thermal printer so I can print receipts. Here is my code:
from escpos import printer
from escpos import *
import escpos
from escpos import config
import usb.core
import usb.util
import usb.backend.libusb1
from ctypes import c_void_p, c_int
backend = usb.backend.libusb1.get_backend(find_library=lambda x: "libusb-1.0.dll")
backend.lib.libusb_set_option.argtypes = [c_void_p, c_int]
backend.lib.libusb_set_option(backend.ctx, 1)
p = printer.Usb(0x04b8,0x0e15,0,0x82,0x01, backend=backend)
p.text('test')
I am using a usbdk backend, without it I get a 'NotImplementedError: Operation not supported or unimplemented on this platform.' I'm doing this because for my program to work I need to use the default Epson drivers. When I run this code the error I get is:
<File "C:\Users\maxsl\anaconda3\lib\site-packages\usb\core.py", line
234, in get_interface_and_endpoint
return self._ep_info[endpoint_address]
KeyError: 1
During handling of the above exception, another exception occurred:
File
"C:\Users\maxsl\anaconda3\lib\site-packages\usb\backend\libusb1.py",
line 604, in _check
raise USBError(_strerror(ret), ret, _libusb_errno[ret])
USBError: [Errno None] Other error>
This error only occurs when I add p.text() in. Finding the printer and everything else is no problem. I also want to say that write() works in the PyUSB module, but it would be much more convenient for me to not have to translate the outputs in my program to the confusing ESC/P language.
I am using Spyder 4 with anaconda (python 3.7) 64-bit, libusb 1.0.22b9, most recent pyusb on github (PyPi version got unimplemented error), and python-escpos 3.0a8. I believe they are all 64-bit as well. I have the libusb1.dll from 64x folder in my System32 and the 86x one in SysWoW64 as recommended. I also have Usbdk installed. Please let me know if you have any ideas to fix or if you need more details. Been googling this for like a week.
Isn't it a problem with the printer's USB mode setting?
TM-T20II printer has the modes of USB vender-defined class (COM Port) and USB printer class.
The VID/PID is USB vender-defined class=0x04b8:0x0202 and USB printer class=0x04b8:0x0e15 respectively.
TM-T20II Technical Reference Guide page 89
You should be able to change it with the printer's setting utility.
Alternatively, try changing the PID designation to 0x0202 as is, or try communicating as a COM port instead of a raw USB device.
Or it is possible that the advanced printer driver or Windows print spooler is already using the device and other programs cannot be used.
If the device driver is installed, try uninstalling it.
For anyone else with the same problem as me, what I did was I installed Epson's TM Virtual Port Driver and set the printer to a COM port. I then had to go into the printer's settings and manually change the port to the virtual one. I then altered my code to this:
from escpos import printer
pr = printer.Serial('COM2')
data= '''
hello world
'''
pr.text(data)
pr.close()
And it finally worked! You can see I cut my code down quite a bit. It turns out I don't even need to change the backend. So strange Usb doesn't work but serial does. As long as it works though! Thanks to kunif for the guidance to my solution, never even considered checking the serial ports.

Why can't VSCode load MicroPython 'machine'?

I have installed the MicroPython IDE and Python extension in accordance with the VSCode instructions. This is my first use of VSCode and I have searched for a solution and failed. when I try to debug this code:
import machine
import time
led = machine.Pin(2, machine.Pin.OUT)
button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)
while button.value():
led.on()
time.sleep(1)
led.off()
time.sleep(1)
led.on()
I get this result: Module Not Found Error "no module named 'machine' "
I would very much appreciate your assistance.
Regards
John
You are dealing with two separate Python environments:
The "PC Python" (also called CPython) on your development machine
MicroPython running on embedded device like ESP32.
When testing on PC, you are running your code in CPython. But if you transfer it to the device, it runs within MicroPython. Both environments are very similar but some differences exist.
The machine module is one such difference. It exists only in MicroPython and allows actual access to the hardware. Thus, if you run your program in CPython, you get exactly the error you described.
You can either test your program on an actual device. Or you "mock" the machine module, i.e. you create that module as "dummy" implementation for testing on PC. It would at least need to contain the Pin() class, which could for example print the state changes to command line.
There is an example for such a mock on GitHub: https://github.com/tflander/esp32-machine-emulator
A minimal example for your case: Create machine.py containing:
class Pin:
IN = 0
OUT = 0
PULL_UP = 0
def __init__(self, number, mode=-1, pull=-1):
self.number = number
def on(self):
print('Pin %d switches ON' % self.number)
def off(self):
print('Pin %d switches OFF' % self.number)
def value(self):
return 1
# ... add other methods when needed ...
... and put it somewhere where your script can import it from.

Serial communication inside a custom library

I made a custom library to communicate with my own board. The codes in library work but when i call the library itself i get an error.
I assumed the library is not working, so i put a print function in the library. It seems, that function works and the functions with serial communication are the problem.
I checked the communication code by itself but it works each time. Assuming there are some things to handle when using serial in a custom library, which i dont know any.
iDealibrary.py
import serial
import time
ser=serial.Serial('COM5',9600)
def ConnectIdeaLab():
ser.sendBreak()
a=ser.read()
b=ser.read()
if(a==b'O' and b ==b'K' ):
ser.write(b'b')
ser.write(b'b')
ser.write(b'b')
ser.write(b'a')
ser.write(b'a')
c=ser.read()
if(c==b'!'):
ser.write(bytes([3]))
print("iDeaLab Moduna Girildi!")
time.sleep(0.005)
ser.sendBreak()
#this is the connection function.
def printanything(parametre):
print("writing: ",parametre)
#this is the print function to check if library is working.
example.py
import iDealibrary
iDealibrary.ConnectIdeaLab()
iDealibrary.printanything("selam")
#this does not work
I expect the last code to connect and print iDealab moduna girildi. Instead, i get
raise SerialException("ClearCommError failed ({!r})".format(ctypes.WinError()))
I managed to solve the problem. Mad Physicist is right, the problem is serial port stays open. When i try to re-run the program it tries to open a port which is already open.
After adding a CloseSerial function in my library and calling it on the example, the problem solved.
#File name iDealibrary.py
def CloseSerial():
ser.close()
#File name example.py
iDealibrary.ConnectIdeaLab()
iDealibrary.CloseSerial()

MAC, ethernet id using python

How do you get correct MAC/Ethernet id of local network card using python?
Most of the article on Google/stackoverflow suggests to parse the result of ipconfig /all (windows) and ifconfig (Linux).
On windows (2x/xp/7) 'ipconfig /all' works fine but is this a fail safe method?
I am new to linux and I have no idea whether 'ifconfig' is the standard method to get MAC/Ethernet id.
I have to implement a license check method in a python application which is based on local MAC/Ethernet id.
There is a special case when you have a VPN or virtualization apps such as VirtualBox installed. In this case you'll get more then one MAC/Ethernet Ids. This is not going to be a problem if I have to use parsing method but I am not sure.
Cheers
Prashant
import sys
import os
def getMacAddress():
if sys.platform == 'win32':
for line in os.popen("ipconfig /all"):
if line.lstrip().startswith('Physical Address'):
mac = line.split(':')[1].strip().replace('-',':')
break
else:
for line in os.popen("/sbin/ifconfig"):
if line.find('Ether') > -1:
mac = line.split()[4]
break
return mac
Is a cross platform function that will return the answer for you.
On linux, you can access hardware information through sysfs.
>>> ifname = 'eth0'
>>> print open('/sys/class/net/%s/address' % ifname).read()
78:e7:g1:84:b5:ed
This way you avoid the complications of shelling out to ifconfig, and parsing the output.
I have used a socket based solution, works well on linux and I believe windows would be fine too
def getHwAddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15]))
return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
getHwAddr("eth0")
Original Source

Categories

Resources