espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.48k stars 7.26k forks source link

ESP32S3 HID and CDC class both not working (IDFGH-12185) #13240

Closed fenilGhoghari closed 7 months ago

fenilGhoghari commented 7 months ago

Answers checklist.

General issue report

Hello,

I am using ESP32S3 and i want to run USB CDC and HID class both at a same time some of more details here,

I am using HID class to interface Keyboard and CDC class used for Firmware updating have you any idea how can I do this?

Regards, Fenil

fenilGhoghari commented 7 months ago

@songruo can you please help me?

Dazza0 commented 7 months ago

@fenilGhoghari Can't help you without more details from your side. Could you please follow our Github issue template and provide details such as

I am using ESP32S3 and i want to run USB CDC and HID class both at a same time some of more details here, I am using HID class to interface Keyboard and CDC class used for Firmware updating have you any idea how can I do this?

Could you clarify what you are trying to. Are you trying to use the USB Host stack and interface with two device classes (HID and CDC) simultaneously?

fenilGhoghari commented 7 months ago

@Dazza0 Thanks for the reply, I am using 5.2 ESP-IDF.

I am using CDC for Firmware Update and HID to interface Keyboard

Dazza0 commented 7 months ago

@fenilGhoghari

I couldn't found any error log as of now but CDC class is working

I'm struggling to understand what is the issue you are facing. Could you please elaborate?

Dazza0 commented 7 months ago

@fenilGhoghari Closing this issue as I'm not understanding what is the problem you are encountering. Leaving some related links for your reference:

I am using CDC for Firmware Update and HID to interface Keyboard

ProPablo commented 6 months ago

I think I am encountering a similiar situation, my scenario is I am trying to emulate a HID device while also being able to print to console (CDC) for debugging. So the esp is acting as a client for both HID and Serial. Basically I am trying to follow this and implanting some of that code into this template for HID. Using this for help.


#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_HID * TUD_HID_DESC_LEN)

/**
 * @brief HID report descriptor
 *
 * In this example we implement Keyboard + Mouse HID device,
 * so we must define both report descriptors
 */
const uint8_t hid_report_descriptor[] = {
    TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(HID_ITF_PROTOCOL_KEYBOARD)),
    TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(HID_ITF_PROTOCOL_MOUSE))};

/**
 * @brief String descriptor
 */
const char* hid_string_descriptor[5] = {
    // array of pointer to string descriptors
    (char[]){0x09, 0x04},  // 0: is supported language is English (0x0409)
    "TinyUSB",             // 1: Manufacturer
    "TinyUSB Device",      // 2: Product
    "123456",              // 3: Serials, should use chip ID
    "Example HID interface",  // 4: HID
};

/**
 * @brief Configuration descriptor
 *
 * This is a simple configuration descriptor that defines 1 configuration and 1 HID interface
 */
static const uint8_t hid_configuration_descriptor[] = {
    // Configuration number, interface count, string index, total length, attribute, power in mA
    TUD_CONFIG_DESCRIPTOR(1, 1, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),

    // Interface number, string index, boot protocol, report descriptor len, EP In address, size & polling interval
    TUD_HID_DESCRIPTOR(0, 4, false, sizeof(hid_report_descriptor), 0x81, 16, 10),
};

/*** Keyboard Initialisation ****/
void initialise_keyboard() {

    ESP_LOGI(TAG, "USB initialization");
    const tinyusb_config_t tusb_cfg = {
        .device_descriptor = NULL,
        .string_descriptor = hid_string_descriptor,
        .string_descriptor_count = sizeof(hid_string_descriptor) / sizeof(hid_string_descriptor[0]),
        .external_phy = false,
        .configuration_descriptor = hid_configuration_descriptor,
    };

    ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
    ESP_LOGI(TAG, "USB initialization DONE");

}

