HID keyboard + HID generic composite device example

In this section, HID keyboard + HID generic composite device are used as an example.

USB composite device structure examples

/* Two HID classes */
usb_device_class_config_list_struct_t g_UsbDeviceCompositeConfigList =
{
    g_CompositeClassConfig,
    USB_DeviceCallback,
    2U,
};
/* Two HID classes definition */
usb_device_class_config_struct_t g_CompositeClassConfig[2] =
 {
    {
        USB_DeviceHidKeyboardCallback,
        (class_handle_t)NULL,
        &g_UsbDeviceHidKeyboardConfig,
    },
    {
        USB_DeviceHidGenericCallback,
        (class_handle_t)NULL,
        &g_UsbDeviceHidGenericConfig,
    }
};
/* HID generic device config */
usb_device_class_struct_t g_UsbDeviceHidGenericConfig =
{
    g_UsbDeviceHidGenericInterfaceList, /* The interface list of the HID generic */
    kUSB_DeviceClassTypeHid,             /* The HID class type */
    USB_DEVICE_CONFIGURATION_COUNT,          /* The configuration count */
};
/* HID generic device interface list */
usb_device_interface_list_t g_UsbDeviceHidGenericInterfaceList[USB_DEVICE_CONFIGURATION_COUNT] =
{
    {
        USB_HID_GENERIC_INTERFACE_COUNT, /* The interface count of the HID generic */
        g_UsbDeviceHidGenericInterfaces,        /* The interfaces handle */
    },
};
/* HID generic device interfaces */
usb_device_interfaces_struct_t g_UsbDeviceHidGenericInterfaces[USB_HID_GENERIC_INTERFACE_COUNT] =
{
    USB_HID_GENERIC_CLASS,           /* HID generic class code */
    USB_HID_GENERIC_SUBCLASS,        /* HID generic subclass code */
    USB_HID_GENERIC_PROTOCOL,        /* HID generic protocol code */
    USB_HID_GENERIC_INTERFACE_INDEX, /* The interface number of the HID generic */
    g_UsbDeviceHidGenericInterface,         /* Interfaces handle */
    sizeof(g_UsbDeviceHidGenericInterface) / sizeof(usb_device_interface_struct_t),
};
/* HID generic device interface and alternate setting device information */
usb_device_interface_struct_t g_UsbDeviceHidGenericInterface[] =
{
    {
        0U, /* The alternate setting of the interface */
        {
            USB_HID_GENERIC_ENDPOINT_COUNT, /* Endpoint count */
            g_UsbDeviceHidGenericEndpoints,        /* Endpoints handle */
        },
    }
};
/* HID generic device endpoint information for interface USB_HID_GENERIC_INTERFACE_INDEX and alternate setting is 0. */
usb_device_endpoint_struct_t g_UsbDeviceHidGenericEndpoints[USB_HID_GENERIC_ENDPOINT_COUNT] =
{
    /* HID generic interrupt IN pipe */
    {
        USB_HID_GENERIC_ENDPOINT_IN | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
        USB_ENDPOINT_INTERRUPT,
        FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE,
    },
    /* HID generic interrupt OUT pipe */
    {
        USB_HID_GENERIC_ENDPOINT_OUT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
        USB_ENDPOINT_INTERRUPT,
        FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE,
    },
};
/* HID keyboard device config */
usb_device_class_struct_t g_UsbDeviceHidKeyboardConfig =
{
    g_UsbDeviceHidKeyboardInterfaceList, /* The interface list of the HID keyboard */
    kUSB_DeviceClassTypeHid,             /* The HID class type */
    USB_DEVICE_CONFIGURATION_COUNT,          /* The configuration count */
};
/* HID keyboard device interface list */
usb_device_interface_list_t g_UsbDeviceHidKeyboardInterfaceList[USB_DEVICE_CONFIGURATION_COUNT] =
{
    {
        USB_HID_KEYBOARD_INTERFACE_COUNT, /* The interface count of the HID keyboard */
        g_UsbDeviceHidKeyboardInterfaces,        /* The interfaces handle */
    },
};
/* HID generic device interfaces */
usb_device_interfaces_struct_t g_UsbDeviceHidKeyboardInterfaces[USB_HID_KEYBOARD_INTERFACE_COUNT] =
{
    USB_HID_KEYBOARD_CLASS,           /* HID keyboard class code */
    USB_HID_KEYBOARD_SUBCLASS,        /* HID keyboard subclass code */
    USB_HID_KEYBOARD_PROTOCOL,        /* HID keyboard protocol code */
    USB_HID_KEYBOARD_INTERFACE_INDEX, /* The interface number of the HID keyboard */
    g_UsbDeviceHidKeyboardInterface,         /* Interfaces handle */
    sizeof(g_UsbDeviceHidKeyboardInterface) / sizeof(usb_device_interface_struct_t),
};
/* HID generic device interface and alternate setting device information */
usb_device_interface_struct_t g_UsbDeviceHidKeyboardInterface[] =
{
    {
        0U, /* The alternate setting of the interface */
        {
            USB_HID_KEYBOARD_ENDPOINT_COUNT, /* Endpoint count */
            g_UsbDeviceHidKeyboardEndpoints,        /* Endpoints handle */
        },
    }
};
/* HID generic device endpoint information for interface USB_HID_GENERIC_INTERFACE_INDEX and alternate setting is 0. */
usb_device_endpoint_struct_t g_UsbDeviceHidKeyboardEndpoints[USB_HID_KEYBOARD_ENDPOINT_COUNT] =
{
    /* HID keyboard interrupt IN pipe */
    {
        USB_HID_KEYBOARD_ENDPOINT_IN | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
        USB_ENDPOINT_INTERRUPT,
        FS_HID_KEYBOARD_INTERRUPT_IN_PACKET_SIZE,
    },
};

