Skip to content

Instantly share code, notes, and snippets.

@haideralipunjabi
Last active May 11, 2025 16:25
Show Gist options
  • Save haideralipunjabi/69f848591a4d8b86ebbde04a0be8c8c9 to your computer and use it in GitHub Desktop.
Save haideralipunjabi/69f848591a4d8b86ebbde04a0be8c8c9 to your computer and use it in GitHub Desktop.
Attempt at using ESP32 S2 Mini to control HDMI USB Switch
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#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) // Use BOOT signal by default
static const char *TAG = "example";
/************* TinyUSB descriptors ****************/
#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)),
};
const char *hid_string_descriptor[5] = {
(char[]){0x09, 0x04},
"Logitech", // Manufacturer
"Composite Device", // Product
"LOGI123456", // Serial
"Keyboard Interface", // HID interface
};
const tusb_desc_device_t custom_device_descriptor = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0100, // USB 2.0
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = 0x0513, // Example: Logitech
.idProduct = 0x0318, // Example: Known keyboard PID
.bcdDevice = 0x0100,
.iManufacturer = 0x01,
.iProduct = 0x02,
.iSerialNumber = 0x03,
.bNumConfigurations = 0x01};
/**
* @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, true, sizeof(hid_report_descriptor), 0x81, 8, 1),
};
/********* TinyUSB HID callbacks ***************/
// Invoked when received GET HID REPORT DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance)
{
// We use only one interface and one HID report descriptor, so we can ignore parameter 'instance'
return hid_report_descriptor;
}
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
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)
{
(void)instance;
(void)report_id;
(void)report_type;
(void)buffer;
(void)reqlen;
return 0;
}
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
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)
{
}
/********* Application ***************/
void send_key(uint8_t keycode)
{
uint8_t keycodes[6] = {0};
keycodes[0] = keycode;
ESP_LOGI(TAG, "Sending Keyboard report");
tud_hid_keyboard_report(HID_ITF_PROTOCOL_KEYBOARD, 0, keycodes);
vTaskDelay(pdMS_TO_TICKS(50));
tud_hid_keyboard_report(HID_ITF_PROTOCOL_KEYBOARD, 0, NULL);
vTaskDelay(pdMS_TO_TICKS(500));
}
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));
ESP_LOGI(TAG, "USB initialization");
const tinyusb_config_t tusb_cfg = {
.device_descriptor = &custom_device_descriptor,
.string_descriptor = hid_string_descriptor,
.string_descriptor_count = sizeof(hid_string_descriptor) / sizeof(hid_string_descriptor[0]),
.external_phy = false,
#if (TUD_OPT_HIGH_SPEED)
.fs_configuration_descriptor = hid_configuration_descriptor, // HID configuration descriptor for full-speed and high-speed are the same
.hs_configuration_descriptor = hid_configuration_descriptor,
.qualifier_descriptor = NULL,
#else
.configuration_descriptor = hid_configuration_descriptor,
#endif // TUD_OPT_HIGH_SPEED
};
ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
ESP_LOGI(TAG, "USB initialization DONE");
while (1)
{
if (tud_mounted())
{
static bool send_hid_data = true;
if (send_hid_data)
{
send_key(HID_KEY_CONTROL_LEFT);
send_key(HID_KEY_CONTROL_LEFT);
send_key(HID_KEY_2);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment