annotate python/usb.py @ 112:056face59ee7

Added lsusb script
author Windel Bouwman
date Fri, 04 Jan 2013 18:40:05 +0100
parents
children 1f40be088ee8
rev   line source
112
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
1 from ctypes import Structure, POINTER, CDLL
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
2 from ctypes import c_uint16, c_uint8, c_int, c_ssize_t
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
3 from ctypes import byref
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
4
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
5 # libusb wrapper:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
6 libusb = CDLL('libusb-1.0.so')
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
7
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
8 # helper:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
9 def buildfunc(name, argtypes, restype):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
10 f = getattr(libusb, name)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
11 f.argtypes = argtypes
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
12 f.restype = restype
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
13 return f
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
14 def enum(**enums):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
15 reverse = dict((value, key) for key, value in enums.items())
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
16 enums['reverse_mapping'] = reverse
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
17 return type('enum', (), enums)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
18
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
19 # enums
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
20 libusb_class_code = enum(PER_INTERFACE=0, AUDIO=1, COMM=2, HID=3, \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
21 PHYSICAL=5, PRINTER=7, PTP=6, MASS_STORAGE=8, HUB=9, \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
22 DATA=10, SMART_CARD=0xb, CONTENT_SECURITY=0xd, VIDEO=0xe, \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
23 PERSONAL_HEALTHCARE=0xf, DIAGNOSTIC_DEVICE=0xdc, WIRELESS=0xe,\
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
24 APPLICATION=0xfe, VENDOR_SPEC=0xff)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
25 libusb_speed = enum(UNKNOWN=0, LOW=1, FULL=2, HIGH=3, SUPER=4)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
26 libusb_error = enum(SUCCES=0, ERROR_IO=-1, ERROR_INVALID_PARAM=-2, \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
27 ERROR_ACCESS=-3, ERROR_NO_DEVICE=-4, ERROR_NOT_FOUND=-5, \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
28 ERROR_BUSY=-6, ERROR_TIMEOUT=-7, ERROR_OVERFLOW=-8, \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
29 ERROR_PIPE=-9, ERROR_INTERRUPTED=-10, ERROR_NO_MEM=-11, \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
30 ERROR_NOT_SUPPORTED=-12, ERROR_OTHER=-99)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
31 libusb_transfer_status = enum(\
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
32 COMPLETED=0, ERROR=1, TIMED_OUT=2, \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
33 CANCELLED=3, STALL=4, NO_DEVICE=5, OVERFLOW=6)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
34
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
35 # types
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
36 class libusb_context(Structure):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
37 pass
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
38 libusb_context_p = POINTER(libusb_context)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
39 libusb_context_p_p = POINTER(libusb_context_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
40
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
41 class libusb_device(Structure):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
42 pass
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
43 libusb_device_p = POINTER(libusb_device)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
44 libusb_device_p_p = POINTER(libusb_device_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
45 libusb_device_p_p_p = POINTER(libusb_device_p_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
46
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
47 class libusb_device_descriptor(Structure):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
48 _fields_ = [
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
49 ('bLength', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
50 ('bDescriptorType', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
51 ('bcdUSB', c_uint16),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
52 ('bDeviceClass', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
53 ('bDeviceSubClass', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
54 ('bDeviceProtocol', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
55 ('bMaxPacketSize0', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
56 ('idVendor', c_uint16),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
57 ('idProduct', c_uint16),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
58 ('bcdDevice', c_uint16),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
59 ('iManufacturer', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
60 ('iProduct', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
61 ('iSerialNumber', c_uint8),
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
62 ('iNumConfigurations', c_uint8)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
63 ]
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
64 libusb_device_descriptor_p = POINTER(libusb_device_descriptor)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
65
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
66 # functions
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
67 libusb_init = buildfunc('libusb_init', [libusb_context_p_p], c_int)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
68
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
69 libusb_get_device_list = buildfunc('libusb_get_device_list', \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
70 [libusb_context_p, libusb_device_p_p_p], c_ssize_t)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
71 libusb_free_device_list = buildfunc('libusb_free_device_list',\
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
72 [libusb_device_p_p, c_int], None)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
73 libusb_get_bus_number = buildfunc('libusb_get_bus_number', \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
74 [libusb_device_p], c_uint8)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
75 libusb_get_device_address = buildfunc('libusb_get_device_address', \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
76 [libusb_device_p], c_uint8)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
77 libusb_get_device_speed = buildfunc('libusb_get_device_speed', \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
78 [libusb_device_p], c_int)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
79 libusb_unref_device = buildfunc('libusb_unref_device', \
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
80 [libusb_device_p], None)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
81
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
82 libusb_get_device_descriptor = buildfunc('libusb_get_device_descriptor', [libusb_device_p, libusb_device_descriptor_p], c_int)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
83
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
84 # Quick hack function:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
85 #libusb_open_device_with_vid_pid = buildfunc('libusb_open_device_with_vid_pid', [libusb_context_p, ctypes.c_uint16, ctypes.c_uint16], libusb_device_handle_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
86
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
87 # pythonic API:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
88
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
89 class UsbError(Exception):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
90 def __init__(self, msg, errorcode):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
91 if errorcode in libusb_error.reverse_mapping:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
92 errorcode = libusb_error.reverse_mapping[errorcode]
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
93 msg = msg + 'Error code: {0}'.format(errorcode)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
94 super().__init__(msg)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
95
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
96 class UsbContext(object):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
97 """ A usb context in case of multiple use """
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
98 def __init__(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
99 self.context_p = libusb_context_p()
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
100 r = libusb_init(byref(self.context_p))
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
101 if r != 0:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
102 raise UsbError('libusb_init error!', r)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
103 def getDeviceList(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
104 devlist = libusb_device_p_p()
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
105 count = libusb_get_device_list(self.context_p, byref(devlist))
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
106 if count < 0:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
107 raise UsbError('Error getting device list', count)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
108 l = [UsbDevice(self, device_p.contents) for device_p in devlist[0:count]]
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
109 libusb_free_device_list(devlist, 0)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
110 return l
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
111 DeviceList = property(getDeviceList)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
112
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
113 class UsbDevice:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
114 """ A detected usb device """
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
115 def __init__(self, context, device_p):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
116 self.context = context
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
117 self.dev_p = device_p
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
118 def __del__(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
119 libusb_unref_device(self.dev_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
120 def getBusNumber(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
121 return libusb_get_bus_number(self.dev_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
122 BusNumber = property(getBusNumber)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
123 def getDeviceAddress(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
124 return libusb_get_device_address(self.dev_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
125 DeviceAddress = property(getDeviceAddress)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
126 def getSpeed(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
127 s = libusb_get_device_speed(self.dev_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
128 if s in libusb_speed.reverse_mapping:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
129 s = libusb_speed.reverse_mapping[s]
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
130 return s
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
131 Speed = property(getSpeed)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
132 def getDescriptor(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
133 descriptor = libusb_device_descriptor()
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
134 r = libusb_get_device_descriptor(self.dev_p, byref(descriptor))
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
135 if r != 0:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
136 raise UsbError('Error getting descriptor', r)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
137 return descriptor
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
138 Descriptor = property(getDescriptor)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
139 VendorId = property(lambda self: self.Descriptor.idVendor)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
140 ProductId = property(lambda self: self.Descriptor.idProduct)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
141 NumConfigurations = property(lambda self: self.Descriptor.bNumConfigurations)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
142 def open(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
143 """ Opens this device and returns a handle """
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
144 handle_p = libusb_device_handle_p()
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
145 r = libusb_open(self.dev_p, byref(handle_p))
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
146 if r != 0:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
147 raise UsbError('error opening device', r)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
148 return UseDeviceHandle(self, handle_p)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
149 def __repr__(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
150 r2 = 'Usb device: bus {0} address {1} {2:04X}:{3:04X}'.format(self.BusNumber, self.DeviceAddress, self.VendorId, self.ProductId)
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
151 return r2
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
152
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
153 class UsbDeviceHandle:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
154 """ Handle to a detected usb device """
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
155 def __init__(self, device, handle_p):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
156 self.device = device
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
157 self.handle_p = handle_p
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
158
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
159 class UsbTransfer:
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
160 def __init__(self):
056face59ee7 Added lsusb script
Windel Bouwman
parents:
diff changeset
161 libusb_alloc_transfer(0)