Handling Non-Standard USB Setup Requests on ESP32-S3 with TinyUSB HID

adasiek1221
Posts: 2
Joined: Sun Sep 15, 2024 2:52 pm

Handling Non-Standard USB Setup Requests on ESP32-S3 with TinyUSB HID

Postby adasiek1221 » Sun Sep 15, 2024 3:07 pm

Hi,

I’m developing a project using the ESP32-S3 with TinyUSB to implement a USB HID interface. While the basic HID communication works perfectly, I’m having trouble handling non-standard USB setup requests (custom bRequest values) sent from the host. Specifically, I want to process and respond to these custom control requests.

Hardware:
ESP32-S2
TinyUSB
Problem:
I’m receiving a custom USB setup packet from the host, but my device is stalling the endpoint instead of processing the request. Here’s an example of the setup packet I'm receiving:


USBD Setup Received 41 00 FD FD 0D 03 00 00
Stall EP0
Image
It appears that my HID implementation is not handling non-standard requests properly, and I need to process these custom bRequest values.

Code Example:
Below is a simplified version of my HID setup. The standard HID functionality is working well, but I’m unsure how to modify the code to capture and handle these non-standard setup requests.

Code: Select all

/*
#include <stdlib.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "tinyusb.h"
#include "class/hid/hid_device.h"
#include "driver/gpio.h"

#define APP_BUTTON (GPIO_NUM_0)
static const char *TAG = "example";

/************* TinyUSB descriptors ****************/
#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN)
#define VENDOR_ID  0x0b49
#define PRODUCT_ID 0x064f
#ifdef CFG_TUSB_DEBUG
#undef CFG_TUSB_DEBUG
#endif

#define CFG_TUSB_DEBUG 3  // Poziom debugowania, gdzie 3 to najbardziej szczegółow
// Deskryptor HID
const uint8_t hid_report_descriptor[] = {
    TUD_HID_REPORT_DESC_GENERIC_INOUT(8)
};

// Deskryptor stringów
const char* hid_string_descriptor[5] = {
    (char[]){0x09, 0x04},  // Język angielski
    "ASCII CORPORATION",    // Producent
    "Drmn4ea Tech",         // Produkt
    "123456",               // Numer seryjny
    "ASCII Vib",            // Nazwa interfejsu
};

// Deskryptor urządzenia
static const tusb_desc_device_t hid_device_descriptor = {
    .bLength = sizeof(tusb_desc_device_t),
    .bDescriptorType = TUSB_DESC_DEVICE,
    .bcdUSB = 0x0100,      // USB 1.1
    .bDeviceClass = 0x00,
    .bDeviceSubClass = 0,
    .bDeviceProtocol = 0,
    .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
    .idVendor = VENDOR_ID,
    .idProduct = PRODUCT_ID,
    .bcdDevice = 0x0100,
    .iManufacturer = 1,
    .iProduct = 2,
    .iSerialNumber = 3,
    .bNumConfigurations = 1
};


// Funkcja obsługująca wszystkie żądania SETUP na EP0
bool tud_control_request_cb(uint8_t rhport, tusb_control_request_t const *request)
{
    ESP_LOGI(TAG, "Obsługa Setup request: bmRequestType=0x%02X, bRequest=0x%02X, wValue=0x%04X, wIndex=0x%04X",
             request->bmRequestType, request->bRequest, request->wValue, request->wIndex);

    // Sprawdzamy, czy jest to Vendor-specific request (bmRequestType = 0x41)
    if (request->bmRequestType == 0x21) {
        ESP_LOGI(TAG, "Vendor-specific request otrzymano!");

        // Odpowiadamy na żądanie kontrolne
        if (request->bRequest == 0x00) {
            // Na przykład: Zwróć jakiś niestandardowy raport lub konfigurację
            const char* response = "Vendor-specific response";
            tud_control_xfer(rhport, request, (void*)response, strlen(response));
            return true;
        }
    }

    // Jeżeli żądanie nie jest obsługiwane, wysyłamy STALL
    return false;
}




// Funkcja do obsługi GET_REPORT
uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
    ESP_LOGI(TAG, "GET_REPORT request: instance=%d, report_id=%d, report_type=%d", instance, report_id, report_type);
    
    // Wypełniamy bufor zerami, aby zwrócić pusty raport
    memset(buffer, 0, reqlen);
    
    // Zwracamy ilość danych do hosta
    return reqlen;
}

