Starting to have functionnal host and device using tu.
This commit is contained in:
parent
8c387da066
commit
1ea377684b
|
|
@ -3,27 +3,13 @@
|
|||
{
|
||||
"name": "Linux",
|
||||
"intelliSenseMode": "linux-gcc-arm",
|
||||
"includePath": [
|
||||
"${env:PICO_SDK_PATH}/src/**/include/",
|
||||
"${env:PICO_SDK_PATH}/lib/**/include/",
|
||||
"${env:PICO_SDK_PATH}/lib/**/src/",
|
||||
"${env:PICO_SDK_PATH}/lib/tinyusb/hw",
|
||||
"${workspaceFolder}/build/generated/pico_base/",
|
||||
"${workspaceFolder}/src/",
|
||||
"${workspaceFolder}/lib/**/"
|
||||
],
|
||||
"compilerPath": "/usr/bin/arm-none-eabi-gcc",
|
||||
"cStandard": "c17",
|
||||
"browse": {
|
||||
"path": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
"limitSymbolsToIncludedHeaders": true
|
||||
},
|
||||
"defines": [
|
||||
"CFG_TUSB_MCU=OPT_MCU_RP2040"
|
||||
]
|
||||
"compileCommands": "build/compile_commands.json"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
"command": "cmake",
|
||||
"args": [
|
||||
"-H.",
|
||||
"-Bbuild"
|
||||
"-Bbuild",
|
||||
"-DCMAKE_EXPORT_COMPILE_COMMANDS=1"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.13)
|
|||
|
||||
# Explicitely define board
|
||||
set(PICO_BOARD pico)
|
||||
if(NOT DEFINED PICO_BOARD)
|
||||
add_definitions(-DPICO_BOARD=${PICO_BOARD})
|
||||
endif()
|
||||
|
||||
# Include pico-sdk cmake support
|
||||
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
|
||||
|
|
@ -19,21 +16,37 @@ pico_sdk_init()
|
|||
add_executable(Pico_Host)
|
||||
add_executable(Pico_Device)
|
||||
|
||||
# Sources
|
||||
target_sources(Pico_Host PUBLIC
|
||||
src/main_host.c
|
||||
src/cdc_app.c
|
||||
src/hid_app.c
|
||||
src/msc_app.c
|
||||
src_host/main.c
|
||||
src_host/cdc_app.c
|
||||
)
|
||||
|
||||
target_sources(Pico_Device PUBLIC
|
||||
src/main_device.c
|
||||
src_device/main.c
|
||||
src_device/usb_descriptor.c
|
||||
)
|
||||
|
||||
# Flags
|
||||
# Enable the reset interface
|
||||
target_compile_definitions(Pico_Device PUBLIC
|
||||
PICO_ENABLE_USB_RESET_VIA_VENDOR_INTERFACE=1
|
||||
# use SDK MS_OS_20 descriptor, as this doesn't have a custom one
|
||||
PICO_USB_RESET_SUPPORT_MS_OS_20_DESCRIPTOR=1
|
||||
# pass the interface number to the SDK MS_OS_20 descriptor
|
||||
PICO_USB_RESET_MS_OS_20_DESCRIPTOR_ITF=4
|
||||
)
|
||||
|
||||
# Include paths
|
||||
target_include_directories(Pico_Host PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/
|
||||
${CMAKE_CURRENT_LIST_DIR}/src_host/
|
||||
)
|
||||
|
||||
target_include_directories(Pico_Device PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/src_device/
|
||||
)
|
||||
|
||||
# Libs
|
||||
target_link_libraries(Pico_Host
|
||||
pico_stdlib
|
||||
tinyusb_board
|
||||
|
|
@ -42,13 +55,17 @@ target_link_libraries(Pico_Host
|
|||
|
||||
target_link_libraries(Pico_Device
|
||||
pico_stdlib
|
||||
tinyusb_board
|
||||
tinyusb_device
|
||||
)
|
||||
|
||||
# Output
|
||||
pico_enable_stdio_usb(Pico_Device 1)
|
||||
|
||||
# Outputs
|
||||
pico_add_extra_outputs(Pico_Host)
|
||||
pico_add_extra_outputs(Pico_Device)
|
||||
|
||||
# Flash target
|
||||
# Flash targets
|
||||
add_custom_target(Flash_Host
|
||||
DEPENDS Pico_Host
|
||||
COMMAND picotool load -f ${PROJECT_BINARY_DIR}/Pico_Host.uf2
|
||||
|
|
|
|||
298
src/hid_app.c
298
src/hid_app.c
|
|
@ -1,298 +0,0 @@
|
|||
/*
|
||||
* 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_task(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#include <pico/stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
stdio_init_all();
|
||||
|
||||
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
||||
|
||||
while(true)
|
||||
{
|
||||
static uint64_t last_time = 0;
|
||||
uint64_t time = time_us_64();
|
||||
if(time - last_time > 1000 * 1000)
|
||||
{
|
||||
last_time = time;
|
||||
|
||||
static bool led_state = true;
|
||||
led_state = !led_state;
|
||||
|
||||
gpio_put(PICO_DEFAULT_LED_PIN, led_state);
|
||||
|
||||
printf("led_state : %d\n", led_state);
|
||||
}
|
||||
|
||||
tight_loop_contents();
|
||||
}
|
||||
|
||||
return PICO_OK;
|
||||
}
|
||||
111
src/main_host.c
111
src/main_host.c
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* 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>
|
||||
#include "tusb_config.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_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) {
|
||||
board_init();
|
||||
|
||||
printf("TinyUSB Host CDC MSC HID Example\r\n");
|
||||
|
||||
// init host stack on configured roothub port
|
||||
const tusb_rhport_init_t rh_init = {
|
||||
.role = TUSB_ROLE_HOST,
|
||||
.speed = TUH_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL,
|
||||
};
|
||||
TU_ASSERT(tuh_rhport_init(BOARD_TUH_RHPORT, &rh_init));
|
||||
|
||||
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
|
||||
|
||||
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) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
#if TUSB_VERSION_NUMBER > 1800
|
||||
// board_millis has been removed from tinyusb. Use tusb_time_millis_api instead
|
||||
#define board_millis tusb_time_millis_api
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Blinking Task
|
||||
//--------------------------------------------------------------------+
|
||||
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
|
||||
start_ms += interval_ms;
|
||||
|
||||
board_led_write(led_state);
|
||||
led_state = 1 - led_state; // toggle
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
static scsi_inquiry_resp_t inquiry_resp;
|
||||
|
||||
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", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.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, &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");
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <tusb.h>
|
||||
#include <bsp/board.h>
|
||||
#include <pico/stdio.h>
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
#define LED_BLINK_DELAY_MS 1000
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Initialize TinyUSB stack
|
||||
board_init();
|
||||
tusb_init();
|
||||
|
||||
// let pico sdk use the first cdc interface for std io
|
||||
stdio_init_all();
|
||||
|
||||
uint32_t start_ms = 0;
|
||||
bool led_state = false;
|
||||
|
||||
// main run loop
|
||||
while(true)
|
||||
{
|
||||
// TinyUSB device task | must be called regurlarly
|
||||
tud_task();
|
||||
|
||||
if(board_millis() - start_ms > LED_BLINK_DELAY_MS)
|
||||
{
|
||||
board_led_write(led_state);
|
||||
led_state = ! led_state;
|
||||
start_ms += LED_BLINK_DELAY_MS;
|
||||
|
||||
if(tud_cdc_n_connected(0))
|
||||
{
|
||||
printf("Connected to CDC 0\n");
|
||||
}
|
||||
|
||||
if(tud_cdc_n_connected(1))
|
||||
{
|
||||
printf("Connected to CDC 1\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// callback when data is received on a CDC interface
|
||||
void tud_cdc_rx_cb(uint8_t itf)
|
||||
{
|
||||
// allocate buffer for the data in the stack
|
||||
uint8_t buf[CFG_TUD_CDC_RX_BUFSIZE];
|
||||
|
||||
printf("RX CDC %d\n", itf);
|
||||
|
||||
// read the available data
|
||||
// | IMPORTANT: also do this for CDC0 because otherwise
|
||||
// | you won't be able to print anymore to CDC0
|
||||
// | next time this function is called
|
||||
uint32_t count = tud_cdc_n_read(itf, buf, sizeof(buf));
|
||||
|
||||
// check if the data was received on the second cdc interface
|
||||
if (itf == 1) {
|
||||
// process the received data
|
||||
buf[count] = 0; // null-terminate the string
|
||||
// now echo data back to the console on CDC 0
|
||||
printf("Received on CDC 1: %s\n", buf);
|
||||
|
||||
// and echo back OK on CDC 1
|
||||
tud_cdc_n_write(itf, (uint8_t const *) "OK\r\n", 4);
|
||||
tud_cdc_n_write_flush(itf);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_CONFIG_H_
|
||||
#define _TUSB_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CFG_TUD_ENABLED (1)
|
||||
|
||||
// Legacy RHPORT configuration
|
||||
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED)
|
||||
#ifndef BOARD_TUD_RHPORT
|
||||
#define BOARD_TUD_RHPORT (0)
|
||||
#endif
|
||||
// end legacy RHPORT
|
||||
|
||||
//------------------------
|
||||
// DEVICE CONFIGURATION //
|
||||
//------------------------
|
||||
|
||||
// Enable 2 CDC classes
|
||||
#define CFG_TUD_CDC (2)
|
||||
// Set CDC FIFO buffer sizes
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE (64)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (64)
|
||||
#define CFG_TUD_CDC_EP_BUFSIZE (64)
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE (64)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
/**
|
||||
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <tusb.h>
|
||||
#include <bsp/board_api.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "pico/usb_reset.h"
|
||||
|
||||
// set some example Vendor and Product ID
|
||||
// the board will use to identify at the host
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define CDC_EXAMPLE_VID 0xCafe
|
||||
// use _PID_MAP to generate unique PID for each interface
|
||||
#define CDC_EXAMPLE_PID (0x4100 | _PID_MAP(CDC, 0))
|
||||
// set to 2.10 so the MS_OS_20_DESCRIPTOR works
|
||||
#define CDC_EXAMPLE_BCD 0x0210
|
||||
|
||||
// String descriptors referenced with .i... in the descriptor tables
|
||||
|
||||
enum {
|
||||
STRID_LANGID = 0, // 0: supported language ID
|
||||
STRID_MANUFACTURER, // 1: Manufacturer
|
||||
STRID_PRODUCT, // 2: Product
|
||||
STRID_SERIAL, // 3: Serials
|
||||
STRID_CDC_0, // 4: CDC Interface 0
|
||||
STRID_CDC_1, // 5: CDC Interface 1
|
||||
STRID_RPI_RESET, // 6: Reset Interface
|
||||
};
|
||||
|
||||
// array of pointer to string descriptors
|
||||
char const *string_desc_arr[] = {
|
||||
// switched because board is little endian
|
||||
(const char[]) { 0x09, 0x04 }, // 0: supported language is English (0x0409)
|
||||
"Raspberry Pi", // 1: Manufacturer
|
||||
"Pico (2)", // 2: Product
|
||||
NULL, // 3: Serials (null so it uses unique ID if available)
|
||||
"Pico SDK stdio", // 4: CDC Interface 0
|
||||
"Custom CDC", // 5: CDC Interface 1,
|
||||
"Reset" // 6: Reset Interface
|
||||
};
|
||||
|
||||
// defines a descriptor that will be communicated to the host
|
||||
tusb_desc_device_t const desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = CDC_EXAMPLE_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_MISC, // CDC is a subclass of misc
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON, // CDC uses common subclass
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD, // CDC uses IAD
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, // 64 bytes
|
||||
|
||||
.idVendor = CDC_EXAMPLE_VID,
|
||||
.idProduct = CDC_EXAMPLE_PID,
|
||||
.bcdDevice = 0x0100, // Device release number
|
||||
|
||||
.iManufacturer = STRID_MANUFACTURER, // Index of manufacturer string
|
||||
.iProduct = STRID_PRODUCT, // Index of product string
|
||||
.iSerialNumber = STRID_SERIAL, // Index of serial number string
|
||||
|
||||
.bNumConfigurations = 0x01 // 1 configuration
|
||||
};
|
||||
|
||||
// called when host requests to get device descriptor
|
||||
uint8_t const *tud_descriptor_device_cb(void);
|
||||
|
||||
enum {
|
||||
ITF_NUM_CDC_0 = 0,
|
||||
ITF_NUM_CDC_0_DATA,
|
||||
ITF_NUM_CDC_1,
|
||||
ITF_NUM_CDC_1_DATA,
|
||||
ITF_NUM_RPI_RESET,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
static_assert(ITF_NUM_RPI_RESET == PICO_USB_RESET_MS_OS_20_DESCRIPTOR_ITF, "ITF_NUM_RPI_RESET must be equal to the PICO_USB_RESET_MS_OS_20_DESCRIPTOR_ITF set in CMakeLists.txt");
|
||||
|
||||
// total length of configuration descriptor
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN + TUD_RPI_RESET_DESC_LEN)
|
||||
|
||||
// define endpoint numbers
|
||||
#define EPNUM_CDC_0_NOTIF 0x81 // notification endpoint for CDC 0
|
||||
#define EPNUM_CDC_0_OUT 0x02 // out endpoint for CDC 0
|
||||
#define EPNUM_CDC_0_IN 0x82 // in endpoint for CDC 0
|
||||
|
||||
#define EPNUM_CDC_1_NOTIF 0x84 // notification endpoint for CDC 1
|
||||
#define EPNUM_CDC_1_OUT 0x05 // out endpoint for CDC 1
|
||||
#define EPNUM_CDC_1_IN 0x85 // in endpoint for CDC 1
|
||||
|
||||
// configure descriptor (for 2 CDC interfaces)
|
||||
uint8_t const desc_configuration[] = {
|
||||
// config descriptor | how much power in mA, count of interfaces, ...
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x80, 100),
|
||||
|
||||
// CDC 0: Communication Interface - TODO: get 64 from tusb_config.h
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, STRID_CDC_0, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
|
||||
// CDC 0: Data Interface
|
||||
//TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0_DATA, 4, 0x01, 0x02),
|
||||
|
||||
// CDC 1: Communication Interface - TODO: get 64 from tusb_config.h
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, STRID_CDC_1, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
|
||||
// CDC 1: Data Interface
|
||||
//TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1_DATA, 4, 0x03, 0x04),
|
||||
|
||||
// RPi Reset Interface
|
||||
TUD_RPI_RESET_DESCRIPTOR(ITF_NUM_RPI_RESET, STRID_RPI_RESET),
|
||||
};
|
||||
|
||||
// called when host requests to get configuration descriptor
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index);
|
||||
|
||||
// more device descriptor this time the qualifier
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = CDC_EXAMPLE_BCD,
|
||||
|
||||
.bDeviceClass = TUSB_CLASS_CDC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// called when host requests to get device qualifier descriptor
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void);
|
||||
|
||||
// buffer to hold the string descriptor during the request | plus 1 for the null terminator
|
||||
static uint16_t _desc_str[32 + 1];
|
||||
|
||||
// called when host request to get string descriptor
|
||||
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid);
|
||||
|
||||
// --------------------------------------------------------------------+
|
||||
// IMPLEMENTATION
|
||||
// --------------------------------------------------------------------+
|
||||
|
||||
uint8_t const *tud_descriptor_device_cb(void)
|
||||
{
|
||||
return (uint8_t const *)&desc_device;
|
||||
}
|
||||
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const *)&desc_device_qualifier;
|
||||
}
|
||||
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
// avoid unused parameter warning and keep function signature consistent
|
||||
(void)index;
|
||||
|
||||
return desc_configuration;
|
||||
}
|
||||
|
||||
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||
{
|
||||
// TODO: check lang id
|
||||
(void) langid;
|
||||
size_t char_count;
|
||||
|
||||
// Determine which string descriptor to return
|
||||
switch (index) {
|
||||
case STRID_LANGID:
|
||||
memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2);
|
||||
char_count = 1;
|
||||
break;
|
||||
|
||||
case STRID_SERIAL:
|
||||
// try to read the serial from the board
|
||||
char_count = board_usb_get_serial(_desc_str + 1, 32);
|
||||
break;
|
||||
|
||||
default:
|
||||
// COPYRIGHT NOTE: Based on TinyUSB example
|
||||
// Windows wants utf16le
|
||||
|
||||
// Determine which string descriptor to return
|
||||
if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy string descriptor into _desc_str
|
||||
const char *str = string_desc_arr[index];
|
||||
|
||||
char_count = strlen(str);
|
||||
size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
|
||||
// Cap at max char
|
||||
if (char_count > max_count) {
|
||||
char_count = max_count;
|
||||
}
|
||||
|
||||
// Convert ASCII string into UTF-16
|
||||
for (size_t i = 0; i < char_count; i++) {
|
||||
_desc_str[1 + i] = str[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// First byte is the length (including header), second byte is string type
|
||||
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (char_count * 2 + 2));
|
||||
|
||||
return _desc_str;
|
||||
}
|
||||
|
|
@ -24,44 +24,48 @@
|
|||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
#include "bsp/board_api.h"
|
||||
#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;
|
||||
size_t get_console_inputs(uint8_t* buf, size_t bufsize)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
buf[count] = (uint8_t) ch;
|
||||
count++;
|
||||
}
|
||||
while (count < bufsize) {
|
||||
int ch = board_getchar();
|
||||
if (ch <= 0) break;
|
||||
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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>
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
#define LED_BLINK_DELAY_MS 1000
|
||||
|
||||
extern void cdc_app_task(void);
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void) {
|
||||
board_init();
|
||||
|
||||
gpio_set_function(12, UART_FUNCSEL_NUM(uart0, 12));
|
||||
gpio_set_function(13, UART_FUNCSEL_NUM(uart0, 13));
|
||||
|
||||
printf("TinyUSB Host CDC Example\n");
|
||||
|
||||
// init host stack on configured roothub port
|
||||
const tusb_rhport_init_t rh_init = {
|
||||
.role = TUSB_ROLE_HOST,
|
||||
.speed = TUH_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL,
|
||||
};
|
||||
|
||||
if(!tuh_rhport_init(BOARD_TUH_RHPORT, &rh_init))
|
||||
{
|
||||
printf("Failed to init rhport.\n");
|
||||
return PICO_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
uint32_t start_ms = 0;
|
||||
bool led_state = false;
|
||||
|
||||
while(true)
|
||||
{
|
||||
// tinyusb host task
|
||||
tuh_task();
|
||||
|
||||
if(board_millis() - start_ms > LED_BLINK_DELAY_MS)
|
||||
{
|
||||
board_led_write(led_state);
|
||||
led_state = ! led_state;
|
||||
start_ms += LED_BLINK_DELAY_MS;
|
||||
}
|
||||
|
||||
cdc_app_task();
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
#define _TUSB_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -40,11 +40,11 @@
|
|||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_OS
|
||||
#define CFG_TUSB_OS OPT_OS_NONE
|
||||
#define CFG_TUSB_OS OPT_OS_NONE
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_DEBUG
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#define CFG_TUSB_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
|
|
@ -62,63 +62,49 @@
|
|||
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Host Configuration
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// Enable Host stack
|
||||
#define CFG_TUH_ENABLED 1
|
||||
// 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
|
||||
// #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
|
||||
// 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 --------------------------
|
||||
#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
|
||||
|
||||
// RHPort number used for host can be defined by board.mk, default to port 0
|
||||
#ifndef BOARD_TUH_RHPORT
|
||||
#define BOARD_TUH_RHPORT 0
|
||||
#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
|
||||
#define BOARD_TUH_MAX_SPEED OPT_MODE_FULL_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
|
||||
#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 0
|
||||
#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 (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
|
||||
|
|
@ -129,7 +115,7 @@
|
|||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
||||
Loading…
Reference in New Issue