diff options
| author | Andrzej Tokarski <[email protected]> | 2022-11-21 21:45:10 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-11-21 21:45:10 +0100 |
| commit | b41f5eadb3143d0bfaf211d9bc84c95e5d623c29 (patch) | |
| tree | 313da7c8988a2b443e6ab5647fa1177e84e424a6 /examples/host | |
| parent | 89eac75085134d570dc26dffaf3d8f204aef5359 (diff) | |
| parent | 4a2e424103b0a2626a6cb464a350c68ae109cc7e (diff) | |
Merge branch 'master' into midihost
Diffstat (limited to 'examples/host')
| -rw-r--r-- | examples/host/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | examples/host/bare_api/Makefile | 3 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/CMakeLists.txt | 14 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/Makefile | 9 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/src/main.c | 8 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/src/msc_app.c | 3 | ||||
| -rw-r--r-- | examples/host/cdc_msc_hid/src/tusb_config.h | 6 | ||||
| -rw-r--r-- | examples/host/hid_controller/Makefile | 3 | ||||
| -rw-r--r-- | examples/host/hid_controller/src/hid_app.c | 1 | ||||
| -rw-r--r-- | examples/host/msc_file_explorer/CMakeLists.txt | 48 | ||||
| -rw-r--r-- | examples/host/msc_file_explorer/Makefile | 38 | ||||
| -rw-r--r-- | examples/host/msc_file_explorer/only.txt | 11 | ||||
| -rw-r--r-- | examples/host/msc_file_explorer/src/main.c | 95 | ||||
| -rw-r--r-- | examples/host/msc_file_explorer/src/msc_app.c | 637 | ||||
| -rw-r--r-- | examples/host/msc_file_explorer/src/tusb_config.h | 114 |
15 files changed, 970 insertions, 24 deletions
diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index 39a41c4ae..025b4670c 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -6,6 +6,8 @@ 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(midi_rx)
\ No newline at end of file +family_add_subdirectory(midi_rx) +family_add_subdirectory(msc_file_explorer) diff --git a/examples/host/bare_api/Makefile b/examples/host/bare_api/Makefile index 13e14df53..84555a889 100644 --- a/examples/host/bare_api/Makefile +++ b/examples/host/bare_api/Makefile @@ -11,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/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index c4a4d8e63..5b44ef217 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -29,4 +29,16 @@ target_include_directories(${PROJECT} PUBLIC family_configure_host_example(${PROJECT}) # For rp2040, un-comment to enable pico-pio-usb -# family_add_pico_pio_usb(${PROJECT}) +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 + ) diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 272acbac8..ad28076a0 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -6,11 +6,12 @@ INC += \ $(TOP)/hw \ # Example source -EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +EXAMPLE_SOURCE = \ + 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/main.c b/examples/host/cdc_msc_hid/src/main.c index 664cbf035..d26e41e8d 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -54,13 +54,8 @@ int main(void) tuh_task(); led_blinking_task(); -#if CFG_TUH_CDC cdc_task(); -#endif - -#if CFG_TUH_HID hid_app_task(); -#endif } return 0; @@ -69,7 +64,6 @@ int main(void) //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ -#if CFG_TUH_CDC CFG_TUSB_MEM_SECTION static char serial_in_buffer[64] = { 0 }; // invoked ISR context @@ -90,8 +84,6 @@ 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..80a5eab6f 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -25,8 +25,6 @@ #include "tusb.h" -#if CFG_TUH_MSC - //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -103,4 +101,3 @@ void tuh_msc_umount_cb(uint8_t dev_addr) // } } -#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..c515405cb 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -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 diff --git a/examples/host/hid_controller/Makefile b/examples/host/hid_controller/Makefile index 06dc56914..e7fbd741f 100644 --- a/examples/host/hid_controller/Makefile +++ b/examples/host/hid_controller/Makefile @@ -12,9 +12,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..75c91400e 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -162,7 +162,6 @@ 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); - } // check if different than 2 diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt new file mode 100644 index 000000000..5d443ea9b --- /dev/null +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -0,0 +1,48 @@ +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}) + +# 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 + ) diff --git a/examples/host/msc_file_explorer/Makefile b/examples/host/msc_file_explorer/Makefile new file mode 100644 index 000000000..de2f9c01c --- /dev/null +++ b/examples/host/msc_file_explorer/Makefile @@ -0,0 +1,38 @@ +include ../../../tools/top.mk +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..ab2cfd498 --- /dev/null +++ b/examples/host/msc_file_explorer/src/main.c @@ -0,0 +1,95 @@ +/* + * 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.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..aa193f3ce --- /dev/null +++ b/examples/host/msc_file_explorer/src/msc_app.c @@ -0,0 +1,637 @@ +/* + * 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, msc_cbw_t const* cbw, msc_csw_t const* 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); +} + +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, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + (void) dev_addr; (void) cbw; (void) csw; + _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); + 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); + 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 char 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..ddf8368f4 --- /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) +#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports + +//------------- MSC -------------// +#define CFG_TUH_MSC_MAXLUN 4 // typical for most card reader + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ |
