コード例 #1
0
    def test_unique_endpoints(self):
        endpoint_desc1 = usb_descriptors.EndpointDescriptor(
            bEndpointAddress=0x01,
            bmAttributes=0x02,
            wMaxPacketSize=64,
            bInterval=1)
        endpoint_desc2 = usb_descriptors.EndpointDescriptor(
            bEndpointAddress=0x81,
            bmAttributes=0x02,
            wMaxPacketSize=64,
            bInterval=1)
        endpoint_desc3 = usb_descriptors.EndpointDescriptor(
            bEndpointAddress=0x01,
            bmAttributes=0x01,
            wMaxPacketSize=32,
            bInterval=10)

        interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=1)
        interface_desc.AddEndpoint(endpoint_desc1)
        interface_desc.AddEndpoint(endpoint_desc2)
        with self.assertRaisesRegexp(RuntimeError,
                                     'Endpoint 0x01 already defined'):
            interface_desc.AddEndpoint(endpoint_desc3)
コード例 #2
0
    def test_configuration_descriptor(self):
        endpoint_desc = usb_descriptors.EndpointDescriptor(
            bEndpointAddress=0x01,
            bmAttributes=0x02,
            wMaxPacketSize=64,
            bInterval=1)
        encoded_endpoint = '\x07\x05\x01\x02\x40\x00\x01'
        self.assertEquals(endpoint_desc.Encode(), encoded_endpoint)

        interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=1)
        interface_desc.AddEndpoint(endpoint_desc)
        self.assertEquals([endpoint_desc], interface_desc.GetEndpoints())
        encoded_interface = ('\x09\x04\x01\x00\x01\xFF\xFF\xFF\x00' +
                             encoded_endpoint)
        self.assertEquals(interface_desc.Encode(), encoded_interface)

        configuration_desc = usb_descriptors.ConfigurationDescriptor(
            bmAttributes=0xC0, MaxPower=100)
        configuration_desc.AddInterface(interface_desc)
        self.assertEquals([interface_desc], configuration_desc.GetInterfaces())
        encoded_configuration = ('\x09\x02\x19\x00\x01\x01\x00\xC0\x64' +
                                 encoded_interface)
        self.assertEquals(configuration_desc.Encode(), encoded_configuration)
