Example #1
0
    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
Example #2
0
    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
Example #3
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))
Example #4
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)
            )
Example #5
0
    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
Example #6
0
    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)
            )
Example #7
0
 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
Example #8
0
    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
Example #9
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]
Example #10
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
Example #11
0
    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
Example #12
0
 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
Example #13
0
    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))
Example #14
0
 def __init__(self, ep):
     self.address = ep.bEndpointAddress
     self.interval = ep.bInterval
     self.maxPacketSize = ep.wMaxPacketSize
     self.type = util.endpoint_type(ep.bmAttributes)
Example #15
0
 def __init__(self, ep):
     self.address = ep.bEndpointAddress
     self.interval = ep.bInterval
     self.maxPacketSize = ep.wMaxPacketSize
     self.type = util.endpoint_type(ep.bmAttributes)
Example #16
0
    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()