Skip to content

Commit 23dcb76

Browse files
committed
Merge branch 'feat/hid_example_supports_p4' into 'master'
feat(usb_device): hid example supports esp32p4 See merge request ae_group/esp-iot-solution!1359
2 parents 3679276 + 2a88b3b commit 23dcb76

File tree

8 files changed

+112
-78
lines changed

8 files changed

+112
-78
lines changed

.gitlab/ci/build.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -851,9 +851,7 @@ build_example_usb_device_usb_hid_device:
851851
extends:
852852
- .build_examples_template
853853
- .rules:build:example_usb_device_usb_hid_device
854-
parallel:
855-
matrix:
856-
- IMAGE: espressif/idf:release-v5.0
854+
- .build_idf_version_greater_equal_v5_0
857855
variables:
858856
EXAMPLE_DIR: examples/usb/device/usb_hid_device
859857

examples/usb/device/usb_hid_device/README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## USB HID Device example
22

3-
This example demonstrates how to use ESP32-Sx USB function as the HID device. Buttons are used to trigger such signals as a keyboard or mouse.
3+
This example demonstrates how to use ESP32-S2/S3/P4 USB function as the HID device. Buttons are used to trigger such signals as a keyboard or mouse.
44

55
* Supports traditional six-key keyboard mode
66
* Supports full key no-conflict keyboard mode
@@ -9,17 +9,21 @@ This example demonstrates how to use ESP32-Sx USB function as the HID device. Bu
99

1010
### Hardware Required
1111

12-
- Any ESP32-S2 or ESP32-S3 development board with **buttons**
12+
- Any ESP32-S2/S3/P4 development board with **buttons**
1313

1414
- Hardware Connection:
15-
- GPIO19 to D
16-
- GPIO20 to D+
15+
16+
| | USB_DP | USB_DM |
17+
| ------------ | ------ | ------ |
18+
| ESP32-S2/S3 | GPIO20 | GPIO19 |
19+
| ESP32-P4 2.0 | pin 50 | pin 49 |
20+
| ESP32-P4 1.1 | GPIO27 | GPIO26 |
1721

1822
### Configure the project
1923

2024
By default the buttons act as a mouse, you can use `idf.py menuconfig` change `USB HID Device Demo->hid class subclass` to `keyboard`.
2125