コード例 #3
0
ファイル: echo_gadget.py プロジェクト: sokolovp/BraveMining
  def __init__(self, endpoints):
    """Create an echo gadget.
    """
    fs_interfaces = []
    hs_interfaces = []

    if len(endpoints) >= 1:
      iface_num, iface_string, in_endpoint, out_endpoint = endpoints[0]
      fs_intr_interface_desc = usb_descriptors.InterfaceDescriptor(
          bInterfaceNumber=iface_num,
          bInterfaceClass=usb_constants.DeviceClass.VENDOR,
          bInterfaceSubClass=0,
          bInterfaceProtocol=0,
          iInterface=iface_string,
      )
      fs_intr_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=out_endpoint,
          bmAttributes=usb_constants.TransferType.INTERRUPT,
          wMaxPacketSize=64,
          bInterval=1  # 1ms
      ))
      fs_intr_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=in_endpoint,
          bmAttributes=usb_constants.TransferType.INTERRUPT,
          wMaxPacketSize=64,
          bInterval=1  # 1ms
      ))
      fs_interfaces.append(fs_intr_interface_desc)

      hs_intr_interface_desc = usb_descriptors.InterfaceDescriptor(
          bInterfaceNumber=iface_num,
          bInterfaceClass=usb_constants.DeviceClass.VENDOR,
          bInterfaceSubClass=0,
          bInterfaceProtocol=0,
          iInterface=iface_string
      )
      hs_intr_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=out_endpoint,
          bmAttributes=usb_constants.TransferType.INTERRUPT,
          wMaxPacketSize=64,
          bInterval=4  # 1ms
      ))
      hs_intr_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=in_endpoint,
          bmAttributes=usb_constants.TransferType.INTERRUPT,
          wMaxPacketSize=64,
          bInterval=4  # 1ms
      ))
      hs_interfaces.append(hs_intr_interface_desc)

    if len(endpoints) >= 2:
      iface_num, iface_string, in_endpoint, out_endpoint = endpoints[1]
      fs_bulk_interface_desc = usb_descriptors.InterfaceDescriptor(
          bInterfaceNumber=iface_num,
          bInterfaceClass=usb_constants.DeviceClass.VENDOR,
          bInterfaceSubClass=0,
          bInterfaceProtocol=0,
          iInterface=iface_string
      )
      fs_bulk_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=out_endpoint,
          bmAttributes=usb_constants.TransferType.BULK,
          wMaxPacketSize=64,
          bInterval=0
      ))
      fs_bulk_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=in_endpoint,
          bmAttributes=usb_constants.TransferType.BULK,
          wMaxPacketSize=64,
          bInterval=0
      ))
      fs_interfaces.append(fs_bulk_interface_desc)

      hs_bulk_interface_desc = usb_descriptors.InterfaceDescriptor(
          bInterfaceNumber=iface_num,
          bInterfaceClass=usb_constants.DeviceClass.VENDOR,
          bInterfaceSubClass=0,
          bInterfaceProtocol=0,
          iInterface=iface_string
      )
      hs_bulk_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=out_endpoint,
          bmAttributes=usb_constants.TransferType.BULK,
          wMaxPacketSize=512,
          bInterval=0
      ))
      hs_bulk_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=in_endpoint,
          bmAttributes=usb_constants.TransferType.BULK,
          wMaxPacketSize=512,
          bInterval=0
      ))
      hs_interfaces.append(hs_bulk_interface_desc)

    if len(endpoints) >= 3:
      iface_num, iface_string, in_endpoint, out_endpoint = endpoints[2]
      fs_interfaces.append(usb_descriptors.InterfaceDescriptor(
          bInterfaceNumber=iface_num,
          bInterfaceClass=usb_constants.DeviceClass.VENDOR,
          bInterfaceSubClass=0,
          bInterfaceProtocol=0,
          iInterface=iface_string
      ))
      fs_isoc_interface_desc = usb_descriptors.InterfaceDescriptor(
          bInterfaceNumber=iface_num,
          bAlternateSetting=1,
          bInterfaceClass=usb_constants.DeviceClass.VENDOR,
          bInterfaceSubClass=0,
          bInterfaceProtocol=0,
          iInterface=iface_string
      )
      fs_isoc_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=out_endpoint,
          bmAttributes=usb_constants.TransferType.ISOCHRONOUS,
          wMaxPacketSize=1023,
          bInterval=1  # 1ms
      ))
      fs_isoc_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=in_endpoint,
          bmAttributes=usb_constants.TransferType.ISOCHRONOUS,
          wMaxPacketSize=1023,
          bInterval=1  # 1ms
      ))
      fs_interfaces.append(fs_isoc_interface_desc)

      hs_interfaces.append(usb_descriptors.InterfaceDescriptor(
          bInterfaceNumber=iface_num,
          bInterfaceClass=usb_constants.DeviceClass.VENDOR,
          bInterfaceSubClass=0,
          bInterfaceProtocol=0,
          iInterface=iface_string
      ))
      hs_isoc_interface_desc = usb_descriptors.InterfaceDescriptor(
          bInterfaceNumber=iface_num,
          bAlternateSetting=1,
          bInterfaceClass=usb_constants.DeviceClass.VENDOR,
          bInterfaceSubClass=0,
          bInterfaceProtocol=0,
          iInterface=iface_string
      )
      hs_isoc_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=out_endpoint,
          bmAttributes=usb_constants.TransferType.ISOCHRONOUS,
          wMaxPacketSize=512,
          bInterval=4  # 1ms
      ))
      hs_isoc_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor(
          bEndpointAddress=in_endpoint,
          bmAttributes=usb_constants.TransferType.ISOCHRONOUS,
          wMaxPacketSize=512,
          bInterval=4  # 1ms
      ))
      hs_interfaces.append(hs_isoc_interface_desc)

    super(EchoCompositeFeature, self).__init__(fs_interfaces, hs_interfaces)
