Handling Non-Standard USB Setup Requests on ESP32-S3 with TinyUSB HID
Posted: 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
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.
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!
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
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));
}
}
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!