Parent topic:HID keyboard + HID generic composite device example

USB composite device descriptor examples

Modify the vendor ID and product ID for the device descriptor in the “usb_device_descriptor.c” file.

Change the interface number as shown in the configuration descriptor in the “usb_device_descriptor.c” file.

Merge the HID keyboard and HID generic configuration descriptor (in the “usb_device_descriptor.c” file) from the HID mouse + HID keyboard example and hid_generic example and change the endpoint number to be consistent with section USB composite device structure examples.

Parent topic:HID keyboard + HID generic composite device example

USB composite device application example

Class configuration

USB_DEVICE_CONFIG_HID is set to 2 in usb_device_config.h

USB_DEVICE_CONFIG_ENDPOINTS is set to 4 in usb_device_config.h

Parent topic:USB composite device application example

HID + HID Application structure

typedef struct _usb_device_composite_struct
{
    usb_device_handle                  deviceHandle;
    class_handle_t                     hidKeyboardHandle;
    class_handle_t                     hidGenericHandle;
    uint8_t                            speed;
    uint8_t                            attach;
    uint8_t                            currentConfiguration;
    uint8_t                            currentInterfaceAlternateSetting[USB_COMPOSITE_INTERFACE_COUNT];
} usb_device_composite_struct_t;
/* HID keyboard structure */
typedef struct _usb_device_hid_keyboard_struct
{
    uint8_t                   buffer[USB_HID_KEYBOARD_IN_BUFFER_LENGTH];
    uint8_t                   idleRate;
} usb_device_hid_keyboard_struct_t;
/* HID generic structure */
typedef struct _usb_device_hid_generic_struct
{
    uint32_t                  buffer[2][USB_HID_GENERIC_IN_BUFFER_LENGTH>>2];
    uint8_t                   bufferIndex;
    uint8_t                   idleRate;
} usb_device_hid_generic_struct_t;

Parent topic:USB composite device application example

