add some code
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(usb_surface_dial)
|
||||
@@ -0,0 +1,49 @@
|
||||
## USB HID Surface Dial
|
||||
|
||||
This example shows how to use the ESP32-Sx USB function to emulate a Windows knob that allows volume control, page up and down, and more.
|
||||
|
||||
## Hardware Required
|
||||
|
||||

|
||||
|
||||
- Any ESP32-Sx development board with **knob** functionality.
|
||||
- The knob can be a series of rotary encoders with push function such as EC11
|
||||
- It is also possible to use three buttons that simulate: press, left turn, right turn
|
||||
|
||||
- Hardware Connection:
|
||||
- GPIO19 to USB_D-
|
||||
- GPIO20 to USB_D+
|
||||
- GPIO42 to EC11_E
|
||||
- GPIO1 to EC11_A
|
||||
- GPIO2 to EC11_C
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Build and Flash
|
||||
|
||||
1. Set up the `ESP-IDF` environment variables,you can refer [Set up the environment variables](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html#step-4-set-up-the-environment-variables), Linux can using:
|
||||
|
||||
```
|
||||
. $HOME/esp/esp-idf/export.sh
|
||||
```
|
||||
|
||||
2. Set ESP-IDF build target to `esp32s2` or `esp32s3`
|
||||
|
||||
```bash
|
||||
idf.py set-target esp32s2
|
||||
```
|
||||
|
||||
3. Build, Flash, output log
|
||||
|
||||
```bash
|
||||
idf.py build flash monitor
|
||||
```
|
||||
|
||||
## How To Use
|
||||
|
||||
* Connect the USB to the Windows USB port and wait for the USB device to finish installing
|
||||
* Press and hold the button to wake up the Windows wheel
|
||||
|
||||

|
||||
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 954 KiB |
@@ -0,0 +1,8 @@
|
||||
idf_component_register(
|
||||
SRCS "main.c" "usb_descriptors.c"
|
||||
INCLUDE_DIRS "."
|
||||
)
|
||||
|
||||
idf_component_get_property(tusb_lib leeebo__tinyusb_src COMPONENT_LIB)
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
target_link_libraries(${tusb_lib} PRIVATE ${COMPONENT_LIB})
|
||||
@@ -0,0 +1,24 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
choice DEVELOPMENT_BOARD_SELECTION
|
||||
prompt "Select the development board you are using"
|
||||
default ESP32_S3_USB_OTG if IDF_TARGET_ESP32S3
|
||||
default ESP32_S2_GENERIC if IDF_TARGET_ESP32S2
|
||||
help
|
||||
Select this option to choose the board for the example.
|
||||
|
||||
config ESP32_S3_USB_OTG
|
||||
bool "ESP32 S3 USB OTG"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
|
||||
config ESP32_S3_GENERIC
|
||||
bool "ESP32 S3 GENERIC"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
|
||||
config ESP32_S2_GENERIC
|
||||
bool "ESP32 S2 GENERIC"
|
||||
depends on IDF_TARGET_ESP32S2
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,19 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
## Required IDF version
|
||||
idf:
|
||||
version: ">=4.4.0"
|
||||
espressif/button:
|
||||
version: ">=2.3.0"
|
||||
override_path: "../../../../../components/button"
|
||||
leeebo/tinyusb_src:
|
||||
version: ">=0.0.4"
|
||||
espressif/knob:
|
||||
version: ">=0.1.0"
|
||||
override_path: "../../../../../components/knob"
|
||||
espressif/esp32_s3_usb_otg:
|
||||
version: "^1.5.1"
|
||||
rules:
|
||||
- if: "target in [esp32s3]"
|
||||
lvgl/lvgl: #temp to workaround bsp issue
|
||||
version: "9.2.0"
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_private/usb_phy.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "tusb.h"
|
||||
#include "tusb_config.h"
|
||||
#include "iot_button.h"
|
||||
#include "iot_knob.h"
|
||||
#ifdef CONFIG_ESP32_S3_USB_OTG
|
||||
#include "bsp/esp-bsp.h"
|
||||
#endif
|
||||
|
||||
#define TAG "DIAL"
|
||||
|
||||
#define GPIO_BUTTON 42
|
||||
#define GPIO_KNOB_A 1
|
||||
#define GPIO_KNOB_B 2
|
||||
|
||||
#define REPORT_ID 1
|
||||
#define DIAL_R 0xC8
|
||||
#define DIAL_L 0x38
|
||||
#define DIAL_PRESS 0x01
|
||||
#define DIAL_RELEASE 0x00
|
||||
#define DIAL_R_F 0x14
|
||||
#define DIAL_L_F 0xEC
|
||||
|
||||
static button_handle_t s_btn = 0;
|
||||
static knob_handle_t s_knob = 0;
|
||||
static usb_phy_handle_t s_phy_hdl;
|
||||
|
||||
static void usb_phy_init(void)
|
||||
{
|
||||
// Configure USB PHY
|
||||
usb_phy_config_t phy_conf = {
|
||||
.controller = USB_PHY_CTRL_OTG,
|
||||
.otg_mode = USB_OTG_MODE_DEVICE,
|
||||
.target = USB_PHY_TARGET_INT,
|
||||
};
|
||||
usb_new_phy(&phy_conf, &s_phy_hdl);
|
||||
}
|
||||
|
||||
static void surface_dial_report(uint8_t key)
|
||||
{
|
||||
uint8_t _dial_report[2];
|
||||
_dial_report[0] = key;
|
||||
_dial_report[1] = 0;
|
||||
if (key == DIAL_L || key == DIAL_L_F) {
|
||||
_dial_report[1] = 0xff;
|
||||
}
|
||||
tud_hid_report(REPORT_ID, _dial_report, 2);
|
||||
}
|
||||
|
||||
static void _button_press_down_cb(void *arg, void *data)
|
||||
{
|
||||
ESP_LOGI(TAG, "BTN: BUTTON_PRESS_DOWN");
|
||||
surface_dial_report(DIAL_PRESS);
|
||||
}
|
||||
|
||||
static void _button_press_up_cb(void *arg, void *data)
|
||||
{
|
||||
ESP_LOGI(TAG, "BTN: BUTTON_PRESS_UP[%"PRIu32"]", iot_button_get_ticks_time((button_handle_t)arg));
|
||||
surface_dial_report(DIAL_RELEASE);
|
||||
}
|
||||
|
||||
static void _knob_right_cb(void *arg, void *data)
|
||||
{
|
||||
ESP_LOGI(TAG, "KONB: KONB_RIGHT,count_value:%"PRId32"", iot_knob_get_count_value((button_handle_t)arg));
|
||||
surface_dial_report(DIAL_L);
|
||||
}
|
||||
|
||||
static void _knob_left_cb(void *arg, void *data)
|
||||
{
|
||||
ESP_LOGI(TAG, "KONB: KONB_LEFT,count_value:%"PRId32"", iot_knob_get_count_value((button_handle_t)arg));
|
||||
surface_dial_report(DIAL_R);
|
||||
}
|
||||
|
||||
static void _button_init(void)
|
||||
{
|
||||
button_config_t cfg = {
|
||||
.type = BUTTON_TYPE_GPIO,
|
||||
.long_press_time = 1000,
|
||||
.short_press_time = 200,
|
||||
.gpio_button_config = {
|
||||
.gpio_num = GPIO_BUTTON,
|
||||
.active_level = 0,
|
||||
},
|
||||
};
|
||||
s_btn = iot_button_create(&cfg);
|
||||
iot_button_register_cb(s_btn, BUTTON_PRESS_DOWN, _button_press_down_cb, NULL);
|
||||
iot_button_register_cb(s_btn, BUTTON_PRESS_UP, _button_press_up_cb, NULL);
|
||||
}
|
||||
|
||||
static void _knob_init(void)
|
||||
{
|
||||
knob_config_t cfg = {
|
||||
.default_direction = 0,
|
||||
.gpio_encoder_a = GPIO_KNOB_A,
|
||||
.gpio_encoder_b = GPIO_KNOB_B,
|
||||
};
|
||||
s_knob = iot_knob_create(&cfg);
|
||||
if (NULL == s_knob) {
|
||||
ESP_LOGE(TAG, "knob create failed");
|
||||
}
|
||||
|
||||
iot_knob_register_cb(s_knob, KNOB_LEFT, _knob_left_cb, NULL);
|
||||
iot_knob_register_cb(s_knob, KNOB_RIGHT, _knob_right_cb, NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
#ifdef CONFIG_ESP32_S3_USB_OTG
|
||||
bsp_usb_mode_select_device();
|
||||
#endif
|
||||
usb_phy_init();
|
||||
_button_init();
|
||||
_knob_init();
|
||||
|
||||
tusb_init();
|
||||
|
||||
size_t timeout_tick = pdMS_TO_TICKS(10);
|
||||
while (1) {
|
||||
tud_task();
|
||||
vTaskDelay(timeout_tick);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// TODO not Implemented
|
||||
(void) instance;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) reqlen;
|
||||
return 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)
|
||||
{
|
||||
(void) instance;
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
(void) buffer;
|
||||
(void) bufsize;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_CONFIG_H_
|
||||
#define _TUSB_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board Specific Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// RHPort number used for device can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUD_RHPORT
|
||||
#define BOARD_TUD_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUD_MAX_SPEED
|
||||
#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COMMON CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by compiler flags for flexibility
|
||||
#ifndef CFG_TUSB_MCU
|
||||
#error CFG_TUSB_MCU must be defined
|
||||
#endif
|
||||
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
|
||||
|
||||
#ifndef CFG_TUSB_OS
|
||||
#define CFG_TUSB_OS OPT_OS_FREERTOS
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_DEBUG
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
// Enable Device stack
|
||||
#define CFG_TUD_ENABLED 1
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||
* into those specific section.
|
||||
* e.g
|
||||
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
||||
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
||||
*/
|
||||
#ifndef CFG_TUSB_MEM_SECTION
|
||||
#define CFG_TUSB_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// DEVICE CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_HID 1
|
||||
#define CFG_TUD_CDC 0
|
||||
#define CFG_TUD_MSC 0
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_EP_BUFSIZE 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
|
||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
||||
*
|
||||
* Auto ProductID layout's Bitmap:
|
||||
* [MSB] HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_desc_device_t const desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
uint8_t const *tud_descriptor_device_cb(void)
|
||||
{
|
||||
return (uint8_t const *) &desc_device;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HID Report Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Keyboard Report Descriptor Template
|
||||
#define TUD_HID_REPORT_DESC_DIAL(...) \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( 0x0e ) ,\
|
||||
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
|
||||
/* Report ID if any */\
|
||||
__VA_ARGS__ \
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DIGITIZER ) ,\
|
||||
HID_USAGE ( 0x21 ) ,\
|
||||
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
|
||||
HID_USAGE ( 1 ) ,\
|
||||
HID_REPORT_COUNT ( 1 ) ,\
|
||||
HID_REPORT_SIZE ( 1 ) ,\
|
||||
HID_LOGICAL_MIN ( 0 ) ,\
|
||||
HID_LOGICAL_MAX ( 1 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
|
||||
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
|
||||
HID_USAGE ( HID_USAGE_DESKTOP_DIAL ) ,\
|
||||
HID_REPORT_COUNT ( 1 ) ,\
|
||||
HID_REPORT_SIZE ( 15 ) ,\
|
||||
HID_UNIT_EXPONENT( 15 ) ,\
|
||||
HID_UNIT ( 0x14 ) ,\
|
||||
HID_PHYSICAL_MIN_N ( -3600, 2 ) ,\
|
||||
HID_PHYSICAL_MAX_N ( 3600, 2 ) ,\
|
||||
HID_LOGICAL_MIN_N ( -3600, 2 ) ,\
|
||||
HID_LOGICAL_MAX_N ( 3600, 2 ) ,\
|
||||
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE) ,\
|
||||
HID_COLLECTION_END ,\
|
||||
HID_COLLECTION_END \
|
||||
|
||||
uint8_t const desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_DIAL(HID_REPORT_ID(1))
|
||||
};
|
||||
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf)
|
||||
{
|
||||
if (itf == 0) {
|
||||
return desc_hid_report;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
enum {
|
||||
ITF_NUM_HID,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN )
|
||||
|
||||
#define EPNUM_HID 0x81
|
||||
|
||||
uint8_t const desc_configuration[] = {
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100),
|
||||
|
||||
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10),
|
||||
};
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
return desc_configuration;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// String Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// array of pointer to string descriptors
|
||||
char const *string_desc_arr [] = {
|
||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||
"TinyUSB", // 1: Manufacturer
|
||||
"TinyUSB Device", // 2: Product
|
||||
"123456", // 3: Serials, should use chip ID
|
||||
"Surface Dial", // 4: Interface 1 String
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
// Invoked when received GET STRING DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||
{
|
||||
(void) langid;
|
||||
|
||||
uint8_t chr_count;
|
||||
|
||||
if (index == 0) {
|
||||
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
||||
chr_count = 1;
|
||||
} else {
|
||||
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
|
||||
|
||||
if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *str = string_desc_arr[index];
|
||||
|
||||
// Cap at max char
|
||||
chr_count = (uint8_t) strlen(str);
|
||||
if (chr_count > 31) {
|
||||
chr_count = 31;
|
||||
}
|
||||
|
||||
// Convert ASCII string into UTF-16
|
||||
for (uint8_t i = 0; i < chr_count; i++) {
|
||||
_desc_str[1 + i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
|
||||
|
||||
return _desc_str;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESP32_S3_USB_OTG=y
|
||||
Reference in New Issue
Block a user