Merge branch 'master' into fork/atoktoto/midihost
# Conflicts: # hw/bsp/rp2040/family.cmake # src/class/midi/midi.h # src/class/midi/midi_device.c # src/device/usbd_control.c # src/host/hcd.h # src/host/usbh.c # src/host/usbh.h
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
|
||||
|
||||
project(tinyusb_host_examples)
|
||||
project(tinyusb_host_examples C CXX ASM)
|
||||
family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# family_add_subdirectory will filter what to actually add based on selected FAMILY
|
||||
family_add_subdirectory(bare_api)
|
||||
family_add_subdirectory(cdc_msc_hid)
|
||||
family_add_subdirectory(cdc_msc_hid_freertos)
|
||||
family_add_subdirectory(device_info)
|
||||
family_add_subdirectory(hid_controller)
|
||||
family_add_subdirectory(midi_rx)
|
||||
family_add_subdirectory(msc_file_explorer)
|
||||
|
@@ -1,15 +1,20 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
|
||||
|
||||
# gets PROJECT name for the example
|
||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
project(${PROJECT})
|
||||
project(${PROJECT} C CXX ASM)
|
||||
|
||||
# Checks this example is valid for the family and initializes the project
|
||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Espressif has its own cmake build system
|
||||
if(FAMILY STREQUAL "espressif")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
@@ -22,9 +27,6 @@ target_include_directories(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
# Configure compilation flags and libraries for the example... see the corresponding function
|
||||
# in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT})
|
||||
|
||||
# For rp2040, un-comment to enable pico-pio-usb
|
||||
# family_add_pico_pio_usb(${PROJECT})
|
||||
# Configure compilation flags and libraries for the example without RTOS.
|
||||
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT} noos)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
include ../../../tools/top.mk
|
||||
include ../../make.mk
|
||||
include ../../build_system/make/make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
@@ -11,14 +10,4 @@ EXAMPLE_SOURCE += \
|
||||
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
# TinyUSB Host Stack source
|
||||
SRC_C += \
|
||||
src/class/cdc/cdc_host.c \
|
||||
src/class/hid/hid_host.c \
|
||||
src/class/msc/msc_host.c \
|
||||
src/host/hub.c \
|
||||
src/host/usbh.c \
|
||||
src/portable/ohci/ohci.c \
|
||||
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
|
||||
|
||||
include ../../rules.mk
|
||||
include ../../build_system/make/rules.mk
|
||||
|
@@ -1,11 +1,17 @@
|
||||
mcu:KINETIS_KL
|
||||
mcu:LPC175X_6X
|
||||
mcu:LPC177X_8X
|
||||
mcu:LPC18XX
|
||||
mcu:LPC40XX
|
||||
mcu:LPC43XX
|
||||
mcu:MIMXRT
|
||||
mcu:MIMXRT1XXX
|
||||
mcu:MIMXRT10XX
|
||||
mcu:MIMXRT11XX
|
||||
mcu:RP2040
|
||||
mcu:MSP432E4
|
||||
mcu:RX65X
|
||||
mcu:RAXXX
|
||||
mcu:MAX3421
|
||||
mcu:STM32F4
|
||||
mcu:STM32F7
|
||||
mcu:STM32H7
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -23,17 +23,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* This example current worked and tested with following controller
|
||||
* - Sony DualShock 4 [CUH-ZCT2x] VID = 0x054c, PID = 0x09cc
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
#include "class/hid/hid.h"
|
||||
|
||||
// English
|
||||
#define LANGUAGE_ID 0x0409
|
||||
@@ -65,7 +62,15 @@ int main(void)
|
||||
printf("TinyUSB Bare API Example\r\n");
|
||||
|
||||
// init host stack on configured roothub port
|
||||
tuh_init(BOARD_TUH_RHPORT);
|
||||
tusb_rhport_init_t host_init = {
|
||||
.role = TUSB_ROLE_HOST,
|
||||
.speed = TUSB_SPEED_AUTO
|
||||
};
|
||||
tusb_init(BOARD_TUH_RHPORT, &host_init);
|
||||
|
||||
if (board_init_after_tusb) {
|
||||
board_init_after_tusb();
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -410,10 +415,11 @@ static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
|
||||
}
|
||||
|
||||
static void print_utf16(uint16_t *temp_buf, size_t buf_len) {
|
||||
if ((temp_buf[0] & 0xff) == 0) return; // empty
|
||||
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
|
||||
size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
|
||||
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
|
||||
((uint8_t*) temp_buf)[utf8_len] = '\0';
|
||||
|
||||
printf((char*)temp_buf);
|
||||
printf("%s", (char*)temp_buf);
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -23,29 +23,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_CONFIG_H_
|
||||
#define _TUSB_CONFIG_H_
|
||||
#ifndef TUSB_CONFIG_H_
|
||||
#define TUSB_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board Specific Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COMMON CONFIGURATION
|
||||
// Common Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by compiler flags for flexibility
|
||||
@@ -61,12 +47,6 @@
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_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.
|
||||
@@ -74,16 +54,48 @@
|
||||
* - 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
|
||||
#ifndef CFG_TUH_MEM_SECTION
|
||||
#define CFG_TUH_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#ifndef CFG_TUH_MEM_ALIGN
|
||||
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// CONFIGURATION
|
||||
// Host Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RP2040
|
||||
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
|
||||
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
|
||||
|
||||
// host roothub port is 1 if using either pio-usb or max3421
|
||||
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
|
||||
#define BOARD_TUH_RHPORT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
|
||||
|
||||
//------------------------- Board Specific --------------------------
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Driver Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Size of buffer to hold descriptors and other data used for enumeration
|
||||
@@ -94,7 +106,7 @@
|
||||
|
||||
// max device support (excluding hub device)
|
||||
// 1 hub typically has 4 ports
|
||||
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1)
|
||||
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
|
||||
|
||||
// Max endpoint per device
|
||||
#define CFG_TUH_ENDPOINT_MAX 8
|
||||
@@ -106,4 +118,4 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
||||
#endif
|
||||
|
@@ -1,44 +1,35 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
|
||||
|
||||
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
|
||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
project(${PROJECT})
|
||||
project(${PROJECT} C CXX ASM)
|
||||
|
||||
# Checks this example is valid for the family and initializes the project
|
||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Espressif has its own cmake build system
|
||||
if(FAMILY STREQUAL "espressif")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
target_sources(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
|
||||
)
|
||||
|
||||
# Example include
|
||||
target_include_directories(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
# Configure compilation flags and libraries for the example... see the corresponding function
|
||||
# in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT})
|
||||
|
||||
# For rp2040, un-comment to enable pico-pio-usb
|
||||
family_add_pico_pio_usb(${PROJECT})
|
||||
|
||||
# due to warnings from Pico-PIO-USB
|
||||
target_compile_options(${PROJECT} PUBLIC
|
||||
-Wno-error=shadow
|
||||
-Wno-error=cast-align
|
||||
-Wno-error=cast-qual
|
||||
-Wno-error=redundant-decls
|
||||
-Wno-error=sign-conversion
|
||||
-Wno-error=conversion
|
||||
-Wno-error=sign-compare
|
||||
-Wno-error=unused-function
|
||||
)
|
||||
# Configure compilation flags and libraries for the example without RTOS.
|
||||
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT} noos)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
include ../../../tools/top.mk
|
||||
include ../../make.mk
|
||||
include ../../build_system/make/make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
@@ -7,20 +6,11 @@ INC += \
|
||||
|
||||
# Example source
|
||||
EXAMPLE_SOURCE = \
|
||||
src/hid_app.c \
|
||||
src/cdc_app.c \
|
||||
src/hid_app.c \
|
||||
src/main.c \
|
||||
src/msc_app.c \
|
||||
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
# TinyUSB Host Stack source
|
||||
SRC_C += \
|
||||
src/class/cdc/cdc_host.c \
|
||||
src/class/hid/hid_host.c \
|
||||
src/class/msc/msc_host.c \
|
||||
src/host/hub.c \
|
||||
src/host/usbh.c \
|
||||
src/portable/ohci/ohci.c \
|
||||
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
|
||||
|
||||
include ../../rules.mk
|
||||
include ../../build_system/make/rules.mk
|
||||
|
@@ -1,11 +1,17 @@
|
||||
mcu:KINETIS_KL
|
||||
mcu:LPC175X_6X
|
||||
mcu:LPC177X_8X
|
||||
mcu:LPC18XX
|
||||
mcu:LPC40XX
|
||||
mcu:LPC43XX
|
||||
mcu:MIMXRT
|
||||
mcu:MIMXRT1XXX
|
||||
mcu:MIMXRT10XX
|
||||
mcu:MIMXRT11XX
|
||||
mcu:RP2040
|
||||
mcu:MSP432E4
|
||||
mcu:RX65X
|
||||
mcu:RAXXX
|
||||
mcu:MAX3421
|
||||
mcu:STM32F4
|
||||
mcu:STM32F7
|
||||
mcu:STM32H7
|
||||
|
109
examples/host/cdc_msc_hid/src/cdc_app.c
Normal file
109
examples/host/cdc_msc_hid/src/cdc_app.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, 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.
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
#include "bsp/board_api.h"
|
||||
|
||||
size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
|
||||
size_t count = 0;
|
||||
while (count < bufsize) {
|
||||
int ch = board_getchar();
|
||||
if (ch <= 0) break;
|
||||
|
||||
buf[count] = (uint8_t) ch;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void cdc_app_task(void) {
|
||||
uint8_t buf[64 + 1]; // +1 for extra null character
|
||||
uint32_t const bufsize = sizeof(buf) - 1;
|
||||
|
||||
uint32_t count = get_console_inputs(buf, bufsize);
|
||||
buf[count] = 0;
|
||||
|
||||
// loop over all mounted interfaces
|
||||
for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
|
||||
if (tuh_cdc_mounted(idx)) {
|
||||
// console --> cdc interfaces
|
||||
if (count) {
|
||||
tuh_cdc_write(idx, buf, count);
|
||||
tuh_cdc_write_flush(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when received new data
|
||||
void tuh_cdc_rx_cb(uint8_t idx) {
|
||||
uint8_t buf[64 + 1]; // +1 for extra null character
|
||||
uint32_t const bufsize = sizeof(buf) - 1;
|
||||
|
||||
// forward cdc interfaces -> console
|
||||
uint32_t count = tuh_cdc_read(idx, buf, bufsize);
|
||||
buf[count] = 0;
|
||||
|
||||
printf("%s", (char*) buf);
|
||||
}
|
||||
|
||||
// Invoked when a device with CDC interface is mounted
|
||||
// idx is index of cdc interface in the internal pool.
|
||||
void tuh_cdc_mount_cb(uint8_t idx) {
|
||||
tuh_itf_info_t itf_info = {0};
|
||||
tuh_cdc_itf_get_info(idx, &itf_info);
|
||||
|
||||
printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
|
||||
itf_info.desc.bInterfaceNumber);
|
||||
|
||||
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
// If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack
|
||||
// while eneumerating new cdc device
|
||||
cdc_line_coding_t line_coding = {0};
|
||||
if (tuh_cdc_get_local_line_coding(idx, &line_coding)) {
|
||||
printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
|
||||
printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
|
||||
}
|
||||
#else
|
||||
// Set Line Coding upon mounted
|
||||
cdc_line_coding_t new_line_coding = { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 };
|
||||
tuh_cdc_set_line_coding(idx, &new_line_coding, NULL, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Invoked when a device with CDC interface is unmounted
|
||||
void tuh_cdc_umount_cb(uint8_t idx) {
|
||||
tuh_itf_info_t itf_info = {0};
|
||||
tuh_cdc_itf_get_info(idx, &itf_info);
|
||||
|
||||
printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
|
||||
itf_info.desc.bInterfaceNumber);
|
||||
}
|
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -130,13 +130,12 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// look up new key in previous keys
|
||||
static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode)
|
||||
{
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
{
|
||||
if (report->keycode[i] == keycode) return true;
|
||||
static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) {
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (report->keycode[i] == keycode) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -160,7 +159,9 @@ static void process_kbd_report(hid_keyboard_report_t const *report)
|
||||
putchar(ch);
|
||||
if ( ch == '\r' ) putchar('\n'); // added new line for enter key
|
||||
|
||||
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
|
||||
fflush(stdout); // flush right away, else nanolib will wait for newline
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// TODO example skips key released
|
||||
@@ -233,6 +234,7 @@ 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) 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;
|
||||
@@ -247,7 +249,7 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c
|
||||
// Composite report, 1st byte is report ID, data starts from 2nd byte
|
||||
uint8_t const rpt_id = report[0];
|
||||
|
||||
// Find report id in the arrray
|
||||
// Find report id in the array
|
||||
for(uint8_t i=0; i<rpt_count; i++)
|
||||
{
|
||||
if (rpt_id == rpt_info_arr[i].report_id )
|
||||
@@ -263,7 +265,7 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c
|
||||
|
||||
if (!rpt_info)
|
||||
{
|
||||
printf("Couldn't find the report info for this report !\r\n");
|
||||
printf("Couldn't find report info !\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -27,75 +27,65 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void);
|
||||
|
||||
extern void cdc_task(void);
|
||||
extern void cdc_app_task(void);
|
||||
extern void hid_app_task(void);
|
||||
|
||||
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
|
||||
// API to read/rite MAX3421's register. Implemented by TinyUSB
|
||||
extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
|
||||
extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
|
||||
#endif
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void)
|
||||
{
|
||||
int main(void) {
|
||||
board_init();
|
||||
|
||||
printf("TinyUSB Host CDC MSC HID Example\r\n");
|
||||
|
||||
// init host stack on configured roothub port
|
||||
tuh_init(BOARD_TUH_RHPORT);
|
||||
tusb_rhport_init_t host_init = {
|
||||
.role = TUSB_ROLE_HOST,
|
||||
.speed = TUSB_SPEED_AUTO
|
||||
};
|
||||
tusb_init(BOARD_TUH_RHPORT, &host_init);
|
||||
|
||||
while (1)
|
||||
{
|
||||
// tinyusb host task
|
||||
tuh_task();
|
||||
led_blinking_task();
|
||||
|
||||
cdc_task();
|
||||
hid_app_task();
|
||||
if (board_init_after_tusb) {
|
||||
board_init_after_tusb();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
|
||||
// FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
|
||||
enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
|
||||
tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB CDC
|
||||
//--------------------------------------------------------------------+
|
||||
CFG_TUSB_MEM_SECTION static char serial_in_buffer[64] = { 0 };
|
||||
|
||||
// invoked ISR context
|
||||
void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes)
|
||||
{
|
||||
(void) event;
|
||||
(void) pipe_id;
|
||||
(void) xferred_bytes;
|
||||
|
||||
printf(serial_in_buffer);
|
||||
tu_memclr(serial_in_buffer, sizeof(serial_in_buffer));
|
||||
|
||||
tuh_cdc_receive(dev_addr, serial_in_buffer, sizeof(serial_in_buffer), true); // waiting for next data
|
||||
}
|
||||
|
||||
void cdc_task(void)
|
||||
{
|
||||
while (1) {
|
||||
// tinyusb host task
|
||||
tuh_task();
|
||||
|
||||
led_blinking_task();
|
||||
cdc_app_task();
|
||||
hid_app_task();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void tuh_mount_cb(uint8_t dev_addr)
|
||||
{
|
||||
void tuh_mount_cb(uint8_t dev_addr) {
|
||||
// application set-up
|
||||
printf("A device with address %d is mounted\r\n", dev_addr);
|
||||
}
|
||||
|
||||
void tuh_umount_cb(uint8_t dev_addr)
|
||||
{
|
||||
void tuh_umount_cb(uint8_t dev_addr) {
|
||||
// application tear-down
|
||||
printf("A device with address %d is unmounted \r\n", dev_addr);
|
||||
}
|
||||
@@ -104,15 +94,14 @@ void tuh_umount_cb(uint8_t dev_addr)
|
||||
//--------------------------------------------------------------------+
|
||||
// Blinking Task
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void)
|
||||
{
|
||||
void led_blinking_task(void) {
|
||||
const uint32_t interval_ms = 1000;
|
||||
static uint32_t start_ms = 0;
|
||||
|
||||
static bool led_state = false;
|
||||
|
||||
// Blink every interval ms
|
||||
if ( board_millis() - start_ms < interval_ms) return; // not enough time
|
||||
if (board_millis() - start_ms < interval_ms) return; // not enough time
|
||||
start_ms += interval_ms;
|
||||
|
||||
board_led_write(led_state);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -30,8 +30,11 @@
|
||||
//--------------------------------------------------------------------+
|
||||
static scsi_inquiry_resp_t inquiry_resp;
|
||||
|
||||
bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
|
||||
bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data)
|
||||
{
|
||||
msc_cbw_t const* cbw = cb_data->cbw;
|
||||
msc_csw_t const* csw = cb_data->csw;
|
||||
|
||||
if (csw->status != 0)
|
||||
{
|
||||
printf("Inquiry failed\r\n");
|
||||
@@ -45,8 +48,8 @@ bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const
|
||||
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
|
||||
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
|
||||
|
||||
printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size));
|
||||
printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
|
||||
printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024*1024)/block_size));
|
||||
printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -57,47 +60,11 @@ void tuh_msc_mount_cb(uint8_t dev_addr)
|
||||
printf("A MassStorage device is mounted\r\n");
|
||||
|
||||
uint8_t const lun = 0;
|
||||
tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb);
|
||||
//
|
||||
// //------------- file system (only 1 LUN support) -------------//
|
||||
// uint8_t phy_disk = dev_addr-1;
|
||||
// disk_initialize(phy_disk);
|
||||
//
|
||||
// if ( disk_is_ready(phy_disk) )
|
||||
// {
|
||||
// if ( f_mount(phy_disk, &fatfs[phy_disk]) != FR_OK )
|
||||
// {
|
||||
// puts("mount failed");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// f_chdrive(phy_disk); // change to newly mounted drive
|
||||
// f_chdir("/"); // root as current dir
|
||||
//
|
||||
// cli_init();
|
||||
// }
|
||||
tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb, 0);
|
||||
}
|
||||
|
||||
void tuh_msc_umount_cb(uint8_t dev_addr)
|
||||
{
|
||||
(void) dev_addr;
|
||||
printf("A MassStorage device is unmounted\r\n");
|
||||
|
||||
// uint8_t phy_disk = dev_addr-1;
|
||||
//
|
||||
// f_mount(phy_disk, NULL); // unmount disk
|
||||
// disk_deinitialize(phy_disk);
|
||||
//
|
||||
// if ( phy_disk == f_get_current_drive() )
|
||||
// { // active drive is unplugged --> change to other drive
|
||||
// for(uint8_t i=0; i<CFG_TUH_DEVICE_MAX; i++)
|
||||
// {
|
||||
// if ( disk_is_ready(i) )
|
||||
// {
|
||||
// f_chdrive(i);
|
||||
// cli_init(); // refractor, rename
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -30,28 +30,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board Specific Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RP2040
|
||||
// change to 1 if using pico-pio-usb as host controller for raspberry rp2040
|
||||
#define CFG_TUH_RPI_PIO_USB 0
|
||||
#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB
|
||||
#endif
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COMMON CONFIGURATION
|
||||
// Common Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by compiler flags for flexibility
|
||||
@@ -67,12 +47,6 @@
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_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.
|
||||
@@ -80,34 +54,80 @@
|
||||
* - 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
|
||||
#ifndef CFG_TUH_MEM_SECTION
|
||||
#define CFG_TUH_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#ifndef CFG_TUH_MEM_ALIGN
|
||||
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// CONFIGURATION
|
||||
// Host Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RP2040
|
||||
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
|
||||
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
|
||||
|
||||
// host roothub port is 1 if using either pio-usb or max3421
|
||||
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
|
||||
#define BOARD_TUH_RHPORT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
|
||||
|
||||
//------------------------- Board Specific --------------------------
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Driver Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Size of buffer to hold descriptors and other data used for enumeration
|
||||
#define CFG_TUH_ENUMERATION_BUFSIZE 256
|
||||
|
||||
#define CFG_TUH_HUB 1 // number of supported hubs
|
||||
#define CFG_TUH_CDC 1
|
||||
#define CFG_TUH_HID 4 // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_CDC 1 // CDC ACM
|
||||
#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_MSC 1
|
||||
#define CFG_TUH_VENDOR 0
|
||||
|
||||
// max device support (excluding hub device)
|
||||
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
|
||||
// max device support (excluding hub device): 1 hub typically has 4 ports
|
||||
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
|
||||
|
||||
//------------- HID -------------//
|
||||
#define CFG_TUH_HID_EPIN_BUFSIZE 64
|
||||
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
|
||||
|
||||
//------------- CDC -------------//
|
||||
|
||||
// Set Line Control state on enumeration/mounted:
|
||||
// DTR ( bit 0), RTS (bit 1)
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03
|
||||
|
||||
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
|
||||
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
|
||||
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
35
examples/host/cdc_msc_hid_freertos/CMakeLists.txt
Normal file
35
examples/host/cdc_msc_hid_freertos/CMakeLists.txt
Normal file
@@ -0,0 +1,35 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
|
||||
|
||||
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
|
||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
project(${PROJECT} C CXX ASM)
|
||||
|
||||
# Checks this example is valid for the family and initializes the project
|
||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Espressif has its own cmake build system
|
||||
if(FAMILY STREQUAL "espressif")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
target_sources(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
|
||||
)
|
||||
|
||||
# Example include
|
||||
target_include_directories(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
# Configure compilation flags and libraries for the example without RTOS.
|
||||
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT} freertos)
|
17
examples/host/cdc_msc_hid_freertos/Makefile
Normal file
17
examples/host/cdc_msc_hid_freertos/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
RTOS = freertos
|
||||
include ../../build_system/make/make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
$(TOP)/hw \
|
||||
|
||||
# Example source
|
||||
EXAMPLE_SOURCE = \
|
||||
src/cdc_app.c \
|
||||
src/hid_app.c \
|
||||
src/main.c \
|
||||
src/msc_app.c \
|
||||
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
include ../../build_system/make/rules.mk
|
15
examples/host/cdc_msc_hid_freertos/only.txt
Normal file
15
examples/host/cdc_msc_hid_freertos/only.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
mcu:ESP32P4
|
||||
mcu:LPC175X_6X
|
||||
mcu:LPC177X_8X
|
||||
mcu:LPC18XX
|
||||
mcu:LPC40XX
|
||||
mcu:LPC43XX
|
||||
mcu:MIMXRT1XXX
|
||||
mcu:MIMXRT10XX
|
||||
mcu:MIMXRT11XX
|
||||
mcu:MSP432E4
|
||||
mcu:RX65X
|
||||
mcu:MAX3421
|
||||
mcu:STM32F4
|
||||
mcu:STM32F7
|
||||
mcu:STM32H7
|
1
examples/host/cdc_msc_hid_freertos/skip.txt
Normal file
1
examples/host/cdc_msc_hid_freertos/skip.txt
Normal file
@@ -0,0 +1 @@
|
||||
mcu:RP2040
|
6
examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt
Normal file
6
examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# This file is for ESP-IDF only
|
||||
idf_component_register(SRCS "cdc_app.c" "hid_app.c" "main.c" "msc_app.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES boards tinyusb_src)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format)
|
131
examples/host/cdc_msc_hid_freertos/src/cdc_app.c
Normal file
131
examples/host/cdc_msc_hid_freertos/src/cdc_app.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, 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.
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
#include "bsp/board_api.h"
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#define CDC_STACK_SZIE 2048
|
||||
#else
|
||||
#define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2)
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
StackType_t cdc_stack[CDC_STACK_SZIE];
|
||||
StaticTask_t cdc_taskdef;
|
||||
#endif
|
||||
|
||||
static void cdc_app_task(void* param);
|
||||
|
||||
void cdc_app_init(void) {
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef);
|
||||
#else
|
||||
xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// helper
|
||||
size_t get_console_inputs(uint8_t *buf, size_t bufsize) {
|
||||
size_t count = 0;
|
||||
while (count < bufsize) {
|
||||
int ch = board_getchar();
|
||||
if (ch <= 0) break;
|
||||
|
||||
buf[count] = (uint8_t) ch;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void cdc_app_task(void* param) {
|
||||
(void) param;
|
||||
|
||||
uint8_t buf[64 + 1]; // +1 for extra null character
|
||||
uint32_t const bufsize = sizeof(buf) - 1;
|
||||
|
||||
while (1) {
|
||||
uint32_t count = get_console_inputs(buf, bufsize);
|
||||
buf[count] = 0;
|
||||
|
||||
if (count) {
|
||||
// loop over all mounted interfaces
|
||||
for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
|
||||
if (tuh_cdc_mounted(idx)) {
|
||||
// console --> cdc interfaces
|
||||
tuh_cdc_write(idx, buf, count);
|
||||
tuh_cdc_write_flush(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when received new data
|
||||
void tuh_cdc_rx_cb(uint8_t idx) {
|
||||
uint8_t buf[64 + 1]; // +1 for extra null character
|
||||
uint32_t const bufsize = sizeof(buf) - 1;
|
||||
|
||||
// forward cdc interfaces -> console
|
||||
uint32_t count = tuh_cdc_read(idx, buf, bufsize);
|
||||
buf[count] = 0;
|
||||
|
||||
printf("%s", (char *) buf);
|
||||
}
|
||||
|
||||
void tuh_cdc_mount_cb(uint8_t idx) {
|
||||
tuh_itf_info_t itf_info = { 0 };
|
||||
tuh_cdc_itf_get_info(idx, &itf_info);
|
||||
|
||||
printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber);
|
||||
|
||||
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
// CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration
|
||||
// otherwise you need to call tuh_cdc_set_line_coding() first
|
||||
cdc_line_coding_t line_coding = { 0 };
|
||||
if (tuh_cdc_get_local_line_coding(idx, &line_coding)) {
|
||||
printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
|
||||
printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void tuh_cdc_umount_cb(uint8_t idx) {
|
||||
tuh_itf_info_t itf_info = { 0 };
|
||||
tuh_cdc_itf_get_info(idx, &itf_info);
|
||||
|
||||
printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber);
|
||||
}
|
267
examples/host/cdc_msc_hid_freertos/src/hid_app.c
Normal file
267
examples/host/cdc_msc_hid_freertos/src/hid_app.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021, 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 "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// If your host terminal support ansi escape code such as TeraTerm
|
||||
// it can be use to simulate mouse cursor movement within terminal
|
||||
#define USE_ANSI_ESCAPE 0
|
||||
|
||||
#define MAX_REPORT 4
|
||||
|
||||
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
|
||||
|
||||
// Each HID instance can has multiple reports
|
||||
static struct {
|
||||
uint8_t report_count;
|
||||
tuh_hid_report_info_t report_info[MAX_REPORT];
|
||||
} 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_init(void) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when device with hid interface is mounted
|
||||
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
|
||||
// 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) {
|
||||
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" };
|
||||
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) {
|
||||
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)) {
|
||||
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) {
|
||||
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) {
|
||||
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
||||
|
||||
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;
|
||||
|
||||
case HID_ITF_PROTOCOL_MOUSE:
|
||||
TU_LOG2("HID receive boot mouse report\r\n");
|
||||
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;
|
||||
}
|
||||
|
||||
// continue to request to receive report
|
||||
if (!tuh_hid_receive_report(dev_addr, instance)) {
|
||||
printf("Error: cannot request to receive report\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Keyboard
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// look up new key in previous keys
|
||||
static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) {
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (report->keycode[i] == keycode) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void process_kbd_report(hid_keyboard_report_t const *report) {
|
||||
static hid_keyboard_report_t prev_report = { 0, 0, { 0 } }; // previous report to check key released
|
||||
|
||||
//------------- example code ignore control (non-printable) key affects -------------//
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (report->keycode[i]) {
|
||||
if (find_key_in_report(&prev_report, report->keycode[i])) {
|
||||
// exist in previous report means the current key is holding
|
||||
} else {
|
||||
// not existed in previous report means the current key is pressed
|
||||
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
|
||||
uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
|
||||
putchar(ch);
|
||||
if (ch == '\r') putchar('\n'); // added new line for enter key
|
||||
|
||||
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
|
||||
fflush(stdout); // flush right away, else nanolib will wait for newline
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// TODO example skips key released
|
||||
}
|
||||
|
||||
prev_report = *report;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Mouse
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void cursor_movement(int8_t x, int8_t y, int8_t wheel) {
|
||||
#if USE_ANSI_ESCAPE
|
||||
// Move X using ansi escape
|
||||
if ( x < 0) {
|
||||
printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left
|
||||
}else if ( x > 0) {
|
||||
printf(ANSI_CURSOR_FORWARD(%d), x); // move right
|
||||
}
|
||||
|
||||
// Move Y using ansi escape
|
||||
if ( y < 0) {
|
||||
printf(ANSI_CURSOR_UP(%d), (-y)); // move up
|
||||
}else if ( y > 0) {
|
||||
printf(ANSI_CURSOR_DOWN(%d), y); // move down
|
||||
}
|
||||
|
||||
// Scroll using ansi escape
|
||||
if (wheel < 0) {
|
||||
printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up
|
||||
}else if (wheel > 0) {
|
||||
printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down
|
||||
}
|
||||
|
||||
printf("\r\n");
|
||||
#else
|
||||
printf("(%d %d %d)\r\n", x, y, wheel);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void process_mouse_report(hid_mouse_report_t const *report) {
|
||||
static hid_mouse_report_t prev_report = { 0 };
|
||||
|
||||
//------------- button state -------------//
|
||||
uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
|
||||
if (button_changed_mask & report->buttons) {
|
||||
printf(" %c%c%c ",
|
||||
report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
|
||||
report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
|
||||
report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
|
||||
}
|
||||
|
||||
//------------- cursor movement -------------//
|
||||
cursor_movement(report->x, report->y, report->wheel);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Generic Report
|
||||
//--------------------------------------------------------------------+
|
||||
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
|
||||
(void) dev_addr;
|
||||
|
||||
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;
|
||||
|
||||
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 {
|
||||
// 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) {
|
||||
rpt_info = &rpt_info_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
report++;
|
||||
len--;
|
||||
}
|
||||
|
||||
if (!rpt_info) {
|
||||
printf("Couldn't find report info !\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples:
|
||||
// - Keyboard : Desktop, Keyboard
|
||||
// - Mouse : Desktop, Mouse
|
||||
// - Gamepad : Desktop, Gamepad
|
||||
// - 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) {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
171
examples/host/cdc_msc_hid_freertos/src/main.c
Normal file
171
examples/host/cdc_msc_hid_freertos/src/main.c
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#define USBH_STACK_SIZE 4096
|
||||
#else
|
||||
// Increase stack size when debug log is enabled
|
||||
#define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTOTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
/* Blink pattern
|
||||
* - 250 ms : device not mounted
|
||||
* - 1000 ms : device mounted
|
||||
* - 2500 ms : device is suspended
|
||||
*/
|
||||
enum {
|
||||
BLINK_NOT_MOUNTED = 250,
|
||||
BLINK_MOUNTED = 1000,
|
||||
BLINK_SUSPENDED = 2500,
|
||||
};
|
||||
|
||||
// static timer & task
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
StaticTimer_t blinky_tmdef;
|
||||
|
||||
StackType_t usb_host_stack[USBH_STACK_SIZE];
|
||||
StaticTask_t usb_host_taskdef;
|
||||
#endif
|
||||
|
||||
TimerHandle_t blinky_tm;
|
||||
|
||||
static void led_blinky_cb(TimerHandle_t xTimer);
|
||||
static void usb_host_task(void* param);
|
||||
|
||||
extern void cdc_app_init(void);
|
||||
extern void hid_app_init(void);
|
||||
extern void msc_app_init(void);
|
||||
|
||||
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
|
||||
// API to read/rite MAX3421's register. Implemented by TinyUSB
|
||||
extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
|
||||
extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
|
||||
#endif
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void) {
|
||||
board_init();
|
||||
|
||||
printf("TinyUSB Host CDC MSC HID with FreeRTOS Example\r\n");
|
||||
|
||||
// Create soft timer for blinky, task for tinyusb stack
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef);
|
||||
xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef);
|
||||
#else
|
||||
blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb);
|
||||
xTaskCreate(usb_host_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL);
|
||||
#endif
|
||||
|
||||
xTimerStart(blinky_tm, 0);
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
#endif
|
||||
|
||||
// USB Host task
|
||||
// This top level thread process all usb events and invoke callbacks
|
||||
static void usb_host_task(void *param) {
|
||||
(void) param;
|
||||
|
||||
// init host stack on configured roothub port
|
||||
tusb_rhport_init_t host_init = {
|
||||
.role = TUSB_ROLE_HOST,
|
||||
.speed = TUSB_SPEED_AUTO
|
||||
};
|
||||
|
||||
if (!tusb_init(BOARD_TUH_RHPORT, &host_init)) {
|
||||
printf("Failed to init USB Host Stack\r\n");
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
if (board_init_after_tusb) {
|
||||
board_init_after_tusb();
|
||||
}
|
||||
|
||||
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
|
||||
// FeatherWing MAX3421E use MAX3421E's GPIO0 for VBUS enable
|
||||
enum { IOPINS1_ADDR = 20u << 3, /* 0xA0 */ };
|
||||
tuh_max3421_reg_write(BOARD_TUH_RHPORT, IOPINS1_ADDR, 0x01, false);
|
||||
#endif
|
||||
|
||||
cdc_app_init();
|
||||
hid_app_init();
|
||||
msc_app_init();
|
||||
|
||||
// RTOS forever loop
|
||||
while (1) {
|
||||
// put this thread to waiting state until there is new events
|
||||
tuh_task();
|
||||
|
||||
// following code only run if tuh_task() process at least 1 event
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void tuh_mount_cb(uint8_t dev_addr) {
|
||||
// application set-up
|
||||
printf("A device with address %d is mounted\r\n", dev_addr);
|
||||
}
|
||||
|
||||
void tuh_umount_cb(uint8_t dev_addr) {
|
||||
// application tear-down
|
||||
printf("A device with address %d is unmounted \r\n", dev_addr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// BLINKING TASK
|
||||
//--------------------------------------------------------------------+
|
||||
static void led_blinky_cb(TimerHandle_t xTimer) {
|
||||
(void) xTimer;
|
||||
static bool led_state = false;
|
||||
|
||||
board_led_write(led_state);
|
||||
led_state = 1 - led_state; // toggle
|
||||
}
|
70
examples/host/cdc_msc_hid_freertos/src/msc_app.c
Normal file
70
examples/host/cdc_msc_hid_freertos/src/msc_app.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
// define the buffer to be place in USB/DMA memory with correct alignment/cache line size
|
||||
CFG_TUH_MEM_SECTION static struct {
|
||||
TUH_EPBUF_TYPE_DEF(scsi_inquiry_resp_t, inquiry);
|
||||
} scsi_resp;
|
||||
|
||||
void msc_app_init(void) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) {
|
||||
msc_cbw_t const *cbw = cb_data->cbw;
|
||||
msc_csw_t const *csw = cb_data->csw;
|
||||
|
||||
if (csw->status != 0) {
|
||||
printf("Inquiry failed\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Print out Vendor ID, Product ID and Rev
|
||||
printf("%.8s %.16s rev %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id, scsi_resp.inquiry.product_rev);
|
||||
|
||||
// Get capacity of device
|
||||
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
|
||||
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
|
||||
|
||||
printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024 * 1024) / block_size));
|
||||
printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------- IMPLEMENTATION -------------//
|
||||
void tuh_msc_mount_cb(uint8_t dev_addr) {
|
||||
printf("A MassStorage device is mounted\r\n");
|
||||
|
||||
uint8_t const lun = 0;
|
||||
tuh_msc_inquiry(dev_addr, lun, &scsi_resp.inquiry, inquiry_complete_cb, 0);
|
||||
}
|
||||
|
||||
void tuh_msc_umount_cb(uint8_t dev_addr) {
|
||||
(void) dev_addr;
|
||||
printf("A MassStorage device is unmounted\r\n");
|
||||
}
|
140
examples/host/cdc_msc_hid_freertos/src/tusb_config.h
Normal file
140
examples/host/cdc_msc_hid_freertos/src/tusb_config.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Common Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by compiler flags for flexibility
|
||||
#ifndef CFG_TUSB_MCU
|
||||
#error CFG_TUSB_MCU must be defined
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_OS
|
||||
#define CFG_TUSB_OS OPT_OS_FREERTOS
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_DEBUG
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* 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_TUH_MEM_SECTION
|
||||
#define CFG_TUH_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUH_MEM_ALIGN
|
||||
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Host Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RP2040
|
||||
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
|
||||
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
|
||||
|
||||
// host roothub port is 1 if using either pio-usb or max3421
|
||||
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
|
||||
#define BOARD_TUH_RHPORT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
|
||||
|
||||
//------------------------- Board Specific --------------------------
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Driver Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Size of buffer to hold descriptors and other data used for enumeration
|
||||
#define CFG_TUH_ENUMERATION_BUFSIZE 256
|
||||
|
||||
#define CFG_TUH_HUB 1 // number of supported hubs
|
||||
#define CFG_TUH_CDC 1 // CDC ACM
|
||||
#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_MSC 1
|
||||
#define CFG_TUH_VENDOR 0
|
||||
|
||||
// max device support (excluding hub device): 1 hub typically has 4 ports
|
||||
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
|
||||
|
||||
//------------- HID -------------//
|
||||
#define CFG_TUH_HID_EPIN_BUFSIZE 64
|
||||
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
|
||||
|
||||
//------------- CDC -------------//
|
||||
|
||||
// Set Line Control state on enumeration/mounted:
|
||||
// DTR ( bit 0), RTS (bit 1)
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03
|
||||
|
||||
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
|
||||
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
|
||||
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
32
examples/host/device_info/CMakeLists.txt
Normal file
32
examples/host/device_info/CMakeLists.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
|
||||
|
||||
# gets PROJECT name for the example
|
||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
project(${PROJECT} C CXX ASM)
|
||||
|
||||
# Checks this example is valid for the family and initializes the project
|
||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Espressif has its own cmake build system
|
||||
if(FAMILY STREQUAL "espressif")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
target_sources(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
)
|
||||
|
||||
# Example include
|
||||
target_include_directories(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
# Configure compilation flags and libraries for the example without RTOS.
|
||||
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT} noos)
|
13
examples/host/device_info/Makefile
Normal file
13
examples/host/device_info/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
include ../../build_system/make/make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
$(TOP)/hw \
|
||||
|
||||
# Example source
|
||||
EXAMPLE_SOURCE += \
|
||||
src/main.c
|
||||
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
include ../../build_system/make/rules.mk
|
20
examples/host/device_info/only.txt
Normal file
20
examples/host/device_info/only.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
mcu:ESP32S2
|
||||
mcu:ESP32S3
|
||||
mcu:ESP32P4
|
||||
mcu:KINETIS_KL
|
||||
mcu:LPC175X_6X
|
||||
mcu:LPC177X_8X
|
||||
mcu:LPC18XX
|
||||
mcu:LPC40XX
|
||||
mcu:LPC43XX
|
||||
mcu:MAX3421
|
||||
mcu:MIMXRT1XXX
|
||||
mcu:MIMXRT10XX
|
||||
mcu:MIMXRT11XX
|
||||
mcu:MSP432E4
|
||||
mcu:RP2040
|
||||
mcu:RX65X
|
||||
mcu:RAXXX
|
||||
mcu:STM32F4
|
||||
mcu:STM32F7
|
||||
mcu:STM32H7
|
4
examples/host/device_info/src/CMakeLists.txt
Normal file
4
examples/host/device_info/src/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# This file is for ESP-IDF only
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES boards tinyusb_src)
|
308
examples/host/device_info/src/main.c
Normal file
308
examples/host/device_info/src/main.c
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Host example will get device descriptors of attached devices and print it out via uart/rtt (logger) as follows:
|
||||
* Device 1: ID 046d:c52f SN 11223344
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 0200
|
||||
bDeviceClass 0
|
||||
bDeviceSubClass 0
|
||||
bDeviceProtocol 0
|
||||
bMaxPacketSize0 8
|
||||
idVendor 0x046d
|
||||
idProduct 0xc52f
|
||||
bcdDevice 2200
|
||||
iManufacturer 1 Logitech
|
||||
iProduct 2 USB Receiver
|
||||
iSerialNumber 0
|
||||
bNumConfigurations 1
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
// English
|
||||
#define LANGUAGE_ID 0x0409
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
enum {
|
||||
BLINK_NOT_MOUNTED = 250,
|
||||
BLINK_MOUNTED = 1000,
|
||||
BLINK_SUSPENDED = 2500,
|
||||
};
|
||||
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
|
||||
// Declare for buffer for usb transfer, may need to be in USB/DMA section and
|
||||
// multiple of dcache line size if dcache is enabled (for some ports).
|
||||
CFG_TUH_MEM_SECTION struct {
|
||||
TUH_EPBUF_TYPE_DEF(tusb_desc_device_t, device);
|
||||
TUH_EPBUF_DEF(serial, 64*sizeof(uint16_t));
|
||||
TUH_EPBUF_DEF(buf, 128*sizeof(uint16_t));
|
||||
} desc;
|
||||
|
||||
void led_blinking_task(void* param);
|
||||
static void print_utf16(uint16_t* temp_buf, size_t buf_len);
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
void init_freertos_task(void);
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Main
|
||||
//--------------------------------------------------------------------
|
||||
void init_tinyusb(void) {
|
||||
// init host stack on configured roothub port
|
||||
tusb_rhport_init_t host_init = {
|
||||
.role = TUSB_ROLE_HOST,
|
||||
.speed = TUSB_SPEED_AUTO
|
||||
};
|
||||
tusb_init(BOARD_TUH_RHPORT, &host_init);
|
||||
|
||||
if (board_init_after_tusb) {
|
||||
board_init_after_tusb();
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
board_init();
|
||||
printf("TinyUSB Device Info Example\r\n");
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
init_freertos_task();
|
||||
#else
|
||||
init_tinyusb();
|
||||
while (1) {
|
||||
tuh_task(); // tinyusb host task
|
||||
led_blinking_task(NULL);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*------------- TinyUSB Callbacks -------------*/
|
||||
|
||||
// Invoked when device is mounted (configured)
|
||||
void tuh_mount_cb(uint8_t daddr) {
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
|
||||
// Get Device Descriptor
|
||||
uint8_t xfer_result = tuh_descriptor_get_device_sync(daddr, &desc.device, 18);
|
||||
if (XFER_RESULT_SUCCESS != xfer_result) {
|
||||
printf("Failed to get device descriptor\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Device %u: ID %04x:%04x SN ", daddr, desc.device.idVendor, desc.device.idProduct);
|
||||
xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, desc.serial, sizeof(desc.serial));
|
||||
if (XFER_RESULT_SUCCESS != xfer_result) {
|
||||
uint16_t* serial = (uint16_t*)(uintptr_t) desc.serial;
|
||||
serial[0] = 'n';
|
||||
serial[1] = '/';
|
||||
serial[2] = 'a';
|
||||
serial[3] = 0;
|
||||
}
|
||||
print_utf16((uint16_t*)(uintptr_t) desc.serial, sizeof(desc.serial)/2);
|
||||
printf("\r\n");
|
||||
|
||||
printf("Device Descriptor:\r\n");
|
||||
printf(" bLength %u\r\n", desc.device.bLength);
|
||||
printf(" bDescriptorType %u\r\n", desc.device.bDescriptorType);
|
||||
printf(" bcdUSB %04x\r\n", desc.device.bcdUSB);
|
||||
printf(" bDeviceClass %u\r\n", desc.device.bDeviceClass);
|
||||
printf(" bDeviceSubClass %u\r\n", desc.device.bDeviceSubClass);
|
||||
printf(" bDeviceProtocol %u\r\n", desc.device.bDeviceProtocol);
|
||||
printf(" bMaxPacketSize0 %u\r\n", desc.device.bMaxPacketSize0);
|
||||
printf(" idVendor 0x%04x\r\n", desc.device.idVendor);
|
||||
printf(" idProduct 0x%04x\r\n", desc.device.idProduct);
|
||||
printf(" bcdDevice %04x\r\n", desc.device.bcdDevice);
|
||||
|
||||
// Get String descriptor using Sync API
|
||||
|
||||
printf(" iManufacturer %u ", desc.device.iManufacturer);
|
||||
xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf));
|
||||
if (XFER_RESULT_SUCCESS == xfer_result) {
|
||||
print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
printf(" iProduct %u ", desc.device.iProduct);
|
||||
xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf));
|
||||
if (XFER_RESULT_SUCCESS == xfer_result) {
|
||||
print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
printf(" iSerialNumber %u ", desc.device.iSerialNumber);
|
||||
printf((char*)desc.serial); // serial is already to UTF-8
|
||||
printf("\r\n");
|
||||
|
||||
printf(" bNumConfigurations %u\r\n", desc.device.bNumConfigurations);
|
||||
}
|
||||
|
||||
// Invoked when device is unmounted (bus reset/unplugged)
|
||||
void tuh_umount_cb(uint8_t daddr) {
|
||||
blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
printf("Device removed, address = %d\r\n", daddr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// String Descriptor Helper
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static void _convert_utf16le_to_utf8(const uint16_t* utf16, size_t utf16_len, uint8_t* utf8, size_t utf8_len) {
|
||||
// TODO: Check for runover.
|
||||
(void) utf8_len;
|
||||
// Get the UTF-16 length out of the data itself.
|
||||
|
||||
for (size_t i = 0; i < utf16_len; i++) {
|
||||
uint16_t chr = utf16[i];
|
||||
if (chr < 0x80) {
|
||||
*utf8++ = chr & 0xffu;
|
||||
} else if (chr < 0x800) {
|
||||
*utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
|
||||
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
|
||||
} else {
|
||||
// TODO: Verify surrogate.
|
||||
*utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
|
||||
*utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
|
||||
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
|
||||
}
|
||||
// TODO: Handle UTF-16 code points that take two entries.
|
||||
}
|
||||
}
|
||||
|
||||
// Count how many bytes a utf-16-le encoded string will take in utf-8.
|
||||
static int _count_utf8_bytes(const uint16_t* buf, size_t len) {
|
||||
size_t total_bytes = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
uint16_t chr = buf[i];
|
||||
if (chr < 0x80) {
|
||||
total_bytes += 1;
|
||||
} else if (chr < 0x800) {
|
||||
total_bytes += 2;
|
||||
} else {
|
||||
total_bytes += 3;
|
||||
}
|
||||
// TODO: Handle UTF-16 code points that take two entries.
|
||||
}
|
||||
return (int) total_bytes;
|
||||
}
|
||||
|
||||
static void print_utf16(uint16_t* temp_buf, size_t buf_len) {
|
||||
if ((temp_buf[0] & 0xff) == 0) return; // empty
|
||||
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
|
||||
size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
|
||||
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t*) temp_buf, sizeof(uint16_t) * buf_len);
|
||||
((uint8_t*) temp_buf)[utf8_len] = '\0';
|
||||
|
||||
printf("%s", (char*) temp_buf);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Blinking Task
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void* param) {
|
||||
(void) param;
|
||||
static uint32_t start_ms = 0;
|
||||
static bool led_state = false;
|
||||
|
||||
while (1) {
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS);
|
||||
#else
|
||||
if (board_millis() - start_ms < blink_interval_ms) {
|
||||
return; // not enough time
|
||||
}
|
||||
#endif
|
||||
|
||||
start_ms += blink_interval_ms;
|
||||
board_led_write(led_state);
|
||||
led_state = 1 - led_state; // toggle
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// FreeRTOS
|
||||
//--------------------------------------------------------------------+
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
|
||||
#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#define USB_STACK_SIZE 4096
|
||||
#else
|
||||
// Increase stack size when debug log is enabled
|
||||
#define USB_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
|
||||
#endif
|
||||
|
||||
|
||||
// static task
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
StackType_t blinky_stack[BLINKY_STACK_SIZE];
|
||||
StaticTask_t blinky_taskdef;
|
||||
|
||||
StackType_t usb_stack[USB_STACK_SIZE];
|
||||
StaticTask_t usb_taskdef;
|
||||
#endif
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
#endif
|
||||
|
||||
void usb_host_task(void *param) {
|
||||
(void) param;
|
||||
init_tinyusb();
|
||||
while (1) {
|
||||
tuh_task();
|
||||
}
|
||||
}
|
||||
|
||||
void init_freertos_task(void) {
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef);
|
||||
xTaskCreateStatic(usb_host_task, "usbh", USB_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_stack, &usb_taskdef);
|
||||
#else
|
||||
xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL);
|
||||
xTaskCreate(usb_host_task, "usbh", USB_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||
#endif
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
120
examples/host/device_info/src/tusb_config.h
Normal file
120
examples/host/device_info/src/tusb_config.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Common Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by compiler flags for flexibility
|
||||
#ifndef CFG_TUSB_MCU
|
||||
#error CFG_TUSB_MCU must be defined
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_OS
|
||||
#define CFG_TUSB_OS OPT_OS_NONE
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_DEBUG
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* 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_TUH_MEM_SECTION
|
||||
#define CFG_TUH_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUH_MEM_ALIGN
|
||||
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Host Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RP2040
|
||||
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
|
||||
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
|
||||
|
||||
// host roothub port is 1 if using either pio-usb or max3421
|
||||
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
|
||||
#define BOARD_TUH_RHPORT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
|
||||
|
||||
//------------------------- Board Specific --------------------------
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Driver Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Size of buffer to hold descriptors and other data used for enumeration
|
||||
#define CFG_TUH_ENUMERATION_BUFSIZE 256
|
||||
|
||||
// only hub class is enabled
|
||||
#define CFG_TUH_HUB 1
|
||||
|
||||
// max device support (excluding hub device)
|
||||
// 1 hub typically has 4 ports
|
||||
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -1,31 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
|
||||
|
||||
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
|
||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
project(${PROJECT})
|
||||
project(${PROJECT} C CXX ASM)
|
||||
|
||||
# Checks this example is valid for the family and initializes the project
|
||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Espressif has its own cmake build system
|
||||
if(FAMILY STREQUAL "espressif")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
target_sources(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
)
|
||||
|
||||
# Example include
|
||||
target_include_directories(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
# Configure compilation flags and libraries for the example... see the corresponding function
|
||||
# in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT})
|
||||
|
||||
# For rp2040, un-comment to enable pico-pio-usb
|
||||
# family_add_pico_pio_usb(${PROJECT})
|
||||
# Configure compilation flags and libraries for the example without RTOS.
|
||||
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT} noos)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
include ../../../tools/top.mk
|
||||
include ../../make.mk
|
||||
include ../../build_system/make/make.mk
|
||||
|
||||
INC += \
|
||||
src \
|
||||
@@ -12,14 +11,4 @@ EXAMPLE_SOURCE += \
|
||||
|
||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
|
||||
|
||||
# TinyUSB Host Stack source
|
||||
SRC_C += \
|
||||
src/class/cdc/cdc_host.c \
|
||||
src/class/hid/hid_host.c \
|
||||
src/class/msc/msc_host.c \
|
||||
src/host/hub.c \
|
||||
src/host/usbh.c \
|
||||
src/portable/ohci/ohci.c \
|
||||
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
|
||||
|
||||
include ../../rules.mk
|
||||
include ../../build_system/make/rules.mk
|
||||
|
@@ -1,11 +1,17 @@
|
||||
mcu:KINETIS_KL
|
||||
mcu:LPC175X_6X
|
||||
mcu:LPC177X_8X
|
||||
mcu:LPC18XX
|
||||
mcu:LPC40XX
|
||||
mcu:LPC43XX
|
||||
mcu:MIMXRT
|
||||
mcu:MIMXRT1XXX
|
||||
mcu:MIMXRT10XX
|
||||
mcu:MIMXRT11XX
|
||||
mcu:RP2040
|
||||
mcu:MSP432E4
|
||||
mcu:RX65X
|
||||
mcu:RAXXX
|
||||
mcu:MAX3421
|
||||
mcu:STM32F4
|
||||
mcu:STM32F7
|
||||
mcu:STM32H7
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
/* From https://www.kernel.org/doc/html/latest/input/gamepad.html
|
||||
@@ -91,9 +91,8 @@ typedef struct TU_ATTR_PACKED
|
||||
uint8_t counter : 6; // +1 each report
|
||||
};
|
||||
|
||||
// comment out since not used by this example
|
||||
// uint8_t l2_trigger; // 0 released, 0xff fully pressed
|
||||
// uint8_t r2_trigger; // as above
|
||||
uint8_t l2_trigger; // 0 released, 0xff fully pressed
|
||||
uint8_t r2_trigger; // as above
|
||||
|
||||
// uint16_t timestamp;
|
||||
// uint8_t battery;
|
||||
@@ -105,15 +104,54 @@ typedef struct TU_ATTR_PACKED
|
||||
|
||||
} sony_ds4_report_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
// First 16 bits set what data is pertinent in this structure (1 = set; 0 = not set)
|
||||
uint8_t set_rumble : 1;
|
||||
uint8_t set_led : 1;
|
||||
uint8_t set_led_blink : 1;
|
||||
uint8_t set_ext_write : 1;
|
||||
uint8_t set_left_volume : 1;
|
||||
uint8_t set_right_volume : 1;
|
||||
uint8_t set_mic_volume : 1;
|
||||
uint8_t set_speaker_volume : 1;
|
||||
uint8_t set_flags2;
|
||||
|
||||
uint8_t reserved;
|
||||
|
||||
uint8_t motor_right;
|
||||
uint8_t motor_left;
|
||||
|
||||
uint8_t lightbar_red;
|
||||
uint8_t lightbar_green;
|
||||
uint8_t lightbar_blue;
|
||||
uint8_t lightbar_blink_on;
|
||||
uint8_t lightbar_blink_off;
|
||||
|
||||
uint8_t ext_data[8];
|
||||
|
||||
uint8_t volume_left;
|
||||
uint8_t volume_right;
|
||||
uint8_t volume_mic;
|
||||
uint8_t volume_speaker;
|
||||
|
||||
uint8_t other[9];
|
||||
} sony_ds4_output_report_t;
|
||||
|
||||
static bool ds4_mounted = false;
|
||||
static uint8_t ds4_dev_addr = 0;
|
||||
static uint8_t ds4_instance = 0;
|
||||
static uint8_t motor_left = 0;
|
||||
static uint8_t motor_right = 0;
|
||||
|
||||
// check if device is Sony DualShock 4
|
||||
static inline bool is_sony_ds4(uint8_t dev_addr)
|
||||
{
|
||||
uint16_t vid, pid;
|
||||
tuh_vid_pid_get(dev_addr, &vid, &pid);
|
||||
|
||||
return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4
|
||||
|| (vid == 0x0f0d && pid == 0x005e) // Hori FC4
|
||||
|| (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U)
|
||||
return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4
|
||||
|| (vid == 0x0f0d && pid == 0x005e) // Hori FC4
|
||||
|| (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U)
|
||||
|| (vid == 0x1f4f && pid == 0x1002) // ASW GG xrd controller
|
||||
);
|
||||
}
|
||||
@@ -124,7 +162,23 @@ static inline bool is_sony_ds4(uint8_t dev_addr)
|
||||
|
||||
void hid_app_task(void)
|
||||
{
|
||||
// nothing to do
|
||||
if (ds4_mounted)
|
||||
{
|
||||
const uint32_t interval_ms = 200;
|
||||
static uint32_t start_ms = 0;
|
||||
|
||||
uint32_t current_time_ms = board_millis();
|
||||
if ( current_time_ms - start_ms >= interval_ms)
|
||||
{
|
||||
start_ms = current_time_ms;
|
||||
|
||||
sony_ds4_output_report_t output_report = {0};
|
||||
output_report.set_rumble = 1;
|
||||
output_report.motor_left = motor_left;
|
||||
output_report.motor_right = motor_right;
|
||||
tuh_hid_send_report(ds4_dev_addr, ds4_instance, 5, &output_report, sizeof(output_report));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -149,6 +203,14 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
|
||||
// Sony DualShock 4 [CUH-ZCT2x]
|
||||
if ( is_sony_ds4(dev_addr) )
|
||||
{
|
||||
if (!ds4_mounted)
|
||||
{
|
||||
ds4_dev_addr = dev_addr;
|
||||
ds4_instance = instance;
|
||||
motor_left = 0;
|
||||
motor_right = 0;
|
||||
ds4_mounted = true;
|
||||
}
|
||||
// request to receive report
|
||||
// tuh_hid_report_received_cb() will be invoked when report is available
|
||||
if ( !tuh_hid_receive_report(dev_addr, instance) )
|
||||
@@ -162,6 +224,10 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
|
||||
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);
|
||||
if (ds4_mounted && ds4_dev_addr == dev_addr && ds4_instance == instance)
|
||||
{
|
||||
ds4_mounted = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check if different than 2
|
||||
@@ -179,14 +245,15 @@ bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2)
|
||||
result = diff_than_2(rpt1->x, rpt2->x) || diff_than_2(rpt1->y , rpt2->y ) ||
|
||||
diff_than_2(rpt1->z, rpt2->z) || diff_than_2(rpt1->rz, rpt2->rz);
|
||||
|
||||
// check the reset with mem compare
|
||||
result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-4);
|
||||
// check the rest with mem compare
|
||||
result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-6);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void process_sony_ds4(uint8_t const* report, uint16_t len)
|
||||
{
|
||||
(void)len;
|
||||
const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" };
|
||||
|
||||
// previous report used to compare for changes
|
||||
@@ -234,6 +301,10 @@ void process_sony_ds4(uint8_t const* report, uint16_t len)
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
// The left and right triggers control the intensity of the left and right rumble motors
|
||||
motor_left = ds4_report.l2_trigger;
|
||||
motor_right = ds4_report.r2_trigger;
|
||||
|
||||
prev_report = ds4_report;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -52,7 +52,15 @@ int main(void)
|
||||
printf("Note: Events only displayed for explicit supported controllers\r\n");
|
||||
|
||||
// init host stack on configured roothub port
|
||||
tuh_init(BOARD_TUH_RHPORT);
|
||||
tusb_rhport_init_t host_init = {
|
||||
.role = TUSB_ROLE_HOST,
|
||||
.speed = TUSB_SPEED_AUTO
|
||||
};
|
||||
tusb_init(BOARD_TUH_RHPORT, &host_init);
|
||||
|
||||
if (board_init_after_tusb) {
|
||||
board_init_after_tusb();
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -68,8 +76,6 @@ int main(void)
|
||||
hid_app_task();
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -30,22 +30,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board Specific Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COMMON CONFIGURATION
|
||||
// Common Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by compiler flags for flexibility
|
||||
@@ -61,12 +47,6 @@
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_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.
|
||||
@@ -74,16 +54,48 @@
|
||||
* - 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
|
||||
#ifndef CFG_TUH_MEM_SECTION
|
||||
#define CFG_TUH_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#ifndef CFG_TUH_MEM_ALIGN
|
||||
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// CONFIGURATION
|
||||
// Host Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RP2040
|
||||
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
|
||||
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
|
||||
|
||||
// host roothub port is 1 if using either pio-usb or max3421
|
||||
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
|
||||
#define BOARD_TUH_RHPORT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
|
||||
|
||||
//------------------------- Board Specific --------------------------
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Driver Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Size of buffer to hold descriptors and other data used for enumeration
|
||||
@@ -91,13 +103,12 @@
|
||||
|
||||
#define CFG_TUH_HUB 0
|
||||
#define CFG_TUH_CDC 0
|
||||
#define CFG_TUH_HID 4 // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_MSC 0
|
||||
#define CFG_TUH_VENDOR 0
|
||||
|
||||
// max device support (excluding hub device)
|
||||
// 1 hub typically has 4 ports
|
||||
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1)
|
||||
// max device support (excluding hub device): 1 hub typically has 4 ports
|
||||
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
|
||||
|
||||
//------------- HID -------------//
|
||||
|
||||
|
@@ -1,48 +1,47 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
|
||||
|
||||
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
|
||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
project(${PROJECT})
|
||||
project(${PROJECT} C CXX ASM)
|
||||
|
||||
# Checks this example is valid for the family and initializes the project
|
||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Espressif has its own cmake build system
|
||||
if(FAMILY STREQUAL "espressif")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
target_sources(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
|
||||
${TOP}/lib/fatfs/source/ff.c
|
||||
${TOP}/lib/fatfs/source/ffsystem.c
|
||||
${TOP}/lib/fatfs/source/ffunicode.c
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
|
||||
${TOP}/lib/fatfs/source/ff.c
|
||||
${TOP}/lib/fatfs/source/ffsystem.c
|
||||
${TOP}/lib/fatfs/source/ffunicode.c
|
||||
)
|
||||
|
||||
# Suppress warnings on fatfs
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
set_source_files_properties(
|
||||
${TOP}/lib/fatfs/source/ff.c
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual"
|
||||
)
|
||||
endif ()
|
||||
|
||||
# Example include
|
||||
target_include_directories(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${TOP}/lib/fatfs/source
|
||||
${TOP}/lib/embedded-cli
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${TOP}/lib/fatfs/source
|
||||
${TOP}/lib/embedded-cli
|
||||
)
|
||||
|
||||
# Configure compilation flags and libraries for the example... see the corresponding function
|
||||
# in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT})
|
||||
|
||||
# For rp2040, un-comment to enable pico-pio-usb
|
||||
family_add_pico_pio_usb(${PROJECT})
|
||||
|
||||
# due to warnings from Pico-PIO-USB and fatfs
|
||||
target_compile_options(${PROJECT} PUBLIC
|
||||
-Wno-error=shadow
|
||||
-Wno-error=cast-align
|
||||
-Wno-error=cast-qual
|
||||
-Wno-error=redundant-decls
|
||||
-Wno-error=sign-conversion
|
||||
-Wno-error=conversion
|
||||
-Wno-error=sign-compare
|
||||
-Wno-error=unused-function
|
||||
)
|
||||
# Configure compilation flags and libraries for the example without RTOS.
|
||||
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
|
||||
family_configure_host_example(${PROJECT} noos)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
include ../../../tools/top.mk
|
||||
include ../../make.mk
|
||||
include ../../build_system/make/make.mk
|
||||
|
||||
FATFS_PATH = lib/fatfs/source
|
||||
|
||||
@@ -25,14 +24,4 @@ SRC_C += \
|
||||
# suppress warning caused by fatfs
|
||||
CFLAGS += -Wno-error=cast-qual
|
||||
|
||||
# TinyUSB Host Stack source
|
||||
SRC_C += \
|
||||
src/class/cdc/cdc_host.c \
|
||||
src/class/hid/hid_host.c \
|
||||
src/class/msc/msc_host.c \
|
||||
src/host/hub.c \
|
||||
src/host/usbh.c \
|
||||
src/portable/ohci/ohci.c \
|
||||
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
|
||||
|
||||
include ../../rules.mk
|
||||
include ../../build_system/make/rules.mk
|
||||
|
@@ -1,11 +1,17 @@
|
||||
mcu:KINETIS_KL
|
||||
mcu:LPC175X_6X
|
||||
mcu:LPC177X_8X
|
||||
mcu:LPC18XX
|
||||
mcu:LPC40XX
|
||||
mcu:LPC43XX
|
||||
mcu:MIMXRT
|
||||
mcu:MIMXRT1XXX
|
||||
mcu:MIMXRT10XX
|
||||
mcu:MIMXRT11XX
|
||||
mcu:RP2040
|
||||
mcu:MSP432E4
|
||||
mcu:RX65X
|
||||
mcu:RAXXX
|
||||
mcu:MAX3421
|
||||
mcu:STM32F4
|
||||
mcu:STM32F7
|
||||
mcu:STM32H7
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -23,35 +23,72 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* Example to show how to navigate mass storage device with built-in command line.
|
||||
* Type help for list of supported commands and syntax (mostly linux commands)
|
||||
|
||||
> help
|
||||
* help
|
||||
Print list of commands
|
||||
* cat
|
||||
Usage: cat [FILE]...
|
||||
Concatenate FILE(s) to standard output..
|
||||
* cd
|
||||
Usage: cd [DIR]...
|
||||
Change the current directory to DIR.
|
||||
* cp
|
||||
Usage: cp SOURCE DEST
|
||||
Copy SOURCE to DEST.
|
||||
* ls
|
||||
Usage: ls [DIR]...
|
||||
List information about the FILEs (the current directory by default).
|
||||
* pwd
|
||||
Usage: pwd
|
||||
Print the name of the current working directory.
|
||||
* mkdir
|
||||
Usage: mkdir DIR...
|
||||
Create the DIRECTORY(ies), if they do not already exist..
|
||||
* mv
|
||||
Usage: mv SOURCE DEST...
|
||||
Rename SOURCE to DEST.
|
||||
* rm
|
||||
Usage: rm [FILE]...
|
||||
Remove (unlink) the FILE(s).
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#include "msc_app.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void);
|
||||
|
||||
// from msc_app.c
|
||||
extern bool msc_app_init(void);
|
||||
extern void msc_app_task(void);
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void)
|
||||
{
|
||||
int main(void) {
|
||||
board_init();
|
||||
|
||||
printf("TinyUSB Host MassStorage Explorer Example\r\n");
|
||||
|
||||
// init host stack on configured roothub port
|
||||
tuh_init(BOARD_TUH_RHPORT);
|
||||
tusb_rhport_init_t host_init = {
|
||||
.role = TUSB_ROLE_HOST,
|
||||
.speed = TUSB_SPEED_AUTO
|
||||
};
|
||||
tusb_init(BOARD_TUH_RHPORT, &host_init);
|
||||
|
||||
if (board_init_after_tusb) {
|
||||
board_init_after_tusb();
|
||||
}
|
||||
|
||||
msc_app_init();
|
||||
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
// tinyusb host task
|
||||
tuh_task();
|
||||
|
||||
@@ -66,28 +103,25 @@ int main(void)
|
||||
// TinyUSB Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void tuh_mount_cb(uint8_t dev_addr)
|
||||
{
|
||||
void tuh_mount_cb(uint8_t dev_addr) {
|
||||
(void) dev_addr;
|
||||
}
|
||||
|
||||
void tuh_umount_cb(uint8_t dev_addr)
|
||||
{
|
||||
void tuh_umount_cb(uint8_t dev_addr) {
|
||||
(void) dev_addr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Blinking Task
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void)
|
||||
{
|
||||
void led_blinking_task(void) {
|
||||
const uint32_t interval_ms = 1000;
|
||||
static uint32_t start_ms = 0;
|
||||
|
||||
static bool led_state = false;
|
||||
|
||||
// Blink every interval ms
|
||||
if ( board_millis() - start_ms < interval_ms) return; // not enough time
|
||||
if (board_millis() - start_ms < interval_ms) return; // not enough time
|
||||
start_ms += interval_ms;
|
||||
|
||||
board_led_write(led_state);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include "tusb.h"
|
||||
#include "bsp/board.h"
|
||||
#include "bsp/board_api.h"
|
||||
|
||||
#include "ff.h"
|
||||
#include "diskio.h"
|
||||
@@ -53,7 +53,11 @@ static CLI_UINT cli_buffer[BYTES_TO_CLI_UINTS(CLI_BUFFER_SIZE)];
|
||||
static FATFS fatfs[CFG_TUH_DEVICE_MAX]; // for simplicity only support 1 LUN per device
|
||||
static volatile bool _disk_busy[CFG_TUH_DEVICE_MAX];
|
||||
|
||||
static scsi_inquiry_resp_t inquiry_resp;
|
||||
// define the buffer to be place in USB/DMA memory with correct alignment/cache line size
|
||||
CFG_TUH_MEM_SECTION static struct {
|
||||
TUH_EPBUF_TYPE_DEF(scsi_inquiry_resp_t, inquiry);
|
||||
} scsi_resp;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
@@ -63,10 +67,15 @@ bool cli_init(void);
|
||||
|
||||
bool msc_app_init(void)
|
||||
{
|
||||
for(size_t i=0; i<CFG_TUH_DEVICE_MAX; i++) _disk_busy[i] = false;
|
||||
for(size_t i=0; i<CFG_TUH_DEVICE_MAX; i++) {
|
||||
_disk_busy[i] = false;
|
||||
}
|
||||
|
||||
// disable stdout buffered for echoing typing command
|
||||
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
|
||||
setbuf(stdout, NULL);
|
||||
#endif
|
||||
|
||||
cli_init();
|
||||
|
||||
return true;
|
||||
@@ -74,7 +83,9 @@ bool msc_app_init(void)
|
||||
|
||||
void msc_app_task(void)
|
||||
{
|
||||
if (!_cli) return;
|
||||
if (!_cli) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ch = board_getchar();
|
||||
if ( ch > 0 )
|
||||
@@ -92,9 +103,10 @@ void msc_app_task(void)
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) {
|
||||
msc_cbw_t const* cbw = cb_data->cbw;
|
||||
msc_csw_t const* csw = cb_data->csw;
|
||||
|
||||
bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
|
||||
{
|
||||
if (csw->status != 0)
|
||||
{
|
||||
printf("Inquiry failed\r\n");
|
||||
@@ -102,13 +114,13 @@ bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const
|
||||
}
|
||||
|
||||
// Print out Vendor ID, Product ID and Rev
|
||||
printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev);
|
||||
printf("%.8s %.16s rev %.4s\r\n", scsi_resp.inquiry.vendor_id, scsi_resp.inquiry.product_id, scsi_resp.inquiry.product_rev);
|
||||
|
||||
// Get capacity of device
|
||||
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
|
||||
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
|
||||
|
||||
printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size));
|
||||
printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024*1024)/block_size));
|
||||
// printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
|
||||
|
||||
// For simplicity: we only mount 1 LUN per device
|
||||
@@ -140,7 +152,7 @@ void tuh_msc_mount_cb(uint8_t dev_addr)
|
||||
printf("A MassStorage device is mounted\r\n");
|
||||
|
||||
uint8_t const lun = 0;
|
||||
tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb);
|
||||
tuh_msc_inquiry(dev_addr, lun, &scsi_resp.inquiry, inquiry_complete_cb, 0);
|
||||
}
|
||||
|
||||
void tuh_msc_umount_cb(uint8_t dev_addr)
|
||||
@@ -178,9 +190,9 @@ static void wait_for_disk_io(BYTE pdrv)
|
||||
}
|
||||
}
|
||||
|
||||
static bool disk_io_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
|
||||
static bool disk_io_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data)
|
||||
{
|
||||
(void) dev_addr; (void) cbw; (void) csw;
|
||||
(void) dev_addr; (void) cb_data;
|
||||
_disk_busy[dev_addr-1] = false;
|
||||
return true;
|
||||
}
|
||||
@@ -212,7 +224,7 @@ DRESULT disk_read (
|
||||
uint8_t const lun = 0;
|
||||
|
||||
_disk_busy[pdrv] = true;
|
||||
tuh_msc_read10(dev_addr, lun, buff, sector, (uint16_t) count, disk_io_complete);
|
||||
tuh_msc_read10(dev_addr, lun, buff, sector, (uint16_t) count, disk_io_complete, 0);
|
||||
wait_for_disk_io(pdrv);
|
||||
|
||||
return RES_OK;
|
||||
@@ -231,7 +243,7 @@ DRESULT disk_write (
|
||||
uint8_t const lun = 0;
|
||||
|
||||
_disk_busy[pdrv] = true;
|
||||
tuh_msc_write10(dev_addr, lun, buff, sector, (uint16_t) count, disk_io_complete);
|
||||
tuh_msc_write10(dev_addr, lun, buff, sector, (uint16_t) count, disk_io_complete, 0);
|
||||
wait_for_disk_io(pdrv);
|
||||
|
||||
return RES_OK;
|
||||
@@ -285,18 +297,11 @@ void cli_cmd_mkdir(EmbeddedCli *cli, char *args, void *context);
|
||||
void cli_cmd_mv(EmbeddedCli *cli, char *args, void *context);
|
||||
void cli_cmd_rm(EmbeddedCli *cli, char *args, void *context);
|
||||
|
||||
void cli_write_char(EmbeddedCli *cli, char c)
|
||||
{
|
||||
static void cli_write_char(EmbeddedCli *cli, char c) {
|
||||
(void) cli;
|
||||
putchar((int) c);
|
||||
}
|
||||
|
||||
void cli_cmd_unknown(EmbeddedCli *cli, CliCommand *command)
|
||||
{
|
||||
(void) cli;
|
||||
printf("%s: command not found\r\n", command->name);
|
||||
}
|
||||
|
||||
bool cli_init(void)
|
||||
{
|
||||
EmbeddedCliConfig *config = embeddedCliDefaultConfig();
|
||||
@@ -410,7 +415,7 @@ void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context)
|
||||
{
|
||||
for(UINT c = 0; c < count; c++)
|
||||
{
|
||||
const char ch = buf[c];
|
||||
const uint8_t ch = buf[c];
|
||||
if (isprint(ch) || iscntrl(ch))
|
||||
{
|
||||
putchar(ch);
|
||||
@@ -535,10 +540,10 @@ void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context)
|
||||
printf("%-40s", fno.fname);
|
||||
if (fno.fsize < 1024)
|
||||
{
|
||||
printf("%lu B\r\n", fno.fsize);
|
||||
printf("%" PRIu32 " B\r\n", fno.fsize);
|
||||
}else
|
||||
{
|
||||
printf("%lu KB\r\n", fno.fsize / 1024);
|
||||
printf("%" PRIu32 " KB\r\n", fno.fsize / 1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
35
examples/host/msc_file_explorer/src/msc_app.h
Normal file
35
examples/host/msc_file_explorer/src/msc_app.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 MSC_APP_H
|
||||
#define MSC_APP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool msc_app_init(void);
|
||||
void msc_app_task(void);
|
||||
|
||||
|
||||
#endif
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -30,28 +30,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board Specific Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RP2040
|
||||
// change to 1 if using pico-pio-usb as host controller for raspberry rp2040
|
||||
#define CFG_TUH_RPI_PIO_USB 0
|
||||
#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB
|
||||
#endif
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// COMMON CONFIGURATION
|
||||
// Common Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// defined by compiler flags for flexibility
|
||||
@@ -67,12 +47,6 @@
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_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.
|
||||
@@ -80,16 +54,48 @@
|
||||
* - 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
|
||||
#ifndef CFG_TUH_MEM_SECTION
|
||||
#define CFG_TUH_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#ifndef CFG_TUH_MEM_ALIGN
|
||||
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// CONFIGURATION
|
||||
// Host Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_RP2040
|
||||
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
|
||||
// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
|
||||
|
||||
// host roothub port is 1 if using either pio-usb or max3421
|
||||
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
|
||||
#define BOARD_TUH_RHPORT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Default is max speed that hardware controller could support with on-chip PHY
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
|
||||
|
||||
//------------------------- Board Specific --------------------------
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#endif
|
||||
|
||||
// RHPort max operational speed can defined by board.mk
|
||||
#ifndef BOARD_TUH_MAX_SPEED
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Driver Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Size of buffer to hold descriptors and other data used for enumeration
|
||||
@@ -101,8 +107,8 @@
|
||||
#define CFG_TUH_HID 0 // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_VENDOR 0
|
||||
|
||||
// max device support (excluding hub device)
|
||||
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
|
||||
// max device support (excluding hub device): 1 hub typically has 4 ports
|
||||
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
|
||||
|
||||
//------------- MSC -------------//
|
||||
#define CFG_TUH_MSC_MAXLUN 4 // typical for most card reader
|
||||
|
Reference in New Issue
Block a user