// Deskryptor konfiguracji
static const uint8_t hid_configuration_descriptor[] = {
    TUD_CONFIG_DESCRIPTOR(1, 1, 0, TUSB_DESC_TOTAL_LEN, 0x80, 98),
    TUD_HID_DESCRIPTOR(0, 4, false, sizeof(hid_report_descriptor), 0x81, 8, 10),  // IN (0x81)
    TUD_HID_DESCRIPTOR(1, 4, false, sizeof(hid_report_descriptor), 0x00, 8, 10)   // OUT (0x02)
};

/********* TinyUSB HID callbacks ***************/

// Deskryptor raportu HID
uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance) {
    return hid_report_descriptor;
}

// Odbieranie danych od hosta (OUT endpoint)
void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
    ESP_LOGI(TAG, "Odebrano dane od hosta: %.*s", bufsize, buffer);
}

/********* Application ***************/

void app_main(void) {
    ESP_LOGI(TAG, "Inicjalizacja USB HID");

    const tinyusb_config_t tusb_cfg = {
        .device_descriptor = &hid_device_descriptor,
        .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 HID zainicjalizowane");

    while (1) {
        if (tud_mounted()) {
            //ESP_LOGI(TAG, "Urządzenie HID podłączone i działa, oczekiwanie na dane...");
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

Question:
Is there a way to capture and handle non-standard USB setup requests using TinyUSB in HID mode? Specifically, I want to intercept and process custom bRequest values in the setup packets (for example: 0x41 00 FD FD 0D 03 00 00). How can I extend my HID implementation to handle these custom requests?

Any help or guidance on how to implement this would be greatly appreciated.

Thanks!
Attachments
tusb_hid.zip
(23.87 MiB) Downloaded 55 times

adasiek1221
Posts: 2
Joined: Sun Sep 15, 2024 2:52 pm

Re: Handling Non-Standard USB Setup Requests on ESP32-S3 with TinyUSB HID

Postby adasiek1221 » Thu Sep 19, 2024 11:39 am

I solved the problem less professionally by modifying liblary usbtinyusb catching the case responsilbe for setup request in class usbd.c

Code: Select all

case DCD_EVENT_SETUP_RECEIVED:
    TU_LOG_PTR(USBD_DBG, &event.setup_received);
    TU_LOG(USBD_DBG, "\r\n");

    // Mark as connected after receiving the 1st setup packet.
    _usbd_dev.connected = 1;

    // Clear busy and claimed flags for control endpoints
    _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = 0;
    _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0;
    _usbd_dev.ep_status[0][TUSB_DIR_IN].busy = 0;
    _usbd_dev.ep_status[0][TUSB_DIR_IN].claimed = 0;

    // Sprawdzenie, czy to żądanie niestandardowe (0x41 wskazuje na niestandardowy request)
    if (event.setup_received.bmRequestType == 0x41) // Niestandardowy request od hosta
    {
        TU_LOG(USBD_DBG, "Odebrano vendor-specific żądanie\n");

        // Bufor na dane z event.setup_received
        char buffer[128]; // Dostosuj rozmiar bufora do swoich potrzeb

        // Przekonwertuj dane na format heksadecymalny (8 bajtów, zgodnie z Twoim przykładem)
        snprintf(buffer, sizeof(buffer), 
                 "%02X %02X %04X %04X %04X", 
                 event.setup_received.bmRequestType, 
                 event.setup_received.bRequest, 
                 event.setup_received.wValue, 
                 event.setup_received.wIndex, 
                 event.setup_received.wLength);

        // Wyświetlaj dane w prostszym formacie
        TU_LOG(USBD_DBG, "Zawartość bufora: %s", buffer);

        // Wysyłanie bufora jako odpowiedź do hosta
        tud_control_xfer(event.rhport, &event.setup_received, buffer, strlen(buffer));

        // Wywołanie callbacka tud_hid_set_report_cb, aby przetworzyć dane
        tud_hid_set_report_cb(0, event.setup_received.bRequest, HID_REPORT_TYPE_OUTPUT, (uint8_t*)buffer, strlen(buffer));

        break;
    }

Who is online

Users browsing this forum: snutw_ and 118 guests