HID + HID application

  1. Define and initialize the configuration structure.

    static usb_device_composite_struct_t g_UsbDeviceComposite;
    usb_device_class_struct_t g_UsbDeviceHidGenericConfig;
    usb_device_class_struct_t g_UsbDeviceHidKeyboardConfig;
    usb_device_class_config_struct_t g_CompositeClassConfig[2] =
    {
        {
            USB_DeviceHidKeyboardCallback,
            (class_handle_t)NULL,
            &g_UsbDeviceHidKeyboardConfig,
        },
        {
            USB_DeviceHidGenericCallback,
            (class_handle_t)NULL,
            &g_UsbDeviceHidGenericConfig,
        }
    };
    usb_device_class_config_list_struct_t g_UsbDeviceCompositeConfigList =
    {
        g_CompositeClassConfig,
        USB_DeviceCallback,
        2U,
    };
    
    
  2. Add USB ISR.

    #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
    void USBHS_IRQHandler(void) { USB_DeviceEhciIsrFunction(g_UsbDeviceComposite.deviceHandle); }
    #endif
    #if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
    void USB0_IRQHandler(void) { USB_DeviceKhciIsrFunction(g_UsbDeviceComposite.deviceHandle); }
    #endif
    #if defined(USB_DEVICE_CONFIG_LPC3511IP) && (USB_DEVICE_CONFIG_LPC3511IP > 0U)
    void USB0_IRQHandler(void)
    {
        USB_DeviceLpc3511IpIsrFunction(g_UsbDeviceHidMouse.deviceHandle);
    }
    #endif
    
    
  3. Enable the USB device clock.

    #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
        CLOCK_EnableUsbhs0Clock(kCLOCK_UsbSrcPll0, CLOCK_GetFreq(kCLOCK_PllFllSelClk));
        USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ);
    #endif
    #if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
    #if ((defined FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED) && (FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED))
        CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcIrc48M, 48000000U);
    #else
        CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcPll0, CLOCK_GetFreq(kCLOCK_PllFllSelClk));
    #endif /* FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED */
    #endif
    #if defined(USB_DEVICE_CONFIG_LPC3511IP) && (USB_DEVICE_CONFIG_LPC3511IP > 0U)
        CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcFro, CLOCK_GetFreq(kCLOCK_FroHf));
    #endif
    
    
  4. Set the default state.

    g_UsbDeviceComposite.speed = USB_SPEED_FULL;
    g_UsbDeviceComposite.attach = 0U;
    g_UsbDeviceComposite.hidGenericHandle = (class_handle_t)NULL;
    g_UsbDeviceComposite.hidKeyboardHandle = (class_handle_t)NULL;
    g_UsbDeviceComposite.deviceHandle = NULL;
    
    
  5. Initialize the USB device.

    if (kStatus_USB_Success !=
        USB_DeviceClassInit(CONTROLLER_ID, &g_UsbDeviceCompositeConfigList, &g_UsbDeviceComposite.deviceHandle))
    {
        usb_echo("USB device composite demo init failed\r\n");
        return;
    }
    else
    {
        usb_echo("USB device composite demo\r\n");
        …
    }
    
    
  6. Save each class handle when the device is initialized successfully.

    /* Get the HID keyboard class handle */
    g_UsbDeviceComposite.hidKeyboardHandle = g_UsbDeviceCompositeConfigList.config[0].classHandle;
    /* Get the HID generic class handle */
    g_UsbDeviceComposite.hidGenericHandle = g_UsbDeviceCompositeConfigList.config[1].classHandle;
    
    
  7. Initialize the HID keyboard and HID generic application.

    USB_DeviceHidKeyboardInit(&g_UsbDeviceComposite);
    USB_DeviceHidGenericInit(&g_UsbDeviceComposite);
    
    
  8. Set the device ISR priority and enable the device interrupt.

    NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY);
    NVIC_EnableIRQ((IRQn_Type)irqNumber);
    
    
  9. Start the device functionality.

    USB_DeviceRun(g_UsbDeviceComposite.deviceHandle);
    
  10. Poll the device task when the “USB_DEVICE_CONFIG_USE_TASK” is non-zero. Poll the HID keyboard and HID generic task when these tasks are implemented.

    #if USB_DEVICE_CONFIG_USE_TASK
    #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
            USB_DeviceEhciTaskFunction(g_UsbDeviceComposite.deviceHandle);
    #endif
    #if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
            USB_DeviceKhciTaskFunction(g_UsbDeviceComposite.deviceHandle);
    #endif
    #if defined(USB_DEVICE_CONFIG_LPC3511IP) && (USB_DEVICE_CONFIG_LPC3511IP > 0U)
            USB_DeviceLpc3511IpTaskFunction(g_UsbDeviceHidMouse.deviceHandle);
    #endif
    #endif
    
    

Parent topic:USB composite device application example

Parent topic:HID keyboard + HID generic composite device example