コード例 #4
0
    def StartEndpoint(self, endpoint_desc):
        """Activate an endpoint.

    To enable a hardware endpoint the appropriate endpoint file must be opened
    and the endpoint descriptors written to it. Linux requires both full- and
    high-speed descriptors to be written for a high-speed device but since the
    endpoint is always reinitialized after disconnect only the high-speed
    endpoint will be valid in this case.

    Args:
      endpoint_desc: Endpoint descriptor.

    Raises:
      RuntimeError: If the hardware endpoint is in use or the configuration
          is not supported by the hardware.
    """
        endpoint_addr = endpoint_desc.bEndpointAddress
        name, hw_ep_type, hw_ep_size = self._hw_eps[endpoint_addr]

        if name in self._ep_fds:
            raise RuntimeError(
                'Hardware endpoint {} already in use.'.format(name))

        ep_type = USB_TRANSFER_TYPE_TO_MASK[endpoint_desc.bmAttributes
                                            & usb_constants.TransferType.MASK]
        ep_size = endpoint_desc.wMaxPacketSize

        if not hw_ep_type & ep_type:
            raise RuntimeError(
                'Hardware endpoint {} does not support this transfer '
                'type.'.format(name))
        elif hw_ep_size < ep_size:
            raise RuntimeError(
                'Hardware endpoint {} only supports a maximum packet '
                'size of {}, {} requested.'.format(name, hw_ep_size, ep_size))

        fd = os.open(os.path.join(self._ep_dir, name), os.O_RDWR)

        buf = struct.pack('=I', 1)
        if self._gadget.GetSpeed() == usb_constants.Speed.HIGH:
            # The full speed endpoint descriptor will not be used but Linux requires
            # one to be provided.
            full_speed_endpoint = usb_descriptors.EndpointDescriptor(
                bEndpointAddress=endpoint_desc.bEndpointAddress,
                bmAttributes=0,
                wMaxPacketSize=0,
                bInterval=0)
            buf = ''.join(
                [buf,
                 full_speed_endpoint.Encode(),
                 endpoint_desc.Encode()])
        else:
            buf = ''.join([buf, endpoint_desc.Encode()])
        os.write(fd, buf)

        pipe_r, pipe_w = multiprocessing.Pipe(False)
        child = None

        # gadgetfs doesn't support polling on the endpoint file descriptors (why?)
        # so we have to start background threads for each.
        if endpoint_addr & usb_constants.Dir.IN:

            def WriterProcess():
                while True:
                    data = pipe_r.recv()
                    written = os.write(fd, data)
                    print('IN bEndpointAddress=0x{:02X} length={}'.format(
                        endpoint_addr, written))

            child = multiprocessing.Process(target=WriterProcess)
            self._ep_fds[endpoint_addr] = fd, child, pipe_w
        else:

            def ReceivePacket(unused_fd, unused_events):
                data = pipe_r.recv()
                print('OUT bEndpointAddress=0x{:02X} length={}'.format(
                    endpoint_addr, len(data)))
                self._gadget.ReceivePacket(endpoint_addr, data)

            def ReaderProcess():
                while True:
                    data = os.read(fd, ep_size)
                    pipe_w.send(data)

            child = multiprocessing.Process(target=ReaderProcess)
            pipe_fd = pipe_r.fileno()
            self._io_loop.add_handler(pipe_fd, ReceivePacket,
                                      self._io_loop.READ)
            self._ep_fds[endpoint_addr] = fd, child, pipe_r

        child.start()
        print 'Started endpoint 0x{:02X}.'.format(endpoint_addr)
