legacy.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. # Copyright (C) 2009-2011 Wander Lairson Costa
  2. #
  3. # The following terms apply to all files associated
  4. # with the software unless explicitly disclaimed in individual files.
  5. #
  6. # The authors hereby grant permission to use, copy, modify, distribute,
  7. # and license this software and its documentation for any purpose, provided
  8. # that existing copyright notices are retained in all copies and that this
  9. # notice is included verbatim in any distributions. No written agreement,
  10. # license, or royalty fee is required for any of the authorized uses.
  11. # Modifications to this software may be copyrighted by their authors
  12. # and need not follow the licensing terms described here, provided that
  13. # the new terms are clearly indicated on the first page of each file where
  14. # they apply.
  15. #
  16. # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
  17. # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  18. # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
  19. # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
  20. # POSSIBILITY OF SUCH DAMAGE.
  21. #
  22. # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
  23. # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  24. # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
  25. # IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
  26. # NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
  27. # MODIFICATIONS.
  28. import usb.core as core
  29. import usb.util as util
  30. import usb._interop as _interop
  31. import usb.control as control
  32. __author__ = 'Wander Lairson Costa'
  33. USBError = core.USBError
  34. CLASS_AUDIO = 1
  35. CLASS_COMM = 2
  36. CLASS_DATA = 10
  37. CLASS_HID = 3
  38. CLASS_HUB = 9
  39. CLASS_MASS_STORAGE = 8
  40. CLASS_PER_INTERFACE = 0
  41. CLASS_PRINTER = 7
  42. CLASS_VENDOR_SPEC = 255
  43. DT_CONFIG = 2
  44. DT_CONFIG_SIZE = 9
  45. DT_DEVICE = 1
  46. DT_DEVICE_SIZE = 18
  47. DT_ENDPOINT = 5
  48. DT_ENDPOINT_AUDIO_SIZE = 9
  49. DT_ENDPOINT_SIZE = 7
  50. DT_HID = 33
  51. DT_HUB = 41
  52. DT_HUB_NONVAR_SIZE = 7
  53. DT_INTERFACE = 4
  54. DT_INTERFACE_SIZE = 9
  55. DT_PHYSICAL = 35
  56. DT_REPORT = 34
  57. DT_STRING = 3
  58. ENDPOINT_ADDRESS_MASK = 15
  59. ENDPOINT_DIR_MASK = 128
  60. ENDPOINT_IN = 128
  61. ENDPOINT_OUT = 0
  62. ENDPOINT_TYPE_BULK = 2
  63. ENDPOINT_TYPE_CONTROL = 0
  64. ENDPOINT_TYPE_INTERRUPT = 3
  65. ENDPOINT_TYPE_ISOCHRONOUS = 1
  66. ENDPOINT_TYPE_MASK = 3
  67. ERROR_BEGIN = 500000
  68. MAXALTSETTING = 128
  69. MAXCONFIG = 8
  70. MAXENDPOINTS = 32
  71. MAXINTERFACES = 32
  72. RECIP_DEVICE = 0
  73. RECIP_ENDPOINT = 2
  74. RECIP_INTERFACE = 1
  75. RECIP_OTHER = 3
  76. REQ_CLEAR_FEATURE = 1
  77. REQ_GET_CONFIGURATION = 8
  78. REQ_GET_DESCRIPTOR = 6
  79. REQ_GET_INTERFACE = 10
  80. REQ_GET_STATUS = 0
  81. REQ_SET_ADDRESS = 5
  82. REQ_SET_CONFIGURATION = 9
  83. REQ_SET_DESCRIPTOR = 7
  84. REQ_SET_FEATURE = 3
  85. REQ_SET_INTERFACE = 11
  86. REQ_SYNCH_FRAME = 12
  87. TYPE_CLASS = 32
  88. TYPE_RESERVED = 96
  89. TYPE_STANDARD = 0
  90. TYPE_VENDOR = 64
  91. class Endpoint(object):
  92. r"""Endpoint descriptor object."""
  93. def __init__(self, ep):
  94. self.address = ep.bEndpointAddress
  95. self.interval = ep.bInterval
  96. self.maxPacketSize = ep.wMaxPacketSize
  97. self.type = util.endpoint_type(ep.bmAttributes)
  98. class Interface(object):
  99. r"""Interface descriptor object."""
  100. def __init__(self, intf):
  101. self.alternateSetting = intf.bAlternateSetting
  102. self.interfaceNumber = intf.bInterfaceNumber
  103. self.iInterface = intf.iInterface
  104. self.interfaceClass = intf.bInterfaceClass
  105. self.interfaceSubClass = intf.bInterfaceSubClass
  106. self.interfaceProtocol = intf.bInterfaceProtocol
  107. self.endpoints = [Endpoint(e) for e in intf]
  108. class Configuration(object):
  109. r"""Configuration descriptor object."""
  110. def __init__(self, cfg):
  111. self.iConfiguration = cfg.iConfiguration
  112. self.maxPower = cfg.bMaxPower << 2
  113. self.remoteWakeup = (cfg.bmAttributes >> 5) & 1
  114. self.selfPowered = (cfg.bmAttributes >> 6) & 1
  115. self.totalLength = cfg.wTotalLength
  116. self.value = cfg.bConfigurationValue
  117. self.interfaces = [
  118. list(g) for k, g in _interop._groupby(
  119. _interop._sorted(
  120. [Interface(i) for i in cfg],
  121. key=lambda i: i.interfaceNumber
  122. ),
  123. lambda i: i.alternateSetting)
  124. ]
  125. class DeviceHandle(object):
  126. def __init__(self, dev):
  127. self.dev = dev
  128. self.__claimed_interface = -1
  129. def bulkWrite(self, endpoint, buffer, timeout = 100):
  130. r"""Perform a bulk write request to the endpoint specified.
  131. Arguments:
  132. endpoint: endpoint number.
  133. buffer: sequence data buffer to write.
  134. This parameter can be any sequence type.
  135. timeout: operation timeout in miliseconds. (default: 100)
  136. Returns the number of bytes written.
  137. """
  138. return self.dev.write(endpoint, buffer, self.__claimed_interface, timeout)
  139. def bulkRead(self, endpoint, size, timeout = 100):
  140. r"""Performs a bulk read request to the endpoint specified.
  141. Arguments:
  142. endpoint: endpoint number.
  143. size: number of bytes to read.
  144. timeout: operation timeout in miliseconds. (default: 100)
  145. Return a tuple with the data read.
  146. """
  147. return self.dev.read(endpoint, size, self.__claimed_interface, timeout)
  148. def interruptWrite(self, endpoint, buffer, timeout = 100):
  149. r"""Perform a interrupt write request to the endpoint specified.
  150. Arguments:
  151. endpoint: endpoint number.
  152. buffer: sequence data buffer to write.
  153. This parameter can be any sequence type.
  154. timeout: operation timeout in miliseconds. (default: 100)
  155. Returns the number of bytes written.
  156. """
  157. return self.dev.write(endpoint, buffer, self.__claimed_interface, timeout)
  158. def interruptRead(self, endpoint, size, timeout = 100):
  159. r"""Performs a interrupt read request to the endpoint specified.
  160. Arguments:
  161. endpoint: endpoint number.
  162. size: number of bytes to read.
  163. timeout: operation timeout in miliseconds. (default: 100)
  164. Return a tuple with the data read.
  165. """
  166. return self.dev.read(endpoint, size, self.__claimed_interface, timeout)
  167. def controlMsg(self, requestType, request, buffer, value = 0, index = 0, timeout = 100):
  168. r"""Perform a control request to the default control pipe on a device.
  169. Arguments:
  170. requestType: specifies the direction of data flow, the type
  171. of request, and the recipient.
  172. request: specifies the request.
  173. buffer: if the transfer is a write transfer, buffer is a sequence
  174. with the transfer data, otherwise, buffer is the number of
  175. bytes to read.
  176. value: specific information to pass to the device. (default: 0)
  177. index: specific information to pass to the device. (default: 0)
  178. timeout: operation timeout in miliseconds. (default: 100)
  179. Return the number of bytes written.
  180. """
  181. return self.dev.ctrl_transfer(
  182. requestType,
  183. request,
  184. wValue = value,
  185. wIndex = index,
  186. data_or_wLength = buffer,
  187. timeout = timeout
  188. )
  189. def clearHalt(self, endpoint):
  190. r"""Clears any halt status on the specified endpoint.
  191. Arguments:
  192. endpoint: endpoint number.
  193. """
  194. cfg = self.dev.get_active_configuration()
  195. intf = util.find_descriptor(cfg, bInterfaceNumber = self.__claimed_interface)
  196. e = util.find_descriptor(intf, bEndpointAddress = endpoint)
  197. control.clear_feature(self.dev, control.ENDPOINT_HALT, e)
  198. def claimInterface(self, interface):
  199. r"""Claims the interface with the Operating System.
  200. Arguments:
  201. interface: interface number or an Interface object.
  202. """
  203. util.claim_interface(self.dev, interface)
  204. self.__claimed_interface = interface
  205. def releaseInterface(self):
  206. r"""Release an interface previously claimed with claimInterface."""
  207. util.release_interface(self.dev, self.__claimed_interface)
  208. self.__claimed_interface = -1
  209. def reset(self):
  210. r"""Reset the specified device by sending a RESET
  211. down the port it is connected to."""
  212. self.dev.reset()
  213. def resetEndpoint(self, endpoint):
  214. r"""Reset all states for the specified endpoint.
  215. Arguments:
  216. endpoint: endpoint number.
  217. """
  218. self.clearHalt(endpoint)
  219. def setConfiguration(self, configuration):
  220. r"""Set the active configuration of a device.
  221. Arguments:
  222. configuration: a configuration value or a Configuration object.
  223. """
  224. self.dev.set_configuration(configuration)
  225. def setAltInterface(self, alternate):
  226. r"""Sets the active alternate setting of the current interface.
  227. Arguments:
  228. alternate: an alternate setting number or an Interface object.
  229. """
  230. self.dev.set_interface_altsetting(self.__claimed_interface, alternate)
  231. def getString(self, index, length, langid = None):
  232. r"""Retrieve the string descriptor specified by index
  233. and langid from a device.
  234. Arguments:
  235. index: index of descriptor in the device.
  236. length: number of bytes of the string
  237. langid: Language ID. If it is omittedi, will be
  238. used the first language.
  239. """
  240. return util.get_string(self.dev, length, index, langid).encode('ascii')
  241. def getDescriptor(self, desc_type, desc_index, length, endpoint = -1):
  242. r"""Retrieves a descriptor from the device identified by the type
  243. and index of the descriptor.
  244. Arguments:
  245. desc_type: descriptor type.
  246. desc_index: index of the descriptor.
  247. len: descriptor length.
  248. endpoint: ignored.
  249. """
  250. return control.get_descriptor(self.dev, length, desc_type, desc_index)
  251. def detachKernelDriver(self, interface):
  252. r"""Detach a kernel driver from the interface (if one is attached,
  253. we have permission and the operation is supported by the OS)
  254. Arguments:
  255. interface: interface number or an Interface object.
  256. """
  257. self.dev.detach_kernel_driver(interface)
  258. class Device(object):
  259. r"""Device descriptor object"""
  260. def __init__(self, dev):
  261. self.deviceClass = dev.bDeviceClass
  262. self.deviceSubClass = dev.bDeviceSubClass
  263. self.deviceProtocol = dev.bDeviceProtocol
  264. self.deviceVersion = dev.bcdDevice
  265. self.devnum = None
  266. self.filename = ''
  267. self.iManufacturer = dev.iManufacturer
  268. self.iProduct = dev.iProduct
  269. self.iSerialNumber = dev.iSerialNumber
  270. self.idProduct = dev.idProduct
  271. self.idVendor = dev.idVendor
  272. self.maxPacketSize = dev.bMaxPacketSize0
  273. self.usbVersion = dev.bcdUSB
  274. self.configurations = [Configuration(c) for c in dev]
  275. self.dev = dev
  276. def open(self):
  277. r"""Open the device for use.
  278. Return a DeviceHandle object
  279. """
  280. return DeviceHandle(self.dev)
  281. class Bus(object):
  282. r"""Bus object."""
  283. def __init__(self):
  284. self.dirname = ''
  285. self.localtion = 0
  286. self.devices = [Device(d) for d in core.find(find_all=True)]
  287. def busses():
  288. r"""Return a tuple with the usb busses."""
  289. return (Bus(),)