diff options
Diffstat (limited to 'examples/host')
23 files changed, 1230 insertions, 118 deletions
diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index 5c63ec0c0..758973ab2 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -6,5 +6,7 @@ project(tinyusb_host_examples) 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(hid_controller) +family_add_subdirectory(msc_file_explorer) diff --git a/examples/host/bare_api/CMakeLists.txt b/examples/host/bare_api/CMakeLists.txt index bc04b01a7..616edd4ac 100644 --- a/examples/host/bare_api/CMakeLists.txt +++ b/examples/host/bare_api/CMakeLists.txt @@ -26,5 +26,7 @@ target_include_directories(${PROJECT} PUBLIC # 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})
\ No newline at end of file +# Add pico-pio-usb for rp2040 since user can choose to run on bit-banging host +if(FAMILY STREQUAL "rp2040") + family_add_pico_pio_usb(${PROJECT}) +endif() diff --git a/examples/host/bare_api/Makefile b/examples/host/bare_api/Makefile index 13e14df53..058307c40 100644 --- a/examples/host/bare_api/Makefile +++ b/examples/host/bare_api/Makefile @@ -1,4 +1,3 @@ -include ../../../tools/top.mk include ../../make.mk INC += \ @@ -11,9 +10,6 @@ EXAMPLE_SOURCE += \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -# TODO: suppress warning caused by host stack -CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference - # TinyUSB Host Stack source SRC_C += \ src/class/cdc/cdc_host.c \ diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 51cab2de0..bb7fa850e 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/examples/host/bare_api/src/tusb_config.h b/examples/host/bare_api/src/tusb_config.h index ed0aaf7da..64be41a4e 100644 --- a/examples/host/bare_api/src/tusb_config.h +++ b/examples/host/bare_api/src/tusb_config.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -34,6 +34,12 @@ // 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 @@ -94,7 +100,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 diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index c4a4d8e63..d7d1a54d7 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -14,6 +14,7 @@ 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 @@ -28,5 +29,7 @@ target_include_directories(${PROJECT} PUBLIC # 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}) +# Add pico-pio-usb for rp2040 since user can choose to run on bit-banging host +if(FAMILY STREQUAL "rp2040") + family_add_pico_pio_usb(${PROJECT}) +endif() diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 272acbac8..7c16b39d3 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -1,4 +1,3 @@ -include ../../../tools/top.mk include ../../make.mk INC += \ @@ -6,11 +5,13 @@ INC += \ $(TOP)/hw \ # Example source -EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +EXAMPLE_SOURCE = \ + src/cdc_app.c \ + src/hid_app.c \ + src/main.c \ + src/msc_app.c \ -# TODO: suppress warning caused by host stack -CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) # TinyUSB Host Stack source SRC_C += \ diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c new file mode 100644 index 000000000..b1b137e0e --- /dev/null +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -0,0 +1,113 @@ +/* + * 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.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + + +//------------- IMPLEMENTATION -------------// + +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); + } + } + } +} + +// 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((char*) buf); +} + +void tuh_cdc_mount_cb(uint8_t idx) +{ + tuh_cdc_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.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: %lu, 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_cdc_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.bInterfaceNumber); +} diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 11437c2b4..ed53c502d 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -247,7 +247,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 ) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 091c002ac..1f4acb822 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -35,7 +35,7 @@ //--------------------------------------------------------------------+ void led_blinking_task(void); -extern void cdc_task(void); +extern void cdc_app_task(void); extern void hid_app_task(void); /*------------- MAIN -------------*/ @@ -52,45 +52,14 @@ int main(void) { // tinyusb host task tuh_task(); - led_blinking_task(); - -#if CFG_TUH_CDC - cdc_task(); -#endif -#if CFG_TUH_HID + led_blinking_task(); + cdc_app_task(); hid_app_task(); -#endif } } //--------------------------------------------------------------------+ -// USB CDC -//--------------------------------------------------------------------+ -#if CFG_TUH_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) -{ - -} - -#endif - -//--------------------------------------------------------------------+ // TinyUSB Callbacks //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 77a72052d..e9c9676b8 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -25,15 +25,16 @@ #include "tusb.h" -#if CFG_TUH_MSC - //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ 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"); @@ -59,48 +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 -// } -// } -// } } - -#endif diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 33f34315b..4b50f2096 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -34,6 +34,12 @@ // 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 @@ -95,13 +101,24 @@ #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_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } + + #ifdef __cplusplus } #endif diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt index 6153d399a..ac3070b82 100644 --- a/examples/host/hid_controller/CMakeLists.txt +++ b/examples/host/hid_controller/CMakeLists.txt @@ -27,5 +27,7 @@ target_include_directories(${PROJECT} PUBLIC # 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}) +# Add pico-pio-usb for rp2040 since user can choose to run on bit-banging host +if(FAMILY STREQUAL "rp2040") + family_add_pico_pio_usb(${PROJECT}) +endif() diff --git a/examples/host/hid_controller/Makefile b/examples/host/hid_controller/Makefile index 06dc56914..cda2977bc 100644 --- a/examples/host/hid_controller/Makefile +++ b/examples/host/hid_controller/Makefile @@ -1,4 +1,3 @@ -include ../../../tools/top.mk include ../../make.mk INC += \ @@ -12,9 +11,6 @@ EXAMPLE_SOURCE += \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -# TODO: suppress warning caused by host stack -CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference - # TinyUSB Host Stack source SRC_C += \ src/class/cdc/cdc_host.c \ diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c index 582e01959..76de97b41 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -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,7 +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 @@ -180,8 +245,8 @@ 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; } @@ -235,6 +300,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; } } diff --git a/examples/host/hid_controller/src/main.c b/examples/host/hid_controller/src/main.c index 13d1d6cdb..4dcc92587 100644 --- a/examples/host/hid_controller/src/main.c +++ b/examples/host/hid_controller/src/main.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h index 475b9ca8f..2e0dd0dbe 100644 --- a/examples/host/hid_controller/src/tusb_config.h +++ b/examples/host/hid_controller/src/tusb_config.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -34,6 +34,12 @@ // 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 @@ -95,9 +101,8 @@ #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 -------------// diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt new file mode 100644 index 000000000..7955b3078 --- /dev/null +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 3.5) + +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}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +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 + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${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}) + +# Add pico-pio-usb for rp2040 since user can choose to run on bit-banging host +if(FAMILY STREQUAL "rp2040") + family_add_pico_pio_usb(${PROJECT}) +endif() diff --git a/examples/host/msc_file_explorer/Makefile b/examples/host/msc_file_explorer/Makefile new file mode 100644 index 000000000..1fda72b18 --- /dev/null +++ b/examples/host/msc_file_explorer/Makefile @@ -0,0 +1,37 @@ +include ../../make.mk + +FATFS_PATH = lib/fatfs/source + +INC += \ + src \ + $(TOP)/hw \ + $(TOP)/$(FATFS_PATH) \ + $(TOP)/lib/embedded-cli \ + +# Example source +EXAMPLE_SOURCE = \ + src/main.c \ + src/msc_app.c \ + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +# FatFS source +SRC_C += \ + $(FATFS_PATH)/ff.c \ + $(FATFS_PATH)/ffsystem.c \ + $(FATFS_PATH)/ffunicode.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 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt new file mode 100644 index 000000000..fa9c14857 --- /dev/null +++ b/examples/host/msc_file_explorer/only.txt @@ -0,0 +1,11 @@ +mcu:LPC175X_6X +mcu:LPC177X_8X +mcu:LPC18XX +mcu:LPC40XX +mcu:LPC43XX +mcu:MIMXRT +mcu:MIMXRT10XX +mcu:MIMXRT11XX +mcu:RP2040 +mcu:MSP432E4 +mcu:RX65X diff --git a/examples/host/msc_file_explorer/src/main.c b/examples/host/msc_file_explorer/src/main.c new file mode 100644 index 000000000..7b1c2ef27 --- /dev/null +++ b/examples/host/msc_file_explorer/src/main.c @@ -0,0 +1,127 @@ +/* + * 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. + * + */ + +/* 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 "tusb.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) +{ + board_init(); + + printf("TinyUSB Host MassStorage Explorer Example\r\n"); + + // init host stack on configured roothub port + tuh_init(BOARD_TUH_RHPORT); + msc_app_init(); + + while (1) + { + // tinyusb host task + tuh_task(); + + msc_app_task(); + led_blinking_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +void tuh_mount_cb(uint8_t dev_addr) +{ + (void) dev_addr; +} + +void tuh_umount_cb(uint8_t dev_addr) +{ + (void) dev_addr; +} + +//--------------------------------------------------------------------+ +// 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 +} diff --git a/examples/host/msc_file_explorer/src/msc_app.c b/examples/host/msc_file_explorer/src/msc_app.c new file mode 100644 index 000000000..003e2865b --- /dev/null +++ b/examples/host/msc_file_explorer/src/msc_app.c @@ -0,0 +1,640 @@ +/* + * 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 <ctype.h> +#include "tusb.h" +#include "bsp/board.h" + +#include "ff.h" +#include "diskio.h" + +// lib/embedded-cli +#define EMBEDDED_CLI_IMPL +#include "embedded_cli.h" + + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +//------------- embedded-cli -------------// +#define CLI_BUFFER_SIZE 512 +#define CLI_RX_BUFFER_SIZE 16 +#define CLI_CMD_BUFFER_SIZE 64 +#define CLI_HISTORY_SIZE 32 +#define CLI_BINDING_COUNT 8 + +static EmbeddedCli *_cli; +static CLI_UINT cli_buffer[BYTES_TO_CLI_UINTS(CLI_BUFFER_SIZE)]; + +//------------- Elm Chan FatFS -------------// +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; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +bool cli_init(void); + +bool msc_app_init(void) +{ + for(size_t i=0; i<CFG_TUH_DEVICE_MAX; i++) _disk_busy[i] = false; + + // disable stdout buffered for echoing typing command + setbuf(stdout, NULL); + cli_init(); + + return true; +} + +void msc_app_task(void) +{ + if (!_cli) return; + + int ch = board_getchar(); + if ( ch > 0 ) + { + while( ch > 0 ) + { + embeddedCliReceiveChar(_cli, (char) ch); + ch = board_getchar(); + } + embeddedCliProcess(_cli); + } +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + + +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: %lu 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 + uint8_t const drive_num = dev_addr-1; + char drive_path[3] = "0:"; + drive_path[0] += drive_num; + + if ( f_mount(&fatfs[drive_num], drive_path, 1) != FR_OK ) + { + puts("mount failed"); + } + + // change to newly mounted drive + f_chdir(drive_path); + + // print the drive label +// char label[34]; +// if ( FR_OK == f_getlabel(drive_path, label, NULL) ) +// { +// puts(label); +// } + + 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) +{ + printf("A MassStorage device is unmounted\r\n"); + + uint8_t const drive_num = dev_addr-1; + char drive_path[3] = "0:"; + drive_path[0] += drive_num; + + f_unmount(drive_path); + +// 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 +// } +// } +// } +} + +//--------------------------------------------------------------------+ +// DiskIO +//--------------------------------------------------------------------+ + +static void wait_for_disk_io(BYTE pdrv) +{ + while(_disk_busy[pdrv]) + { + tuh_task(); + } +} + +static bool disk_io_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) +{ + (void) dev_addr; (void) cb_data; + _disk_busy[dev_addr-1] = false; + return true; +} + +DSTATUS disk_status ( + BYTE pdrv /* Physical drive nmuber to identify the drive */ +) +{ + uint8_t dev_addr = pdrv + 1; + return tuh_msc_mounted(dev_addr) ? 0 : STA_NODISK; +} + +DSTATUS disk_initialize ( + BYTE pdrv /* Physical drive nmuber to identify the drive */ +) +{ + (void) pdrv; + return 0; // nothing to do +} + +DRESULT disk_read ( + BYTE pdrv, /* Physical drive nmuber to identify the drive */ + BYTE *buff, /* Data buffer to store read data */ + LBA_t sector, /* Start sector in LBA */ + UINT count /* Number of sectors to read */ +) +{ + uint8_t const dev_addr = pdrv + 1; + uint8_t const lun = 0; + + _disk_busy[pdrv] = true; + tuh_msc_read10(dev_addr, lun, buff, sector, (uint16_t) count, disk_io_complete, 0); + wait_for_disk_io(pdrv); + + return RES_OK; +} + +#if FF_FS_READONLY == 0 + +DRESULT disk_write ( + BYTE pdrv, /* Physical drive nmuber to identify the drive */ + const BYTE *buff, /* Data to be written */ + LBA_t sector, /* Start sector in LBA */ + UINT count /* Number of sectors to write */ +) +{ + uint8_t const dev_addr = pdrv + 1; + uint8_t const lun = 0; + + _disk_busy[pdrv] = true; + tuh_msc_write10(dev_addr, lun, buff, sector, (uint16_t) count, disk_io_complete, 0); + wait_for_disk_io(pdrv); + + return RES_OK; +} + +#endif + +DRESULT disk_ioctl ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE cmd, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + uint8_t const dev_addr = pdrv + 1; + uint8_t const lun = 0; + switch ( cmd ) + { + case CTRL_SYNC: + // nothing to do since we do blocking + return RES_OK; + + case GET_SECTOR_COUNT: + *((DWORD*) buff) = (WORD) tuh_msc_get_block_count(dev_addr, lun); + return RES_OK; + + case GET_SECTOR_SIZE: + *((WORD*) buff) = (WORD) tuh_msc_get_block_size(dev_addr, lun); + return RES_OK; + + case GET_BLOCK_SIZE: + *((DWORD*) buff) = 1; // erase block size in units of sector size + return RES_OK; + + default: + return RES_PARERR; + } + + return RES_OK; +} + +//--------------------------------------------------------------------+ +// CLI Commands +//--------------------------------------------------------------------+ + +void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context); +void cli_cmd_cd(EmbeddedCli *cli, char *args, void *context); +void cli_cmd_cp(EmbeddedCli *cli, char *args, void *context); +void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context); +void cli_cmd_pwd(EmbeddedCli *cli, char *args, void *context); +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) +{ + (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(); + config->cliBuffer = cli_buffer; + config->cliBufferSize = CLI_BUFFER_SIZE; + config->rxBufferSize = CLI_RX_BUFFER_SIZE; + config->cmdBufferSize = CLI_CMD_BUFFER_SIZE; + config->historyBufferSize = CLI_HISTORY_SIZE; + config->maxBindingCount = CLI_BINDING_COUNT; + + TU_ASSERT(embeddedCliRequiredSize(config) <= CLI_BUFFER_SIZE); + + _cli = embeddedCliNew(config); + TU_ASSERT(_cli != NULL); + + _cli->writeChar = cli_write_char; + + embeddedCliAddBinding(_cli, (CliCommandBinding) { + "cat", + "Usage: cat [FILE]...\r\n\tConcatenate FILE(s) to standard output..", + true, + NULL, + cli_cmd_cat + }); + + embeddedCliAddBinding(_cli, (CliCommandBinding) { + "cd", + "Usage: cd [DIR]...\r\n\tChange the current directory to DIR.", + true, + NULL, + cli_cmd_cd + }); + + embeddedCliAddBinding(_cli, (CliCommandBinding) { + "cp", + "Usage: cp SOURCE DEST\r\n\tCopy SOURCE to DEST.", + true, + NULL, + cli_cmd_cp + }); + + embeddedCliAddBinding(_cli, (CliCommandBinding) { + "ls", + "Usage: ls [DIR]...\r\n\tList information about the FILEs (the current directory by default).", + true, + NULL, + cli_cmd_ls + }); + + embeddedCliAddBinding(_cli, (CliCommandBinding) { + "pwd", + "Usage: pwd\r\n\tPrint the name of the current working directory.", + true, + NULL, + cli_cmd_pwd + }); + + embeddedCliAddBinding(_cli, (CliCommandBinding) { + "mkdir", + "Usage: mkdir DIR...\r\n\tCreate the DIRECTORY(ies), if they do not already exist..", + true, + NULL, + cli_cmd_mkdir + }); + + embeddedCliAddBinding(_cli, (CliCommandBinding) { + "mv", + "Usage: mv SOURCE DEST...\r\n\tRename SOURCE to DEST.", + true, + NULL, + cli_cmd_mv + }); + + embeddedCliAddBinding(_cli, (CliCommandBinding) { + "rm", + "Usage: rm [FILE]...\r\n\tRemove (unlink) the FILE(s).", + true, + NULL, + cli_cmd_rm + }); + + return true; +} + +void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context) +{ + (void) cli; (void) context; + + uint16_t argc = embeddedCliGetTokenCount(args); + + // need at least 1 argument + if ( argc == 0 ) + { + printf("invalid arguments\r\n"); + return; + } + + for(uint16_t i=0; i<argc; i++) + { + FIL fi; + const char* fpath = embeddedCliGetToken(args, i+1); // token count from 1 + + if ( FR_OK != f_open(&fi, fpath, FA_READ) ) + { + printf("%s: No such file or directory\r\n", fpath); + }else + { + uint8_t buf[512]; + UINT count = 0; + while ( (FR_OK == f_read(&fi, buf, sizeof(buf), &count)) && (count > 0) ) + { + for(UINT c = 0; c < count; c++) + { + const uint8_t ch = buf[c]; + if (isprint(ch) || iscntrl(ch)) + { + putchar(ch); + }else + { + putchar('.'); + } + } + } + } + + f_close(&fi); + } +} + +void cli_cmd_cd(EmbeddedCli *cli, char *args, void *context) +{ + (void) cli; (void) context; + + uint16_t argc = embeddedCliGetTokenCount(args); + + // only support 1 argument + if ( argc != 1 ) + { + printf("invalid arguments\r\n"); + return; + } + + // default is current directory + const char* dpath = args; + + if ( FR_OK != f_chdir(dpath) ) + { + printf("%s: No such file or directory\r\n", dpath); + return; + } +} + +void cli_cmd_cp(EmbeddedCli *cli, char *args, void *context) +{ + (void) cli; (void) context; + + uint16_t argc = embeddedCliGetTokenCount(args); + if ( argc != 2 ) + { + printf("invalid arguments\r\n"); + return; + } + + // default is current directory + const char* src = embeddedCliGetToken(args, 1); + const char* dst = embeddedCliGetToken(args, 2); + + FIL f_src; + FIL f_dst; + + if ( FR_OK != f_open(&f_src, src, FA_READ) ) + { + printf("cannot stat '%s': No such file or directory\r\n", src); + return; + } + + if ( FR_OK != f_open(&f_dst, dst, FA_WRITE | FA_CREATE_ALWAYS) ) + { + printf("cannot create '%s'\r\n", dst); + return; + }else + { + uint8_t buf[512]; + UINT rd_count = 0; + while ( (FR_OK == f_read(&f_src, buf, sizeof(buf), &rd_count)) && (rd_count > 0) ) + { + UINT wr_count = 0; + + if ( FR_OK != f_write(&f_dst, buf, rd_count, &wr_count) ) + { + printf("cannot write to '%s'\r\n", dst); + break; + } + } + } + + f_close(&f_src); + f_close(&f_dst); +} + +void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context) +{ + (void) cli; (void) context; + + uint16_t argc = embeddedCliGetTokenCount(args); + + // only support 1 argument + if ( argc > 1 ) + { + printf("invalid arguments\r\n"); + return; + } + + // default is current directory + const char* dpath = "."; + if (argc) dpath = args; + + DIR dir; + if ( FR_OK != f_opendir(&dir, dpath) ) + { + printf("cannot access '%s': No such file or directory\r\n", dpath); + return; + } + + FILINFO fno; + while( (f_readdir(&dir, &fno) == FR_OK) && (fno.fname[0] != 0) ) + { + if ( fno.fname[0] != '.' ) // ignore . and .. entry + { + if ( fno.fattrib & AM_DIR ) + { + // directory + printf("/%s\r\n", fno.fname); + }else + { + printf("%-40s", fno.fname); + if (fno.fsize < 1024) + { + printf("%lu B\r\n", fno.fsize); + }else + { + printf("%lu KB\r\n", fno.fsize / 1024); + } + } + } + } + + f_closedir(&dir); +} + +void cli_cmd_pwd(EmbeddedCli *cli, char *args, void *context) +{ + (void) cli; (void) context; + uint16_t argc = embeddedCliGetTokenCount(args); + + if (argc != 0) + { + printf("invalid arguments\r\n"); + return; + } + + char path[256]; + if (FR_OK != f_getcwd(path, sizeof(path))) + { + printf("cannot get current working directory\r\n"); + } + + puts(path); +} + +void cli_cmd_mkdir(EmbeddedCli *cli, char *args, void *context) +{ + (void) cli; (void) context; + + uint16_t argc = embeddedCliGetTokenCount(args); + + // only support 1 argument + if ( argc != 1 ) + { + printf("invalid arguments\r\n"); + return; + } + + // default is current directory + const char* dpath = args; + + if ( FR_OK != f_mkdir(dpath) ) + { + printf("%s: cannot create this directory\r\n", dpath); + return; + } +} + +void cli_cmd_mv(EmbeddedCli *cli, char *args, void *context) +{ + (void) cli; (void) context; + + uint16_t argc = embeddedCliGetTokenCount(args); + if ( argc != 2 ) + { + printf("invalid arguments\r\n"); + return; + } + + // default is current directory + const char* src = embeddedCliGetToken(args, 1); + const char* dst = embeddedCliGetToken(args, 2); + + if ( FR_OK != f_rename(src, dst) ) + { + printf("cannot mv %s to %s\r\n", src, dst); + return; + } +} + +void cli_cmd_rm(EmbeddedCli *cli, char *args, void *context) +{ + (void) cli; (void) context; + + uint16_t argc = embeddedCliGetTokenCount(args); + + // need at least 1 argument + if ( argc == 0 ) + { + printf("invalid arguments\r\n"); + return; + } + + for(uint16_t i=0; i<argc; i++) + { + const char* fpath = embeddedCliGetToken(args, i+1); // token count from 1 + + if ( FR_OK != f_unlink(fpath) ) + { + printf("cannot remove '%s': No such file or directory\r\n", fpath); + } + } +} diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h new file mode 100644 index 000000000..eaf3ea6d4 --- /dev/null +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -0,0 +1,114 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +#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 +//-------------------------------------------------------------------- + +// 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_NONE +#endif + +#ifndef CFG_TUSB_DEBUG +#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. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// 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_MSC 1 +#define CFG_TUH_CDC 0 +#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): 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 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ |
