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