From 86b3e3174dcb68522e3f72c18ef5830b4e6aef53 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 16 Oct 2013 12:05:48 +0700 Subject: [PATCH] refine mouse demo --- demos/bsp/boards/ansi_escape.h | 209 ++++---- demos/bsp/boards/board.h | 277 +++++------ demos/host/src/cli.c | 877 ++++++++++++++++----------------- demos/host/src/main.c | 526 ++++++++++---------- demos/host/src/mouse_app.c | 370 +++++++------- 5 files changed, 1141 insertions(+), 1118 deletions(-) diff --git a/demos/bsp/boards/ansi_escape.h b/demos/bsp/boards/ansi_escape.h index a309b225..c0b59c07 100644 --- a/demos/bsp/boards/ansi_escape.h +++ b/demos/bsp/boards/ansi_escape.h @@ -1,103 +1,106 @@ -/**************************************************************************/ -/*! - @file ansi_esc_code.h - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -/** \file - * \brief TBD - * - * \note TBD - */ - -/** \ingroup TBD - * \defgroup TBD - * \brief TBD - * - * @{ - */ - -#ifndef _TUSB_ANSI_ESC_CODE_H_ -#define _TUSB_ANSI_ESC_CODE_H_ - - -#ifdef __cplusplus - extern "C" { -#endif - -#define CSI_CODE(seq) "\33[" seq -#define CSI_SGR(x) CSI_CODE(#x) "m" - -//------------- Cursor movement -------------// -#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A") -#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B") -#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C") -#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D") -#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E") -#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F") -#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H") - -#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J") -#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K") - -/** text color */ -#define ANSI_TEXT_BLACK CSI_SGR(30) -#define ANSI_TEXT_RED CSI_SGR(31) -#define ANSI_TEXT_GREEN CSI_SGR(32) -#define ANSI_TEXT_YELLOW CSI_SGR(33) -#define ANSI_TEXT_BLUE CSI_SGR(34) -#define ANSI_TEXT_MAGENTA CSI_SGR(35) -#define ANSI_TEXT_CYAN CSI_SGR(36) -#define ANSI_TEXT_WHITE CSI_SGR(37) -#define ANSI_TEXT_DEFAULT CSI_SGR(39) - -/** background color */ -#define ANSI_BG_BLACK CSI_SGR(40) -#define ANSI_BG_RED CSI_SGR(41) -#define ANSI_BG_GREEN CSI_SGR(42) -#define ANSI_BG_YELLOW CSI_SGR(43) -#define ANSI_BG_BLUE CSI_SGR(44) -#define ANSI_BG_MAGENTA CSI_SGR(45) -#define ANSI_BG_CYAN CSI_SGR(46) -#define ANSI_BG_WHITE CSI_SGR(47) -#define ANSI_BG_DEFAULT CSI_SGR(49) - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_ANSI_ESC_CODE_H_ */ - -/** @} */ +/**************************************************************************/ +/*! + @file ansi_esc_code.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \file + * \brief TBD + * + * \note TBD + */ + +/** \ingroup TBD + * \defgroup TBD + * \brief TBD + * + * @{ + */ + +#ifndef _TUSB_ANSI_ESC_CODE_H_ +#define _TUSB_ANSI_ESC_CODE_H_ + + +#ifdef __cplusplus + extern "C" { +#endif + +#define CSI_CODE(seq) "\33[" seq +#define CSI_SGR(x) CSI_CODE(#x) "m" + +//------------- Cursor movement -------------// +#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A") +#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B") +#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C") +#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D") +#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E") +#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F") +#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H") + +#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J") +#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K") + +#define ANSI_SCROLL_UP(n) CSI_CODE(#n "S") +#define ANSI_SCROLL_DOWN(n) CSI_CODE(#n "T") + +/** text color */ +#define ANSI_TEXT_BLACK CSI_SGR(30) +#define ANSI_TEXT_RED CSI_SGR(31) +#define ANSI_TEXT_GREEN CSI_SGR(32) +#define ANSI_TEXT_YELLOW CSI_SGR(33) +#define ANSI_TEXT_BLUE CSI_SGR(34) +#define ANSI_TEXT_MAGENTA CSI_SGR(35) +#define ANSI_TEXT_CYAN CSI_SGR(36) +#define ANSI_TEXT_WHITE CSI_SGR(37) +#define ANSI_TEXT_DEFAULT CSI_SGR(39) + +/** background color */ +#define ANSI_BG_BLACK CSI_SGR(40) +#define ANSI_BG_RED CSI_SGR(41) +#define ANSI_BG_GREEN CSI_SGR(42) +#define ANSI_BG_YELLOW CSI_SGR(43) +#define ANSI_BG_BLUE CSI_SGR(44) +#define ANSI_BG_MAGENTA CSI_SGR(45) +#define ANSI_BG_CYAN CSI_SGR(46) +#define ANSI_BG_WHITE CSI_SGR(47) +#define ANSI_BG_DEFAULT CSI_SGR(49) + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_ANSI_ESC_CODE_H_ */ + +/** @} */ diff --git a/demos/bsp/boards/board.h b/demos/bsp/boards/board.h index 7bbd96ac..49eddc77 100644 --- a/demos/bsp/boards/board.h +++ b/demos/bsp/boards/board.h @@ -1,138 +1,139 @@ -/**************************************************************************/ -/*! - @file board.h - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -/** \file - * \brief TBD - * - * \note TBD - */ - -/** - * \defgroup Group_Board Boards - * \brief TBD - * - * @{ - */ - -#ifndef _TUSB_BOARD_H_ -#define _TUSB_BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#include -#include - -#include "tusb.h" - -//--------------------------------------------------------------------+ -// BOARD DEFINE -//--------------------------------------------------------------------+ -#define BOARD_RF1GHZNODE 1 -#define BOARD_LPCXPRESSO1347 2 - -#define BOARD_NGX4330 3 -#define BOARD_EA4357 4 -#define BOARD_MCB4300 5 -#define BOARD_HITEX4350 6 -#define BOARD_LPCXPRESSO1769 7 - -#define BOARD_LPC4357USB 8 - -//--------------------------------------------------------------------+ -// PRINTF TARGET DEFINE -//--------------------------------------------------------------------+ -#define PRINTF_TARGET_SEMIHOST 1 -#define PRINTF_TARGET_UART 2 -#define PRINTF_TARGET_SWO 3 // aka SWV, ITM -#define PRINTF_TARGET_NONE 4 - -#define PRINTF(...) printf(__VA_ARGS__) - -#if BOARD == 0 - #error BOARD is not defined or supported yet -#elif BOARD == BOARD_NGX4330 - #include "ngx/board_ngx4330.h" -#elif BOARD == BOARD_LPCXPRESSO1347 - #include "lpcxpresso/board_lpcxpresso1347.h" -#elif BOARD == BOARD_RF1GHZNODE - #include "microbuilder/board_rf1ghznode.h" -#elif BOARD == BOARD_EA4357 - #include "embedded_artists/board_ea4357.h" -#elif BOARD == BOARD_MCB4300 - #include "keil/board_mcb4300.h" -#elif BOARD == BOARD_HITEX4350 - #include "hitex/board_hitex4350.h" -#elif BOARD == BOARD_LPCXPRESSO1769 - #include "lpcxpresso/board_lpcxpresso1769.h" -#elif BOARD == BOARD_LPC4357USB - #include "microbuilder/board_lpc4357usb.h" -#else - #error BOARD is not defined or supported yet -#endif - -//--------------------------------------------------------------------+ -// Common Configuration -//--------------------------------------------------------------------+ -#define CFG_TICKS_PER_SECOND 1000 - -#if CFG_PRINTF_TARGET == PRINTF_TARGET_UART - #define CFG_UART_ENABLE 1 - #define CFG_UART_BAUDRATE 115200 -#endif - -//--------------------------------------------------------------------+ -// Board Common API -//--------------------------------------------------------------------+ -// Init board peripherals : Clock, UART, LEDs, Buttons -void board_init(void); -void board_leds(uint32_t on_mask, uint32_t off_mask); -uint32_t board_uart_send(uint8_t *buffer, uint32_t length); -uint32_t board_uart_recv(uint8_t *buffer, uint32_t length); -uint8_t board_uart_getchar(void); - -extern volatile uint32_t system_ticks; - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_BOARD_H_ */ - -/** @} */ +/**************************************************************************/ +/*! + @file board.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \file + * \brief TBD + * + * \note TBD + */ + +/** + * \defgroup Group_Board Boards + * \brief TBD + * + * @{ + */ + +#ifndef _TUSB_BOARD_H_ +#define _TUSB_BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include +#include + +#include "ansi_escape.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// BOARD DEFINE +//--------------------------------------------------------------------+ +#define BOARD_RF1GHZNODE 1 +#define BOARD_LPCXPRESSO1347 2 + +#define BOARD_NGX4330 3 +#define BOARD_EA4357 4 +#define BOARD_MCB4300 5 +#define BOARD_HITEX4350 6 +#define BOARD_LPCXPRESSO1769 7 + +#define BOARD_LPC4357USB 8 + +//--------------------------------------------------------------------+ +// PRINTF TARGET DEFINE +//--------------------------------------------------------------------+ +#define PRINTF_TARGET_SEMIHOST 1 +#define PRINTF_TARGET_UART 2 +#define PRINTF_TARGET_SWO 3 // aka SWV, ITM +#define PRINTF_TARGET_NONE 4 + +#define PRINTF(...) printf(__VA_ARGS__) + +#if BOARD == 0 + #error BOARD is not defined or supported yet +#elif BOARD == BOARD_NGX4330 + #include "ngx/board_ngx4330.h" +#elif BOARD == BOARD_LPCXPRESSO1347 + #include "lpcxpresso/board_lpcxpresso1347.h" +#elif BOARD == BOARD_RF1GHZNODE + #include "microbuilder/board_rf1ghznode.h" +#elif BOARD == BOARD_EA4357 + #include "embedded_artists/board_ea4357.h" +#elif BOARD == BOARD_MCB4300 + #include "keil/board_mcb4300.h" +#elif BOARD == BOARD_HITEX4350 + #include "hitex/board_hitex4350.h" +#elif BOARD == BOARD_LPCXPRESSO1769 + #include "lpcxpresso/board_lpcxpresso1769.h" +#elif BOARD == BOARD_LPC4357USB + #include "microbuilder/board_lpc4357usb.h" +#else + #error BOARD is not defined or supported yet +#endif + +//--------------------------------------------------------------------+ +// Common Configuration +//--------------------------------------------------------------------+ +#define CFG_TICKS_PER_SECOND 1000 + +#if CFG_PRINTF_TARGET == PRINTF_TARGET_UART + #define CFG_UART_ENABLE 1 + #define CFG_UART_BAUDRATE 115200 +#endif + +//--------------------------------------------------------------------+ +// Board Common API +//--------------------------------------------------------------------+ +// Init board peripherals : Clock, UART, LEDs, Buttons +void board_init(void); +void board_leds(uint32_t on_mask, uint32_t off_mask); +uint32_t board_uart_send(uint8_t *buffer, uint32_t length); +uint32_t board_uart_recv(uint8_t *buffer, uint32_t length); +uint8_t board_uart_getchar(void); + +extern volatile uint32_t system_ticks; + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_BOARD_H_ */ + +/** @} */ diff --git a/demos/host/src/cli.c b/demos/host/src/cli.c index d507cc60..a9bef79a 100644 --- a/demos/host/src/cli.c +++ b/demos/host/src/cli.c @@ -1,439 +1,438 @@ -/**************************************************************************/ -/*! - @file cli.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/**************************************************************************/ - -#include "cli.h" -#include "ctype.h" - -#if TUSB_CFG_HOST_MSC - -#include "ff.h" -#include "diskio.h" -#include "boards/ansi_escape.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define CLI_MAX_BUFFER 256 -#define CLI_FILE_READ_BUFFER (4*1024) - -enum { - ASCII_BACKSPACE = 8, -}; - -typedef enum { - CLI_ERROR_NONE = 0, - CLI_ERROR_INVALID_PARA, - CLI_ERROR_INVALID_PATH, - CLI_ERROR_FILE_EXISTED, - CLI_ERROR_FAILED -}cli_error_t; - -static char const * const cli_error_message[] = -{ - [CLI_ERROR_NONE ] = 0, - [CLI_ERROR_INVALID_PARA ] = "Invalid parameter(s)", - [CLI_ERROR_INVALID_PATH ] = "No such file or directory", - [CLI_ERROR_FILE_EXISTED ] = "file or directory already exists", - [CLI_ERROR_FAILED ] = "failed to execute" -}; - -//--------------------------------------------------------------------+ -// CLI Database definition -//--------------------------------------------------------------------+ - -// command, function, description -#define CLI_COMMAND_TABLE(ENTRY) \ - ENTRY(unknown , cli_cmd_unknown , NULL ) \ - ENTRY(help , cli_cmd_help , NULL ) \ - ENTRY(cls , cli_cmd_clear , "Clear the screen." ) \ - ENTRY(ls , cli_cmd_list , "List information about the FILEs (the current directory by default).") \ - ENTRY(cd , cli_cmd_changedir, "change the current directory." ) \ - ENTRY(cat , cli_cmd_cat , "display contents of a file." ) \ - ENTRY(cp , cli_cmd_copy , "Copies one or more files to another location." ) \ - ENTRY(mkdir , cli_cmd_mkdir , "Create a DIRECTORY, if it does not already exist." ) \ - -//--------------------------------------------------------------------+ -// Expands the function to have the standard function signature -//--------------------------------------------------------------------+ -#define CLI_PROTOTYPE_EXPAND(command, function, description) \ - cli_error_t function(char *); - -CLI_COMMAND_TABLE(CLI_PROTOTYPE_EXPAND); - -//--------------------------------------------------------------------+ -// Expand to enum value -//--------------------------------------------------------------------+ -#define CLI_ENUM_EXPAND(command, function, description) CLI_CMDTYPE_##command, -typedef enum { - CLI_COMMAND_TABLE(CLI_ENUM_EXPAND) - CLI_CMDTYPE_COUNT -}cli_cmdtype_t; - -//--------------------------------------------------------------------+ -// Expand to string table -//--------------------------------------------------------------------+ -#define CLI_STRING_EXPAND(command, function, description) #command, -char const* const cli_string_tbl[] = -{ - CLI_COMMAND_TABLE(CLI_STRING_EXPAND) - 0 -}; - -//--------------------------------------------------------------------+ -// Expand to Description table -//--------------------------------------------------------------------+ -#define CLI_DESCRIPTION_EXPAND(command, function, description) description, -char const* const cli_description_tbl[] = -{ - CLI_COMMAND_TABLE(CLI_DESCRIPTION_EXPAND) - 0 -}; - - -//--------------------------------------------------------------------+ -// Expand to Command Lookup Table -//--------------------------------------------------------------------+ -#define CMD_LOOKUP_EXPAND(command, function, description)\ - [CLI_CMDTYPE_##command] = function,\ - -typedef cli_error_t (* const cli_cmdfunc_t)(char *); -static cli_cmdfunc_t cli_command_tbl[] = -{ - CLI_COMMAND_TABLE(CMD_LOOKUP_EXPAND) -}; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static char cli_buffer[CLI_MAX_BUFFER]; -uint8_t fileread_buffer[CLI_FILE_READ_BUFFER] TUSB_CFG_ATTR_USBRAM; -static char volume_label[20]; - -static inline void drive_number2letter(char * p_path) ATTR_ALWAYS_INLINE; -static inline void drive_number2letter(char * p_path) -{ - if (p_path[1] == ':') - { - p_path[0] = 'E' + p_path[0] - '0' ; - } -} - -static inline void drive_letter2number(char * p_path) ATTR_ALWAYS_INLINE; -static inline void drive_letter2number(char * p_path) -{ - if (p_path[1] == ':') - { - p_path[0] = p_path[0] - 'E' + '0'; - } -} - - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ -// NOTES: prompt re-use cli_buffer --> should not be called when cli_buffer has contents -void cli_command_prompt(void) -{ - f_getcwd(cli_buffer, CLI_MAX_BUFFER); - drive_number2letter(cli_buffer); - printf("\n%s %s\n$ ", - (volume_label[0] !=0) ? volume_label : "No Label", - cli_buffer); - - memclr_(cli_buffer, CLI_MAX_BUFFER); -} - -void cli_init(void) -{ - memclr_(cli_buffer, CLI_MAX_BUFFER); - f_getlabel(NULL, volume_label, NULL); - cli_command_prompt(); -} - -void cli_poll(char ch) -{ - if ( isprint(ch) ) - { // accumulate & echo - if (strlen(cli_buffer) < CLI_MAX_BUFFER) - { - cli_buffer[ strlen(cli_buffer) ] = ch; - putchar(ch); - }else - { - puts("cli buffer overflows"); - memclr_(cli_buffer, CLI_MAX_BUFFER); - } - } - else if ( ch == ASCII_BACKSPACE && strlen(cli_buffer)) - { - printf(ANSI_CURSOR_BACKWARD(1) ANSI_ERASE_LINE(0) ); // move cursor back & clear to the end of line - cli_buffer[ strlen(cli_buffer)-1 ] = 0; - } - else if ( ch == '\r') - { // execute command - //------------- Separate Command & Parameter -------------// - putchar('\n'); - char* p_space = strchr(cli_buffer, ' '); - uint32_t command_len = (p_space == NULL) ? strlen(cli_buffer) : (p_space - cli_buffer); - char* p_para = (p_space == NULL) ? (cli_buffer+command_len) : (p_space+1); // point to NULL-character or after space - - //------------- Find entered command in lookup table & execute it -------------// - cli_cmdtype_t cmd_id; - for(cmd_id = CLI_CMDTYPE_COUNT - 1; cmd_id > CLI_CMDTYPE_unknown; cmd_id--) - { - if( 0 == strncmp(cli_buffer, cli_string_tbl[cmd_id], command_len) ) - { - break; - } - } - - cli_error_t error = cli_command_tbl[cmd_id]( p_para ); // command execution, (unknown command if cannot find) - - if (CLI_ERROR_NONE != error) puts(cli_error_message[error]); // error message output if any - - //------------- print out current path -------------// - cli_command_prompt(); - } - else if (ch=='\t') // \t may be used for auto-complete later - { - - } -} - -//--------------------------------------------------------------------+ -// UNKNOWN Command -//--------------------------------------------------------------------+ -cli_error_t cli_cmd_unknown(char * para) -{ - puts("unknown command, please type \"help\" for list of supported commands"); - return CLI_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// HELP command -//--------------------------------------------------------------------+ -cli_error_t cli_cmd_help(char * para) -{ - puts("current supported commands are:"); - for(cli_cmdtype_t cmd_id = CLI_CMDTYPE_help+1; cmd_id < CLI_CMDTYPE_COUNT; cmd_id++) - { - printf("%s\t%s\n", cli_string_tbl[cmd_id], cli_description_tbl[cmd_id]); - } - - return CLI_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// Clear Screen Command -//--------------------------------------------------------------------+ -cli_error_t cli_cmd_clear(char* p_para) -{ - printf(ANSI_ERASE_SCREEN(2) ANSI_CURSOR_POSITION(1,1) ); - return CLI_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// LS Command -//--------------------------------------------------------------------+ -cli_error_t cli_cmd_list(char * p_para) -{ - if ( strlen(p_para) == 0 ) // list current directory - { - DIR target_dir; - if ( FR_OK != f_opendir(&target_dir, ".") ) return CLI_ERROR_FAILED; - - TCHAR long_filename[_MAX_LFN]; - FILINFO dir_entry = - { - .lfname = long_filename, - .lfsize = _MAX_LFN - }; - while( (f_readdir(&target_dir, &dir_entry) == FR_OK) && dir_entry.fname[0] != 0) - { - if ( dir_entry.fname[0] != '.' ) // ignore . and .. entry - { - TCHAR const * const p_name = (dir_entry.lfname[0] != 0) ? dir_entry.lfname : dir_entry.fname; - if ( dir_entry.fattrib & AM_DIR ) // directory - { - printf("/%s", p_name); - }else - { - printf("%-40s%d KB", p_name, dir_entry.fsize / 1000); - } - putchar('\n'); - } - } - -// (void) f_closedir(&target_dir); - } - else - { - puts("ls only supports list current directory only, try to cd to that folder first"); - return CLI_ERROR_INVALID_PARA; - } - - return CLI_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// CD Command -//--------------------------------------------------------------------+ -cli_error_t cli_cmd_changedir(char * p_para) -{ - if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA; - - drive_letter2number(p_para); - - if ( FR_OK != f_chdir(p_para) ) - { - return CLI_ERROR_INVALID_PATH; - } - - if ( p_para[1] == ':') - { // path has drive letter --> change drive, update volume label - f_chdrive(p_para[0] - '0'); - f_getlabel(NULL, volume_label, NULL); - } - - return CLI_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// CAT Command -//--------------------------------------------------------------------+ -cli_error_t cli_cmd_cat(char *p_para) -{ - if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA; - - FIL file; - - switch( f_open(&file, p_para, FA_READ) ) - { - case FR_OK: - { - uint32_t bytes_read = 0; - - if ( (FR_OK == f_read(&file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read)) && (bytes_read > 0) ) - { - if ( file.fsize < 0x80000 ) // ~ 500KB - { - putchar('\n'); - do { - for(uint32_t i=0; i 0) ); - }else - { // not display file contents if first character is not printable (high chance of binary file) - printf("%s 's contents is too large\n", p_para); - } - } - f_close(&file); - } - break; - - case FR_INVALID_NAME: - return CLI_ERROR_INVALID_PATH; - - default : - return CLI_ERROR_FAILED; - } - - return CLI_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// Make Directory command -//--------------------------------------------------------------------+ -cli_error_t cli_cmd_mkdir(char *p_para) -{ - if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA; - - return (f_mkdir(p_para) == FR_OK) ? CLI_ERROR_NONE : CLI_ERROR_FAILED; -} - -//--------------------------------------------------------------------+ -// COPY command -//--------------------------------------------------------------------+ -cli_error_t cli_cmd_copy(char *p_para) -{ - char* p_space = strchr(p_para, ' '); - if ( p_space == NULL ) return CLI_ERROR_INVALID_PARA; - - *p_space = 0; // replace space by NULL-character - char* p_dest = p_space+1; - - if ( strlen(p_dest) == 0 ) return CLI_ERROR_INVALID_PARA; - - drive_letter2number(p_para); - drive_letter2number(p_dest); - - //------------- Check Existence of source & dest file -------------// - cli_error_t error = CLI_ERROR_NONE; - FIL src_file, dest_file; - - if ( FR_OK != f_open(&src_file , p_para, FA_READ) ) return CLI_ERROR_INVALID_PATH; - switch ( f_open(&dest_file, p_dest, FA_WRITE | FA_CREATE_NEW) ) - { - case FR_EXIST: - error = CLI_ERROR_FILE_EXISTED; - break;\ - - case FR_OK: - while(1) - { - uint32_t bytes_read = 0; - uint32_t bytes_write = 0; - FRESULT res; - - res = f_read(&src_file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read); /* Read a chunk of src file */ - if ( (res != FR_OK) || (bytes_read == 0) ) break; /* error or eof */ - - res = f_write(&dest_file, fileread_buffer, bytes_read, &bytes_write); /* Write it to the dst file */ - if ( (res != FR_OK) || (bytes_write < bytes_read) ) break; /* error or disk full */ - } - - f_close(&dest_file); - break; - - default: - error = CLI_ERROR_FAILED; - break; - } - - f_close(&src_file); - - return error; -} -#endif +/**************************************************************************/ +/*! + @file cli.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ + +#include "cli.h" +#include "ctype.h" + +#if TUSB_CFG_HOST_MSC + +#include "ff.h" +#include "diskio.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +#define CLI_MAX_BUFFER 256 +#define CLI_FILE_READ_BUFFER (4*1024) + +enum { + ASCII_BACKSPACE = 8, +}; + +typedef enum { + CLI_ERROR_NONE = 0, + CLI_ERROR_INVALID_PARA, + CLI_ERROR_INVALID_PATH, + CLI_ERROR_FILE_EXISTED, + CLI_ERROR_FAILED +}cli_error_t; + +static char const * const cli_error_message[] = +{ + [CLI_ERROR_NONE ] = 0, + [CLI_ERROR_INVALID_PARA ] = "Invalid parameter(s)", + [CLI_ERROR_INVALID_PATH ] = "No such file or directory", + [CLI_ERROR_FILE_EXISTED ] = "file or directory already exists", + [CLI_ERROR_FAILED ] = "failed to execute" +}; + +//--------------------------------------------------------------------+ +// CLI Database definition +//--------------------------------------------------------------------+ + +// command, function, description +#define CLI_COMMAND_TABLE(ENTRY) \ + ENTRY(unknown , cli_cmd_unknown , NULL ) \ + ENTRY(help , cli_cmd_help , NULL ) \ + ENTRY(cls , cli_cmd_clear , "Clear the screen." ) \ + ENTRY(ls , cli_cmd_list , "List information about the FILEs (the current directory by default).") \ + ENTRY(cd , cli_cmd_changedir, "change the current directory." ) \ + ENTRY(cat , cli_cmd_cat , "display contents of a file." ) \ + ENTRY(cp , cli_cmd_copy , "Copies one or more files to another location." ) \ + ENTRY(mkdir , cli_cmd_mkdir , "Create a DIRECTORY, if it does not already exist." ) \ + +//--------------------------------------------------------------------+ +// Expands the function to have the standard function signature +//--------------------------------------------------------------------+ +#define CLI_PROTOTYPE_EXPAND(command, function, description) \ + cli_error_t function(char *); + +CLI_COMMAND_TABLE(CLI_PROTOTYPE_EXPAND); + +//--------------------------------------------------------------------+ +// Expand to enum value +//--------------------------------------------------------------------+ +#define CLI_ENUM_EXPAND(command, function, description) CLI_CMDTYPE_##command, +typedef enum { + CLI_COMMAND_TABLE(CLI_ENUM_EXPAND) + CLI_CMDTYPE_COUNT +}cli_cmdtype_t; + +//--------------------------------------------------------------------+ +// Expand to string table +//--------------------------------------------------------------------+ +#define CLI_STRING_EXPAND(command, function, description) #command, +char const* const cli_string_tbl[] = +{ + CLI_COMMAND_TABLE(CLI_STRING_EXPAND) + 0 +}; + +//--------------------------------------------------------------------+ +// Expand to Description table +//--------------------------------------------------------------------+ +#define CLI_DESCRIPTION_EXPAND(command, function, description) description, +char const* const cli_description_tbl[] = +{ + CLI_COMMAND_TABLE(CLI_DESCRIPTION_EXPAND) + 0 +}; + + +//--------------------------------------------------------------------+ +// Expand to Command Lookup Table +//--------------------------------------------------------------------+ +#define CMD_LOOKUP_EXPAND(command, function, description)\ + [CLI_CMDTYPE_##command] = function,\ + +typedef cli_error_t (* const cli_cmdfunc_t)(char *); +static cli_cmdfunc_t cli_command_tbl[] = +{ + CLI_COMMAND_TABLE(CMD_LOOKUP_EXPAND) +}; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static char cli_buffer[CLI_MAX_BUFFER]; +uint8_t fileread_buffer[CLI_FILE_READ_BUFFER] TUSB_CFG_ATTR_USBRAM; +static char volume_label[20]; + +static inline void drive_number2letter(char * p_path) ATTR_ALWAYS_INLINE; +static inline void drive_number2letter(char * p_path) +{ + if (p_path[1] == ':') + { + p_path[0] = 'E' + p_path[0] - '0' ; + } +} + +static inline void drive_letter2number(char * p_path) ATTR_ALWAYS_INLINE; +static inline void drive_letter2number(char * p_path) +{ + if (p_path[1] == ':') + { + p_path[0] = p_path[0] - 'E' + '0'; + } +} + + +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ +// NOTES: prompt re-use cli_buffer --> should not be called when cli_buffer has contents +void cli_command_prompt(void) +{ + f_getcwd(cli_buffer, CLI_MAX_BUFFER); + drive_number2letter(cli_buffer); + printf("\n%s %s\n$ ", + (volume_label[0] !=0) ? volume_label : "No Label", + cli_buffer); + + memclr_(cli_buffer, CLI_MAX_BUFFER); +} + +void cli_init(void) +{ + memclr_(cli_buffer, CLI_MAX_BUFFER); + f_getlabel(NULL, volume_label, NULL); + cli_command_prompt(); +} + +void cli_poll(char ch) +{ + if ( isprint(ch) ) + { // accumulate & echo + if (strlen(cli_buffer) < CLI_MAX_BUFFER) + { + cli_buffer[ strlen(cli_buffer) ] = ch; + putchar(ch); + }else + { + puts("cli buffer overflows"); + memclr_(cli_buffer, CLI_MAX_BUFFER); + } + } + else if ( ch == ASCII_BACKSPACE && strlen(cli_buffer)) + { + printf(ANSI_CURSOR_BACKWARD(1) ANSI_ERASE_LINE(0) ); // move cursor back & clear to the end of line + cli_buffer[ strlen(cli_buffer)-1 ] = 0; + } + else if ( ch == '\r') + { // execute command + //------------- Separate Command & Parameter -------------// + putchar('\n'); + char* p_space = strchr(cli_buffer, ' '); + uint32_t command_len = (p_space == NULL) ? strlen(cli_buffer) : (p_space - cli_buffer); + char* p_para = (p_space == NULL) ? (cli_buffer+command_len) : (p_space+1); // point to NULL-character or after space + + //------------- Find entered command in lookup table & execute it -------------// + cli_cmdtype_t cmd_id; + for(cmd_id = CLI_CMDTYPE_COUNT - 1; cmd_id > CLI_CMDTYPE_unknown; cmd_id--) + { + if( 0 == strncmp(cli_buffer, cli_string_tbl[cmd_id], command_len) ) + { + break; + } + } + + cli_error_t error = cli_command_tbl[cmd_id]( p_para ); // command execution, (unknown command if cannot find) + + if (CLI_ERROR_NONE != error) puts(cli_error_message[error]); // error message output if any + + //------------- print out current path -------------// + cli_command_prompt(); + } + else if (ch=='\t') // \t may be used for auto-complete later + { + + } +} + +//--------------------------------------------------------------------+ +// UNKNOWN Command +//--------------------------------------------------------------------+ +cli_error_t cli_cmd_unknown(char * para) +{ + puts("unknown command, please type \"help\" for list of supported commands"); + return CLI_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// HELP command +//--------------------------------------------------------------------+ +cli_error_t cli_cmd_help(char * para) +{ + puts("current supported commands are:"); + for(cli_cmdtype_t cmd_id = CLI_CMDTYPE_help+1; cmd_id < CLI_CMDTYPE_COUNT; cmd_id++) + { + printf("%s\t%s\n", cli_string_tbl[cmd_id], cli_description_tbl[cmd_id]); + } + + return CLI_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// Clear Screen Command +//--------------------------------------------------------------------+ +cli_error_t cli_cmd_clear(char* p_para) +{ + printf(ANSI_ERASE_SCREEN(2) ANSI_CURSOR_POSITION(1,1) ); + return CLI_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// LS Command +//--------------------------------------------------------------------+ +cli_error_t cli_cmd_list(char * p_para) +{ + if ( strlen(p_para) == 0 ) // list current directory + { + DIR target_dir; + if ( FR_OK != f_opendir(&target_dir, ".") ) return CLI_ERROR_FAILED; + + TCHAR long_filename[_MAX_LFN]; + FILINFO dir_entry = + { + .lfname = long_filename, + .lfsize = _MAX_LFN + }; + while( (f_readdir(&target_dir, &dir_entry) == FR_OK) && dir_entry.fname[0] != 0) + { + if ( dir_entry.fname[0] != '.' ) // ignore . and .. entry + { + TCHAR const * const p_name = (dir_entry.lfname[0] != 0) ? dir_entry.lfname : dir_entry.fname; + if ( dir_entry.fattrib & AM_DIR ) // directory + { + printf("/%s", p_name); + }else + { + printf("%-40s%d KB", p_name, dir_entry.fsize / 1000); + } + putchar('\n'); + } + } + +// (void) f_closedir(&target_dir); + } + else + { + puts("ls only supports list current directory only, try to cd to that folder first"); + return CLI_ERROR_INVALID_PARA; + } + + return CLI_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// CD Command +//--------------------------------------------------------------------+ +cli_error_t cli_cmd_changedir(char * p_para) +{ + if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA; + + drive_letter2number(p_para); + + if ( FR_OK != f_chdir(p_para) ) + { + return CLI_ERROR_INVALID_PATH; + } + + if ( p_para[1] == ':') + { // path has drive letter --> change drive, update volume label + f_chdrive(p_para[0] - '0'); + f_getlabel(NULL, volume_label, NULL); + } + + return CLI_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// CAT Command +//--------------------------------------------------------------------+ +cli_error_t cli_cmd_cat(char *p_para) +{ + if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA; + + FIL file; + + switch( f_open(&file, p_para, FA_READ) ) + { + case FR_OK: + { + uint32_t bytes_read = 0; + + if ( (FR_OK == f_read(&file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read)) && (bytes_read > 0) ) + { + if ( file.fsize < 0x80000 ) // ~ 500KB + { + putchar('\n'); + do { + for(uint32_t i=0; i 0) ); + }else + { // not display file contents if first character is not printable (high chance of binary file) + printf("%s 's contents is too large\n", p_para); + } + } + f_close(&file); + } + break; + + case FR_INVALID_NAME: + return CLI_ERROR_INVALID_PATH; + + default : + return CLI_ERROR_FAILED; + } + + return CLI_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// Make Directory command +//--------------------------------------------------------------------+ +cli_error_t cli_cmd_mkdir(char *p_para) +{ + if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA; + + return (f_mkdir(p_para) == FR_OK) ? CLI_ERROR_NONE : CLI_ERROR_FAILED; +} + +//--------------------------------------------------------------------+ +// COPY command +//--------------------------------------------------------------------+ +cli_error_t cli_cmd_copy(char *p_para) +{ + char* p_space = strchr(p_para, ' '); + if ( p_space == NULL ) return CLI_ERROR_INVALID_PARA; + + *p_space = 0; // replace space by NULL-character + char* p_dest = p_space+1; + + if ( strlen(p_dest) == 0 ) return CLI_ERROR_INVALID_PARA; + + drive_letter2number(p_para); + drive_letter2number(p_dest); + + //------------- Check Existence of source & dest file -------------// + cli_error_t error = CLI_ERROR_NONE; + FIL src_file, dest_file; + + if ( FR_OK != f_open(&src_file , p_para, FA_READ) ) return CLI_ERROR_INVALID_PATH; + switch ( f_open(&dest_file, p_dest, FA_WRITE | FA_CREATE_NEW) ) + { + case FR_EXIST: + error = CLI_ERROR_FILE_EXISTED; + break;\ + + case FR_OK: + while(1) + { + uint32_t bytes_read = 0; + uint32_t bytes_write = 0; + FRESULT res; + + res = f_read(&src_file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read); /* Read a chunk of src file */ + if ( (res != FR_OK) || (bytes_read == 0) ) break; /* error or eof */ + + res = f_write(&dest_file, fileread_buffer, bytes_read, &bytes_write); /* Write it to the dst file */ + if ( (res != FR_OK) || (bytes_write < bytes_read) ) break; /* error or disk full */ + } + + f_close(&dest_file); + break; + + default: + error = CLI_ERROR_FAILED; + break; + } + + f_close(&src_file); + + return error; +} +#endif diff --git a/demos/host/src/main.c b/demos/host/src/main.c index 05624d55..5f30ce4e 100644 --- a/demos/host/src/main.c +++ b/demos/host/src/main.c @@ -1,263 +1,263 @@ -/**************************************************************************/ -/*! - @file main.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include -#include -#include - -#include "boards/board.h" -#include "tusb.h" - -#if TUSB_CFG_OS != TUSB_OS_NONE -#include "app_os_prio.h" -#endif - -#include "mouse_app.h" -#include "keyboard_app.h" -#include "msc_app.h" -#include "cdc_serial_app.h" -#include "rndis_app.h" - -#if defined(__CODE_RED) // TODO to be removed - #include - #include - // Variable to store CRP value in. Will be placed automatically - // by the linker when "Enable Code Read Protect" selected. - // See crp.h header for more information - __CRP const unsigned int CRP_WORD = CRP_NO_CRP ; -#endif - -#if 0 -#include "lwip/opt.h" -#include "lwip/sys.h" -#include "lwip/memp.h" -#include "lwip/tcpip.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/timers.h" -#include "netif/etharp.h" -#if LWIP_DHCP -#include "lwip/dhcp.h" -#endif -#include "../contrib/apps/httpserver/httpserver-netconn.h" -#include "arch/lpc18xx_43xx_emac.h" -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para); -OSAL_TASK_DEF(led_blinking_task, 128, LED_BLINKING_APP_TASK_PRIO); - -void print_greeting(void); -//static inline void wait_blocking_ms(uint32_t ms); - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ - -#if TUSB_CFG_OS == TUSB_OS_NONE -// like a real RTOS, this function is a main loop invoking each task in application and never return -void os_none_start_scheduler(void) -{ - while (1) - { - tusb_task_runner(); - led_blinking_task(NULL); - - keyboard_app_task(NULL); - mouse_app_task(NULL); - msc_app_task(NULL); - cdc_serial_app_task(NULL); - rndis_app_task(NULL); - - } -} -#endif - -int main(void) -{ - board_init(); - print_greeting(); - - tusb_init(); - - //------------- application task init -------------// - (void) osal_task_create( OSAL_TASK_REF(led_blinking_task) ); - - keyboard_app_init(); - mouse_app_init(); - msc_app_init(); - cdc_serial_app_init(); - rndis_app_init(); - - //------------- start OS scheduler (never return) -------------// -#if TUSB_CFG_OS == TUSB_OS_FREERTOS - vTaskStartScheduler(); -#elif TUSB_CFG_OS == TUSB_OS_NONE - os_none_start_scheduler(); -#elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX - while(1) - { - osDelay(osWaitForever); // CMSIS RTX osKernelStart already started, main() is a task - } -#else - #error need to start RTOS schduler -#endif - - while(1) { } // should not be reached here - - return 0; -} - -//--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para) -{ - static uint32_t led_on_mask = 0; - - #if 0 - // FIXME OSAL NONE problem, invoke only 1 - network_init(); - http_server_netconn_init(); - #endif - - OSAL_TASK_LOOP_BEGIN - - osal_task_delay(1000); - - board_leds(led_on_mask, 1 - led_on_mask); - led_on_mask = 1 - led_on_mask; // toggle - - OSAL_TASK_LOOP_END -} - -//--------------------------------------------------------------------+ -// HELPER FUNCTION -//--------------------------------------------------------------------+ -void print_greeting(void) -{ - printf("\n\ ---------------------------------------------------------------------\n\ -- Host Demo (a tinyusb example)\n\ -- if you find any bugs or get any questions, feel free to file an\n\ -- issue at https://github.com/hathach/tinyusb\n\ ---------------------------------------------------------------------\n\n" - ); - - puts("This demo support the following classes"); - if (TUSB_CFG_HOST_HUB ) puts(" - Hub"); - if (TUSB_CFG_HOST_HID_MOUSE ) puts(" - HID Mouse"); - if (TUSB_CFG_HOST_HID_KEYBOARD ) puts(" - HID Keyboard"); - if (TUSB_CFG_HOST_MSC ) puts(" - Mass Storage"); - if (TUSB_CFG_HOST_CDC ) puts(" - Communication Device Class"); -} - -//static inline void wait_blocking_us(volatile uint32_t us) -//{ -// us *= (SystemCoreClock / 1000000) / 3; -// while(us--); -//} -// -//static inline void wait_blocking_ms(uint32_t ms) -//{ -// wait_blocking_us(ms * 1000); -//} - -#if 0 -static struct netif lpc_netif; - -/* Callback for TCPIP thread to indicate TCPIP init is done */ -static void tcpip_init_done_signal(void *arg) -{ - /* Tell main thread TCP/IP init is done */ - *(uint32_t *) arg = 1; -} - -void network_init(void) -{ - ip_addr_t ipaddr, netmask, gw; - volatile uint32_t tcpip_init_done = 0; - -#if NO_SYS - lwip_init(); -#else - /* Wait until the TCP/IP thread is finished before - continuing or weird things may happen */ - LWIP_DEBUGF(LWIP_DBG_ON, ("Waiting for TCPIP thread to initialize...\n")); - tcpip_init(tcpip_init_done_signal, (void*)&tcpip_init_done); - while (!tcpip_init_done); -// tcpip_init(NULL, NULL); -#endif - - /* Static IP assignment */ -#if LWIP_DHCP - IP4_ADDR(&gw, 0, 0, 0, 0); - IP4_ADDR(&ipaddr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); -#else - IP4_ADDR(&gw, 192, 168, 1, 1); - IP4_ADDR(&ipaddr, 192, 168, 1, 57); - IP4_ADDR(&netmask, 255, 255, 255, 0); -#endif - - /* Add netif interface for lpc18xx_43xx */ - if (!netif_add(&lpc_netif, &ipaddr, &netmask, &gw, NULL, lpc_enetif_init, - tcpip_input)) - LWIP_ASSERT("Net interface failed to initialize\r\n", 0); - - netif_set_default(&lpc_netif); - netif_set_up(&lpc_netif); - - /* Enable MAC interrupts only after LWIP is ready */ - NVIC_SetPriority(ETHERNET_IRQn, ((0x01<<3)|0x01)); - NVIC_EnableIRQ(ETHERNET_IRQn); - -#if LWIP_DHCP - dhcp_start(&lpc_netif); -#endif -} -#endif +/**************************************************************************/ +/*! + @file main.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include +#include +#include + +#include "boards/board.h" +#include "tusb.h" + +#if TUSB_CFG_OS != TUSB_OS_NONE +#include "app_os_prio.h" +#endif + +#include "mouse_app.h" +#include "keyboard_app.h" +#include "msc_app.h" +#include "cdc_serial_app.h" +#include "rndis_app.h" + +#if defined(__CODE_RED) // TODO to be removed + #include + #include + // Variable to store CRP value in. Will be placed automatically + // by the linker when "Enable Code Read Protect" selected. + // See crp.h header for more information + __CRP const unsigned int CRP_WORD = CRP_NO_CRP ; +#endif + +#if 0 +#include "lwip/opt.h" +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/tcpip.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/timers.h" +#include "netif/etharp.h" +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif +#include "../contrib/apps/httpserver/httpserver-netconn.h" +#include "arch/lpc18xx_43xx_emac.h" +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para); +OSAL_TASK_DEF(led_blinking_task, 128, LED_BLINKING_APP_TASK_PRIO); + +void print_greeting(void); +//static inline void wait_blocking_ms(uint32_t ms); + +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ + +#if TUSB_CFG_OS == TUSB_OS_NONE +// like a real RTOS, this function is a main loop invoking each task in application and never return +void os_none_start_scheduler(void) +{ + while (1) + { + tusb_task_runner(); + led_blinking_task(NULL); + + keyboard_app_task(NULL); + mouse_app_task(NULL); + msc_app_task(NULL); + cdc_serial_app_task(NULL); + rndis_app_task(NULL); + + } +} +#endif + +int main(void) +{ + board_init(); + print_greeting(); + + tusb_init(); + + //------------- application task init -------------// + (void) osal_task_create( OSAL_TASK_REF(led_blinking_task) ); + + keyboard_app_init(); + mouse_app_init(); + msc_app_init(); + cdc_serial_app_init(); + rndis_app_init(); + + //------------- start OS scheduler (never return) -------------// +#if TUSB_CFG_OS == TUSB_OS_FREERTOS + vTaskStartScheduler(); +#elif TUSB_CFG_OS == TUSB_OS_NONE + os_none_start_scheduler(); +#elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX + while(1) + { + osDelay(osWaitForever); // CMSIS RTX osKernelStart already started, main() is a task + } +#else + #error need to start RTOS schduler +#endif + + while(1) { } // should not be reached here + + return 0; +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para) +{ + static uint32_t led_on_mask = 0; + + #if 0 + // FIXME OSAL NONE problem, invoke only 1 + network_init(); + http_server_netconn_init(); + #endif + + OSAL_TASK_LOOP_BEGIN + + osal_task_delay(1000); + + board_leds(led_on_mask, 1 - led_on_mask); + led_on_mask = 1 - led_on_mask; // toggle + + OSAL_TASK_LOOP_END +} + +//--------------------------------------------------------------------+ +// HELPER FUNCTION +//--------------------------------------------------------------------+ +void print_greeting(void) +{ + printf("\n\ +--------------------------------------------------------------------\n\ +- Host Demo (a tinyusb example)\n\ +- if you find any bugs or get any questions, feel free to file an\n\ +- issue at https://github.com/hathach/tinyusb\n\ +--------------------------------------------------------------------\n\n" + ); + + puts("This demo support the following classes"); + if (TUSB_CFG_HOST_HUB ) puts(" - Hub (1 level only)"); + if (TUSB_CFG_HOST_HID_MOUSE ) puts(" - HID Mouse"); + if (TUSB_CFG_HOST_HID_KEYBOARD ) puts(" - HID Keyboard"); + if (TUSB_CFG_HOST_MSC ) puts(" - Mass Storage"); + if (TUSB_CFG_HOST_CDC ) puts(" - Communication Device Class"); +} + +//static inline void wait_blocking_us(volatile uint32_t us) +//{ +// us *= (SystemCoreClock / 1000000) / 3; +// while(us--); +//} +// +//static inline void wait_blocking_ms(uint32_t ms) +//{ +// wait_blocking_us(ms * 1000); +//} + +#if 0 +static struct netif lpc_netif; + +/* Callback for TCPIP thread to indicate TCPIP init is done */ +static void tcpip_init_done_signal(void *arg) +{ + /* Tell main thread TCP/IP init is done */ + *(uint32_t *) arg = 1; +} + +void network_init(void) +{ + ip_addr_t ipaddr, netmask, gw; + volatile uint32_t tcpip_init_done = 0; + +#if NO_SYS + lwip_init(); +#else + /* Wait until the TCP/IP thread is finished before + continuing or weird things may happen */ + LWIP_DEBUGF(LWIP_DBG_ON, ("Waiting for TCPIP thread to initialize...\n")); + tcpip_init(tcpip_init_done_signal, (void*)&tcpip_init_done); + while (!tcpip_init_done); +// tcpip_init(NULL, NULL); +#endif + + /* Static IP assignment */ +#if LWIP_DHCP + IP4_ADDR(&gw, 0, 0, 0, 0); + IP4_ADDR(&ipaddr, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); +#else + IP4_ADDR(&gw, 192, 168, 1, 1); + IP4_ADDR(&ipaddr, 192, 168, 1, 57); + IP4_ADDR(&netmask, 255, 255, 255, 0); +#endif + + /* Add netif interface for lpc18xx_43xx */ + if (!netif_add(&lpc_netif, &ipaddr, &netmask, &gw, NULL, lpc_enetif_init, + tcpip_input)) + LWIP_ASSERT("Net interface failed to initialize\r\n", 0); + + netif_set_default(&lpc_netif); + netif_set_up(&lpc_netif); + + /* Enable MAC interrupts only after LWIP is ready */ + NVIC_SetPriority(ETHERNET_IRQn, ((0x01<<3)|0x01)); + NVIC_EnableIRQ(ETHERNET_IRQn); + +#if LWIP_DHCP + dhcp_start(&lpc_netif); +#endif +} +#endif diff --git a/demos/host/src/mouse_app.c b/demos/host/src/mouse_app.c index e3709091..df18b966 100644 --- a/demos/host/src/mouse_app.c +++ b/demos/host/src/mouse_app.c @@ -1,175 +1,195 @@ -/**************************************************************************/ -/*! - @file mouse_app.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "mouse_app.h" - -#if TUSB_CFG_OS != TUSB_OS_NONE -#include "app_os_prio.h" -#endif - - -#if TUSB_CFG_HOST_HID_MOUSE - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define QUEUE_MOUSE_REPORT_DEPTH 4 - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -OSAL_TASK_DEF(mouse_app_task, 128, MOUSE_APP_TASK_PRIO); -OSAL_QUEUE_DEF(queue_mouse_def, QUEUE_MOUSE_REPORT_DEPTH, tusb_mouse_report_t); - -static osal_queue_handle_t queue_mouse_hdl; -static tusb_mouse_report_t usb_mouse_report TUSB_CFG_ATTR_USBRAM; - -static inline void process_mouse_report(tusb_mouse_report_t const * p_report); - -//--------------------------------------------------------------------+ -// tinyusb callback (ISR context) -//--------------------------------------------------------------------+ -void tusbh_hid_mouse_mounted_cb(uint8_t dev_addr) -{ - // application set-up - - puts("\na Mouse device is mounted"); - - osal_queue_flush(queue_mouse_hdl); - (void) tusbh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); // first report -} - -void tusbh_hid_mouse_unmounted_cb(uint8_t dev_addr) -{ - // application tear-down - puts("\na Mouse device is unmounted\n"); -} - -void tusbh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event) -{ - switch(event) - { - case TUSB_EVENT_XFER_COMPLETE: - osal_queue_send(queue_mouse_hdl, &usb_mouse_report); - (void) tusbh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); - break; - - case TUSB_EVENT_XFER_ERROR: - (void) tusbh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); // ignore & continue - break; - - default : - break; - } -} - -//--------------------------------------------------------------------+ -// APPLICATION -// NOTICE: MOUSE REPORT IS NOT CORRECT UNTIL A DECENT HID PARSER IS -// IMPLEMENTED, MEANWHILE IT CAN MISS DISPLAY BUTTONS OR X,Y etc -//--------------------------------------------------------------------+ -void mouse_app_init(void) -{ - memclr_(&usb_mouse_report, sizeof(tusb_mouse_report_t)); - - queue_mouse_hdl = osal_queue_create( OSAL_QUEUE_REF(queue_mouse_def) ); - ASSERT_PTR( queue_mouse_hdl, VOID_RETURN); - - ASSERT( TUSB_ERROR_NONE == osal_task_create( OSAL_TASK_REF(mouse_app_task) ), - VOID_RETURN ); -} - -//------------- main task -------------// -OSAL_TASK_FUNCTION( mouse_app_task ) (void* p_task_para) -{ - tusb_error_t error; - tusb_mouse_report_t mouse_report; - - OSAL_TASK_LOOP_BEGIN - - osal_queue_receive(queue_mouse_hdl, &mouse_report, OSAL_TIMEOUT_WAIT_FOREVER, &error); - process_mouse_report(&mouse_report); - - OSAL_TASK_LOOP_END -} - -//--------------------------------------------------------------------+ -// HELPER -//--------------------------------------------------------------------+ -static inline void process_mouse_report(tusb_mouse_report_t const * p_report) -{ - static tusb_mouse_report_t prev_report = { 0 }; - - //------------- button state -------------// - uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons; - if ( button_changed_mask & p_report->buttons) - { - // example only display button pressed, ignore hold & dragging etc - printf(" %c%c%c ", - p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', - p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', - p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); - } - - //------------- movement (disabled for clearer demo) -------------// - if ( p_report->wheel != 0 ) - { - printf(" %c ", p_report->wheel > 0 ? 'U' : 'D'); - } - -// if ( p_report->x != 0 || p_report->y != 0 ) -// { -// printf(" (%d, %d) ", p_report->x, p_report->y); -// } - -} - -#else - -// dummy implementation to remove #ifdef in main.c -void mouse_app_init(void) { } -OSAL_TASK_FUNCTION( mouse_app_task ) (void* p_task_para) -{ - OSAL_TASK_LOOP_BEGIN - OSAL_TASK_LOOP_END -} - -#endif +/**************************************************************************/ +/*! + @file mouse_app.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "mouse_app.h" + +#if TUSB_CFG_OS != TUSB_OS_NONE +#include "app_os_prio.h" +#endif + + +#if TUSB_CFG_HOST_HID_MOUSE + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +#define QUEUE_MOUSE_REPORT_DEPTH 4 + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +OSAL_TASK_DEF(mouse_app_task, 128, MOUSE_APP_TASK_PRIO); +OSAL_QUEUE_DEF(queue_mouse_def, QUEUE_MOUSE_REPORT_DEPTH, tusb_mouse_report_t); + +static osal_queue_handle_t queue_mouse_hdl; +static tusb_mouse_report_t usb_mouse_report TUSB_CFG_ATTR_USBRAM; + +static inline void process_mouse_report(tusb_mouse_report_t const * p_report); + +//--------------------------------------------------------------------+ +// tinyusb callback (ISR context) +//--------------------------------------------------------------------+ +void tusbh_hid_mouse_mounted_cb(uint8_t dev_addr) +{ + // application set-up + + puts("\na Mouse device is mounted"); + + osal_queue_flush(queue_mouse_hdl); + (void) tusbh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); // first report +} + +void tusbh_hid_mouse_unmounted_cb(uint8_t dev_addr) +{ + // application tear-down + puts("\na Mouse device is unmounted\n"); +} + +void tusbh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event) +{ + switch(event) + { + case TUSB_EVENT_XFER_COMPLETE: + osal_queue_send(queue_mouse_hdl, &usb_mouse_report); + (void) tusbh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); + break; + + case TUSB_EVENT_XFER_ERROR: + (void) tusbh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); // ignore & continue + break; + + default : + break; + } +} + +//--------------------------------------------------------------------+ +// APPLICATION +// NOTICE: MOUSE REPORT IS NOT CORRECT UNTIL A DECENT HID PARSER IS +// IMPLEMENTED, MEANWHILE IT CAN MISS DISPLAY BUTTONS OR X,Y etc +//--------------------------------------------------------------------+ +void mouse_app_init(void) +{ + memclr_(&usb_mouse_report, sizeof(tusb_mouse_report_t)); + + queue_mouse_hdl = osal_queue_create( OSAL_QUEUE_REF(queue_mouse_def) ); + ASSERT_PTR( queue_mouse_hdl, VOID_RETURN); + + ASSERT( TUSB_ERROR_NONE == osal_task_create( OSAL_TASK_REF(mouse_app_task) ), + VOID_RETURN ); +} + +//------------- main task -------------// +OSAL_TASK_FUNCTION( mouse_app_task ) (void* p_task_para) +{ + tusb_error_t error; + tusb_mouse_report_t mouse_report; + + OSAL_TASK_LOOP_BEGIN + + osal_queue_receive(queue_mouse_hdl, &mouse_report, OSAL_TIMEOUT_WAIT_FOREVER, &error); + process_mouse_report(&mouse_report); + + OSAL_TASK_LOOP_END +} + +//--------------------------------------------------------------------+ +// HELPER +//--------------------------------------------------------------------+ +void cursor_movement(int8_t x, int8_t y, int8_t wheel) +{ + //------------- X -------------// + if ( x < 0) + { // move left + printf(ANSI_CURSOR_BACKWARD(%d), (-x)); + }else if ( x > 0) + { // move right + printf(ANSI_CURSOR_FORWARD(%d), x); + }else { } + + //------------- Y -------------// + if ( y < 0) + { // move up + printf(ANSI_CURSOR_UP(%d), (-y)); + }else if ( y > 0) + { // move down + printf(ANSI_CURSOR_DOWN(%d), y); + }else { } + + //------------- wheel -------------// + if (wheel < 0) + { // scroll up + printf(ANSI_SCROLL_UP(%d), (-wheel)); + }else if (wheel > 0) + { // scroll down + printf(ANSI_SCROLL_DOWN(%d), wheel); + }else { } +} + +static inline void process_mouse_report(tusb_mouse_report_t const * p_report) +{ + static tusb_mouse_report_t prev_report = { 0 }; + + //------------- button state -------------// + uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons; + if ( button_changed_mask & p_report->buttons) + { + printf(" %c%c%c ", + p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + } + + //------------- cursor movement -------------// + cursor_movement(p_report->x, p_report->y, p_report->wheel); +} + +#else + +// dummy implementation to remove #ifdef in main.c +void mouse_app_init(void) { } +OSAL_TASK_FUNCTION( mouse_app_task ) (void* p_task_para) +{ + OSAL_TASK_LOOP_BEGIN + OSAL_TASK_LOOP_END +} + +#endif