コード例 #5
0
    def __init__(self):
        """Create an echo gadget.
    """
        device_desc = usb_descriptors.DeviceDescriptor(
            idVendor=usb_constants.VendorID.GOOGLE,
            idProduct=usb_constants.ProductID.GOOGLE_ECHO_GADGET,
            bcdUSB=0x0200,
            iManufacturer=1,
            iProduct=2,
            iSerialNumber=3,
            bcdDevice=0x0100)

        fs_config_desc = usb_descriptors.ConfigurationDescriptor(
            bmAttributes=0x80, MaxPower=50)
        fs_intr_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=0,
            bInterfaceClass=usb_constants.DeviceClass.VENDOR,
            bInterfaceSubClass=0,
            bInterfaceProtocol=0,
            iInterface=4,
        )
        fs_intr_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x01,
                bmAttributes=usb_constants.TransferType.INTERRUPT,
                wMaxPacketSize=64,
                bInterval=1  # 1ms
            ))
        fs_intr_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x81,
                bmAttributes=usb_constants.TransferType.INTERRUPT,
                wMaxPacketSize=64,
                bInterval=1  # 1ms
            ))
        fs_config_desc.AddInterface(fs_intr_interface_desc)

        fs_bulk_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=1,
            bInterfaceClass=usb_constants.DeviceClass.VENDOR,
            bInterfaceSubClass=0,
            bInterfaceProtocol=0,
            iInterface=5)
        fs_bulk_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x02,
                bmAttributes=usb_constants.TransferType.BULK,
                wMaxPacketSize=64,
                bInterval=0))
        fs_bulk_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x82,
                bmAttributes=usb_constants.TransferType.BULK,
                wMaxPacketSize=64,
                bInterval=0))
        fs_config_desc.AddInterface(fs_bulk_interface_desc)

        fs_config_desc.AddInterface(
            usb_descriptors.InterfaceDescriptor(
                bInterfaceNumber=2,
                bInterfaceClass=usb_constants.DeviceClass.VENDOR,
                bInterfaceSubClass=0,
                bInterfaceProtocol=0,
                iInterface=6))
        fs_isoc_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=2,
            bAlternateSetting=1,
            bInterfaceClass=usb_constants.DeviceClass.VENDOR,
            bInterfaceSubClass=0,
            bInterfaceProtocol=0,
            iInterface=6)
        fs_isoc_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x03,
                bmAttributes=usb_constants.TransferType.ISOCHRONOUS,
                wMaxPacketSize=1023,
                bInterval=1  # 1ms
            ))
        fs_isoc_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x83,
                bmAttributes=usb_constants.TransferType.ISOCHRONOUS,
                wMaxPacketSize=1023,
                bInterval=1  # 1ms
            ))
        fs_config_desc.AddInterface(fs_isoc_interface_desc)

        hs_config_desc = usb_descriptors.ConfigurationDescriptor(
            bmAttributes=0x80, MaxPower=50)

        hs_intr_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=0,
            bInterfaceClass=usb_constants.DeviceClass.VENDOR,
            bInterfaceSubClass=0,
            bInterfaceProtocol=0,
            iInterface=4)
        hs_intr_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x01,
                bmAttributes=usb_constants.TransferType.INTERRUPT,
                wMaxPacketSize=64,
                bInterval=4  # 1ms
            ))
        hs_intr_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x81,
                bmAttributes=usb_constants.TransferType.INTERRUPT,
                wMaxPacketSize=64,
                bInterval=4  # 1ms
            ))
        hs_config_desc.AddInterface(hs_intr_interface_desc)

        hs_bulk_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=1,
            bInterfaceClass=usb_constants.DeviceClass.VENDOR,
            bInterfaceSubClass=0,
            bInterfaceProtocol=0,
            iInterface=5)
        hs_bulk_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x02,
                bmAttributes=usb_constants.TransferType.BULK,
                wMaxPacketSize=512,
                bInterval=0))
        hs_bulk_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x82,
                bmAttributes=usb_constants.TransferType.BULK,
                wMaxPacketSize=512,
                bInterval=0))
        hs_config_desc.AddInterface(hs_bulk_interface_desc)

        hs_config_desc.AddInterface(
            usb_descriptors.InterfaceDescriptor(
                bInterfaceNumber=2,
                bInterfaceClass=usb_constants.DeviceClass.VENDOR,
                bInterfaceSubClass=0,
                bInterfaceProtocol=0,
                iInterface=6))
        hs_isoc_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=2,
            bAlternateSetting=1,
            bInterfaceClass=usb_constants.DeviceClass.VENDOR,
            bInterfaceSubClass=0,
            bInterfaceProtocol=0,
            iInterface=6)
        hs_isoc_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x03,
                bmAttributes=usb_constants.TransferType.ISOCHRONOUS,
                wMaxPacketSize=1024,
                bInterval=4  # 1ms
            ))
        hs_isoc_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x83,
                bmAttributes=usb_constants.TransferType.ISOCHRONOUS,
                wMaxPacketSize=1024,
                bInterval=4  # 1ms
            ))
        hs_config_desc.AddInterface(hs_isoc_interface_desc)

        super(EchoGadget, self).__init__(device_desc, fs_config_desc,
                                         hs_config_desc)
        self.AddStringDescriptor(1, 'Google Inc.')
        self.AddStringDescriptor(2, 'Echo Gadget')
        self.AddStringDescriptor(3, '{:06X}'.format(uuid.getnode()))
        self.AddStringDescriptor(4, 'Interrupt Echo')
        self.AddStringDescriptor(5, 'Bulk Echo')
        self.AddStringDescriptor(6, 'Isochronous Echo')
