Exemplo n.º 1
0
    def set_di_cos(self, lines):
        """
        Enable COS IRQ on specific Digital Input lines.
        COS (change of state) IRQ can be enabled on each Digital Input line.

        :params lines: The DI lines as bit mask.
        """

        if lines < 0 or lines > 0xff:
            raise RuntimeError("Lines is not a 8 bit bitmask")

        # enable interrupt on the CPLD
        bmreq = build_request_type(CTRL_IN, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        self.dev.ctrl_transfer(bmreq,
                               BREQUEST_CPLD,
                               wValue=0xd000,
                               wIndex=0,
                               data_or_wLength=[lines],
                               timeout=self.timeout)

        # maybe clear interrupt?
        bmreq = build_request_type(CTRL_OUT, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        self.dev.ctrl_transfer(bmreq,
                               BREQUEST_COS,
                               wValue=0x00,
                               wIndex=0x00,
                               data_or_wLength=[],
                               timeout=self.timeout)
Exemplo n.º 2
0
    def set_counter_min_pulse_width(self, counter, pulse):
        """
        :params counter: Define which counter should work.
        :params pulse: Define the pulse width in 1/48Mhz steps (16 bit).
        """

        value = struct.pack('<H', pulse)

        wValue = 0xd028

        # bit 3 define which counter
        if counter == 0:
            wValue |= 0x4
        elif counter == 1:
            wValue |= 0x0
        else:
            raise RuntimeError(
                "Argument counter is out of range. counter must be 0-1")

        bmreq = build_request_type(CTRL_OUT, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        self.dev.ctrl_transfer(bmreq,
                               BREQUEST_CPLD,
                               wValue,
                               wIndex=0,
                               data_or_wLength=value,
                               timeout=self.timeout)
Exemplo n.º 3
0
def set_descriptor(dev, desc, desc_type, desc_index, wIndex=None):
    r"""Update an existing descriptor or add a new one.

    dev is the Device object to which the request will be
    sent to.

    The desc parameter is the descriptor to be sent to the device.
    desc_type and desc_index are the descriptor type and index,
    respectively. wIndex index is used for string descriptors
    and represents the Language ID. For other types of descriptors,
    it is zero.
    """
    wValue = desc_index | (desc_type << 8)
    bmRequestType = util.build_request_type(
        util.CTRL_OUT,
        util.CTRL_TYPE_STANDARD,
        util.CTRL_RECIPIENT_DEVICE
    )
    dev.ctrl_transfer(
        bmRequestType=bmRequestType,
        bRequest=0x07,
        wValue=wValue,
        wIndex=wIndex,
        data_or_wLength=desc
    )
Exemplo n.º 4
0
def get_descriptor(dev, desc_size, desc_type, desc_index, request_type = util.CTRL_TYPE_STANDARD, wIndex = 0):
    r"""Return the specified descriptor.

    dev is the Device object to which the request will be
    sent to.

    desc_size is the descriptor size.

    desc_type and desc_index are the descriptor type and index,
    respectively. request_type is one of CTRL_TYPE_STANDARD,
    CTRL_TYPE_CLASS, CTRL_TYPE_VENDOR, or CTRL_TYPE_RESERVED. 
    wIndex index is used for string descriptors and represents
    the Language ID. For other types of descriptors, it is zero.
    """
    wValue = desc_index | (desc_type << 8)

    bmRequestType = util.build_request_type(
                        util.CTRL_IN,
                        request_type,
                        util.CTRL_RECIPIENT_DEVICE)

    return dev.ctrl_transfer(
            bmRequestType = bmRequestType,
            bRequest = 0x06,
            wValue = wValue,
            wIndex = wIndex,
            data_or_wLength = desc_size)
Exemplo n.º 5
0
def get_descriptor(dev, desc_size, desc_type, desc_index, wIndex=0):
    r"""Return the specified descriptor.

    dev is the Device object to which the request will be
    sent to.

    desc_size is the descriptor size.

    desc_type and desc_index are the descriptor type and index,
    respectively. wIndex index is used for string descriptors
    and represents the Language ID. For other types of descriptors,
    it is zero.
    """
    wValue = desc_index | (desc_type << 8)
    bmRequestType = util.build_request_type(
        util.CTRL_IN,
        util.CTRL_TYPE_STANDARD,
        util.CTRL_RECIPIENT_DEVICE
    )
    return dev.ctrl_transfer(
        bmRequestType=bmRequestType,
        bRequest=0x06,
        wValue=wValue,
        wIndex=wIndex,
        data_or_wLength=desc_size
    )
Exemplo n.º 6
0
def set_descriptor(dev, desc, desc_type, desc_index, request_type = util.CTRL_TYPE_STANDARD, wIndex = None):
    r"""Update an existing descriptor or add a new one.

    dev is the Device object to which the request will be
    sent to.

    The desc parameter is the descriptor to be sent to the device.
    desc_type and desc_index are the descriptor type and index,
    respectively. request_type is one of CTRL_TYPE_STANDARD,
    CTRL_TYPE_CLASS, CTRL_TYPE_VENDOR, or CTRL_TYPE_RESERVED.
    wIndex index is used for string descriptors and represents 
    the Language ID. For other types of descriptors, it is zero.
    """
    wValue = desc_index | (desc_type << 8)

    bmRequestType = util.build_request_type(
                        util.CTRL_OUT,
                        request_type,
                        util.CTRL_RECIPIENT_DEVICE)

    dev.ctrl_transfer(
        bmRequestType = bmRequestType,
        bRequest = 0x07,
        wValue = wValue,
        wIndex = wIndex,
        data_or_wLength = desc)
Exemplo n.º 7
0
 def update_displays(self):
     """
     Converts strings to radio panel bytes, and updates the displays.
     """
     display_state = ""
     for value in self.lcd_state.values():
         display_state += value
     text_bytes = convert_string_to_bytes(display_state)
     outType = util.build_request_type(
         util.CTRL_OUT, util.CTRL_TYPE_CLASS,
         util.CTRL_RECIPIENT_INTERFACE)  # 0x21
     self.device.ctrl_transfer(outType, 0x09, 0x03, 0x00, text_bytes)
Exemplo n.º 8
0
 def _send_query(self):
     command = bytearray(8)
     command[0] = 0x08
     command[-1] = 0x02
     bmRequestType = build_request_type(
         CTRL_OUT, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE)
     self.device.ctrl_transfer(
         bmRequestType=bmRequestType,
         bRequest=0x09,
         wValue=(2 << 8 | 0x08),
         wIndex=0,
         data_or_wLength=command,
     )
Exemplo n.º 9
0
 def _send_query(self):
     command = bytearray(8)
     command[0] = 0x08
     command[-1] = 0x02
     bmRequestType = build_request_type(
         CTRL_OUT, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE)
     self.device.ctrl_transfer(
         bmRequestType=bmRequestType,
         bRequest=0x09,
         wValue=(2 << 8 | 0x08),
         wIndex=0,
         data_or_wLength=command,
     )
Exemplo n.º 10
0
def get_interface(dev, bInterfaceNumber):
    r"""Get the current alternate setting of the interface.

    dev is the Device object to which the request will be
    sent to.
    """
    bmRequestType = util.build_request_type(util.CTRL_IN,
                                            util.CTRL_TYPE_STANDARD,
                                            util.CTRL_RECIPIENT_INTERFACE)
    return dev.ctrl_transfer(bmRequestType=bmRequestType,
                             bRequest=0x0a,
                             wIndex=bInterfaceNumber,
                             data_or_wLength=1)[0]
Exemplo n.º 11
0
    def get_counter(self, counter, ctype=COUNTER_TYPE_COUNTER):
        """
        Return the counter frequency of a counter.

        :param ctype: The type of the counter. COUNTER_TYPE_FREQUENCY or COUNTER_TYPE_COUNTER
        :param counter: The counter to retrieve. 0 or 1.
        :returns: Depending on ctype a count or 20ns clock period.
        """

        wValue = 0xd000

        if ctype == COUNTER_TYPE_FREQUENCY:
            wValue |= 0x18
        elif ctype == COUNTER_TYPE_COUNTER:
            wValue |= 0x20
        else:
            raise RuntimeError("Unknown counter type!")

        # bit 3 define which counter
        if counter == 0:
            wValue |= 0x4
        elif counter == 1:
            wValue |= 0x0
        else:
            raise RuntimeError(
                "Argument counter is out of range. counter must be 0-1")

        bmreq = build_request_type(CTRL_IN, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        transfer = self.dev.ctrl_transfer(bmreq,
                                          BREQUEST_CPLD,
                                          wValue,
                                          wIndex=0,
                                          data_or_wLength=4,
                                          timeout=self.timeout)

        # counter:
        # 5263
        # [ 0x8f, 0x14, 0x00, 0x00 ]

        # freq:
        # 9.647365 Hz.
        # [ 0x5c, 0xeb, 0x4b, 0x00 ]

        # freq:
        # 968.054199 Hz.
        # [ 0xb0, 0xc1, 0x00, 0x00 ]

        return struct.unpack('<I', transfer[0:4])[0]
Exemplo n.º 12
0
def get_configuration(dev):
    r"""Get the current active configuration of the device.

    dev is the Device object to which the request will be
    sent to.

    This function differs from the Device.get_active_configuration
    method because the later may use cached data, while this
    function always does a device request.
    """
    bmRequestType = util.build_request_type(util.CTRL_IN,
                                            util.CTRL_TYPE_STANDARD,
                                            util.CTRL_RECIPIENT_DEVICE)
    return dev.ctrl_transfer(bmRequestType, bRequest=0x08,
                             data_or_wLength=1)[0]
Exemplo n.º 13
0
    def get_dos(self):
        """
        Retrieve the Digital Output state from the device.

        :returns: A bit mask. Each bit represents a single line.
        """
        bmreq = build_request_type(CTRL_IN, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        transfer = self.dev.ctrl_transfer(bmreq,
                                          BREQUEST_DO,
                                          wValue=0x4,
                                          wIndex=0,
                                          data_or_wLength=1,
                                          timeout=self.timeout)
        return transfer[0]
Exemplo n.º 14
0
def _parse_recipient(recipient, direction):
    if recipient is None:
        r = util.CTRL_RECIPIENT_DEVICE
        wIndex = 0
    elif isinstance(recipient, core.Interface):
        r = util.CTRL_RECIPIENT_INTERFACE
        wIndex = recipient.bInterfaceNumber
    elif isinstance(recipient, core.Endpoint):
        r = util.CTRL_RECIPIENT_ENDPOINT
        wIndex = recipient.bEndpointAddress
    else:
        raise ValueError('Invalid recipient.')
    bmRequestType = util.build_request_type(direction, util.CTRL_TYPE_STANDARD,
                                            r)
    return (bmRequestType, wIndex)
Exemplo n.º 15
0
    def set_counter(self,
                    counter,
                    counter_filter=False,
                    polarity=False,
                    reset_frequency_counter=False,
                    reset_edge_counter=False):
        """
        Change counter properties or reset the counter or frequenct value.

        :params counter_filter: Enable digital input filter.
        :params polarity: Set polarity to high (True) or low (False)
        :params reset_frequency_counter: Reset the frequency counter.
        :params reset_edge_counter: Reset the edge counter.
        """

        wValue = 0xd010

        # bit 3 define which counter
        if counter == 0:
            wValue |= 0x4
        elif counter == 1:
            wValue |= 0x0
        else:
            raise RuntimeError(
                "Argument counter is out of range. counter must be 0-1")

        value = 0

        if counter_filter:
            value |= 0x1

        if reset_edge_counter:
            value |= 0x2

        if reset_frequency_counter:
            value |= 0x4

        if polarity:
            value |= 0x8

        bmreq = build_request_type(CTRL_OUT, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        self.dev.ctrl_transfer(bmreq,
                               BREQUEST_CPLD,
                               wValue,
                               wIndex=0x00,
                               data_or_wLength=[value, 0x00, 0x00, 0x00],
                               timeout=self.timeout)
Exemplo n.º 16
0
    def get_device_id(self):
        """
        Read the device id, which can be set via a rotary switch.

        :returns: device id (0-7)
        """

        bmreq = build_request_type(CTRL_IN, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        transfer = self.dev.ctrl_transfer(bmreq,
                                          BREQUEST_DEVICE_ID,
                                          0x4,
                                          wIndex=0,
                                          data_or_wLength=1,
                                          timeout=self.timeout)
        return transfer[0]
Exemplo n.º 17
0
def get_interface(dev, bInterfaceNumber):
    r"""Get the current alternate setting of the interface.

    dev is the Device object to which the request will be
    sent to.
    """
    bmRequestType = util.build_request_type(
                            util.CTRL_IN,
                            util.CTRL_TYPE_STANDARD,
                            util.CTRL_RECIPIENT_INTERFACE)

    return dev.ctrl_transfer(
                bmRequestType = bmRequestType,
                bRequest = 0x0a,
                wIndex = bInterfaceNumber,
                data_or_wLength = 1)[0]
Exemplo n.º 18
0
    def get_dos_initial(self):
        """
        Get the initial Digital Output state after power up.

        :returns: A bit msak. Each bit represents a single line.
        """
        bmreq = build_request_type(CTRL_IN, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        transfer = self.dev.ctrl_transfer(bmreq,
                                          BREQUEST_INITIAL,
                                          wValue=0xd028,
                                          wIndex=0,
                                          data_or_wLength=2,
                                          timeout=self.timeout)

        return struct.unpack('<H', transfer[0:2])[0]
Exemplo n.º 19
0
    def get_dis(self):
        """
        Read the state of all Digital Inputs

        :returns: A bit mask. Each bit represents a single line.
        """

        bmreq = build_request_type(CTRL_IN, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        transfer = self.dev.ctrl_transfer(bmreq,
                                          BREQUEST_CPLD,
                                          wValue=0xd00a,
                                          wIndex=0,
                                          data_or_wLength=1,
                                          timeout=self.timeout)
        return transfer[0]
Exemplo n.º 20
0
    def cb_test_get_cfg_desc(self, key, value, timestamp):
        """Verify the device provides required HID descriptors.

        USB Device Class Definition for HID, v1.11, paragraph 7.1:
        When a Get_Descriptor(Configuration) request is issued, it
        returns (...), and the HID descriptor for each interface.
        """
        kwargs_cfg_desc_req = {
            'bmRequestType':
            build_request_type(CTRL_IN, CTRL_TYPE_STANDARD,
                               CTRL_RECIPIENT_DEVICE),
            'bRequest':
            USB_REQUEST_GET_DESCRIPTOR,
            # Descriptor Index (part of wValue) is reset to zero.
            'wValue':
            build_get_desc_value(DESC_TYPE_CONFIG, 0x00),
            # wIndex is reset to zero.
            'wIndex':
            0x00,
            # wLength unknown, set to 1024.
            'data_or_wLength':
            1024
        }
        mbed_hid_dev = None
        try:
            mbed_hid_dev = retry_fun_call(
                fun=functools.partial(self.get_usb_dev, self.dut_usb_dev_sn),  # pylint: disable=not-callable
                num_retries=20,
                retry_delay=0.05)
        except RetryError as exc:
            self.notify_error(exc)
            return
        try:
            # Request the Configuration descriptor.
            cfg_desc = mbed_hid_dev.ctrl_transfer(**kwargs_cfg_desc_req)  # pylint: disable=not-callable
            raise_if_false(
                DESC_TYPE_HID_HID in get_descriptor_types(cfg_desc),
                'No HID class descriptor in the Configuration descriptor.')
        except usb.core.USBError as exc:
            self.notify_failure(
                'Get_Descriptor request failed. {}'.format(exc))
        except RuntimeError as exc:
            self.notify_failure(exc)
        else:
            self.notify_success()
Exemplo n.º 21
0
    def set_dos_initial(self, lines):
        """
        Set the initial Digital Output state after power up.

        :params lines: A bit msak. Each bit represents a single line.
        """

        if lines < 0 or lines > 0xff:
            raise RuntimeError("Invalid Value for lines. lines must be 8 bit")

        bmreq = build_request_type(CTRL_OUT, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        self.dev.ctrl_transfer(bmreq,
                               BREQUEST_INITIAL,
                               wValue=0xd028,
                               wIndex=lines,
                               data_or_wLength=[],
                               timeout=self.timeout)
Exemplo n.º 22
0
def setReport(reportId, data):
    #PYUSB_DEBUG=debug
    #LIBUSB_DEBUG=3
    #print "test"
    #print util.build_request_type(util.CTRL_OUT, util.CTRL_TYPE_CLASS, util.CTRL_RECIPIENT_INTERFACE)
    r = dev.ctrl_transfer(
        util.build_request_type(
            util.CTRL_OUT, util.CTRL_TYPE_CLASS,
            util.CTRL_RECIPIENT_INTERFACE),  # bmRequestType,
        REQ_HID_SET_REPORT,
        0x0300,  #HID_REPORT_TYPE_OUTPUT | reportId,
        0,  # feature_interface_num
        data,  # data
        timeout=6000  # timeout (1000 was too small for C_FREE)
    )
    #ctrl_transfer(0x21, 0x09, 0x209, 0, data, timeout)
    #dev.ctrl_transfer(0x21, 0x09, 0x0300, 0, data, timeout)
    return r
Exemplo n.º 23
0
def _parse_recipient(recipient, direction):
    if recipient is None:
        r = util.CTRL_RECIPIENT_DEVICE
        wIndex = 0
    elif isinstance(recipient, core.Interface):
        r = util.CTRL_RECIPIENT_INTERFACE
        wIndex = recipient.bInterfaceNumber
    elif isinstance(recipient, core.Endpoint):
        r = util.CTRL_RECIPIENT_ENDPOINT
        wIndex = recipient.bEndpointAddress
    else:
        raise ValueError('Invalid recipient.')
    bmRequestType = util.build_request_type(
        direction,
        util.CTRL_TYPE_STANDARD,
        r
    )
    return (bmRequestType, wIndex)
Exemplo n.º 24
0
    def set_dos(self, lines):
        """
        Set the Digital Outputs.

        :param lines: A bit mask describing the new state.
        """

        if lines < 0 or lines > 0xff:
            raise RuntimeError("Invalid Value for lines. lines must be 8 bit")

        # there is only one port with 8 lines
        bmreq = build_request_type(CTRL_OUT, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        self.dev.ctrl_transfer(bmreq,
                               BREQUEST_DO,
                               wValue=0xff03,
                               wIndex=lines,
                               data_or_wLength=[],
                               timeout=self.timeout)
Exemplo n.º 25
0
def set_button_control(dev):

    # Transfer control to the button HID interface
    bm_request_type = util.build_request_type(
        util.CTRL_OUT,
        util.CTRL_TYPE_CLASS,
        util.CTRL_RECIPIENT_INTERFACE
    )

    state = array('B', [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02])
    ret = dev.ctrl_transfer(bm_request_type, 0x09, 0x00, 0x00, state)
    if ret < 0:
        print "Error reading control response"
        return -1
    if ret == 0:
        print "Device didn't sent enough data"
        return -1

    return 0
Exemplo n.º 26
0
def get_configuration(dev):
    r"""Get the current active configuration of the device.

    dev is the Device object to which the request will be
    sent to.

    This function differs from the Device.get_active_configuration
    method because the later may use cached data, while this
    function always does a device request.
    """
    bmRequestType = util.build_request_type(
                            util.CTRL_IN,
                            util.CTRL_TYPE_STANDARD,
                            util.CTRL_RECIPIENT_DEVICE)

    return dev.ctrl_transfer(
                bmRequestType,
                bRequest = 0x08,
                data_or_wLength = 1)[0]
Exemplo n.º 27
0
    def set_di_min_pulse_width(self, pulse):
        """
        Set the minimum pulse width for the digital filter.
        The CPLD can filter digital inputs to ensure a level change last at least some time.
        The pulse width length can be only set for all inputs, but it can be enabled or disabled
        for each line indivitual.

        :params pulse: Define the pulse width in 1/48Mhz steps (16 bit).
        """

        value = struct.pack('<H', pulse)

        bmreq = build_request_type(CTRL_OUT, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        self.dev.ctrl_transfer(bmreq,
                               BREQUEST_CPLD,
                               wValue=0xd00c,
                               wIndex=0,
                               data_or_wLength=value,
                               timeout=self.timeout)
Exemplo n.º 28
0
    def set_di_digital_filter(self, lines):
        """
        Enable minimum pulse width filter on specific Digital Inputs.

        See set_di_min_pulse_width for further information on the digital filter.

        :params lines: The DI lines as bit mask.
        """

        if lines < 0 or lines > 0xff:
            raise RuntimeError("Invalid Value for lines. lines must be 8 bit")

        bmreq = build_request_type(CTRL_OUT, CTRL_TYPE_VENDOR,
                                   CTRL_RECIPIENT_DEVICE)
        self.dev.ctrl_transfer(bmreq,
                               BREQUEST_CPLD,
                               wValue=0xd00c,
                               wIndex=0,
                               data_or_wLength=[lines],
                               timeout=self.timeout)
Exemplo n.º 29
0
    def cb_test_get_cfg_desc(self, key, value, timestamp):
        """Verify the device provides required HID descriptors.

        USB Device Class Definition for HID, v1.11, paragraph 7.1:
        When a Get_Descriptor(Configuration) request is issued, it
        returns (...), and the HID descriptor for each interface.
        """
        kwargs_cfg_desc_req = {
            'bmRequestType': build_request_type(
                CTRL_IN, CTRL_TYPE_STANDARD, CTRL_RECIPIENT_DEVICE),
            'bRequest': USB_REQUEST_GET_DESCRIPTOR,
            # Descriptor Index (part of wValue) is reset to zero.
            'wValue': build_get_desc_value(DESC_TYPE_CONFIG, 0x00),
            # wIndex is reset to zero.
            'wIndex': 0x00,
            # wLength unknown, set to 1024.
            'data_or_wLength': 1024}
        mbed_hid_dev = None
        try:
            mbed_hid_dev = retry_fun_call(
                fun=functools.partial(self.get_usb_dev, self.dut_usb_dev_sn),  # pylint: disable=not-callable
                num_retries=20,
                retry_delay=0.05)
        except RetryError as exc:
            self.notify_error(exc)
            return
        try:
            # Request the Configuration descriptor.
            cfg_desc = mbed_hid_dev.ctrl_transfer(**kwargs_cfg_desc_req)  # pylint: disable=not-callable
            raise_if_false(DESC_TYPE_HID_HID in get_descriptor_types(cfg_desc),
                           'No HID class descriptor in the Configuration descriptor.')
        except usb.core.USBError as exc:
            self.notify_failure('Get_Descriptor request failed. {}'.format(exc))
        except RuntimeError as exc:
            self.notify_failure(exc)
        else:
            self.notify_success()
Exemplo n.º 30
0
    def cb_test_class_requests(self, key, value, timestamp):
        """Verify all required HID requests are supported.

        USB Device Class Definition for HID, v1.11, Appendix G:
        1. Get_Report -- required for all types,
        2. Set_Report -- not required if dev doesn't declare an Output Report,
        3. Get_Idle -- required for keyboards,
        4. Set_Idle -- required for keyboards,
        5. Get_Protocol -- required for boot_keyboard and boot_mouse,
        6. Set_Protocol -- required for boot_keyboard and boot_mouse.

        Details in USB Device Class Definition for HID, v1.11, paragraph 7.2.
        """
        kwargs_get_report_request = {
            'bmRequestType':
            build_request_type(CTRL_IN, CTRL_TYPE_CLASS,
                               CTRL_RECIPIENT_INTERFACE),
            'bRequest':
            HID_REQUEST_GET_REPORT,
            # wValue: ReportType = Input, ReportID = 0 (not used)
            'wValue': (0x01 << 8) | 0x00,
            # wIndex: InterfaceNumber (defined later)
            'wIndex':
            None,
            # wLength: unknown, set to 1024
            'data_or_wLength':
            1024
        }
        kwargs_get_idle_request = {
            'bmRequestType':
            build_request_type(CTRL_IN, CTRL_TYPE_CLASS,
                               CTRL_RECIPIENT_INTERFACE),
            'bRequest':
            HID_REQUEST_GET_IDLE,
            # wValue: 0, ReportID = 0 (not used)
            'wValue': (0x00 << 8) | 0x00,
            # wIndex: InterfaceNumber (defined later)
            'wIndex':
            None,
            'data_or_wLength':
            1
        }
        kwargs_set_idle_request = {
            'bmRequestType':
            build_request_type(CTRL_OUT, CTRL_TYPE_CLASS,
                               CTRL_RECIPIENT_INTERFACE),
            'bRequest':
            HID_REQUEST_SET_IDLE,
            # wValue: Duration, ReportID = 0 (all input reports)
            'wValue': (KEYBOARD_IDLE_RATE_TO_SET << 8) | 0x00,
            # wIndex: InterfaceNumber (defined later)
            'wIndex':
            None,
            'data_or_wLength':
            0
        }
        kwargs_get_protocol_request = {
            'bmRequestType':
            build_request_type(CTRL_IN, CTRL_TYPE_CLASS,
                               CTRL_RECIPIENT_INTERFACE),
            'bRequest':
            HID_REQUEST_GET_PROTOCOL,
            'wValue':
            0x00,
            # wIndex: InterfaceNumber (defined later)
            'wIndex':
            None,
            'data_or_wLength':
            1
        }
        kwargs_set_protocol_request = {
            'bmRequestType':
            build_request_type(CTRL_OUT, CTRL_TYPE_CLASS,
                               CTRL_RECIPIENT_INTERFACE),
            'bRequest':
            HID_REQUEST_SET_PROTOCOL,
            'wValue':
            HID_PROTOCOL_TO_SET,
            # wIndex: InterfaceNumber (defined later)
            'wIndex':
            None,
            'data_or_wLength':
            0
        }
        mbed_hid_dev = None
        try:
            mbed_hid_dev = retry_fun_call(
                fun=functools.partial(self.get_usb_dev, self.dut_usb_dev_sn),  # pylint: disable=not-callable
                num_retries=20,
                retry_delay=0.05)
        except RetryError as exc:
            self.notify_error(exc)
            return
        hid_dev_type = None
        tested_request_name = None
        try:
            for intf in mbed_hid_dev.get_active_configuration():  # pylint: disable=not-callable
                hid_dev_type = get_usbhid_dev_type(intf)
                if hid_dev_type is None:
                    continue
                try:
                    if mbed_hid_dev.is_kernel_driver_active(
                            intf.bInterfaceNumber):
                        mbed_hid_dev.detach_kernel_driver(
                            intf.bInterfaceNumber)  # pylint: disable=not-callable
                except (NotImplementedError, AttributeError):
                    pass
                if hid_dev_type == 'boot_keyboard':
                    # 4. Set_Idle
                    tested_request_name = 'Set_Idle'
                    kwargs_set_idle_request['wIndex'] = intf.bInterfaceNumber
                    mbed_hid_dev.ctrl_transfer(**kwargs_set_idle_request)  # pylint: disable=not-callable
                    # 3. Get_Idle
                    tested_request_name = 'Get_Idle'
                    kwargs_get_idle_request['wIndex'] = intf.bInterfaceNumber
                    idle_rate = mbed_hid_dev.ctrl_transfer(
                        **kwargs_get_idle_request)  # pylint: disable=not-callable
                    raise_if_different(KEYBOARD_IDLE_RATE_TO_SET, idle_rate,
                                       'Invalid idle rate received. ')
                if hid_dev_type in ('boot_keyboard', 'boot_mouse'):
                    # 6. Set_Protocol
                    tested_request_name = 'Set_Protocol'
                    kwargs_set_protocol_request[
                        'wIndex'] = intf.bInterfaceNumber
                    mbed_hid_dev.ctrl_transfer(**kwargs_set_protocol_request)  # pylint: disable=not-callable
                    # 5. Get_Protocol
                    tested_request_name = 'Get_Protocol'
                    kwargs_get_protocol_request[
                        'wIndex'] = intf.bInterfaceNumber
                    protocol = mbed_hid_dev.ctrl_transfer(
                        **kwargs_get_protocol_request)  # pylint: disable=not-callable
                    raise_if_different(HID_PROTOCOL_TO_SET, protocol,
                                       'Invalid protocol received. ')
                # 1. Get_Report
                tested_request_name = 'Get_Report'
                kwargs_get_report_request['wIndex'] = intf.bInterfaceNumber
                mbed_hid_dev.ctrl_transfer(**kwargs_get_report_request)  # pylint: disable=not-callable
        except usb.core.USBError as exc:
            self.notify_failure(
                'The {!r} does not support the {!r} HID class request ({}).'.
                format(hid_dev_type, tested_request_name, exc))
        except RuntimeError as exc:
            self.notify_failure(
                'Set/Get data mismatch for {!r} for the {!r} HID class request ({}).'
                .format(hid_dev_type, tested_request_name, exc))
        else:
            self.notify_success()
Exemplo n.º 31
0
    def cb_test_get_hid_desc(self, key, value, timestamp):
        """Verify the device handles Get_Descriptor request correctly.

        Two requests are tested for every HID interface:
        1. Get_Descriptor(HID),
        2. Get_Descriptor(Report).
        Details in USB Device Class Definition for HID, v1.11, paragraph 7.1.
        """
        kwargs_hid_desc_req = {
            'bmRequestType':
            build_request_type(CTRL_IN, CTRL_TYPE_STANDARD,
                               CTRL_RECIPIENT_INTERFACE),
            'bRequest':
            USB_REQUEST_GET_DESCRIPTOR,
            # Descriptor Index (part of wValue) is reset to zero for
            # HID class descriptors other than Physical ones.
            'wValue':
            build_get_desc_value(DESC_TYPE_HID_HID, 0x00),
            # wIndex is replaced with the Interface Number in the loop.
            'wIndex':
            None,
            'data_or_wLength':
            DESC_LEN_HID_HID
        }
        kwargs_report_desc_req = {
            'bmRequestType':
            build_request_type(CTRL_IN, CTRL_TYPE_STANDARD,
                               CTRL_RECIPIENT_INTERFACE),
            'bRequest':
            USB_REQUEST_GET_DESCRIPTOR,
            # Descriptor Index (part of wValue) is reset to zero for
            # HID class descriptors other than Physical ones.
            'wValue':
            build_get_desc_value(DESC_TYPE_HID_REPORT, 0x00),
            # wIndex is replaced with the Interface Number in the loop.
            'wIndex':
            None,
            # wLength is replaced with the Report Descriptor Length in the loop.
            'data_or_wLength':
            None
        }
        mbed_hid_dev = None
        report_desc_lengths = []
        try:
            mbed_hid_dev = retry_fun_call(
                fun=functools.partial(self.get_usb_dev, self.dut_usb_dev_sn),  # pylint: disable=not-callable
                num_retries=20,
                retry_delay=0.05)
        except RetryError as exc:
            self.notify_error(exc)
            return
        try:
            for intf in mbed_hid_dev.get_active_configuration():  # pylint: disable=not-callable
                if intf.bInterfaceClass != USB_CLASS_HID:
                    continue
                try:
                    if mbed_hid_dev.is_kernel_driver_active(
                            intf.bInterfaceNumber):
                        mbed_hid_dev.detach_kernel_driver(
                            intf.bInterfaceNumber)  # pylint: disable=not-callable
                except (NotImplementedError, AttributeError):
                    pass

                # Request the HID descriptor.
                kwargs_hid_desc_req['wIndex'] = intf.bInterfaceNumber
                hid_desc = mbed_hid_dev.ctrl_transfer(**kwargs_hid_desc_req)  # pylint: disable=not-callable
                try:
                    bNumDescriptors, bDescriptorType, wDescriptorLength = get_hid_descriptor_parts(
                        hid_desc)  # pylint: disable=invalid-name
                except TypeError as exc:
                    self.notify_error(exc)
                    return
                raise_if_different(
                    1, bNumDescriptors,
                    'Exactly one HID Report descriptor expected. ')
                raise_if_different(DESC_TYPE_HID_REPORT, bDescriptorType,
                                   'Invalid HID class descriptor type. ')
                raise_if_false(wDescriptorLength > 0,
                               'Invalid HID Report descriptor length. ')

                # Request the Report descriptor.
                kwargs_report_desc_req['wIndex'] = intf.bInterfaceNumber
                kwargs_report_desc_req['data_or_wLength'] = wDescriptorLength
                report_desc = mbed_hid_dev.ctrl_transfer(
                    **kwargs_report_desc_req)  # pylint: disable=not-callable
                raise_if_different(
                    wDescriptorLength, len(report_desc),
                    'The size of data received does not match the HID Report descriptor length. '
                )
                report_desc_lengths.append(len(report_desc))
        except usb.core.USBError as exc:
            self.notify_failure(
                'Get_Descriptor request failed. {}'.format(exc))
        except RuntimeError as exc:
            self.notify_failure(exc)
        else:
            # Send the report desc len to the device.
            # USBHID::report_desc_length() returns uint16_t
            msg_value = '{0:04x}'.format(max(report_desc_lengths))
            self.notify_success(msg_value)
Exemplo n.º 32
0
    def cb_test_get_hid_desc(self, key, value, timestamp):
        """Verify the device handles Get_Descriptor request correctly.

        Two requests are tested for every HID interface:
        1. Get_Descriptor(HID),
        2. Get_Descriptor(Report).
        Details in USB Device Class Definition for HID, v1.11, paragraph 7.1.
        """
        kwargs_hid_desc_req = {
            'bmRequestType': build_request_type(
                CTRL_IN, CTRL_TYPE_STANDARD, CTRL_RECIPIENT_INTERFACE),
            'bRequest': USB_REQUEST_GET_DESCRIPTOR,
            # Descriptor Index (part of wValue) is reset to zero for
            # HID class descriptors other than Physical ones.
            'wValue': build_get_desc_value(DESC_TYPE_HID_HID, 0x00),
            # wIndex is replaced with the Interface Number in the loop.
            'wIndex': None,
            'data_or_wLength': DESC_LEN_HID_HID}
        kwargs_report_desc_req = {
            'bmRequestType': build_request_type(
                CTRL_IN, CTRL_TYPE_STANDARD, CTRL_RECIPIENT_INTERFACE),
            'bRequest': USB_REQUEST_GET_DESCRIPTOR,
            # Descriptor Index (part of wValue) is reset to zero for
            # HID class descriptors other than Physical ones.
            'wValue': build_get_desc_value(DESC_TYPE_HID_REPORT, 0x00),
            # wIndex is replaced with the Interface Number in the loop.
            'wIndex': None,
            # wLength is replaced with the Report Descriptor Length in the loop.
            'data_or_wLength': None}
        mbed_hid_dev = None
        report_desc_lengths = []
        try:
            mbed_hid_dev = retry_fun_call(
                fun=functools.partial(self.get_usb_dev, self.dut_usb_dev_sn),  # pylint: disable=not-callable
                num_retries=20,
                retry_delay=0.05)
        except RetryError as exc:
            self.notify_error(exc)
            return
        try:
            for intf in mbed_hid_dev.get_active_configuration():  # pylint: disable=not-callable
                if intf.bInterfaceClass != USB_CLASS_HID:
                    continue
                try:
                    if mbed_hid_dev.is_kernel_driver_active(intf.bInterfaceNumber):
                        mbed_hid_dev.detach_kernel_driver(intf.bInterfaceNumber)  # pylint: disable=not-callable
                except (NotImplementedError, AttributeError):
                    pass

                # Request the HID descriptor.
                kwargs_hid_desc_req['wIndex'] = intf.bInterfaceNumber
                hid_desc = mbed_hid_dev.ctrl_transfer(**kwargs_hid_desc_req)  # pylint: disable=not-callable
                try:
                    bNumDescriptors, bDescriptorType, wDescriptorLength = get_hid_descriptor_parts(hid_desc)  # pylint: disable=invalid-name
                except TypeError as exc:
                    self.notify_error(exc)
                    return
                raise_if_different(1, bNumDescriptors, 'Exactly one HID Report descriptor expected. ')
                raise_if_different(DESC_TYPE_HID_REPORT, bDescriptorType, 'Invalid HID class descriptor type. ')
                raise_if_false(wDescriptorLength > 0, 'Invalid HID Report descriptor length. ')

                # Request the Report descriptor.
                kwargs_report_desc_req['wIndex'] = intf.bInterfaceNumber
                kwargs_report_desc_req['data_or_wLength'] = wDescriptorLength
                report_desc = mbed_hid_dev.ctrl_transfer(**kwargs_report_desc_req)  # pylint: disable=not-callable
                raise_if_different(wDescriptorLength, len(report_desc),
                                   'The size of data received does not match the HID Report descriptor length. ')
                report_desc_lengths.append(len(report_desc))
        except usb.core.USBError as exc:
            self.notify_failure('Get_Descriptor request failed. {}'.format(exc))
        except RuntimeError as exc:
            self.notify_failure(exc)
        else:
            # Send the report desc len to the device.
            # USBHID::report_desc_length() returns uint16_t
            msg_value = '{0:04x}'.format(max(report_desc_lengths))
            self.notify_success(msg_value)
Exemplo n.º 33
0
    def cb_test_class_requests(self, key, value, timestamp):
        """Verify all required HID requests are supported.

        USB Device Class Definition for HID, v1.11, Appendix G:
        1. Get_Report -- required for all types,
        2. Set_Report -- not required if dev doesn't declare an Output Report,
        3. Get_Idle -- required for keyboards,
        4. Set_Idle -- required for keyboards,
        5. Get_Protocol -- required for boot_keyboard and boot_mouse,
        6. Set_Protocol -- required for boot_keyboard and boot_mouse.

        Details in USB Device Class Definition for HID, v1.11, paragraph 7.2.
        """
        kwargs_get_report_request = {
            'bmRequestType': build_request_type(
                CTRL_IN, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE),
            'bRequest': HID_REQUEST_GET_REPORT,
            # wValue: ReportType = Input, ReportID = 0 (not used)
            'wValue': (0x01 << 8) | 0x00,
            # wIndex: InterfaceNumber (defined later)
            'wIndex': None,
            # wLength: unknown, set to 1024
            'data_or_wLength': 1024}
        kwargs_get_idle_request = {
            'bmRequestType': build_request_type(
                CTRL_IN, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE),
            'bRequest': HID_REQUEST_GET_IDLE,
            # wValue: 0, ReportID = 0 (not used)
            'wValue': (0x00 << 8) | 0x00,
            # wIndex: InterfaceNumber (defined later)
            'wIndex': None,
            'data_or_wLength': 1}
        kwargs_set_idle_request = {
            'bmRequestType': build_request_type(
                CTRL_OUT, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE),
            'bRequest': HID_REQUEST_SET_IDLE,
            # wValue: Duration, ReportID = 0 (all input reports)
            'wValue': (KEYBOARD_IDLE_RATE_TO_SET << 8) | 0x00,
            # wIndex: InterfaceNumber (defined later)
            'wIndex': None,
            'data_or_wLength': 0}
        kwargs_get_protocol_request = {
            'bmRequestType': build_request_type(
                CTRL_IN, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE),
            'bRequest': HID_REQUEST_GET_PROTOCOL,
            'wValue': 0x00,
            # wIndex: InterfaceNumber (defined later)
            'wIndex': None,
            'data_or_wLength': 1}
        kwargs_set_protocol_request = {
            'bmRequestType': build_request_type(
                CTRL_OUT, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE),
            'bRequest': HID_REQUEST_SET_PROTOCOL,
            'wValue': HID_PROTOCOL_TO_SET,
            # wIndex: InterfaceNumber (defined later)
            'wIndex': None,
            'data_or_wLength': 0}
        mbed_hid_dev = None
        try:
            mbed_hid_dev = retry_fun_call(
                fun=functools.partial(self.get_usb_dev, self.dut_usb_dev_sn),  # pylint: disable=not-callable
                num_retries=20,
                retry_delay=0.05)
        except RetryError as exc:
            self.notify_error(exc)
            return
        hid_dev_type = None
        tested_request_name = None
        try:
            for intf in mbed_hid_dev.get_active_configuration():  # pylint: disable=not-callable
                hid_dev_type = get_usbhid_dev_type(intf)
                if hid_dev_type is None:
                    continue
                try:
                    if mbed_hid_dev.is_kernel_driver_active(intf.bInterfaceNumber):
                        mbed_hid_dev.detach_kernel_driver(intf.bInterfaceNumber)  # pylint: disable=not-callable
                except (NotImplementedError, AttributeError):
                    pass
                if hid_dev_type == 'boot_keyboard':
                    # 4. Set_Idle
                    tested_request_name = 'Set_Idle'
                    kwargs_set_idle_request['wIndex'] = intf.bInterfaceNumber
                    mbed_hid_dev.ctrl_transfer(**kwargs_set_idle_request)  # pylint: disable=not-callable
                    # 3. Get_Idle
                    tested_request_name = 'Get_Idle'
                    kwargs_get_idle_request['wIndex'] = intf.bInterfaceNumber
                    idle_rate = mbed_hid_dev.ctrl_transfer(**kwargs_get_idle_request)  # pylint: disable=not-callable
                    raise_if_different(KEYBOARD_IDLE_RATE_TO_SET, idle_rate, 'Invalid idle rate received. ')
                if hid_dev_type in ('boot_keyboard', 'boot_mouse'):
                    # 6. Set_Protocol
                    tested_request_name = 'Set_Protocol'
                    kwargs_set_protocol_request['wIndex'] = intf.bInterfaceNumber
                    mbed_hid_dev.ctrl_transfer(**kwargs_set_protocol_request)  # pylint: disable=not-callable
                    # 5. Get_Protocol
                    tested_request_name = 'Get_Protocol'
                    kwargs_get_protocol_request['wIndex'] = intf.bInterfaceNumber
                    protocol = mbed_hid_dev.ctrl_transfer(**kwargs_get_protocol_request)  # pylint: disable=not-callable
                    raise_if_different(HID_PROTOCOL_TO_SET, protocol, 'Invalid protocol received. ')
                # 1. Get_Report
                tested_request_name = 'Get_Report'
                kwargs_get_report_request['wIndex'] = intf.bInterfaceNumber
                mbed_hid_dev.ctrl_transfer(**kwargs_get_report_request)  # pylint: disable=not-callable
        except usb.core.USBError as exc:
            self.notify_failure('The {!r} does not support the {!r} HID class request ({}).'
                                .format(hid_dev_type, tested_request_name, exc))
        except RuntimeError as exc:
            self.notify_failure('Set/Get data mismatch for {!r} for the {!r} HID class request ({}).'
                                .format(hid_dev_type, tested_request_name, exc))
        else:
            self.notify_success()