def __init__(self, dev): self.dev = dev self.cfg = cfg = dev.get_active_configuration() self.intf = intf = find_descriptor( cfg, bInterfaceClass=CONFIG["class"], bInterfaceSubClass=CONFIG["subclass"], # bInterfaceProtocol=CCID_PROTOCOL_0, ) if intf is None: raise ValueError("Not a CCID device") claim_interface(dev, intf) for ep in intf: if (endpoint_type(ep.bmAttributes) == ENDPOINT_TYPE_BULK and endpoint_direction(ep.bEndpointAddress) == ENDPOINT_OUT): self.bulkout = ep.bEndpointAddress if (endpoint_type(ep.bmAttributes) == ENDPOINT_TYPE_BULK and endpoint_direction(ep.bEndpointAddress) == ENDPOINT_IN): self.bulkin = ep.bEndpointAddress self.seq = 0 self.timeout = 10000
def __init__(self, dev): """ __init__(dev) -> None Initialize the DEV of CCID. device: usb.core.Device object. """ cfg = dev.get_active_configuration() intf = find_descriptor(cfg, bInterfaceClass=CCID_CLASS, bInterfaceSubClass=CCID_SUBCLASS, bInterfaceProtocol=CCID_PROTOCOL_0) if intf is None: raise ValueError("Not a CCID device") try: claim_interface(dev, intf) except Exception as e: print(e) for ep in intf: if endpoint_type(ep.bmAttributes) == ENDPOINT_TYPE_BULK and \ endpoint_direction(ep.bEndpointAddress) == ENDPOINT_OUT: self.__bulkout = ep.bEndpointAddress if endpoint_type(ep.bmAttributes) == ENDPOINT_TYPE_BULK and \ endpoint_direction(ep.bEndpointAddress) == ENDPOINT_IN: self.__bulkin = ep.bEndpointAddress assert len(intf.extra_descriptors) == 54 assert intf.extra_descriptors[1] == 33 if (intf.extra_descriptors[42] & 0x02): # Short APDU level exchange self.__use_APDU = True elif (intf.extra_descriptors[42] & 0x04): # Short and extended APDU level exchange self.__use_APDU = True elif (intf.extra_descriptors[42] & 0x01): # TPDU level exchange self.__use_APDU = False else: raise ValueError("Unknown exchange level") # Check other bits??? # intf.extra_descriptors[40] # intf.extra_descriptors[41] self.__dev = dev self.__timeout = 10000 self.__seq = 0
def write(self, endpoint, data, timeout=None): r"""Write data to the endpoint. This method is used to send data to the device. The endpoint parameter corresponds to the bEndpointAddress member whose endpoint you want to communicate with. The data parameter should be a sequence like type convertible to the array type (see array module). The timeout is specified in miliseconds. The method returns the number of bytes written. """ backend = self._ctx.backend fn_map = { util.ENDPOINT_TYPE_BULK: backend.bulk_write, util.ENDPOINT_TYPE_INTR: backend.intr_write, util.ENDPOINT_TYPE_ISO: backend.iso_write } intf, ep = self._ctx.setup_request(self, endpoint) fn = fn_map[util.endpoint_type(ep.bmAttributes)] return fn(self._ctx.handle, ep.bEndpointAddress, intf.bInterfaceNumber, _interop.as_array(data), self.__get_timeout(timeout))
def write(self, endpoint, data, timeout = None): r"""Write data to the endpoint. This method is used to send data to the device. The endpoint parameter corresponds to the bEndpointAddress member whose endpoint you want to communicate with. The data parameter should be a sequence like type convertible to the array type (see array module). The timeout is specified in miliseconds. The method returns the number of bytes written. """ backend = self._ctx.backend fn_map = { util.ENDPOINT_TYPE_BULK:backend.bulk_write, util.ENDPOINT_TYPE_INTR:backend.intr_write, util.ENDPOINT_TYPE_ISO:backend.iso_write } intf, ep = self._ctx.setup_request(self, endpoint) fn = fn_map[util.endpoint_type(ep.bmAttributes)] return fn( self._ctx.handle, ep.bEndpointAddress, intf.bInterfaceNumber, _interop.as_array(data), self.__get_timeout(timeout) )
def retrieve_device_endpoints(cls, device, return_endpoint_address=False): ep_bulk_in = None ep_bulk_out = None ep_interrupt_in = None # Retrieve device endpoints (BULK and INTERRUPT) for config in device: for intf in config: for ep in intf.endpoints(): ep_type = endpoint_type(ep.bmAttributes) ep_direction = endpoint_direction(ep.bEndpointAddress) if ep_type == ENDPOINT_TYPE_BULK and ep_direction == ENDPOINT_IN: ep_bulk_in = ep elif ep_type == ENDPOINT_TYPE_BULK and ep_direction == ENDPOINT_OUT: ep_bulk_out = ep elif ep_type == ENDPOINT_TYPE_INTR and ep_direction == ENDPOINT_IN: ep_interrupt_in = ep # Ensure that all three endpoints are found if not ep_bulk_in: raise Exception("Missing bulk in endpoint.") elif not ep_bulk_out: raise Exception("Missing bulk out endpoint.") elif not ep_interrupt_in: raise Exception("Missing interrupt in endpoint.") if return_endpoint_address: return ep_bulk_in.address, ep_bulk_out.address, ep_interrupt_in.address else: return ep_bulk_in, ep_bulk_out, ep_interrupt_in
def read(self, endpoint, size, timeout = None): r"""Read data from the endpoint. This method is used to receive data from the device. The endpoint parameter corresponds to the bEndpointAddress member whose endpoint you want to communicate with. The size parameters tells how many bytes you want to read. The timeout is specified in miliseconds. The method returns an array object with the data read. """ backend = self._ctx.backend fn_map = { util.ENDPOINT_TYPE_BULK:backend.bulk_read, util.ENDPOINT_TYPE_INTR:backend.intr_read, util.ENDPOINT_TYPE_ISO:backend.iso_read } intf, ep = self._ctx.setup_request(self, endpoint) fn = fn_map[util.endpoint_type(ep.bmAttributes)] return fn( self._ctx.handle, ep.bEndpointAddress, intf.bInterfaceNumber, size, self.__get_timeout(timeout) )
def __setup_device(self, dev): '''Get endpoints for a device. True on success.''' self.__inep = None self.__outep = None self.__intep = None self.__cfg = None self.__dev = None self.__intf = None # Attempt to find the USB in, out and interrupt endpoints for a PTP # interface. for cfg in dev: for intf in cfg: if intf.bInterfaceClass == PTP_USB_CLASS: for ep in intf: ep_type = endpoint_type(ep.bmAttributes) ep_dir = endpoint_direction(ep.bEndpointAddress) if ep_type == ENDPOINT_TYPE_BULK: if ep_dir == ENDPOINT_IN: self.__inep = ep elif ep_dir == ENDPOINT_OUT: self.__outep = ep elif ((ep_type == ENDPOINT_TYPE_INTR) and (ep_dir == ENDPOINT_IN)): self.__intep = ep if not (self.__inep and self.__outep and self.__intep): self.__inep = None self.__outep = None self.__intep = None else: self.__cfg = cfg self.__dev = dev self.__intf = intf return True return False
def __init__(self, dev): """ __init__(dev) -> None Initialize the DEV of CCID. device: usb.core.Device object. """ cfg = dev.get_active_configuration() intf = find_descriptor(cfg, bInterfaceClass=CCID_CLASS, bInterfaceSubClass=CCID_SUBCLASS, bInterfaceProtocol=CCID_PROTOCOL_0) if intf is None: raise ValueError("Not a CCID device") claim_interface(dev, intf) for ep in intf: if endpoint_type(ep.bmAttributes) == ENDPOINT_TYPE_BULK and \ endpoint_direction(ep.bEndpointAddress) == ENDPOINT_OUT: self.__bulkout = ep.bEndpointAddress if endpoint_type(ep.bmAttributes) == ENDPOINT_TYPE_BULK and \ endpoint_direction(ep.bEndpointAddress) == ENDPOINT_IN: self.__bulkin = ep.bEndpointAddress assert len(intf.extra_descriptors) == 54 assert intf.extra_descriptors[1] == 33 if (intf.extra_descriptors[42] & 0x02): # Short APDU level exchange self.__use_APDU = True elif (intf.extra_descriptors[42] & 0x04): # Short and extended APDU level exchange self.__use_APDU = True elif (intf.extra_descriptors[42] & 0x01): # TPDU level exchange self.__use_APDU = False else: raise ValueError("Unknown exchange level") # Check other bits??? # intf.extra_descriptors[40] # intf.extra_descriptors[41] self.__dev = dev self.__timeout = 10000 self.__seq = 0
def get_endpoint(direction): predicate = lambda ep: \ util.endpoint_type(ep.bmAttributes) == util.ENDPOINT_TYPE_BULK and \ util.endpoint_direction(ep.bEndpointAddress) == direction eps = list(filter(predicate, endpoints)) if len(eps) == 0: raise NeotoolsError( 'Cannot find endpoint with direction %s' % direction) return eps[0]
def get_endpoint_type(self, device, address, intf): intf = self.get_interface(device, intf) key = (address, intf.bInterfaceNumber, intf.bAlternateSetting) try: return self._ep_type_map[key] except KeyError: e = util.find_descriptor(intf, bEndpointAddress=address) etype = util.endpoint_type(e.bmAttributes) self._ep_type_map[key] = etype return etype
def read(self, endpoint, size_or_buffer, timeout = None): r"""Read data from the endpoint. This method is used to receive data from the device. The endpoint parameter corresponds to the bEndpointAddress member whose endpoint you want to communicate with. The size_or_buffer parameter either tells how many bytes you want to read or supplies the buffer to receive the data (it *must* be an object of the type array). The timeout is specified in miliseconds. If the size_or_buffer parameter is the number of bytes to read, the method returns an array object with the data read. If the size_or_buffer parameter is an array object, it returns the number of bytes actually read. """ backend = self._ctx.backend fn_map = { util.ENDPOINT_TYPE_BULK:backend.bulk_read, util.ENDPOINT_TYPE_INTR:backend.intr_read, util.ENDPOINT_TYPE_ISO:backend.iso_read } intf, ep = self._ctx.setup_request(self, endpoint) fn = fn_map[util.endpoint_type(ep.bmAttributes)] if isinstance(size_or_buffer, array.array): buff = size_or_buffer else: # here we consider it is a integer buff = util.create_buffer(size_or_buffer) ret = fn( self._ctx.handle, ep.bEndpointAddress, intf.bInterfaceNumber, buff, self.__get_timeout(timeout), self._stopped) if isinstance(size_or_buffer, array.array): return ret elif ret != len(buff) * buff.itemsize: return buff[:ret] else: return buff
def __setup_device(self, dev): '''Get endpoints for a device. True on success.''' self.__inep = None self.__outep = None self.__intep = None self.__cfg = None self.__dev = None self.__intf = None # Attempt to find the USB in, out and interrupt endpoints for a PTP # interface. for cfg in dev: for intf in cfg: if intf.bInterfaceClass == PTP_USB_CLASS: for ep in intf: ep_type = endpoint_type(ep.bmAttributes) ep_dir = endpoint_direction(ep.bEndpointAddress) if ep_type == ENDPOINT_TYPE_BULK: if ep_dir == ENDPOINT_IN: self.__inep = ep elif ep_dir == ENDPOINT_OUT: self.__outep = ep elif ((ep_type == ENDPOINT_TYPE_INTR) and (ep_dir == ENDPOINT_IN)): self.__intep = ep if not (self.__inep and self.__outep and self.__intep): self.__inep = None self.__outep = None self.__intep = None else: logger.debug('Found {}'.format(repr(self.__inep))) logger.debug('Found {}'.format(repr(self.__outep))) logger.debug('Found {}'.format(repr(self.__intep))) self.__cfg = cfg self.__dev = dev self.__intf = intf return True return False
def read(self, endpoint, size, timeout=None): r"""Read data from the endpoint. This method is used to receive data from the device. The endpoint parameter corresponds to the bEndpointAddress member whose endpoint you want to communicate with. The size parameters tells how many bytes you want to read. The timeout is specified in miliseconds. The method returns an array object with the data read. """ backend = self._ctx.backend fn_map = { util.ENDPOINT_TYPE_BULK: backend.bulk_read, util.ENDPOINT_TYPE_INTR: backend.intr_read, util.ENDPOINT_TYPE_ISO: backend.iso_read } intf, ep = self._ctx.setup_request(self, endpoint) fn = fn_map[util.endpoint_type(ep.bmAttributes)] return fn(self._ctx.handle, ep.bEndpointAddress, intf.bInterfaceNumber, size, self.__get_timeout(timeout))
def __init__(self, ep): self.address = ep.bEndpointAddress self.interval = ep.bInterval self.maxPacketSize = ep.wMaxPacketSize self.type = util.endpoint_type(ep.bmAttributes)
def __init__(self, product: int, timeout: Optional[float] = 5) -> None: print(f"__init__({product}, {timeout})") if timeout is not None: timeout += time() while True: device = find(idVendor=0x27c6, idProduct=product) if device is not None: try: if get_status(device) == 0x0001: break except USBError as error: if (error.backend_error_code != -1 and error.backend_error_code != -4): raise error if timeout is not None and time() > timeout: if device is None: raise USBTimeoutError("Device not found", -5, 19) raise USBTimeoutError("Invalid device state", -12, 131) sleep(0.01) self.device: USBDevice = device print(f"Found Goodix device: \"{self.device.product}\" " f"from \"{self.device.manufacturer}\" " f"on bus {self.device.bus} " f"address {self.device.address}.") interface = find_descriptor(self.device.get_active_configuration(), bInterfaceClass=CLASS_DATA) if interface is None: raise USBError("Interface data not found", -5, 6) print(f"Found interface data: {interface.bInterfaceNumber}") endpoint_in = find_descriptor( interface, custom_match=lambda endpoint: endpoint_direction( endpoint.bEndpointAddress) == ENDPOINT_IN and endpoint_type( endpoint.bmAttributes) == ENDPOINT_TYPE_BULK) if endpoint_in is None: raise USBError("Endpoint in not found", -5, 6) self.endpoint_in: int = endpoint_in.bEndpointAddress print(f"Found endpoint in: {hex(self.endpoint_in)}") endpoint_out = find_descriptor( interface, custom_match=lambda endpoint: endpoint_direction( endpoint.bEndpointAddress) == ENDPOINT_OUT and endpoint_type( endpoint.bmAttributes) == ENDPOINT_TYPE_BULK) if endpoint_out is None: raise USBError("Endpoint out not found", -5, 6) self.endpoint_out: int = endpoint_out.bEndpointAddress print(f"Found endpoint out: {hex(self.endpoint_out)}") # Empty device reply buffer (Current patch while waiting for a fix) self.empty_buffer()