Merge branch 'master' into fork/atoktoto/midihost
# Conflicts: # src/host/usbh.c
This commit is contained in:
8
.idea/cmake.xml
generated
8
.idea/cmake.xml
generated
@@ -12,6 +12,8 @@
|
||||
<configuration PROFILE_NAME="feather_rp2040" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pico_sdk -DPICO_BOARD=adafruit_feather_rp2040 -DLOG=1" />
|
||||
<configuration PROFILE_NAME="feather_rp2040_max3421" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_rp2040_max3421 -DLOG=1" />
|
||||
<configuration PROFILE_NAME="metro_rp2040" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pico_sdk -DPICO_BOARD=adafruit_metro_rp2040 -DLOG=1 -DMAX3421_HOST=1" />
|
||||
<configuration PROFILE_NAME="adafruit_metro_rp2350" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=adafruit_metro_rp2350 -DLOG=1" />
|
||||
<configuration PROFILE_NAME="adafruit_fruit_jam" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=adafruit_fruit_jam -DLOG=1 -DCFLAGS_CLI="-DCFG_TUH_RPI_PIO_USB=1"" />
|
||||
<configuration PROFILE_NAME="adafruit_feather_esp32_v2" ENABLED="false" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=adafruit_feather_esp32_v2 -DMAX3421_HOST=1 -DLOG=1">
|
||||
<ADDITIONAL_GENERATION_ENVIRONMENT>
|
||||
<envs>
|
||||
@@ -80,14 +82,14 @@
|
||||
<configuration PROFILE_NAME="samd11_xplained" ENABLED="false" CONFIG_NAME="MinSizeRel" GENERATION_OPTIONS="-DBOARD=samd11_xplained" />
|
||||
<configuration PROFILE_NAME="atsaml21_xpro" ENABLED="false" GENERATION_OPTIONS="-DBOARD=atsaml21_xpro" />
|
||||
<configuration PROFILE_NAME="feather_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_m4_express -DLOG=1 -DLOGGER=RTT -DMAX3421_HOST=1" />
|
||||
<configuration PROFILE_NAME="metro_m4_express" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express -DLOG=1 -DLOGGER=RTT -DMAX3421_HOST=1" />
|
||||
<configuration PROFILE_NAME="metro_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express -DLOG=1 -DLOGGER=RTT -DMAX3421_HOST=1" />
|
||||
<configuration PROFILE_NAME="feather_m4_express-zephyr" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_m4_express -DLOG=1 -DMAX3421_HOST=1 -DRTOS=zephyr" />
|
||||
<configuration PROFILE_NAME="itsybitsy_m4" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=itsybitsy_m4" />
|
||||
<configuration PROFILE_NAME="same54_xplained" ENABLED="false" GENERATION_OPTIONS="-DBOARD=same54_xplained -DLOG=1 -DLOGGER=RTT" />
|
||||
<configuration PROFILE_NAME="samg55_xplained" ENABLED="false" GENERATION_OPTIONS="-DBOARD=samg55_xplained" />
|
||||
<configuration PROFILE_NAME="feather_nrf52840_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_nrf52840_express -DLOG=1 -DLOGGER=RTT -DMAX3421_HOST=1" />
|
||||
<configuration PROFILE_NAME="pca10056" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10056 -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1" />
|
||||
<configuration PROFILE_NAME="pca10056-zephyr" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10056 -DLOG=1 -DTRACE_ETM=1 -DRTOS=zephyr" BUILD_OPTIONS="-v" />
|
||||
<configuration PROFILE_NAME="pca10056" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10056 -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1" />
|
||||
<configuration PROFILE_NAME="pca10056-zephyr" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10056 -DLOG=1 -DTRACE_ETM=1 -DRTOS=zephyr" BUILD_OPTIONS="-v" />
|
||||
<configuration PROFILE_NAME="pca10095" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10095 -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1" />
|
||||
<configuration PROFILE_NAME="metro m7 1011 sd" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m7_1011_sd -DLOG=1 -DLOGGER=RTT -DTRACE_ETM=1" />
|
||||
<configuration PROFILE_NAME="metro_m7_1011" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m7_1011 -DLOG=1 -DLOGGER=RTT" />
|
||||
|
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -2,5 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/hw/mcu/raspberry_pi/Pico-PIO-USB" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@@ -39,18 +39,16 @@
|
||||
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
|
||||
|
||||
// Each HID instance can has multiple reports
|
||||
static struct
|
||||
{
|
||||
static struct {
|
||||
uint8_t report_count;
|
||||
tuh_hid_report_info_t report_info[MAX_REPORT];
|
||||
}hid_info[CFG_TUH_HID];
|
||||
} hid_info[CFG_TUH_HID];
|
||||
|
||||
static void process_kbd_report(hid_keyboard_report_t const *report);
|
||||
static void process_mouse_report(hid_mouse_report_t const * report);
|
||||
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||
|
||||
void hid_app_task(void)
|
||||
{
|
||||
void hid_app_task(void) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@@ -63,64 +61,57 @@ void hid_app_task(void)
|
||||
// can be used to parse common/simple enough descriptor.
|
||||
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
|
||||
// therefore report_desc = NULL, desc_len = 0
|
||||
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
|
||||
{
|
||||
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
|
||||
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
|
||||
|
||||
// Interface protocol (hid_interface_protocol_enum_t)
|
||||
const char* protocol_str[] = { "None", "Keyboard", "Mouse" };
|
||||
const char *protocol_str[] = {"None", "Keyboard", "Mouse"};
|
||||
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
||||
|
||||
printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]);
|
||||
|
||||
// By default host stack will use activate boot protocol on supported interface.
|
||||
// Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser)
|
||||
if ( itf_protocol == HID_ITF_PROTOCOL_NONE )
|
||||
{
|
||||
if (itf_protocol == HID_ITF_PROTOCOL_NONE) {
|
||||
hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len);
|
||||
printf("HID has %u reports \r\n", hid_info[instance].report_count);
|
||||
}
|
||||
|
||||
// request to receive report
|
||||
// tuh_hid_report_received_cb() will be invoked when report is available
|
||||
if ( !tuh_hid_receive_report(dev_addr, instance) )
|
||||
{
|
||||
if (!tuh_hid_receive_report(dev_addr, instance)) {
|
||||
printf("Error: cannot request to receive report\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when device with hid interface is un-mounted
|
||||
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
|
||||
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
|
||||
}
|
||||
|
||||
// Invoked when received report from device via interrupt endpoint
|
||||
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
|
||||
{
|
||||
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
|
||||
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
||||
|
||||
switch (itf_protocol)
|
||||
{
|
||||
switch (itf_protocol) {
|
||||
case HID_ITF_PROTOCOL_KEYBOARD:
|
||||
TU_LOG2("HID receive boot keyboard report\r\n");
|
||||
process_kbd_report( (hid_keyboard_report_t const*) report );
|
||||
break;
|
||||
process_kbd_report((hid_keyboard_report_t const *) report);
|
||||
break;
|
||||
|
||||
case HID_ITF_PROTOCOL_MOUSE:
|
||||
TU_LOG2("HID receive boot mouse report\r\n");
|
||||
process_mouse_report( (hid_mouse_report_t const*) report );
|
||||
break;
|
||||
process_mouse_report((hid_mouse_report_t const *) report);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Generic report requires matching ReportID and contents with previous parsed report info
|
||||
process_generic_report(dev_addr, instance, report, len);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
// continue to request to receive report
|
||||
if ( !tuh_hid_receive_report(dev_addr, instance) )
|
||||
{
|
||||
if (!tuh_hid_receive_report(dev_addr, instance)) {
|
||||
printf("Error: cannot request to receive report\r\n");
|
||||
}
|
||||
}
|
||||
@@ -231,29 +222,24 @@ static void process_mouse_report(hid_mouse_report_t const * report)
|
||||
//--------------------------------------------------------------------+
|
||||
// Generic Report
|
||||
//--------------------------------------------------------------------+
|
||||
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
|
||||
{
|
||||
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
|
||||
(void) dev_addr;
|
||||
(void) len;
|
||||
|
||||
uint8_t const rpt_count = hid_info[instance].report_count;
|
||||
tuh_hid_report_info_t* rpt_info_arr = hid_info[instance].report_info;
|
||||
tuh_hid_report_info_t* rpt_info = NULL;
|
||||
tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info;
|
||||
tuh_hid_report_info_t *rpt_info = NULL;
|
||||
|
||||
if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0)
|
||||
{
|
||||
if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) {
|
||||
// Simple report without report ID as 1st byte
|
||||
rpt_info = &rpt_info_arr[0];
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// Composite report, 1st byte is report ID, data starts from 2nd byte
|
||||
uint8_t const rpt_id = report[0];
|
||||
|
||||
// Find report id in the array
|
||||
for(uint8_t i=0; i<rpt_count; i++)
|
||||
{
|
||||
if (rpt_id == rpt_info_arr[i].report_id )
|
||||
{
|
||||
for (uint8_t i = 0; i < rpt_count; i++) {
|
||||
if (rpt_id == rpt_info_arr[i].report_id) {
|
||||
rpt_info = &rpt_info_arr[i];
|
||||
break;
|
||||
}
|
||||
@@ -263,8 +249,7 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c
|
||||
len--;
|
||||
}
|
||||
|
||||
if (!rpt_info)
|
||||
{
|
||||
if (!rpt_info) {
|
||||
printf("Couldn't find report info !\r\n");
|
||||
return;
|
||||
}
|
||||
@@ -276,23 +261,22 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c
|
||||
// - Consumer Control (Media Key) : Consumer, Consumer Control
|
||||
// - System Control (Power key) : Desktop, System Control
|
||||
// - Generic (vendor) : 0xFFxx, xx
|
||||
if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP )
|
||||
{
|
||||
switch (rpt_info->usage)
|
||||
{
|
||||
if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) {
|
||||
switch (rpt_info->usage) {
|
||||
case HID_USAGE_DESKTOP_KEYBOARD:
|
||||
TU_LOG1("HID receive keyboard report\r\n");
|
||||
// Assume keyboard follow boot report layout
|
||||
process_kbd_report( (hid_keyboard_report_t const*) report );
|
||||
break;
|
||||
process_kbd_report((hid_keyboard_report_t const *) report);
|
||||
break;
|
||||
|
||||
case HID_USAGE_DESKTOP_MOUSE:
|
||||
TU_LOG1("HID receive mouse report\r\n");
|
||||
// Assume mouse follow boot report layout
|
||||
process_mouse_report( (hid_mouse_report_t const*) report );
|
||||
break;
|
||||
process_mouse_report((hid_mouse_report_t const *) report);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -162,7 +162,6 @@ int board_getchar(void) {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
|
||||
|
||||
#include "esp_private/usb_phy.h"
|
||||
#include "soc/usb_pins.h"
|
||||
|
||||
static usb_phy_handle_t phy_hdl;
|
||||
|
||||
|
@@ -24,6 +24,11 @@
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
/* metadata:
|
||||
name: Adafruit Feather RP2040 with USB Type A Host
|
||||
url: https://www.adafruit.com/product/5723
|
||||
*/
|
||||
|
||||
#ifndef TUSB_BOARD_H
|
||||
#define TUSB_BOARD_H
|
||||
|
||||
|
@@ -24,6 +24,11 @@
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
/* metadata:
|
||||
name: Adafruit Fruit Jam - Mini RP2350
|
||||
url: https://www.adafruit.com/product/6200
|
||||
*/
|
||||
|
||||
#ifndef TUSB_BOARD_H
|
||||
#define TUSB_BOARD_H
|
||||
|
||||
|
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2025 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.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
#ifndef BOARDS_ADAFRUIT_METRO_RP2350_H
|
||||
#define BOARDS_ADAFRUIT_METRO_RP2350_H
|
||||
|
||||
// required for board that is not part of pico-sdk
|
||||
|
||||
// -----------------------------------------------------
|
||||
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
|
||||
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
|
||||
// -----------------------------------------------------
|
||||
|
||||
// pico_cmake_set PICO_PLATFORM=rp2350
|
||||
|
||||
// On some samples, the xosc can take longer to stabilize than is usual
|
||||
#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
|
||||
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
|
||||
#endif
|
||||
|
||||
// For board detection
|
||||
#define ADAFRUIT_METRO_RP2350
|
||||
|
||||
// --- RP2350 VARIANT ---
|
||||
#define PICO_RP2350A 0
|
||||
|
||||
// --- UART ---
|
||||
#ifndef PICO_DEFAULT_UART
|
||||
#define PICO_DEFAULT_UART 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||
#endif
|
||||
|
||||
// --- LED ---
|
||||
#ifndef PICO_DEFAULT_LED_PIN
|
||||
#define PICO_DEFAULT_LED_PIN 23
|
||||
#endif
|
||||
|
||||
#ifndef PICO_DEFAULT_WS2812_PIN
|
||||
#define PICO_DEFAULT_WS2812_PIN 25
|
||||
#endif
|
||||
|
||||
// --- I2C ---
|
||||
#ifndef PICO_DEFAULT_I2C
|
||||
#define PICO_DEFAULT_I2C 0
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||
#define PICO_DEFAULT_I2C_SDA_PIN 20
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||
#define PICO_DEFAULT_I2C_SCL_PIN 21
|
||||
#endif
|
||||
|
||||
// --- SPI ---
|
||||
#ifndef PICO_DEFAULT_SPI
|
||||
#define PICO_DEFAULT_SPI 1
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||
#define PICO_DEFAULT_SPI_SCK_PIN 30
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||
#define PICO_DEFAULT_SPI_TX_PIN 31
|
||||
#endif
|
||||
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||
#define PICO_DEFAULT_SPI_RX_PIN 28
|
||||
#endif
|
||||
|
||||
// --- FLASH ---
|
||||
|
||||
// FruitJam use w25q128 but sdk does not have .s for it, use q080 instead
|
||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||
|
||||
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||
#define PICO_FLASH_SPI_CLKDIV 2
|
||||
#endif
|
||||
|
||||
// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
|
||||
#ifndef PICO_FLASH_SIZE_BYTES
|
||||
#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
|
||||
#ifndef PICO_RP2350_A2_SUPPORTED
|
||||
#define PICO_RP2350_A2_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
#endif
|
4
hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake
Normal file
4
hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
set(PICO_PLATFORM rp2350-arm-s)
|
||||
set(PICO_BOARD adafruit_metro_rp2350)
|
||||
set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR})
|
||||
#set(OPENOCD_SERIAL E6614103E78E8324)
|
57
hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h
Normal file
57
hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2025 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.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
/* metadata:
|
||||
name: Adafruit Metro RP2350
|
||||
url: https://www.adafruit.com/product/6003
|
||||
*/
|
||||
|
||||
#ifndef TUSB_BOARD_H
|
||||
#define TUSB_BOARD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// UART and LED are already defined in pico-sdk board
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// PIO_USB
|
||||
//--------------------------------------------------------------------+
|
||||
// default to pico brain tester
|
||||
#define PICO_DEFAULT_PIO_USB_DP_PIN 32
|
||||
#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 29
|
||||
#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// USB Host MAX3421E
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
40
hw/bsp/rp2040/boards/pico_sdk/board.h
Normal file
40
hw/bsp/rp2040/boards/pico_sdk/board.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2025 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.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef TUSB_BOARD_H
|
||||
#define TUSB_BOARD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// UART and LED are already defined in pico-sdk board
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -26,7 +26,7 @@
|
||||
|
||||
/* metadata:
|
||||
name: Pico
|
||||
url: https://www.raspberrypi.org/products/raspberry-pi-pico/
|
||||
url: https://www.raspberrypi.com/products/raspberry-pi-pico/
|
||||
*/
|
||||
|
||||
#ifndef TUSB_BOARD_H
|
||||
|
@@ -26,7 +26,7 @@
|
||||
|
||||
/* metadata:
|
||||
name: Pico2
|
||||
url: https://www.raspberrypi.org/products/raspberry-pi-pico/
|
||||
url: https://www.raspberrypi.com/products/raspberry-pi-pico-2/
|
||||
*/
|
||||
|
||||
#ifndef TUSB_BOARD_H
|
||||
|
@@ -463,7 +463,7 @@ TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type
|
||||
uint16_t unicode_string[];
|
||||
uint16_t utf16le[];
|
||||
} tusb_desc_string_t;
|
||||
|
||||
// USB Binary Device Object Store (BOS)
|
||||
|
@@ -46,7 +46,7 @@ typedef struct {
|
||||
|
||||
// from hub descriptor
|
||||
uint8_t bNbrPorts;
|
||||
uint8_t bPwrOn2PwrGood; // port power on to good, in 2ms unit
|
||||
uint8_t bPwrOn2PwrGood_2ms; // port power on to good, in 2ms unit
|
||||
// uint16_t wHubCharacteristics;
|
||||
|
||||
hub_port_status_response_t port_status;
|
||||
@@ -279,7 +279,7 @@ static void config_set_port_power (tuh_xfer_t* xfer) {
|
||||
// only use number of ports in hub descriptor
|
||||
hub_desc_cs_t const* desc_hub = (hub_desc_cs_t const*) p_epbuf->ctrl_buf;
|
||||
p_hub->bNbrPorts = desc_hub->bNbrPorts;
|
||||
p_hub->bPwrOn2PwrGood = desc_hub->bPwrOn2PwrGood;
|
||||
p_hub->bPwrOn2PwrGood_2ms = desc_hub->bPwrOn2PwrGood;
|
||||
|
||||
// May need to GET_STATUS
|
||||
|
||||
@@ -301,7 +301,6 @@ static void config_port_power_complete (tuh_xfer_t* xfer) {
|
||||
TU_MESS_FAILED();
|
||||
TU_BREAKPOINT();
|
||||
}
|
||||
// delay bPwrOn2PwrGood * 2 ms before set configuration complete
|
||||
usbh_driver_set_config_complete(daddr, p_hub->itf_num);
|
||||
} else {
|
||||
// power next port
|
||||
|
@@ -1294,13 +1294,17 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu
|
||||
removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX);
|
||||
} else {
|
||||
// Invoke callback before closing driver (maybe call it later ?)
|
||||
if (tuh_umount_cb) tuh_umount_cb(daddr);
|
||||
if (tuh_umount_cb) {
|
||||
tuh_umount_cb(daddr);
|
||||
}
|
||||
}
|
||||
|
||||
// Close class driver
|
||||
for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
|
||||
usbh_class_driver_t const* driver = get_driver(drv_id);
|
||||
if (driver) driver->close(daddr);
|
||||
if (driver) {
|
||||
driver->close(daddr);
|
||||
}
|
||||
}
|
||||
|
||||
hcd_device_close(rhport, daddr);
|
||||
@@ -1357,8 +1361,11 @@ enum {
|
||||
ENUM_HUB_GET_STATUS_2,
|
||||
ENUM_HUB_CLEAR_RESET_2,
|
||||
ENUM_SET_ADDR,
|
||||
|
||||
ENUM_GET_DEVICE_DESC,
|
||||
ENUM_GET_STRING_LANGUAGE_ID,
|
||||
ENUM_GET_STRING_MANUFACTURER,
|
||||
ENUM_GET_STRING_PRODUCT,
|
||||
ENUM_GET_STRING_SERIAL,
|
||||
ENUM_GET_9BYTE_CONFIG_DESC,
|
||||
ENUM_GET_FULL_CONFIG_DESC,
|
||||
ENUM_SET_CONFIG,
|
||||
@@ -1371,25 +1378,25 @@ static void enum_full_complete(void);
|
||||
|
||||
// process device enumeration
|
||||
static void process_enumeration(tuh_xfer_t* xfer) {
|
||||
// Retry a few times with transfers in enumeration since device can be unstable when starting up
|
||||
enum {
|
||||
ATTEMPT_COUNT_MAX = 3,
|
||||
ATTEMPT_DELAY_MS = 100
|
||||
};
|
||||
// Retry a few times while enumerating since device can be unstable when starting up
|
||||
static uint8_t failed_count = 0;
|
||||
if (XFER_RESULT_FAILED == xfer->result) {
|
||||
enum {
|
||||
ATTEMPT_COUNT_MAX = 3,
|
||||
ATTEMPT_DELAY_MS = 100
|
||||
};
|
||||
|
||||
if (XFER_RESULT_SUCCESS != xfer->result) {
|
||||
// retry if not reaching max attempt
|
||||
failed_count++;
|
||||
bool retry = _dev0.enumerating && (failed_count < ATTEMPT_COUNT_MAX);
|
||||
if ( retry ) {
|
||||
failed_count++;
|
||||
if (retry) {
|
||||
tusb_time_delay_ms_api(ATTEMPT_DELAY_MS); // delay a bit
|
||||
TU_LOG1("Enumeration attempt %u\r\n", failed_count);
|
||||
TU_LOG1("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX);
|
||||
retry = tuh_control_xfer(xfer);
|
||||
}
|
||||
|
||||
if (!retry) {
|
||||
enum_full_complete();
|
||||
enum_full_complete(); // complete as failed
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1398,6 +1405,8 @@ static void process_enumeration(tuh_xfer_t* xfer) {
|
||||
|
||||
uint8_t const daddr = xfer->daddr;
|
||||
uintptr_t const state = xfer->user_data;
|
||||
usbh_device_t* dev = get_device(daddr);
|
||||
uint16_t langid = 0x0409; // default is English
|
||||
|
||||
switch (state) {
|
||||
#if CFG_TUH_HUB
|
||||
@@ -1488,7 +1497,6 @@ static void process_enumeration(tuh_xfer_t* xfer) {
|
||||
tusb_time_delay_ms_api(2);
|
||||
|
||||
const uint8_t new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue);
|
||||
|
||||
usbh_device_t* new_dev = get_device(new_addr);
|
||||
TU_ASSERT(new_dev,);
|
||||
new_dev->addressed = 1;
|
||||
@@ -1502,23 +1510,69 @@ static void process_enumeration(tuh_xfer_t* xfer) {
|
||||
// Get full device descriptor
|
||||
TU_LOG_USBH("Get Device Descriptor\r\n");
|
||||
TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t),
|
||||
process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC),);
|
||||
process_enumeration, ENUM_GET_STRING_LANGUAGE_ID),);
|
||||
break;
|
||||
}
|
||||
|
||||
case ENUM_GET_9BYTE_CONFIG_DESC: {
|
||||
tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;
|
||||
usbh_device_t* dev = get_device(daddr);
|
||||
case ENUM_GET_STRING_LANGUAGE_ID: {
|
||||
// save the received device descriptor
|
||||
TU_ASSERT(dev,);
|
||||
|
||||
tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;
|
||||
dev->vid = desc_device->idVendor;
|
||||
dev->pid = desc_device->idProduct;
|
||||
dev->i_manufacturer = desc_device->iManufacturer;
|
||||
dev->i_product = desc_device->iProduct;
|
||||
dev->i_serial = desc_device->iSerialNumber;
|
||||
|
||||
// tuh_descriptor_device_cb(daddr, (tusb_desc_device_t const*) _usbh_epbuf.ctrl);
|
||||
tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
|
||||
process_enumeration, ENUM_GET_STRING_MANUFACTURER);
|
||||
break;
|
||||
}
|
||||
|
||||
case ENUM_GET_STRING_MANUFACTURER: {
|
||||
TU_ASSERT(dev,);
|
||||
const tusb_desc_string_t* desc_langid = (tusb_desc_string_t const*) _usbh_epbuf.ctrl;
|
||||
if (desc_langid->bLength >= 4) {
|
||||
langid = tu_le16toh(desc_langid->utf16le[0]);
|
||||
}
|
||||
if (dev->i_manufacturer != 0) {
|
||||
tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
|
||||
process_enumeration, ENUM_GET_STRING_PRODUCT);
|
||||
break;
|
||||
} else {
|
||||
TU_ATTR_FALLTHROUGH;
|
||||
}
|
||||
}
|
||||
|
||||
case ENUM_GET_STRING_PRODUCT: {
|
||||
TU_ASSERT(dev,);
|
||||
if (state == ENUM_GET_STRING_PRODUCT) {
|
||||
langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet
|
||||
}
|
||||
if (dev->i_product != 0) {
|
||||
tuh_descriptor_get_string(daddr, dev->i_product, 0x0409, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
|
||||
process_enumeration, ENUM_GET_STRING_SERIAL);
|
||||
break;
|
||||
} else {
|
||||
TU_ATTR_FALLTHROUGH;
|
||||
}
|
||||
}
|
||||
|
||||
case ENUM_GET_STRING_SERIAL: {
|
||||
TU_ASSERT(dev,);
|
||||
if (state == ENUM_GET_STRING_SERIAL) {
|
||||
langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet
|
||||
}
|
||||
if (dev->i_serial != 0) {
|
||||
tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
|
||||
process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC);
|
||||
break;
|
||||
} else {
|
||||
TU_ATTR_FALLTHROUGH;
|
||||
}
|
||||
}
|
||||
|
||||
case ENUM_GET_9BYTE_CONFIG_DESC: {
|
||||
// Get 9-byte for total length
|
||||
uint8_t const config_idx = CONFIG_NUM - 1;
|
||||
TU_LOG_USBH("Get Configuration[0] Descriptor (9 bytes)\r\n");
|
||||
@@ -1553,7 +1607,6 @@ static void process_enumeration(tuh_xfer_t* xfer) {
|
||||
|
||||
case ENUM_CONFIG_DRIVER: {
|
||||
TU_LOG_USBH("Device configured\r\n");
|
||||
usbh_device_t* dev = get_device(daddr);
|
||||
TU_ASSERT(dev,);
|
||||
|
||||
dev->configured = 1;
|
||||
|
@@ -274,6 +274,13 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_
|
||||
bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
|
||||
tuh_xfer_cb_t complete_cb, uintptr_t user_data);
|
||||
|
||||
// Get language id string descriptor (control transfer)
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
bool tuh_descriptor_get_string_langid(uint8_t daddr, void* buffer, uint16_t len,
|
||||
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
|
||||
return tuh_descriptor_get_string(daddr, 0, 0, buffer, len, complete_cb, user_data);
|
||||
}
|
||||
|
||||
// Get manufacturer string descriptor (control transfer)
|
||||
// true on success, false if there is on-going control transfer or incorrect parameters
|
||||
bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
|
||||
@@ -313,6 +320,12 @@ uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8
|
||||
// return transfer result
|
||||
uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len);
|
||||
|
||||
// Sync (blocking) version of tuh_descriptor_get_string_langid()
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
uint8_t tuh_descriptor_get_string_langid_sync(uint8_t daddr, void* buffer, uint16_t len) {
|
||||
return tuh_descriptor_get_string_sync(daddr, 0, 0, buffer, len);
|
||||
}
|
||||
|
||||
// Sync (blocking) version of tuh_descriptor_get_manufacturer_string()
|
||||
// return transfer result
|
||||
uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len);
|
||||
|
@@ -459,28 +459,33 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport)
|
||||
}
|
||||
|
||||
// Close all opened endpoint belong to this device
|
||||
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
|
||||
{
|
||||
void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
|
||||
pico_trace("hcd_device_close %d\n", dev_addr);
|
||||
(void) rhport;
|
||||
|
||||
if (dev_addr == 0) return;
|
||||
// reset epx if it is currently active with unplugged device
|
||||
if (epx.configured && epx.active && epx.dev_addr == dev_addr) {
|
||||
epx.configured = false;
|
||||
*epx.endpoint_control = 0;
|
||||
*epx.buffer_control = 0;
|
||||
hw_endpoint_reset_transfer(&epx);
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++)
|
||||
{
|
||||
hw_endpoint_t* ep = &ep_pool[i];
|
||||
// dev0 only has ep0
|
||||
if (dev_addr != 0) {
|
||||
for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) {
|
||||
hw_endpoint_t *ep = &ep_pool[i];
|
||||
if (ep->dev_addr == dev_addr && ep->configured) {
|
||||
// in case it is an interrupt endpoint, disable it
|
||||
usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1));
|
||||
usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0;
|
||||
|
||||
if (ep->dev_addr == dev_addr && ep->configured)
|
||||
{
|
||||
// in case it is an interrupt endpoint, disable it
|
||||
usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1));
|
||||
usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0;
|
||||
|
||||
// unconfigure the endpoint
|
||||
ep->configured = false;
|
||||
*ep->endpoint_control = 0;
|
||||
*ep->buffer_control = 0;
|
||||
hw_endpoint_reset_transfer(ep);
|
||||
// unconfigure the endpoint
|
||||
ep->configured = false;
|
||||
*ep->endpoint_control = 0;
|
||||
*ep->buffer_control = 0;
|
||||
hw_endpoint_reset_transfer(ep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -557,7 +562,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
|
||||
}
|
||||
|
||||
// If a normal transfer (non-interrupt) then initiate using
|
||||
// sie ctrl registers. Otherwise interrupt ep registers should
|
||||
// sie ctrl registers. Otherwise, interrupt ep registers should
|
||||
// already be configured
|
||||
if ( ep == &epx )
|
||||
{
|
||||
@@ -597,13 +602,12 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
|
||||
(void) rhport;
|
||||
|
||||
// Copy data into setup packet buffer
|
||||
for ( uint8_t i = 0; i < 8; i++ )
|
||||
{
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
usbh_dpram->setup_packet[i] = setup_packet[i];
|
||||
}
|
||||
|
||||
// Configure EP0 struct with setup info for the trans complete
|
||||
struct hw_endpoint * ep = _hw_endpoint_allocate(0);
|
||||
struct hw_endpoint * ep = _hw_endpoint_allocate( (uint8_t) TUSB_XFER_CONTROL);
|
||||
TU_ASSERT(ep);
|
||||
|
||||
// EPX should be inactive
|
||||
|
@@ -110,7 +110,7 @@ void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoi
|
||||
*ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL;
|
||||
// 4.1.2.5.1 Con-current access: 12 cycles (should be good for 48*12Mhz = 576Mhz) after write to buffer control
|
||||
// Don't need delay in host mode as host is in charge
|
||||
if ( !is_host_mode()) {
|
||||
if (!is_host_mode()) {
|
||||
busy_wait_at_least_cycles(12);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user