refine mouse demo

This commit is contained in:
hathach 2013-10-16 12:05:48 +07:00
parent de7e21dc66
commit 86b3e3174d
5 changed files with 1141 additions and 1118 deletions

View File

@ -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_ */
/** @} */

View File

@ -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 <stdint.h>
#include <stdbool.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_ */
/** @} */
/**************************************************************************/
/*!
@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 <stdint.h>
#include <stdbool.h>
#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_ */
/** @} */

View File

@ -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<bytes_read; i++) putchar( fileread_buffer[i] );
}while( (FR_OK == f_read(&file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read)) && (bytes_read > 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<bytes_read; i++) putchar( fileread_buffer[i] );
}while( (FR_OK == f_read(&file, fileread_buffer, CLI_FILE_READ_BUFFER, &bytes_read)) && (bytes_read > 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

View File

@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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 <cr_section_macros.h>
#include <NXP/crp.h>
// 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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 <cr_section_macros.h>
#include <NXP/crp.h>
// 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

View File

@ -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