22-
![](_static/choose_subclass.png)
26+
![](https://dl.espressif.com/AE/esp-iot-solution/usb_hid_device_choose_subclass.png)
2327

2428
### Build and Flash
2529

@@ -31,7 +35,7 @@ By default the buttons act as a mouse, you can use `idf.py menuconfig` change `U
3135
. $HOME/esp/esp-idf/export.sh
3236
```
3337

34-
3. Set ESP-IDF build target to `esp32s2` or `esp32s3`
38+
3. Set ESP-IDF build target to `esp32s2` or `esp32s3` or `esp32p4`
3539

3640
```bash
3741
idf.py set-target esp32s2
-9.15 KB
Binary file not shown.

examples/usb/device/usb_hid_device/hid_device/tusb_config.h

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,10 @@
3232
extern "C" {
3333
#endif
3434

35-
//--------------------------------------------------------------------+
36-
// Board Specific Configuration
37-
//--------------------------------------------------------------------+
38-
39-
// RHPort number used for device can be defined by board.mk, default to port 0
40-
#ifndef BOARD_TUD_RHPORT
41-
#define BOARD_TUD_RHPORT 0
42-
#endif
43-
44-
// RHPort max operational speed can defined by board.mk
45-
#ifndef BOARD_TUD_MAX_SPEED
46-
#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
35+
#ifdef CONFIG_TINYUSB_RHPORT_HS
36+
# define CFG_TUSB_RHPORT1_MODE OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED
37+
#else
38+
# define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED
4739
#endif
4840

4941
//--------------------------------------------------------------------
@@ -64,7 +56,7 @@ extern "C" {
6456
#endif
6557

6658
// Espressif IDF requires "freertos/" prefix in include path
67-
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
59+
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4)
6860
#define CFG_TUSB_OS_INC_PATH freertos/
6961
#endif
7062

@@ -75,9 +67,6 @@ extern "C" {
7567
// Enable Device stack
7668
#define CFG_TUD_ENABLED 1
7769

78-
// Default is max speed that hardware controller could support with on-chip PHY
79-
#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED
80-
8170
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
8271
* Tinyusb use follows macros to declare transferring memory so that they can be put
8372
* into those specific section.

examples/usb/device/usb_hid_device/hid_device/usb_descriptors.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,21 +92,67 @@ uint8_t const *tud_descriptor_device_cb(void)
9292
//--------------------------------------------------------------------+
9393
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN * CFG_TUD_HID)
9494

95-
uint8_t const desc_fs_configuration[] = {
95+
uint8_t const desc_configuration[] = {
9696
// Config number, interface count, string index, total length, attribute, power in mA
9797
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 100),
9898
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
9999
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 4, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), (0x80 | EPNUM_HID_DATA), CFG_TUD_HID_EP_BUFSIZE, 10)
100100
};
101101

102+
#if TUD_OPT_HIGH_SPEED
103+
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
104+
105+
// other speed configuration
106+
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
107+
108+
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
109+
tusb_desc_device_qualifier_t const desc_device_qualifier = {
110+
.bLength = sizeof(tusb_desc_device_qualifier_t),
111+
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
112+
.bcdUSB = 0x0200,
113+
114+
.bDeviceClass = TUSB_CLASS_MISC,
115+
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
116+
.bDeviceProtocol = MISC_PROTOCOL_IAD,
117+
118+
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
119+
.bNumConfigurations = 0x01,
120+
.bReserved = 0x00
121+
};
122+
123+
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
124+
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
125+
// device_qualifier descriptor describes information about a high-speed capable device that would
126+
// change if the device were operating at the other speed. If not highspeed capable stall this request.
127+
uint8_t const* tud_descriptor_device_qualifier_cb(void)
128+
{
129+
return (uint8_t const*) &desc_device_qualifier;
130+
}
131+
132+
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
133+
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
134+
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
135+
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
136+
{
137+
(void) index; // for multiple configurations
138+
139+
// other speed config is basically configuration with type = OHER_SPEED_CONFIG
140+
memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN);
141+
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
142+
143+
// this example use the same configuration for both high and full speed mode
144+
return desc_other_speed_config;
145+
}
146+
#endif
147+
102148
// Invoked when received GET CONFIGURATION DESCRIPTOR
103149
// Application return pointer to descriptor
104150
// Descriptor contents must exist long enough for transfer to complete
105151
uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
106152
{
107153
(void) index; // for multiple configurations
108154

109-
return desc_fs_configuration;
155+
return desc_configuration;
110156
}
111157

112158
//--------------------------------------------------------------------+

examples/usb/device/usb_hid_device/main/Kconfig.projbuild

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ menu "USB HID Device Example"
4444
string "Product Name"
4545
default "HID Demo"
4646

47+
choice TINYUSB_RHPORT
48+
prompt "TinyUSB Root Port"
49+
default TINYUSB_RHPORT_HS if IDF_TARGET_ESP32P4
50+
default TINYUSB_RHPORT_FS
51+
help
52+
Allows set the USB PHY Controller for TinyUSB: HS (USB OTG2.0 PHY for HighSpeed)
53+
54+
config TINYUSB_RHPORT_HS
55+
depends on IDF_TARGET_ESP32P4
56+
bool "High Speed"
57+
58+
config TINYUSB_RHPORT_FS
59+
bool "Full Speed"
60+
endchoice
61+
4762
config ENABLE_FULL_KEY_KEYBOARD
4863
bool "Enable Full Key Keyboard"
4964
default n
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
dependencies:
22
idf: ">=5.0"
33
espressif/button:
4-
version: "~2.5.0"
4+
version: "^4.0.0"
55
espressif/tinyusb:
6-
version: ">=0.15.0~2"
6+
version: ">=0.18.0~1"
77
espressif/esp32_s3_usb_otg:
8-
version: "^1.5.1"
8+
version: "^2.0.0"
99
rules:
1010
- if: "target in [esp32s3]"

examples/usb/device/usb_hid_device/main/usb_hid_device_main.c

Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
1+
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
22
*
33
* SPDX-License-Identifier: Apache-2.0
44
*/
@@ -9,6 +9,7 @@
99
#include "esp_log.h"
1010
#include "sdkconfig.h"
1111
#include "iot_button.h"
12+
#include "button_gpio.h"
1213
#include "esp_private/usb_phy.h"
1314
#include "tinyusb_hid.h"
1415
#ifdef CONFIG_ESP32_S3_USB_OTG
@@ -31,16 +32,6 @@
3132
static int s_button_gpio[EXAMPLE_BUTTON_NUM] = {EXAMPLE_BUTTON_UP, EXAMPLE_BUTTON_DOWN, EXAMPLE_BUTTON_LEFT, EXAMPLE_BUTTON_RIGHT};
3233
static button_handle_t s_button_handles[EXAMPLE_BUTTON_NUM] = {NULL};
3334

34-
static int get_button_gpio(button_handle_t btn_hdl)
35-
{
36-
for (size_t i = 0; i < EXAMPLE_BUTTON_NUM; i++) {
37-
if (s_button_handles[i] == btn_hdl) {
38-
return s_button_gpio[i];
39-
}
40-
}
41-
return -1;
42-
}
43-
4435
#ifdef CONFIG_SUBCLASS_KEYBOARD
4536
#if CONFIG_ENABLE_FULL_KEY_KEYBOARD
4637
static uint8_t keycode[15] = {0};
@@ -93,10 +84,12 @@ static bool remove_key(uint8_t key)
9384
return false;
9485
}
9586
#endif
96-
static void button_keyboard_cb(void *arg, void *arg2)
87+
static void button_keyboard_cb(void *arg, void *data)
9788
{
98-
button_handle_t button_hdl = (button_handle_t)arg;
99-
int button_gpio = get_button_gpio(button_hdl);
89+
int button_gpio = (int)data;
90+
button_event_t event = iot_button_get_event(arg);
91+
ESP_LOGI(TAG, "Button GPIO %d event %d", button_gpio, event);
92+
10093
uint8_t key = 0;
10194
switch (button_gpio) {
10295
case EXAMPLE_BUTTON_UP:
@@ -119,7 +112,7 @@ static void button_keyboard_cb(void *arg, void *arg2)
119112
break;
120113
}
121114

122-
if (iot_button_get_event(button_hdl) == BUTTON_PRESS_UP) {
115+
if (event == BUTTON_PRESS_UP) {
123116
remove_key(key);
124117
ESP_LOGI(TAG, "Remove Keyboard %c", key - HID_KEY_A + 'a');
125118
} else {
@@ -129,10 +122,11 @@ static void button_keyboard_cb(void *arg, void *arg2)
129122
tinyusb_hid_keyboard_report(0, keycode);
130123
}
131124
#elif defined CONFIG_SUBCLASS_MOUSE
132-
static void button_mouse_cb(void *arg, void *arg2)
125+
static void button_mouse_cb(void *arg, void *data)
133126
{
134-
button_handle_t button_hdl = (button_handle_t)arg;
135-
int button_gpio = get_button_gpio(button_hdl);
127+
int button_gpio = (int)data;
128+
ESP_LOGI(TAG, "Button GPIO %d", button_gpio);
129+
136130
int mouse_offset_x = 0, mouse_offset_y = 0;
137131
switch (button_gpio) {
138132
case EXAMPLE_BUTTON_UP:
@@ -208,6 +202,9 @@ static void usb_phy_init(void)
208202
.controller = USB_PHY_CTRL_OTG,
209203
.otg_mode = USB_OTG_MODE_DEVICE,
210204
.target = USB_PHY_TARGET_INT,
205+
#if CONFIG_TINYUSB_RHPORT_HS
206+
.otg_speed = USB_PHY_SPEED_HIGH,
207+
#endif
211208
};
212209
usb_new_phy(&phy_conf, &phy_hdl);
213210
}
@@ -219,46 +216,31 @@ void app_main(void)
219216
#endif
220217
// switch esp usb phy to usb-otg
221218
usb_phy_init();
222-
tud_init(BOARD_TUD_RHPORT);
219+
bool usb_init = tusb_init();
220+
if (!usb_init) {
221+
ESP_LOGE(TAG, "TinyUSB init failed");
222+
return;
223+
}
224+
223225
xTaskCreate(tusb_device_task, "TinyUSB", 4096, NULL, 5, NULL);
224226
tinyusb_hid_init();
225227

226228
/* buttons init, buttons used to simulate keyboard or mouse events */
227-
button_config_t cfg = {
228-
.type = BUTTON_TYPE_GPIO,
229-
.gpio_button_config = {
230-
.active_level = 0,
231-
},
229+
button_config_t btn_cfg = {0};
230+
button_gpio_config_t btn_gpio_cfg = {
231+
.active_level = 0,
232232
};
233233

234234
for (size_t i = 0; i < EXAMPLE_BUTTON_NUM; i++) {
235-
cfg.gpio_button_config.gpio_num = s_button_gpio[i];
236-
s_button_handles[i] = iot_button_create(&cfg);
237-
if (s_button_handles[i] == NULL) {
238-
ESP_LOGE(TAG, "Button io = %d created failed", s_button_gpio[i]);
239-
assert(0);
240-
} else {
241-
ESP_LOGI(TAG, "Button io = %d created", s_button_gpio[i]);
242-
}
243-
}
244-
245-
#ifdef CONFIG_SUBCLASS_KEYBOARD
246-
button_cb_t button_cb = button_keyboard_cb;
247-
ESP_LOGI(TAG, "HID Keyboard demo: press button to simulate keyboard");
248-
#elif defined CONFIG_SUBCLASS_MOUSE
249-
button_cb_t button_cb = button_mouse_cb;
250-
ESP_LOGI(TAG, "HID Mouse demo: press button to simulate mouse");
251-
#endif
252-
ESP_LOGI(TAG, "Wait Mount through USB interface");
253-
254-
/* register button callback, send HID report when click button */
255-
for (size_t i = 0; i < EXAMPLE_BUTTON_NUM; i++) {
235+
btn_gpio_cfg.gpio_num = s_button_gpio[i];
236+
ESP_ERROR_CHECK(iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &s_button_handles[i]));
256237
#ifdef CONFIG_SUBCLASS_KEYBOARD
257-
iot_button_register_cb(s_button_handles[i], BUTTON_PRESS_DOWN, button_cb, NULL);
258-
iot_button_register_cb(s_button_handles[i], BUTTON_PRESS_UP, button_cb, NULL);
238+
ESP_ERROR_CHECK(iot_button_register_cb(s_button_handles[i], BUTTON_PRESS_UP, NULL, button_keyboard_cb, (void*)s_button_gpio[i]));
239+
ESP_ERROR_CHECK(iot_button_register_cb(s_button_handles[i], BUTTON_PRESS_DOWN, NULL, button_keyboard_cb, (void*)s_button_gpio[i]));
259240
#elif defined CONFIG_SUBCLASS_MOUSE
260-
iot_button_register_cb(s_button_handles[i], BUTTON_SINGLE_CLICK, button_cb, NULL);
241+
ESP_ERROR_CHECK(iot_button_register_cb(s_button_handles[i], BUTTON_SINGLE_CLICK, NULL, button_mouse_cb, (void*)s_button_gpio[i]));
261242
#endif
243+
ESP_LOGI(TAG, "Button io = %d created", s_button_gpio[i]);
262244
}
263245

264246
while (1) {

0 commit comments

Comments
 (0)