void app_main(void)
{
    // Initialize button that will trigger HID reports
    const gpio_config_t boot_button_config = {
        .pin_bit_mask = BIT64(APP_BUTTON),
        .mode = GPIO_MODE_INPUT,
        .intr_type = GPIO_INTR_DISABLE,
        .pull_up_en = true,
        .pull_down_en = false,
    };
    ESP_ERROR_CHECK(gpio_config(&boot_button_config));

    initialise_keyboard();

    const tinyusb_config_cdcacm_t acm_cfg = {
        .usb_dev = TINYUSB_USBDEV_0,
        .cdc_port = TINYUSB_CDC_ACM_0,
        .rx_unread_buf_sz = 64,
        //.callback_rx = &tinyusb_cdc_rx_callback,
         .callback_rx = NULL,
        .callback_rx_wanted_char = NULL,
        .callback_line_state_changed = NULL,
        .callback_line_coding_changed = NULL};
    tusb_cdc_acm_init(&acm_cfg);
      esp_tusb_init_console(TINYUSB_CDC_ACM_0);
// And so on...
    }

I'm pretty sure this is possible (see this youtube video), just need some help :') / need docs on composite HID and CDC.

In the end on my linux machine, the HID works fine but I don't get any ports opening up that want to do serial stuffs. I will also note that I have uart logging setup through Menuconfig on some other random pins and I'm using a usb to ttl cable for reading that out. I just want cdc&HID so I dont have to plug in another cable. Big thanks :green_heart:

roma-jam commented 6 months ago

Hi @ProPablo,

For your goal, you may refer to the esp-idf usb device example: https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb/device/tusb_composite_msc_serialdevice

The one thing you should do is to replace MSC interface with HID.

ProPablo commented 6 months ago

Hi, Ive managed to solve this issue counterintuitively by sleeping on it, looking deeper at what you meant by replace MSC interface with HID and also looking more at this.

Ive had a look at that example already, my understanding is every member in tinyusb_config_t that is null is filled in by the framework. In the tusb_composite_msc_serialdevice example all members are null so I wasnt sure how to add cdc to my list of interfaces.

Turns out in order to keep the HID interface definition, the configuration object needs to be specified as such:

#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_CDC_DESC_LEN)
const char* hid_string_descriptor[5] = {
    // array of pointer to string descriptors
    (char[]){0x09, 0x04},  // 0: is supported language is English (0x0409)
    "TinyUSB",             // 1: Manufacturer
    "TinyUSB Device",      // 2: Product
    "123456",              // 3: Serials, should use chip ID
    "Example HID interface",  // 4: HID
"My debugging CDC interface",  // 5: CDC
};

#define EPNUM_CDC_NOTIF   0x81
#define EPNUM_CDC_OUT     0x02
#define EPNUM_CDC_IN      0x82
#define EPNUM_HID   0x83

/************ THIS IS THE IMPORTANT PART *************/
/**
 * @brief Configuration descriptor
 *
 * This is a simple configuration descriptor that defines 1 configuration and 1 HID interface
 */
static const uint8_t hid_configuration_descriptor[] = {
    // Configuration number, interface count, string index, total length, attribute, power in mA
    TUD_CONFIG_DESCRIPTOR(1, 3, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),

    // Interface number, string index, boot protocol, report descriptor len, EP In address, size & polling interval
    TUD_HID_DESCRIPTOR(0, 4, false, sizeof(hid_report_descriptor), EPNUM_HID, 16, 10),

    // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
    TUD_CDC_DESCRIPTOR(1, 5, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),

};

void initialise_keyboard()
{

    ESP_LOGI(TAG, "USB initialization");
    const tinyusb_config_t tusb_cfg = {
        .device_descriptor = NULL,
        .string_descriptor = hid_string_descriptor,
        .string_descriptor_count = sizeof(hid_string_descriptor) / sizeof(hid_string_descriptor[0]),
        .external_phy = false,
        .configuration_descriptor = hid_configuration_descriptor,
    };

    ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
    ESP_LOGI(TAG, "USB initialization DONE");
}

Thank you for the help 💚

cnfatal commented 4 months ago

There is a my project which use HID and CDC composite device: https://github.com/cnfatal/esp32-cdc-keyboard