def testFindConfigureInterfaceEndpointsDevice(self):
        dev = usb.core.find(idVendor=0x0403, idProduct=0x6001)
        dev.set_configuration()
        cfg = dev.get_active_configuration()
        self.assertIsNotNone(cfg)
        itf = cfg[(0, 0)]
        epIn = itf[0]
        epOut = itf[1]
        self.assertTrue(epIn.bEndpointAddress & 0x80 != 0)
        self.assertTrue(epOut.bEndpointAddress & 0x80 == 0)

        # We cannot do this: writing to endpoints is not the way to use the device
        # There seems to be a bit more information that is sent into these endpoints
        maxPacket = epIn.wMaxPacketSize
        data = util.create_buffer(maxPacket)
        nBytes = epIn.read(size_or_buffer=data, timeout=1000)
        print(nBytes, data)

        text = b'aaaabbbbccccddddeeeeffff'
        epOut.write(text)
        epOut.write(text)
        epOut.write(text)
        data = util.create_buffer(maxPacket)
        nBytes = epIn.read(size_or_buffer=data, timeout=1000)
        print(nBytes, data[:nBytes])
        for c in data[:nBytes]:
            print("{0:08b} ".format(c), end='')
Exemple #2
0
def read_extended_data(device, size):
    """
    Read binary data blocks in response to some other command, handling segmentation
    and checksum validation.

    The command sequence is:

        While data left to read
            OUT:    0x10    ASMESSAGE_REQUEST_BLOCK_READ
            IN:     0x4d    ASMESSAGE_RESPONSE_BLOCK_READ
            OUT:    data
    """
    logger.debug('Reading extended data')
    remaining = size
    message = Message(MessageConst.REQUEST_BLOCK_READ, [])
    result = util.create_buffer(0)

    while remaining > 0:
        response = send_message(device, message)
        if response.command() == MessageConst.RESPONSE_BLOCK_READ_EMPTY:
            break
        if response.command() == MessageConst.RESPONSE_BLOCK_READ:
            blocksize = response.argument(1, 4)
            checksum = response.argument(5, 2)
            buf = device.read(blocksize)
            assert calculate_data_checksum(buf) == checksum
            result.extend(buf)
            remaining = remaining - len(buf)
        else:
            raise NeotoolsError('Unexpected response %s' % response)

    return result.tobytes()
Exemple #3
0
    def ctrl_transfer(self,
                      bmRequestType,
                      bRequest,
                      wValue=0,
                      wIndex=0,
                      data_or_wLength=None,
                      timeout=None):
        r"""Do a control transfer on the endpoint 0.

        This method is used to issue a control transfer over the endpoint 0
        (endpoint 0 is required to always be a control endpoint).

        The parameters bmRequestType, bRequest, wValue and wIndex are the same
        of the USB Standard Control Request format.

        Control requests may or may not have a data payload to write/read.
        In cases which it has, the direction bit of the bmRequestType
        field is used to infer the desired request direction. For
        host to device requests (OUT), data_or_wLength parameter is
        the data payload to send, and it must be a sequence type convertible
        to an array object. In this case, the return value is the number
        of bytes written in the data payload. For device to host requests
        (IN), data_or_wLength is either the wLength parameter of the control
        request specifying the number of bytes to read in data payload, and
        the return value is an array object with data read, or an array
        object which the data will be read to, and the return value is the
        number of bytes read.
        """
        try:
            buff = util.create_buffer(data_or_wLength)
        except TypeError:
            buff = _interop.as_array(data_or_wLength)

        self._ctx.managed_open()

        # Thanks to Johannes Stezenbach to point me out that we need to
        # claim the recipient interface
        recipient = bmRequestType & 3
        rqtype = bmRequestType & (3 << 5)
        if recipient == util.CTRL_RECIPIENT_INTERFACE \
                and rqtype != util.CTRL_TYPE_VENDOR:
            interface_number = wIndex & 0xff
            self._ctx.managed_claim_interface(self, interface_number)

        ret = self._ctx.backend.ctrl_transfer(self._ctx.handle, bmRequestType,
                                              bRequest, wValue, wIndex, buff,
                                              self.__get_timeout(timeout))

        if isinstance(data_or_wLength, array.array) \
                or util.ctrl_direction(bmRequestType) == util.CTRL_OUT:
            return ret
        elif ret != len(buff) * buff.itemsize:
            return buff[:ret]
        else:
            return buff
Exemple #4
0
    def ctrl_transfer(self, bmRequestType, bRequest, wValue=0, wIndex=0,
            data_or_wLength = None, timeout = None):
        r"""Do a control transfer on the endpoint 0.

        This method is used to issue a control transfer over the endpoint 0
        (endpoint 0 is required to always be a control endpoint).

        The parameters bmRequestType, bRequest, wValue and wIndex are the same
        of the USB Standard Control Request format.

        Control requests may or may not have a data payload to write/read.
        In cases which it has, the direction bit of the bmRequestType
        field is used to infer the desired request direction. For
        host to device requests (OUT), data_or_wLength parameter is
        the data payload to send, and it must be a sequence type convertible
        to an array object. In this case, the return value is the number
        of bytes written in the data payload. For device to host requests
        (IN), data_or_wLength is either the wLength parameter of the control
        request specifying the number of bytes to read in data payload, and
        the return value is an array object with data read, or an array
        object which the data will be read to, and the return value is the
        number of bytes read.
        """
        try:
            buff = util.create_buffer(data_or_wLength)
        except TypeError:
            buff = _interop.as_array(data_or_wLength)

        self._ctx.managed_open()

        # Thanks to Johannes Stezenbach to point me out that we need to
        # claim the recipient interface
        recipient = bmRequestType & 3
        rqtype = bmRequestType & (3 << 5)
        if recipient == util.CTRL_RECIPIENT_INTERFACE \
                and rqtype != util.CTRL_TYPE_VENDOR:
            interface_number = wIndex & 0xff
            self._ctx.managed_claim_interface(self, interface_number)

        ret = self._ctx.backend.ctrl_transfer(
                                    self._ctx.handle,
                                    bmRequestType,
                                    bRequest,
                                    wValue,
                                    wIndex,
                                    buff,
                                    self.__get_timeout(timeout))

        if isinstance(data_or_wLength, array.array) \
                or util.ctrl_direction(bmRequestType) == util.CTRL_OUT:
            return ret
        elif ret != len(buff) * buff.itemsize:
            return buff[:ret]
        else:
            return buff
Exemple #5
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