コード例 #6
0
    iSerialNumber=3,
    bNumConfigurations=1,
    bcdDevice=0x0100)

fs_config_desc = usb_descriptors.ConfigurationDescriptor(
    bmAttributes=0xC0,
    MaxPower=50)

fs_interface_desc = usb_descriptors.InterfaceDescriptor(
    bInterfaceNumber=0
)
fs_config_desc.AddInterface(fs_interface_desc)

fs_bulk_in_endpoint_desc = usb_descriptors.EndpointDescriptor(
    bEndpointAddress=0x01,
    bmAttributes=usb_constants.TransferType.BULK,
    wMaxPacketSize=64,
    bInterval=0
)
fs_interface_desc.AddEndpoint(fs_bulk_in_endpoint_desc)

fs_bulk_out_endpoint_desc = usb_descriptors.EndpointDescriptor(
    bEndpointAddress=0x81,
    bmAttributes=usb_constants.TransferType.BULK,
    wMaxPacketSize=64,
    bInterval=0
)
fs_interface_desc.AddEndpoint(fs_bulk_out_endpoint_desc)

fs_alt_interface_desc = usb_descriptors.InterfaceDescriptor(
    bInterfaceNumber=0,
    bAlternateSetting=1
コード例 #7
0
    def __init__(self,
                 report_desc,
                 features,
                 packet_size=64,
                 interval_ms=10,
                 interface_number=0,
                 interface_string=0,
                 in_endpoint=0x81,
                 out_endpoint=0x01):
        """Create a composite device feature implementing the HID protocol.

    Args:
      report_desc: HID report descriptor.
      features: Map between Report IDs and HidFeature objects to handle them.
      packet_size: Maximum interrupt packet size.
      interval_ms: Interrupt transfer interval in milliseconds.
      interface_number: Interface number for this feature (default 0).
      in_endpoint: Endpoint number for the IN endpoint (defualt 0x81).
      out_endpoint: Endpoint number for the OUT endpoint or None to disable
          the endpoint (default 0x01).

    Raises:
      ValueError: If any of the parameters are out of range.
    """
        fs_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=interface_number,
            bInterfaceClass=usb_constants.DeviceClass.HID,
            bInterfaceSubClass=0,  # Non-bootable.
            bInterfaceProtocol=0,  # None.
            iInterface=interface_string,
        )

        hs_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=interface_number,
            bInterfaceClass=usb_constants.DeviceClass.HID,
            bInterfaceSubClass=0,  # Non-bootable.
            bInterfaceProtocol=0,  # None.
            iInterface=interface_string,
        )

        hid_desc = usb_descriptors.HidDescriptor()
        hid_desc.AddDescriptor(hid_constants.DescriptorType.REPORT,
                               len(report_desc))
        fs_interface_desc.Add(hid_desc)
        hs_interface_desc.Add(hid_desc)

        fs_interval = math.ceil(math.log(interval_ms, 2)) + 1
        if fs_interval < 1 or fs_interval > 16:
            raise ValueError(
                'Full speed interval out of range: {} ({} ms)'.format(
                    fs_interval, interval_ms))

        fs_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=in_endpoint,
                bmAttributes=usb_constants.TransferType.INTERRUPT,
                wMaxPacketSize=packet_size,
                bInterval=fs_interval))

        hs_interval = math.ceil(math.log(interval_ms, 2)) + 4
        if hs_interval < 1 or hs_interval > 16:
            raise ValueError(
                'High speed interval out of range: {} ({} ms)'.format(
                    hs_interval, interval_ms))

        hs_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=in_endpoint,
                bmAttributes=usb_constants.TransferType.INTERRUPT,
                wMaxPacketSize=packet_size,
                bInterval=hs_interval))

        if out_endpoint is not None:
            fs_interface_desc.AddEndpoint(
                usb_descriptors.EndpointDescriptor(
                    bEndpointAddress=out_endpoint,
                    bmAttributes=usb_constants.TransferType.INTERRUPT,
                    wMaxPacketSize=packet_size,
                    bInterval=fs_interval))
            hs_interface_desc.AddEndpoint(
                usb_descriptors.EndpointDescriptor(
                    bEndpointAddress=out_endpoint,
                    bmAttributes=usb_constants.TransferType.INTERRUPT,
                    wMaxPacketSize=packet_size,
                    bInterval=hs_interval))

        super(HidCompositeFeature, self).__init__([fs_interface_desc],
                                                  [hs_interface_desc])
        self._report_desc = report_desc
        self._features = features
        self._interface_number = interface_number
        self._in_endpoint = in_endpoint
        self._out_endpoint = out_endpoint
