1# Copyright (C) 2009-2014 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 29r"""usb.core - Core USB features. 30 31This module exports: 32 33Device - a class representing a USB device. 34Configuration - a class representing a configuration descriptor. 35Interface - a class representing an interface descriptor. 36Endpoint - a class representing an endpoint descriptor. 37find() - a function to find USB devices. 38show_devices() - a function to show the devices present. 39""" 40 41__author__ = 'Wander Lairson Costa' 42 43__all__ = [ 'Device', 'Configuration', 'Interface', 'Endpoint', 'find', 44 'show_devices' ] 45 46import usb.util as util 47import copy 48import operator 49import usb._interop as _interop 50import usb._objfinalizer as _objfinalizer 51import usb._lookup as _lu 52import logging 53import array 54import threading 55import functools 56 57_logger = logging.getLogger('usb.core') 58 59_DEFAULT_TIMEOUT = 1000 60 61def _set_attr(input, output, fields): 62 for f in fields: 63 setattr(output, f, getattr(input, f)) 64 65def _try_get_string(dev, index, langid = None, default_str_i0 = "", 66 default_access_error = "Error Accessing String"): 67 """ try to get a string, but return a string no matter what 68 """ 69 if index == 0 : 70 string = default_str_i0 71 else: 72 try: 73 if langid is None: 74 string = util.get_string(dev, index) 75 else: 76 string = util.get_string(dev, index, langid) 77 except : 78 string = default_access_error 79 return string 80 81def _try_lookup(table, value, default = ""): 82 """ try to get a string from the lookup table, return "" instead of key 83 error 84 """ 85 try: 86 string = table[ value ] 87 except KeyError: 88 string = default 89 return string 90 91class _DescriptorInfo(str): 92 """ this class is used so that when a descriptor is shown on the 93 terminal it is propely formatted """ 94 def __repr__(self): 95 return self 96 97def synchronized(f): 98 @functools.wraps(f) 99 def wrapper(self, *args, **kwargs): 100 try: 101 self.lock.acquire() 102 return f(self, *args, **kwargs) 103 finally: 104 self.lock.release() 105 return wrapper 106 107class _ResourceManager(object): 108 def __init__(self, dev, backend): 109 self.backend = backend 110 self._active_cfg_index = None 111 self.dev = dev 112 self.handle = None 113 self._claimed_intf = _interop._set() 114 self._ep_info = {} 115 self.lock = threading.RLock() 116 117 @synchronized 118 def managed_open(self): 119 if self.handle is None: 120 self.handle = self.backend.open_device(self.dev) 121 return self.handle 122 123 @synchronized 124 def managed_close(self): 125 if self.handle is not None: 126 self.backend.close_device(self.handle) 127 self.handle = None 128 129 @synchronized 130 def managed_set_configuration(self, device, config): 131 if config is None: 132 cfg = device[0] 133 elif isinstance(config, Configuration): 134 cfg = config 135 elif config == 0: # unconfigured state 136 class MockConfiguration(object): 137 def __init__(self): 138 self.index = None 139 self.bConfigurationValue = 0 140 cfg = MockConfiguration() 141 else: 142 cfg = util.find_descriptor(device, bConfigurationValue=config) 143 144 if cfg is None: 145 raise ValueError("Invalid configuration " + str(config)) 146 147 self.managed_open() 148 self.backend.set_configuration(self.handle, cfg.bConfigurationValue) 149 150 # cache the index instead of the object to avoid cyclic references 151 # of the device and Configuration (Device tracks the _ResourceManager, 152 # which tracks the Configuration, which tracks the Device) 153 self._active_cfg_index = cfg.index 154 155 self._ep_info.clear() 156 157 @synchronized 158 def managed_claim_interface(self, device, intf): 159 self.managed_open() 160 161 if isinstance(intf, Interface): 162 i = intf.bInterfaceNumber 163 else: 164 i = intf 165 166 if i not in self._claimed_intf: 167 self.backend.claim_interface(self.handle, i) 168 self._claimed_intf.add(i) 169 170 @synchronized 171 def managed_release_interface(self, device, intf): 172 if intf is None: 173 cfg = self.get_active_configuration(device) 174 i = cfg[(0,0)].bInterfaceNumber 175 elif isinstance(intf, Interface): 176 i = intf.bInterfaceNumber 177 else: 178 i = intf 179 180 if i in self._claimed_intf: 181 try: 182 self.backend.release_interface(self.handle, i) 183 finally: 184 self._claimed_intf.remove(i) 185 186 @synchronized 187 def managed_set_interface(self, device, intf, alt): 188 if isinstance(intf, Interface): 189 i = intf 190 else: 191 cfg = self.get_active_configuration(device) 192 if intf is None: 193 intf = cfg[(0,0)].bInterfaceNumber 194 if alt is not None: 195 i = util.find_descriptor(cfg, bInterfaceNumber=intf, bAlternateSetting=alt) 196 else: 197 i = util.find_descriptor(cfg, bInterfaceNumber=intf) 198 199 self.managed_claim_interface(device, i) 200 201 if alt is None: 202 alt = i.bAlternateSetting 203 204 self.backend.set_interface_altsetting(self.handle, i.bInterfaceNumber, alt) 205 206 @synchronized 207 def setup_request(self, device, endpoint): 208 # we need the endpoint address, but the "endpoint" parameter 209 # can be either the a Endpoint object or the endpoint address itself 210 if isinstance(endpoint, Endpoint): 211 endpoint_address = endpoint.bEndpointAddress 212 else: 213 endpoint_address = endpoint 214 215 intf, ep = self.get_interface_and_endpoint(device, endpoint_address) 216 self.managed_claim_interface(device, intf) 217 return (intf, ep) 218 219 # Find the interface and endpoint objects which endpoint address belongs to 220 @synchronized 221 def get_interface_and_endpoint(self, device, endpoint_address): 222 try: 223 return self._ep_info[endpoint_address] 224 except KeyError: 225 for intf in self.get_active_configuration(device): 226 ep = util.find_descriptor(intf, bEndpointAddress=endpoint_address) 227 if ep is not None: 228 self._ep_info[endpoint_address] = (intf, ep) 229 return intf, ep 230 231 raise ValueError('Invalid endpoint address ' + hex(endpoint_address)) 232 233 @synchronized 234 def get_active_configuration(self, device): 235 if self._active_cfg_index is None: 236 self.managed_open() 237 cfg = util.find_descriptor( 238 device, 239 bConfigurationValue=self.backend.get_configuration(self.handle) 240 ) 241 if cfg is None: 242 raise USBError('Configuration not set') 243 self._active_cfg_index = cfg.index 244 return cfg 245 return device[self._active_cfg_index] 246 247 @synchronized 248 def release_all_interfaces(self, device): 249 claimed = copy.copy(self._claimed_intf) 250 for i in claimed: 251 try: 252 self.managed_release_interface(device, i) 253 except USBError: 254 # Ignore errors when releasing the interfaces 255 # When the device is disconnected, the call may fail 256 pass 257 258 @synchronized 259 def dispose(self, device, close_handle = True): 260 self.release_all_interfaces(device) 261 if close_handle: 262 self.managed_close() 263 self._ep_info.clear() 264 self._active_cfg_index = None 265 266 267class USBError(IOError): 268 r"""Exception class for USB errors. 269 270 Backends must raise this exception when USB related errors occur. The 271 backend specific error code is available through the 'backend_error_code' 272 member variable. 273 """ 274 275 def __init__(self, strerror, error_code = None, errno = None): 276 r"""Initialize the object. 277 278 This initializes the USBError object. The strerror and errno are passed 279 to the parent object. The error_code parameter is attributed to the 280 backend_error_code member variable. 281 """ 282 283 IOError.__init__(self, errno, strerror) 284 self.backend_error_code = error_code 285 286class NoBackendError(ValueError): 287 r"Exception class when a valid backend is not found." 288 pass 289 290class Endpoint(object): 291 r"""Represent an endpoint object. 292 293 This class contains all fields of the Endpoint Descriptor according to the 294 USB Specification. You can access them as class properties. For example, to 295 access the field bEndpointAddress of the endpoint descriptor, you can do so: 296 297 >>> import usb.core 298 >>> dev = usb.core.find() 299 >>> for cfg in dev: 300 >>> for i in cfg: 301 >>> for e in i: 302 >>> print e.bEndpointAddress 303 """ 304 305 def __init__(self, device, endpoint, interface = 0, 306 alternate_setting = 0, configuration = 0): 307 r"""Initialize the Endpoint object. 308 309 The device parameter is the device object returned by the find() 310 function. endpoint is the endpoint logical index (not the endpoint 311 address). The configuration parameter is the logical index of the 312 configuration (not the bConfigurationValue field). The interface 313 parameter is the interface logical index (not the bInterfaceNumber 314 field) and alternate_setting is the alternate setting logical index 315 (not the bAlternateSetting value). An interface may have only one 316 alternate setting. In this case, the alternate_setting parameter 317 should be zero. By "logical index" we mean the relative order of the 318 configurations returned by the peripheral as a result of GET_DESCRIPTOR 319 request. 320 """ 321 self.device = device 322 self.index = endpoint 323 324 backend = device._ctx.backend 325 326 desc = backend.get_endpoint_descriptor( 327 device._ctx.dev, 328 endpoint, 329 interface, 330 alternate_setting, 331 configuration 332 ) 333 334 _set_attr( 335 desc, 336 self, 337 ( 338 'bLength', 339 'bDescriptorType', 340 'bEndpointAddress', 341 'bmAttributes', 342 'wMaxPacketSize', 343 'bInterval', 344 'bRefresh', 345 'bSynchAddress', 346 'extra_descriptors' 347 ) 348 ) 349 350 def __repr__(self): 351 return "<" + self._str() + ">" 352 353 def __str__(self): 354 headstr = " " + self._str() + " " 355 356 if util.endpoint_direction(self.bEndpointAddress) == util.ENDPOINT_IN: 357 direction = "IN" 358 else: 359 direction = "OUT" 360 361 return "%s%s\n" % (headstr, "=" * (60 - len(headstr))) + \ 362 " %-17s:%#7x (7 bytes)\n" % ( 363 "bLength", self.bLength) + \ 364 " %-17s:%#7x %s\n" % ( 365 "bDescriptorType", self.bDescriptorType, 366 _try_lookup(_lu.descriptors, self.bDescriptorType)) + \ 367 " %-17s:%#7x %s\n" % ( 368 "bEndpointAddress", self.bEndpointAddress, direction) + \ 369 " %-17s:%#7x %s\n" % ( 370 "bmAttributes", self.bmAttributes, 371 _lu.ep_attributes[(self.bmAttributes & 0x3)]) + \ 372 " %-17s:%#7x (%d bytes)\n" % ( 373 "wMaxPacketSize", self.wMaxPacketSize, self.wMaxPacketSize) + \ 374 " %-17s:%#7x" % ("bInterval", self.bInterval) 375 376 def write(self, data, timeout = None): 377 r"""Write data to the endpoint. 378 379 The parameter data contains the data to be sent to the endpoint and 380 timeout is the time limit of the operation. The transfer type and 381 endpoint address are automatically inferred. 382 383 The method returns the number of bytes written. 384 385 For details, see the Device.write() method. 386 """ 387 return self.device.write(self, data, timeout) 388 389 def read(self, size_or_buffer, timeout = None): 390 r"""Read data from the endpoint. 391 392 The parameter size_or_buffer is either the number of bytes to 393 read or an array object where the data will be put in and timeout is the 394 time limit of the operation. The transfer type and endpoint address 395 are automatically inferred. 396 397 The method returns either an array object or the number of bytes 398 actually read. 399 400 For details, see the Device.read() method. 401 """ 402 return self.device.read(self, size_or_buffer, timeout) 403 404 def clear_halt(self): 405 r"""Clear the halt/status condition of the endpoint.""" 406 self.device.clear_halt(self.bEndpointAddress) 407 408 def _str(self): 409 if util.endpoint_direction(self.bEndpointAddress) == util.ENDPOINT_IN: 410 direction = "IN" 411 else: 412 direction = "OUT" 413 414 return ( 415 "ENDPOINT 0x%X: %s %s" % (self.bEndpointAddress, 416 _lu.ep_attributes[(self.bmAttributes & 0x3)], 417 direction)) 418 419class Interface(object): 420 r"""Represent an interface object. 421 422 This class contains all fields of the Interface Descriptor 423 according to the USB Specification. You may access them as class 424 properties. For example, to access the field bInterfaceNumber 425 of the interface descriptor, you can do so: 426 427 >>> import usb.core 428 >>> dev = usb.core.find() 429 >>> for cfg in dev: 430 >>> for i in cfg: 431 >>> print i.bInterfaceNumber 432 """ 433 434 def __init__(self, device, interface = 0, 435 alternate_setting = 0, configuration = 0): 436 r"""Initialize the interface object. 437 438 The device parameter is the device object returned by the find() 439 function. The configuration parameter is the logical index of the 440 configuration (not the bConfigurationValue field). The interface 441 parameter is the interface logical index (not the bInterfaceNumber 442 field) and alternate_setting is the alternate setting logical index 443 (not the bAlternateSetting value). An interface may have only one 444 alternate setting. In this case, the alternate_setting parameter 445 should be zero. By "logical index" we mean the relative order of 446 the configurations returned by the peripheral as a result of 447 GET_DESCRIPTOR request. 448 """ 449 self.device = device 450 self.alternate_index = alternate_setting 451 self.index = interface 452 self.configuration = configuration 453 454 backend = device._ctx.backend 455 456 desc = backend.get_interface_descriptor( 457 self.device._ctx.dev, 458 interface, 459 alternate_setting, 460 configuration 461 ) 462 463 _set_attr( 464 desc, 465 self, 466 ( 467 'bLength', 468 'bDescriptorType', 469 'bInterfaceNumber', 470 'bAlternateSetting', 471 'bNumEndpoints', 472 'bInterfaceClass', 473 'bInterfaceSubClass', 474 'bInterfaceProtocol', 475 'iInterface', 476 'extra_descriptors' 477 ) 478 ) 479 480 def __repr__(self): 481 return "<" + self._str() + ">" 482 483 def __str__(self): 484 """Show all information for the interface.""" 485 486 string = self._get_full_descriptor_str() 487 for endpoint in self: 488 string += "\n" + str(endpoint) 489 return string 490 491 def endpoints(self): 492 r"""Return a tuple of the interface endpoints.""" 493 return tuple(self) 494 495 def set_altsetting(self): 496 r"""Set the interface alternate setting.""" 497 self.device.set_interface_altsetting( 498 self.bInterfaceNumber, 499 self.bAlternateSetting) 500 501 def __iter__(self): 502 r"""Iterate over all endpoints of the interface.""" 503 for i in range(self.bNumEndpoints): 504 yield Endpoint( 505 self.device, 506 i, 507 self.index, 508 self.alternate_index, 509 self.configuration) 510 511 def __getitem__(self, index): 512 r"""Return the Endpoint object in the given position.""" 513 return Endpoint( 514 self.device, 515 index, 516 self.index, 517 self.alternate_index, 518 self.configuration) 519 520 def _str(self): 521 if self.bAlternateSetting: 522 alt_setting = ", %d" % self.bAlternateSetting 523 else: 524 alt_setting = "" 525 526 return "INTERFACE %d%s: %s" % (self.bInterfaceNumber, alt_setting, 527 _try_lookup(_lu.interface_classes, self.bInterfaceClass, 528 default = "Unknown Class")) 529 530 def _get_full_descriptor_str(self): 531 headstr = " " + self._str() + " " 532 return "%s%s\n" % (headstr, "=" * (60 - len(headstr))) + \ 533 " %-19s:%#7x (9 bytes)\n" % ( 534 "bLength", self.bLength) + \ 535 " %-19s:%#7x %s\n" % ( 536 "bDescriptorType", self.bDescriptorType, 537 _try_lookup(_lu.descriptors, self.bDescriptorType)) + \ 538 " %-19s:%#7x\n" % ( 539 "bInterfaceNumber", self.bInterfaceNumber) + \ 540 " %-19s:%#7x\n" % ( 541 "bAlternateSetting", self.bAlternateSetting) + \ 542 " %-19s:%#7x\n" % ( 543 "bNumEndpoints", self.bNumEndpoints) + \ 544 " %-19s:%#7x %s\n" % ( 545 "bInterfaceClass", self.bInterfaceClass, 546 _try_lookup(_lu.interface_classes, self.bInterfaceClass)) + \ 547 " %-19s:%#7x\n" % ( 548 "bInterfaceSubClass", self.bInterfaceSubClass) + \ 549 " %-19s:%#7x\n" % ( 550 "bInterfaceProtocol", self.bInterfaceProtocol) + \ 551 " %-19s:%#7x %s" % ( 552 "iInterface", self.iInterface, 553 _try_get_string(self.device, self.iInterface)) 554 555 556class Configuration(object): 557 r"""Represent a configuration object. 558 559 This class contains all fields of the Configuration Descriptor according to 560 the USB Specification. You may access them as class properties. For 561 example, to access the field bConfigurationValue of the configuration 562 descriptor, you can do so: 563 564 >>> import usb.core 565 >>> dev = usb.core.find() 566 >>> for cfg in dev: 567 >>> print cfg.bConfigurationValue 568 """ 569 570 def __init__(self, device, configuration = 0): 571 r"""Initialize the configuration object. 572 573 The device parameter is the device object returned by the find() 574 function. The configuration parameter is the logical index of the 575 configuration (not the bConfigurationValue field). By "logical index" 576 we mean the relative order of the configurations returned by the 577 peripheral as a result of GET_DESCRIPTOR request. 578 """ 579 self.device = device 580 self.index = configuration 581 582 backend = device._ctx.backend 583 584 desc = backend.get_configuration_descriptor( 585 self.device._ctx.dev, 586 configuration 587 ) 588 589 _set_attr( 590 desc, 591 self, 592 ( 593 'bLength', 594 'bDescriptorType', 595 'wTotalLength', 596 'bNumInterfaces', 597 'bConfigurationValue', 598 'iConfiguration', 599 'bmAttributes', 600 'bMaxPower', 601 'extra_descriptors' 602 ) 603 ) 604 605 def __repr__(self): 606 return "<" + self._str() + ">" 607 608 def __str__(self): 609 string = self._get_full_descriptor_str() 610 for interface in self: 611 string += "\n%s" % str(interface) 612 return string 613 614 def interfaces(self): 615 r"""Return a tuple of the configuration interfaces.""" 616 return tuple(self) 617 618 def set(self): 619 r"""Set this configuration as the active one.""" 620 self.device.set_configuration(self.bConfigurationValue) 621 622 def __iter__(self): 623 r"""Iterate over all interfaces of the configuration.""" 624 for i in range(self.bNumInterfaces): 625 alt = 0 626 try: 627 while True: 628 yield Interface(self.device, i, alt, self.index) 629 alt += 1 630 except (USBError, IndexError): 631 pass 632 633 def __getitem__(self, index): 634 r"""Return the Interface object in the given position. 635 636 index is a tuple of two values with interface index and 637 alternate setting index, respectivally. Example: 638 639 >>> interface = config[(0, 0)] 640 """ 641 return Interface(self.device, index[0], index[1], self.index) 642 643 644 def _str(self): 645 return "CONFIGURATION %d: %d mA" % ( 646 self.bConfigurationValue, 647 _lu.MAX_POWER_UNITS_USB2p0 * self.bMaxPower) 648 649 def _get_full_descriptor_str(self): 650 headstr = " " + self._str() + " " 651 if self.bmAttributes & (1<<6): 652 powered = "Self" 653 else: 654 powered = "Bus" 655 656 if self.bmAttributes & (1<<5): 657 remote_wakeup = ", Remote Wakeup" 658 else: 659 remote_wakeup = "" 660 661 return "%s%s\n" % (headstr, "=" * (60 - len(headstr))) + \ 662 " %-21s:%#7x (9 bytes)\n" % ( 663 "bLength", self.bLength) + \ 664 " %-21s:%#7x %s\n" % ( 665 "bDescriptorType", self.bDescriptorType, 666 _try_lookup(_lu.descriptors, self.bDescriptorType)) + \ 667 " %-21s:%#7x (%d bytes)\n" % ( 668 "wTotalLength", self.wTotalLength, self.wTotalLength) + \ 669 " %-21s:%#7x\n" % ( 670 "bNumInterfaces", self.bNumInterfaces) + \ 671 " %-21s:%#7x\n" % ( 672 "bConfigurationValue", self.bConfigurationValue) + \ 673 " %-21s:%#7x %s\n" % ( 674 "iConfiguration", self.iConfiguration, 675 _try_get_string(self.device, self.iConfiguration)) + \ 676 " %-21s:%#7x %s Powered%s\n" % ( 677 "bmAttributes", self.bmAttributes, powered, remote_wakeup 678 # bit 7 is high, bit 4..0 are 0 679 ) + \ 680 " %-21s:%#7x (%d mA)" % ( 681 "bMaxPower", self.bMaxPower, 682 _lu.MAX_POWER_UNITS_USB2p0 * self.bMaxPower) 683 # FIXME : add a check for superspeed vs usb 2.0 684 685class Device(_objfinalizer.AutoFinalizedObject): 686 r"""Device object. 687 688 This class contains all fields of the Device Descriptor according to the 689 USB Specification. You may access them as class properties. For example, 690 to access the field bDescriptorType of the device descriptor, you can 691 do so: 692 693 >>> import usb.core 694 >>> dev = usb.core.find() 695 >>> dev.bDescriptorType 696 697 Additionally, the class provides methods to communicate with the hardware. 698 Typically, an application will first call the set_configuration() method to 699 put the device in a known configured state, optionally call the 700 set_interface_altsetting() to select the alternate setting (if there is 701 more than one) of the interface used, and call the write() and read() 702 methods to send and receive data, respectively. 703 704 When working in a new hardware, the first try could be like this: 705 706 >>> import usb.core 707 >>> dev = usb.core.find(idVendor=myVendorId, idProduct=myProductId) 708 >>> dev.set_configuration() 709 >>> dev.write(1, 'test') 710 711 This sample finds the device of interest (myVendorId and myProductId should 712 be replaced by the corresponding values of your device), then configures 713 the device (by default, the configuration value is 1, which is a typical 714 value for most devices) and then writes some data to the endpoint 0x01. 715 716 Timeout values for the write, read and ctrl_transfer methods are specified 717 in miliseconds. If the parameter is omitted, Device.default_timeout value 718 will be used instead. This property can be set by the user at anytime. 719 """ 720 721 def __repr__(self): 722 return "<" + self._str() + ">" 723 724 def __str__(self): 725 string = self._get_full_descriptor_str() 726 try: 727 for configuration in self: 728 string += "\n%s" % str(configuration) 729 except USBError: 730 try: 731 configuration = self.get_active_configuration() 732 string += "\n%s" % (configuration.info) 733 except USBError: 734 string += " USBError Accessing Configurations" 735 return string 736 737 def configurations(self): 738 r"""Return a tuple of the device configurations.""" 739 return tuple(self) 740 741 def __init__(self, dev, backend): 742 r"""Initialize the Device object. 743 744 Library users should normally get a Device instance through 745 the find function. The dev parameter is the identification 746 of a device to the backend and its meaning is opaque outside 747 of it. The backend parameter is a instance of a backend 748 object. 749 """ 750 self._ctx = _ResourceManager(dev, backend) 751 self.__default_timeout = _DEFAULT_TIMEOUT 752 self._serial_number, self._product, self._manufacturer = None, None, None 753 self._langids = None 754 755 desc = backend.get_device_descriptor(dev) 756 757 _set_attr( 758 desc, 759 self, 760 ( 761 'bLength', 762 'bDescriptorType', 763 'bcdUSB', 764 'bDeviceClass', 765 'bDeviceSubClass', 766 'bDeviceProtocol', 767 'bMaxPacketSize0', 768 'idVendor', 769 'idProduct', 770 'bcdDevice', 771 'iManufacturer', 772 'iProduct', 773 'iSerialNumber', 774 'bNumConfigurations', 775 'address', 776 'bus', 777 'port_number', 778 'port_numbers', 779 'speed', 780 ) 781 ) 782 783 if desc.bus is not None: 784 self.bus = int(desc.bus) 785 else: 786 self.bus = None 787 788 if desc.address is not None: 789 self.address = int(desc.address) 790 else: 791 self.address = None 792 793 if desc.port_number is not None: 794 self.port_number = int(desc.port_number) 795 else: 796 self.port_number = None 797 798 if desc.speed is not None: 799 self.speed = int(desc.speed) 800 else: 801 self.speed = None 802 803 @property 804 def langids(self): 805 """ Return the USB device's supported language ID codes. 806 807 These are 16-bit codes familiar to Windows developers, where for 808 example instead of en-US you say 0x0409. USB_LANGIDS.pdf on the usb.org 809 developer site for more info. String requests using a LANGID not 810 in this array should not be sent to the device. 811 812 This property will cause some USB traffic the first time it is accessed 813 and cache the resulting value for future use. 814 """ 815 if self._langids is None: 816 try: 817 self._langids = util.get_langids(self) 818 except USBError: 819 self._langids = () 820 return self._langids 821 822 @property 823 def serial_number(self): 824 """ Return the USB device's serial number string descriptor. 825 826 This property will cause some USB traffic the first time it is accessed 827 and cache the resulting value for future use. 828 """ 829 if self._serial_number is None: 830 self._serial_number = util.get_string(self, self.iSerialNumber) 831 return self._serial_number 832 833 @property 834 def product(self): 835 """ Return the USB device's product string descriptor. 836 837 This property will cause some USB traffic the first time it is accessed 838 and cache the resulting value for future use. 839 """ 840 if self._product is None: 841 self._product = util.get_string(self, self.iProduct) 842 return self._product 843 844 @property 845 def manufacturer(self): 846 """ Return the USB device's manufacturer string descriptor. 847 848 This property will cause some USB traffic the first time it is accessed 849 and cache the resulting value for future use. 850 """ 851 if self._manufacturer is None: 852 self._manufacturer = util.get_string(self, self.iManufacturer) 853 return self._manufacturer 854 855 @property 856 def backend(self): 857 """Return the backend being used by the device.""" 858 return self._ctx.backend 859 860 def set_configuration(self, configuration = None): 861 r"""Set the active configuration. 862 863 The configuration parameter is the bConfigurationValue field of the 864 configuration you want to set as active. If you call this method 865 without parameter, it will use the first configuration found. As a 866 device hardly ever has more than one configuration, calling the method 867 without arguments is enough to get the device ready. 868 """ 869 self._ctx.managed_set_configuration(self, configuration) 870 871 def get_active_configuration(self): 872 r"""Return a Configuration object representing the current 873 configuration set. 874 """ 875 return self._ctx.get_active_configuration(self) 876 877 def set_interface_altsetting(self, interface = None, alternate_setting = None): 878 r"""Set the alternate setting for an interface. 879 880 When you want to use an interface and it has more than one alternate 881 setting, you should call this method to select the appropriate 882 alternate setting. If you call the method without one or the two 883 parameters, it will be selected the first one found in the Device in 884 the same way of the set_configuration method. 885 886 Commonly, an interface has only one alternate setting and this call is 887 not necessary. For most devices, either it has more than one 888 alternate setting or not, it is not harmful to make a call to this 889 method with no arguments, as devices will silently ignore the request 890 when there is only one alternate setting, though the USB Spec allows 891 devices with no additional alternate setting return an error to the 892 Host in response to a SET_INTERFACE request. 893 894 If you are in doubt, you may want to call it with no arguments wrapped 895 by a try/except clause: 896 897 >>> try: 898 >>> dev.set_interface_altsetting() 899 >>> except usb.core.USBError: 900 >>> pass 901 """ 902 self._ctx.managed_set_interface(self, interface, alternate_setting) 903 904 def clear_halt(self, ep): 905 r""" Clear the halt/stall condition for the endpoint ep.""" 906 if isinstance(ep, Endpoint): 907 ep = ep.bEndpointAddress 908 self._ctx.managed_open() 909 self._ctx.backend.clear_halt(self._ctx.handle, ep) 910 911 def reset(self): 912 r"""Reset the device.""" 913 self._ctx.managed_open() 914 self._ctx.dispose(self, False) 915 self._ctx.backend.reset_device(self._ctx.handle) 916 self._ctx.dispose(self, True) 917 918 def write(self, endpoint, data, timeout = None): 919 r"""Write data to the endpoint. 920 921 This method is used to send data to the device. The endpoint parameter 922 corresponds to the bEndpointAddress member whose endpoint you want to 923 communicate with. 924 925 The data parameter should be a sequence like type convertible to 926 the array type (see array module). 927 928 The timeout is specified in miliseconds. 929 930 The method returns the number of bytes written. 931 """ 932 backend = self._ctx.backend 933 934 fn_map = { 935 util.ENDPOINT_TYPE_BULK:backend.bulk_write, 936 util.ENDPOINT_TYPE_INTR:backend.intr_write, 937 util.ENDPOINT_TYPE_ISO:backend.iso_write 938 } 939 940 intf, ep = self._ctx.setup_request(self, endpoint) 941 fn = fn_map[util.endpoint_type(ep.bmAttributes)] 942 943 return fn( 944 self._ctx.handle, 945 ep.bEndpointAddress, 946 intf.bInterfaceNumber, 947 _interop.as_array(data), 948 self.__get_timeout(timeout) 949 ) 950 951 def read(self, endpoint, size_or_buffer, timeout = None): 952 r"""Read data from the endpoint. 953 954 This method is used to receive data from the device. The endpoint 955 parameter corresponds to the bEndpointAddress member whose endpoint 956 you want to communicate with. The size_or_buffer parameter either 957 tells how many bytes you want to read or supplies the buffer to 958 receive the data (it *must* be an object of the type array). 959 960 The timeout is specified in miliseconds. 961 962 If the size_or_buffer parameter is the number of bytes to read, the 963 method returns an array object with the data read. If the 964 size_or_buffer parameter is an array object, it returns the number 965 of bytes actually read. 966 """ 967 backend = self._ctx.backend 968 969 fn_map = { 970 util.ENDPOINT_TYPE_BULK:backend.bulk_read, 971 util.ENDPOINT_TYPE_INTR:backend.intr_read, 972 util.ENDPOINT_TYPE_ISO:backend.iso_read 973 } 974 975 intf, ep = self._ctx.setup_request(self, endpoint) 976 fn = fn_map[util.endpoint_type(ep.bmAttributes)] 977 978 if isinstance(size_or_buffer, array.array): 979 buff = size_or_buffer 980 else: # here we consider it is a integer 981 buff = util.create_buffer(size_or_buffer) 982 983 ret = fn( 984 self._ctx.handle, 985 ep.bEndpointAddress, 986 intf.bInterfaceNumber, 987 buff, 988 self.__get_timeout(timeout)) 989 990 if isinstance(size_or_buffer, array.array): 991 return ret 992 elif ret != len(buff) * buff.itemsize: 993 return buff[:ret] 994 else: 995 return buff 996 997 def ctrl_transfer(self, bmRequestType, bRequest, wValue=0, wIndex=0, 998 data_or_wLength = None, timeout = None): 999 r"""Do a control transfer on the endpoint 0. 1000 1001 This method is used to issue a control transfer over the endpoint 0 1002 (endpoint 0 is required to always be a control endpoint). 1003 1004 The parameters bmRequestType, bRequest, wValue and wIndex are the same 1005 of the USB Standard Control Request format. 1006 1007 Control requests may or may not have a data payload to write/read. 1008 In cases which it has, the direction bit of the bmRequestType 1009 field is used to infer the desired request direction. For 1010 host to device requests (OUT), data_or_wLength parameter is 1011 the data payload to send, and it must be a sequence type convertible 1012 to an array object. In this case, the return value is the number 1013 of bytes written in the data payload. For device to host requests 1014 (IN), data_or_wLength is either the wLength parameter of the control 1015 request specifying the number of bytes to read in data payload, and 1016 the return value is an array object with data read, or an array 1017 object which the data will be read to, and the return value is the 1018 number of bytes read. 1019 """ 1020 try: 1021 buff = util.create_buffer(data_or_wLength) 1022 except TypeError: 1023 buff = _interop.as_array(data_or_wLength) 1024 1025 self._ctx.managed_open() 1026 1027 # Thanks to Johannes Stezenbach to point me out that we need to 1028 # claim the recipient interface 1029 recipient = bmRequestType & 3 1030 rqtype = bmRequestType & (3 << 5) 1031 if recipient == util.CTRL_RECIPIENT_INTERFACE \ 1032 and rqtype != util.CTRL_TYPE_VENDOR: 1033 interface_number = wIndex & 0xff 1034 self._ctx.managed_claim_interface(self, interface_number) 1035 1036 ret = self._ctx.backend.ctrl_transfer( 1037 self._ctx.handle, 1038 bmRequestType, 1039 bRequest, 1040 wValue, 1041 wIndex, 1042 buff, 1043 self.__get_timeout(timeout)) 1044 1045 if isinstance(data_or_wLength, array.array) \ 1046 or util.ctrl_direction(bmRequestType) == util.CTRL_OUT: 1047 return ret 1048 elif ret != len(buff) * buff.itemsize: 1049 return buff[:ret] 1050 else: 1051 return buff 1052 1053 def is_kernel_driver_active(self, interface): 1054 r"""Determine if there is kernel driver associated with the interface. 1055 1056 If a kernel driver is active, the object will be unable to perform 1057 I/O. 1058 1059 The interface parameter is the device interface number to check. 1060 """ 1061 self._ctx.managed_open() 1062 return self._ctx.backend.is_kernel_driver_active( 1063 self._ctx.handle, 1064 interface) 1065 1066 def detach_kernel_driver(self, interface): 1067 r"""Detach a kernel driver. 1068 1069 If successful, you will then be able to perform I/O. 1070 1071 The interface parameter is the device interface number to detach the 1072 driver from. 1073 """ 1074 self._ctx.managed_open() 1075 self._ctx.backend.detach_kernel_driver( 1076 self._ctx.handle, 1077 interface) 1078 1079 def attach_kernel_driver(self, interface): 1080 r"""Re-attach an interface's kernel driver, which was previously 1081 detached using detach_kernel_driver(). 1082 1083 The interface parameter is the device interface number to attach the 1084 driver to. 1085 """ 1086 self._ctx.managed_open() 1087 self._ctx.backend.attach_kernel_driver( 1088 self._ctx.handle, 1089 interface) 1090 1091 def __iter__(self): 1092 r"""Iterate over all configurations of the device.""" 1093 for i in range(self.bNumConfigurations): 1094 yield Configuration(self, i) 1095 1096 def __getitem__(self, index): 1097 r"""Return the Configuration object in the given position.""" 1098 return Configuration(self, index) 1099 1100 def _finalize_object(self): 1101 self._ctx.dispose(self) 1102 1103 def __get_timeout(self, timeout): 1104 if timeout is not None: 1105 return timeout 1106 return self.__default_timeout 1107 1108 def __set_def_tmo(self, tmo): 1109 if tmo < 0: 1110 raise ValueError('Timeout cannot be a negative value') 1111 self.__default_timeout = tmo 1112 1113 def __get_def_tmo(self): 1114 return self.__default_timeout 1115 1116 def _str(self): 1117 return "DEVICE ID %04x:%04x on Bus %03d Address %03d" % ( 1118 self.idVendor, self.idProduct, self.bus, self.address) 1119 1120 def _get_full_descriptor_str(self): 1121 headstr = self._str() + " " 1122 1123 if self.bcdUSB & 0xf: 1124 low_bcd_usb = str(self.bcdUSB & 0xf) 1125 else: 1126 low_bcd_usb = "" 1127 1128 if self.bcdDevice & 0xf: 1129 low_bcd_device = str(self.bcdDevice & 0xf) 1130 else: 1131 low_bcd_device = "" 1132 1133 return "%s%s\n" % (headstr, "=" * (60 - len(headstr))) + \ 1134 " %-23s:%#7x (18 bytes)\n" % ( 1135 "bLength", self.bLength) + \ 1136 " %-23s:%#7x %s\n" % ( 1137 "bDescriptorType", self.bDescriptorType, 1138 _try_lookup(_lu.descriptors, self.bDescriptorType)) + \ 1139 " %-23s:%#7x USB %d.%d%s\n" % ( 1140 "bcdUSB", self.bcdUSB, (self.bcdUSB & 0xff00)>>8, 1141 (self.bcdUSB & 0xf0) >> 4, low_bcd_usb) + \ 1142 " %-23s:%#7x %s\n" % ( 1143 "bDeviceClass", self.bDeviceClass, 1144 _try_lookup(_lu.device_classes, self.bDeviceClass)) + \ 1145 " %-23s:%#7x\n" % ( 1146 "bDeviceSubClass", self.bDeviceSubClass) + \ 1147 " %-23s:%#7x\n" % ( 1148 "bDeviceProtocol", self.bDeviceProtocol) + \ 1149 " %-23s:%#7x (%d bytes)\n" % ( 1150 "bMaxPacketSize0", self.bMaxPacketSize0, self.bMaxPacketSize0) + \ 1151 " %-23s: %#06x\n" % ( 1152 "idVendor", self.idVendor) + \ 1153 " %-23s: %#06x\n" % ( 1154 "idProduct", self.idProduct) + \ 1155 " %-23s:%#7x Device %d.%d%s\n" % ( 1156 "bcdDevice", self.bcdDevice, (self.bcdDevice & 0xff00)>>8, 1157 (self.bcdDevice & 0xf0) >> 4, low_bcd_device) + \ 1158 " %-23s:%#7x %s\n" % ( 1159 "iManufacturer", self.iManufacturer, 1160 _try_get_string(self, self.iManufacturer)) + \ 1161 " %-23s:%#7x %s\n" % ( 1162 "iProduct", self.iProduct, 1163 _try_get_string(self, self.iProduct)) + \ 1164 " %-23s:%#7x %s\n" % ( 1165 "iSerialNumber", self.iSerialNumber, 1166 _try_get_string(self, self.iSerialNumber)) + \ 1167 " %-23s:%#7x" % ( 1168 "bNumConfigurations", self.bNumConfigurations) 1169 1170 default_timeout = property( 1171 __get_def_tmo, 1172 __set_def_tmo, 1173 doc = 'Default timeout for transfer I/O functions' 1174 ) 1175 1176 1177def find(find_all=False, backend = None, custom_match = None, **args): 1178 r"""Find an USB device and return it. 1179 1180 find() is the function used to discover USB devices. You can pass as 1181 arguments any combination of the USB Device Descriptor fields to match a 1182 device. For example: 1183 1184 find(idVendor=0x3f4, idProduct=0x2009) 1185 1186 will return the Device object for the device with idVendor field equals 1187 to 0x3f4 and idProduct equals to 0x2009. 1188 1189 If there is more than one device which matchs the criteria, the first one 1190 found will be returned. If a matching device cannot be found the function 1191 returns None. If you want to get all devices, you can set the parameter 1192 find_all to True, then find will return an iterator with all matched devices. 1193 If no matching device is found, it will return an empty iterator. Example: 1194 1195 for printer in find(find_all=True, bDeviceClass=7): 1196 print (printer) 1197 1198 This call will get all the USB printers connected to the system. (actually 1199 may be not, because some devices put their class information in the 1200 Interface Descriptor). 1201 1202 You can also use a customized match criteria: 1203 1204 dev = find(custom_match = lambda d: d.idProduct=0x3f4 and d.idvendor=0x2009) 1205 1206 A more accurate printer finder using a customized match would be like 1207 so: 1208 1209 def is_printer(dev): 1210 import usb.util 1211 if dev.bDeviceClass == 7: 1212 return True 1213 for cfg in dev: 1214 if usb.util.find_descriptor(cfg, bInterfaceClass=7) is not None: 1215 return True 1216 1217 for printer in find(find_all=True, custom_match = is_printer): 1218 print (printer) 1219 1220 Now even if the device class code is in the interface descriptor the 1221 printer will be found. 1222 1223 You can combine a customized match with device descriptor fields. In this 1224 case, the fields must match and the custom_match must return True. In the 1225 our previous example, if we would like to get all printers belonging to the 1226 manufacturer 0x3f4, the code would be like so: 1227 1228 printers = list(find(find_all=True, idVendor=0x3f4, custom_match=is_printer)) 1229 1230 If you want to use find as a 'list all devices' function, just call 1231 it with find_all = True: 1232 1233 devices = list(find(find_all=True)) 1234 1235 Finally, you can pass a custom backend to the find function: 1236 1237 find(backend = MyBackend()) 1238 1239 PyUSB has builtin backends for libusb 0.1, libusb 1.0 and OpenUSB. If you 1240 do not supply a backend explicitly, find() function will select one of the 1241 predefineds backends according to system availability. 1242 1243 Backends are explained in the usb.backend module. 1244 """ 1245 def device_iter(**kwargs): 1246 for dev in backend.enumerate_devices(): 1247 d = Device(dev, backend) 1248 tests = (val == getattr(d, key) for key, val in kwargs.items()) 1249 if _interop._all(tests) and (custom_match is None or custom_match(d)): 1250 yield d 1251 1252 if backend is None: 1253 import usb.backend.libusb1 as libusb1 1254 import usb.backend.libusb0 as libusb0 1255 import usb.backend.openusb as openusb 1256 1257 for m in (libusb1, openusb, libusb0): 1258 backend = m.get_backend() 1259 if backend is not None: 1260 _logger.info('find(): using backend "%s"', m.__name__) 1261 break 1262 else: 1263 raise NoBackendError('No backend available') 1264 1265 if find_all: 1266 return device_iter(**args) 1267 else: 1268 try: 1269 return _interop._next(device_iter(**args)) 1270 except StopIteration: 1271 return None 1272 1273def show_devices(verbose=False, **kwargs): 1274 """Show information about connected devices. 1275 1276 The verbose flag sets to verbose or not. 1277 **kwargs are passed directly to the find() function. 1278 """ 1279 kwargs["find_all"] = True 1280 devices = find(**kwargs) 1281 strings = "" 1282 for device in devices: 1283 if not verbose: 1284 strings += "%s, %s\n" % (device._str(), _try_lookup( 1285 _lu.device_classes, device.bDeviceClass)) 1286 else: 1287 strings += "%s\n\n" % str(device) 1288 1289 return _DescriptorInfo(strings) 1290