コード例 #8
0
    def __init__(self,
                 report_desc,
                 features,
                 vendor_id,
                 product_id,
                 packet_size=64,
                 interval_ms=10,
                 out_endpoint=True,
                 device_version=0x0100):
        """Create a HID gadget.

    Args:
      report_desc: HID report descriptor.
      features: Map between Report IDs and HidFeature objects to handle them.
      vendor_id: Device Vendor ID.
      product_id: Device Product ID.
      packet_size: Maximum interrupt packet size.
      interval_ms: Interrupt transfer interval in milliseconds.
      out_endpoint: Should this device have an interrupt OUT endpoint?
      device_version: Device version number.

    Raises:
      ValueError: If any of the parameters are out of range.
    """
        device_desc = usb_descriptors.DeviceDescriptor(
            idVendor=vendor_id,
            idProduct=product_id,
            bcdUSB=0x0200,
            iManufacturer=1,
            iProduct=2,
            iSerialNumber=3,
            bcdDevice=device_version)

        fs_config_desc = usb_descriptors.ConfigurationDescriptor(
            bmAttributes=0x80, MaxPower=50)
        fs_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=0,
            bInterfaceClass=usb_constants.DeviceClass.HID,
            bInterfaceSubClass=0,  # Non-bootable.
            bInterfaceProtocol=0,  # None.
        )
        fs_config_desc.AddInterface(fs_interface_desc)

        hs_config_desc = usb_descriptors.ConfigurationDescriptor(
            bmAttributes=0x80, MaxPower=50)
        hs_interface_desc = usb_descriptors.InterfaceDescriptor(
            bInterfaceNumber=0,
            bInterfaceClass=usb_constants.DeviceClass.HID,
            bInterfaceSubClass=0,  # Non-bootable.
            bInterfaceProtocol=0,  # None.
        )
        hs_config_desc.AddInterface(hs_interface_desc)

        hid_desc = usb_descriptors.HidDescriptor()
        hid_desc.AddDescriptor(hid_constants.DescriptorType.REPORT,
                               len(report_desc))
        fs_interface_desc.Add(hid_desc)
        hs_interface_desc.Add(hid_desc)

        fs_interval = math.ceil(math.log(interval_ms, 2)) + 1
        if fs_interval < 1 or fs_interval > 16:
            raise ValueError(
                'Full speed interval out of range: {} ({} ms)'.format(
                    fs_interval, interval_ms))

        fs_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x81,
                bmAttributes=usb_constants.TransferType.INTERRUPT,
                wMaxPacketSize=packet_size,
                bInterval=fs_interval))

        hs_interval = math.ceil(math.log(interval_ms, 2)) + 4
        if hs_interval < 1 or hs_interval > 16:
            raise ValueError(
                'High speed interval out of range: {} ({} ms)'.format(
                    hs_interval, interval_ms))

        hs_interface_desc.AddEndpoint(
            usb_descriptors.EndpointDescriptor(
                bEndpointAddress=0x81,
                bmAttributes=usb_constants.TransferType.INTERRUPT,
                wMaxPacketSize=packet_size,
                bInterval=hs_interval))

        if out_endpoint:
            fs_interface_desc.AddEndpoint(
                usb_descriptors.EndpointDescriptor(
                    bEndpointAddress=0x01,
                    bmAttributes=usb_constants.TransferType.INTERRUPT,
                    wMaxPacketSize=packet_size,
                    bInterval=fs_interval))
            hs_interface_desc.AddEndpoint(
                usb_descriptors.EndpointDescriptor(
                    bEndpointAddress=0x01,
                    bmAttributes=usb_constants.TransferType.INTERRUPT,
                    wMaxPacketSize=packet_size,
                    bInterval=hs_interval))

        super(HidGadget, self).__init__(device_desc, fs_config_desc,
                                        hs_config_desc)
        self.AddStringDescriptor(3, '{:06X}'.format(uuid.getnode()))
        self._report_desc = report_desc
        self._features = features