| 
									
										
										
										
											2023-03-17 16:12:49 +07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  |  * The MIT License (MIT) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2019 Ha Thach (tinyusb.org) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | 
					
						
							|  |  |  |  * of this software and associated documentation files (the "Software"), to deal | 
					
						
							|  |  |  |  * in the Software without restriction, including without limitation the rights | 
					
						
							|  |  |  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
					
						
							|  |  |  |  * copies of the Software, and to permit persons to whom the Software is | 
					
						
							|  |  |  |  * furnished to do so, subject to the following conditions: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The above copyright notice and this permission notice shall be included in | 
					
						
							|  |  |  |  * all copies or substantial portions of the Software. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
					
						
							|  |  |  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
					
						
							|  |  |  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
					
						
							|  |  |  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
					
						
							|  |  |  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
					
						
							|  |  |  |  * THE SOFTWARE. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:27:07 +07:00
										 |  |  | #include <ctype.h>
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | #include "tusb.h"
 | 
					
						
							| 
									
										
										
										
											2023-08-03 15:44:05 +07:00
										 |  |  | #include "bsp/board_api.h"
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | #include "ff.h"
 | 
					
						
							|  |  |  | #include "diskio.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // lib/embedded-cli
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | #define EMBEDDED_CLI_IMPL
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | #include "embedded_cli.h"
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:27:07 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | // MACRO TYPEDEF CONSTANT ENUM DECLARATION
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | //------------- embedded-cli -------------//
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  | #define CLI_BUFFER_SIZE     512
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | #define CLI_RX_BUFFER_SIZE  16
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  | #define CLI_CMD_BUFFER_SIZE 64
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | #define CLI_HISTORY_SIZE    32
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  | #define CLI_BINDING_COUNT   8
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static EmbeddedCli *_cli; | 
					
						
							|  |  |  | static CLI_UINT cli_buffer[BYTES_TO_CLI_UINTS(CLI_BUFFER_SIZE)]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | //------------- Elm Chan FatFS -------------//
 | 
					
						
							|  |  |  | static FATFS fatfs[CFG_TUH_DEVICE_MAX]; // for simplicity only support 1 LUN per device
 | 
					
						
							|  |  |  | static volatile bool _disk_busy[CFG_TUH_DEVICE_MAX]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | static scsi_inquiry_resp_t inquiry_resp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  | bool cli_init(void); | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | bool msc_app_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |   for(size_t i=0; i<CFG_TUH_DEVICE_MAX; i++) _disk_busy[i] = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  |   // disable stdout buffered for echoing typing command
 | 
					
						
							| 
									
										
										
										
											2023-08-14 22:01:30 +07:00
										 |  |  |   #ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  |   setbuf(stdout, NULL); | 
					
						
							| 
									
										
										
										
											2023-08-14 22:01:30 +07:00
										 |  |  |   #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  |   cli_init(); | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void msc_app_task(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!_cli) return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-21 16:28:54 +07:00
										 |  |  |   int ch = board_getchar(); | 
					
						
							| 
									
										
										
										
											2022-11-19 15:27:07 +07:00
										 |  |  |   if ( ch > 0 ) | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-11-19 15:27:07 +07:00
										 |  |  |     while( ch > 0 ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       embeddedCliReceiveChar(_cli, (char) ch); | 
					
						
							| 
									
										
										
										
											2022-11-21 16:28:54 +07:00
										 |  |  |       ch = board_getchar(); | 
					
						
							| 
									
										
										
										
											2022-11-19 15:27:07 +07:00
										 |  |  |     } | 
					
						
							|  |  |  |     embeddedCliProcess(_cli); | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-23 16:01:48 +07:00
										 |  |  | bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-11-23 16:01:48 +07:00
										 |  |  |   msc_cbw_t const* cbw = cb_data->cbw; | 
					
						
							|  |  |  |   msc_csw_t const* csw = cb_data->csw; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  |   if (csw->status != 0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("Inquiry failed\r\n"); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Print out Vendor ID, Product ID and Rev
 | 
					
						
							|  |  |  |   printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Get capacity of device
 | 
					
						
							|  |  |  |   uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); | 
					
						
							|  |  |  |   uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); | 
					
						
							| 
									
										
										
										
											2022-11-21 11:52:51 +07:00
										 |  |  |   // printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |   // For simplicity: we only mount 1 LUN per device
 | 
					
						
							|  |  |  |   uint8_t const drive_num = dev_addr-1; | 
					
						
							|  |  |  |   char drive_path[3] = "0:"; | 
					
						
							|  |  |  |   drive_path[0] += drive_num; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( f_mount(&fatfs[drive_num], drive_path, 1) != FR_OK ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     puts("mount failed"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-21 11:52:51 +07:00
										 |  |  |   // change to newly mounted drive
 | 
					
						
							|  |  |  |   f_chdir(drive_path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // print the drive label
 | 
					
						
							|  |  |  | //  char label[34];
 | 
					
						
							|  |  |  | //  if ( FR_OK == f_getlabel(drive_path, label, NULL) )
 | 
					
						
							|  |  |  | //  {
 | 
					
						
							|  |  |  | //    puts(label);
 | 
					
						
							|  |  |  | //  }
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //------------- IMPLEMENTATION -------------//
 | 
					
						
							|  |  |  | void tuh_msc_mount_cb(uint8_t dev_addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   printf("A MassStorage device is mounted\r\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint8_t const lun = 0; | 
					
						
							| 
									
										
										
										
											2022-11-23 16:01:48 +07:00
										 |  |  |   tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb, 0); | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void tuh_msc_umount_cb(uint8_t dev_addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   printf("A MassStorage device is unmounted\r\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |   uint8_t const drive_num = dev_addr-1; | 
					
						
							|  |  |  |   char drive_path[3] = "0:"; | 
					
						
							|  |  |  |   drive_path[0] += drive_num; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   f_unmount(drive_path); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-18 21:38:03 +07:00
										 |  |  | //  if ( phy_disk == f_get_current_drive() )
 | 
					
						
							|  |  |  | //  { // active drive is unplugged --> change to other drive
 | 
					
						
							|  |  |  | //    for(uint8_t i=0; i<CFG_TUH_DEVICE_MAX; i++)
 | 
					
						
							|  |  |  | //    {
 | 
					
						
							|  |  |  | //      if ( disk_is_ready(i) )
 | 
					
						
							|  |  |  | //      {
 | 
					
						
							|  |  |  | //        f_chdrive(i);
 | 
					
						
							|  |  |  | //        cli_init(); // refractor, rename
 | 
					
						
							|  |  |  | //      }
 | 
					
						
							|  |  |  | //    }
 | 
					
						
							|  |  |  | //  }
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | // DiskIO
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void wait_for_disk_io(BYTE pdrv) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   while(_disk_busy[pdrv]) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     tuh_task(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-23 16:01:48 +07:00
										 |  |  | static bool disk_io_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-11-23 16:01:48 +07:00
										 |  |  |   (void) dev_addr; (void) cb_data; | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |   _disk_busy[dev_addr-1] = false; | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DSTATUS disk_status ( | 
					
						
							|  |  |  | 	BYTE pdrv		/* Physical drive nmuber to identify the drive */ | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint8_t dev_addr = pdrv + 1; | 
					
						
							|  |  |  |   return tuh_msc_mounted(dev_addr) ? 0 : STA_NODISK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DSTATUS disk_initialize ( | 
					
						
							|  |  |  | 	BYTE pdrv				/* Physical drive nmuber to identify the drive */ | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) pdrv; | 
					
						
							|  |  |  | 	return 0; // nothing to do
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DRESULT disk_read ( | 
					
						
							|  |  |  | 	BYTE pdrv,		/* Physical drive nmuber to identify the drive */ | 
					
						
							|  |  |  | 	BYTE *buff,		/* Data buffer to store read data */ | 
					
						
							|  |  |  | 	LBA_t sector,	/* Start sector in LBA */ | 
					
						
							|  |  |  | 	UINT count		/* Number of sectors to read */ | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	uint8_t const dev_addr = pdrv + 1; | 
					
						
							|  |  |  | 	uint8_t const lun = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_disk_busy[pdrv] = true; | 
					
						
							| 
									
										
										
										
											2022-11-23 16:01:48 +07:00
										 |  |  | 	tuh_msc_read10(dev_addr, lun, buff, sector, (uint16_t) count, disk_io_complete, 0); | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | 	wait_for_disk_io(pdrv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return RES_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if FF_FS_READONLY == 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DRESULT disk_write ( | 
					
						
							|  |  |  | 	BYTE pdrv,			/* Physical drive nmuber to identify the drive */ | 
					
						
							|  |  |  | 	const BYTE *buff,	/* Data to be written */ | 
					
						
							|  |  |  | 	LBA_t sector,		/* Start sector in LBA */ | 
					
						
							|  |  |  | 	UINT count			/* Number of sectors to write */ | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	uint8_t const dev_addr = pdrv + 1; | 
					
						
							|  |  |  | 	uint8_t const lun = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_disk_busy[pdrv] = true; | 
					
						
							| 
									
										
										
										
											2022-11-23 16:01:48 +07:00
										 |  |  | 	tuh_msc_write10(dev_addr, lun, buff, sector, (uint16_t) count, disk_io_complete, 0); | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | 	wait_for_disk_io(pdrv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return RES_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DRESULT disk_ioctl ( | 
					
						
							|  |  |  | 	BYTE pdrv,		/* Physical drive nmuber (0..) */ | 
					
						
							|  |  |  | 	BYTE cmd,		/* Control code */ | 
					
						
							|  |  |  | 	void *buff		/* Buffer to send/receive control data */ | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   uint8_t const dev_addr = pdrv + 1; | 
					
						
							|  |  |  |   uint8_t const lun = 0; | 
					
						
							|  |  |  |   switch ( cmd ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     case CTRL_SYNC: | 
					
						
							|  |  |  |       // nothing to do since we do blocking
 | 
					
						
							|  |  |  |       return RES_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case GET_SECTOR_COUNT: | 
					
						
							| 
									
										
										
										
											2022-11-21 11:12:10 +07:00
										 |  |  |       *((DWORD*) buff) = (WORD) tuh_msc_get_block_count(dev_addr, lun); | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |       return RES_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case GET_SECTOR_SIZE: | 
					
						
							| 
									
										
										
										
											2022-11-21 11:12:10 +07:00
										 |  |  |       *((WORD*) buff) = (WORD) tuh_msc_get_block_size(dev_addr, lun); | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |       return RES_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case GET_BLOCK_SIZE: | 
					
						
							|  |  |  |       *((DWORD*) buff) = 1;    // erase block size in units of sector size
 | 
					
						
							|  |  |  |       return RES_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return RES_PARERR; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return RES_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | // CLI Commands
 | 
					
						
							|  |  |  | //--------------------------------------------------------------------+
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  | void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context); | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +07:00
										 |  |  | void cli_cmd_cd(EmbeddedCli *cli, char *args, void *context); | 
					
						
							|  |  |  | void cli_cmd_cp(EmbeddedCli *cli, char *args, void *context); | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  | void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context); | 
					
						
							| 
									
										
										
										
											2022-11-21 11:52:51 +07:00
										 |  |  | void cli_cmd_pwd(EmbeddedCli *cli, char *args, void *context); | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  | void cli_cmd_mkdir(EmbeddedCli *cli, char *args, void *context); | 
					
						
							|  |  |  | void cli_cmd_mv(EmbeddedCli *cli, char *args, void *context); | 
					
						
							| 
									
										
										
										
											2022-11-21 11:24:58 +07:00
										 |  |  | void cli_cmd_rm(EmbeddedCli *cli, char *args, void *context); | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | void cli_write_char(EmbeddedCli *cli, char c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) cli; | 
					
						
							|  |  |  |   putchar((int) c); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void cli_cmd_unknown(EmbeddedCli *cli, CliCommand *command) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) cli; | 
					
						
							|  |  |  |   printf("%s: command not found\r\n", command->name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool cli_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   EmbeddedCliConfig *config = embeddedCliDefaultConfig(); | 
					
						
							|  |  |  |   config->cliBuffer         = cli_buffer; | 
					
						
							|  |  |  |   config->cliBufferSize     = CLI_BUFFER_SIZE; | 
					
						
							|  |  |  |   config->rxBufferSize      = CLI_RX_BUFFER_SIZE; | 
					
						
							|  |  |  |   config->cmdBufferSize     = CLI_CMD_BUFFER_SIZE; | 
					
						
							|  |  |  |   config->historyBufferSize = CLI_HISTORY_SIZE; | 
					
						
							|  |  |  |   config->maxBindingCount   = CLI_BINDING_COUNT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   TU_ASSERT(embeddedCliRequiredSize(config) <= CLI_BUFFER_SIZE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _cli = embeddedCliNew(config); | 
					
						
							|  |  |  |   TU_ASSERT(_cli != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _cli->writeChar = cli_write_char; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   embeddedCliAddBinding(_cli, (CliCommandBinding) { | 
					
						
							|  |  |  |     "cat", | 
					
						
							|  |  |  |     "Usage: cat [FILE]...\r\n\tConcatenate FILE(s) to standard output..", | 
					
						
							|  |  |  |     true, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     cli_cmd_cat | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   embeddedCliAddBinding(_cli, (CliCommandBinding) { | 
					
						
							|  |  |  |     "cd", | 
					
						
							|  |  |  |     "Usage: cd [DIR]...\r\n\tChange the current directory to DIR.", | 
					
						
							|  |  |  |     true, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     cli_cmd_cd | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +07:00
										 |  |  |   embeddedCliAddBinding(_cli, (CliCommandBinding) { | 
					
						
							|  |  |  |     "cp", | 
					
						
							|  |  |  |     "Usage: cp SOURCE DEST\r\n\tCopy SOURCE to DEST.", | 
					
						
							|  |  |  |     true, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     cli_cmd_cp | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  |   embeddedCliAddBinding(_cli, (CliCommandBinding) { | 
					
						
							|  |  |  |     "ls", | 
					
						
							|  |  |  |     "Usage: ls [DIR]...\r\n\tList information about the FILEs (the current directory by default).", | 
					
						
							|  |  |  |     true, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     cli_cmd_ls | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-21 11:52:51 +07:00
										 |  |  |   embeddedCliAddBinding(_cli, (CliCommandBinding) { | 
					
						
							|  |  |  |     "pwd", | 
					
						
							|  |  |  |     "Usage: pwd\r\n\tPrint the name of the current working directory.", | 
					
						
							|  |  |  |     true, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     cli_cmd_pwd | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  |   embeddedCliAddBinding(_cli, (CliCommandBinding) { | 
					
						
							|  |  |  |     "mkdir", | 
					
						
							|  |  |  |     "Usage: mkdir DIR...\r\n\tCreate the DIRECTORY(ies), if they do not already exist..", | 
					
						
							|  |  |  |     true, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     cli_cmd_mkdir | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   embeddedCliAddBinding(_cli, (CliCommandBinding) { | 
					
						
							|  |  |  |     "mv", | 
					
						
							| 
									
										
										
										
											2022-11-21 11:24:58 +07:00
										 |  |  |     "Usage: mv SOURCE DEST...\r\n\tRename SOURCE to DEST.", | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  |     true, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     cli_cmd_mv | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-21 11:24:58 +07:00
										 |  |  |   embeddedCliAddBinding(_cli, (CliCommandBinding) { | 
					
						
							|  |  |  |     "rm", | 
					
						
							|  |  |  |     "Usage: rm [FILE]...\r\n\tRemove (unlink) the FILE(s).", | 
					
						
							|  |  |  |     true, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     cli_cmd_rm | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  | void cli_cmd_cat(EmbeddedCli *cli, char *args, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) cli; (void) context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint16_t argc = embeddedCliGetTokenCount(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // need at least 1 argument
 | 
					
						
							|  |  |  |   if ( argc == 0 ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("invalid arguments\r\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(uint16_t i=0; i<argc; i++) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     FIL fi; | 
					
						
							|  |  |  |     const char* fpath = embeddedCliGetToken(args, i+1); // token count from 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( FR_OK != f_open(&fi, fpath, FA_READ) ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       printf("%s: No such file or directory\r\n", fpath); | 
					
						
							|  |  |  |     }else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +07:00
										 |  |  |       uint8_t buf[512]; | 
					
						
							| 
									
										
										
										
											2022-11-21 11:12:10 +07:00
										 |  |  |       UINT count = 0; | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  |       while ( (FR_OK == f_read(&fi, buf, sizeof(buf), &count)) && (count > 0) ) | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2022-11-21 11:12:10 +07:00
										 |  |  |         for(UINT c = 0; c < count; c++) | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2023-03-02 14:32:22 -06:00
										 |  |  |           const uint8_t ch = buf[c]; | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  |           if (isprint(ch) || iscntrl(ch)) | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             putchar(ch); | 
					
						
							|  |  |  |           }else | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             putchar('.'); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     f_close(&fi); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void cli_cmd_cd(EmbeddedCli *cli, char *args, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) cli; (void) context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint16_t argc = embeddedCliGetTokenCount(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // only support 1 argument
 | 
					
						
							|  |  |  |   if ( argc != 1 ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("invalid arguments\r\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // default is current directory
 | 
					
						
							|  |  |  |   const char* dpath = args; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( FR_OK != f_chdir(dpath) ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("%s: No such file or directory\r\n", dpath); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +07:00
										 |  |  | void cli_cmd_cp(EmbeddedCli *cli, char *args, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) cli; (void) context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint16_t argc = embeddedCliGetTokenCount(args); | 
					
						
							|  |  |  |   if ( argc != 2 ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("invalid arguments\r\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // default is current directory
 | 
					
						
							|  |  |  |   const char* src = embeddedCliGetToken(args, 1); | 
					
						
							|  |  |  |   const char* dst = embeddedCliGetToken(args, 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   FIL f_src; | 
					
						
							|  |  |  |   FIL f_dst; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( FR_OK != f_open(&f_src, src, FA_READ) ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("cannot stat '%s': No such file or directory\r\n", src); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( FR_OK != f_open(&f_dst, dst, FA_WRITE | FA_CREATE_ALWAYS) ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("cannot create '%s'\r\n", dst); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   }else | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     uint8_t buf[512]; | 
					
						
							| 
									
										
										
										
											2022-11-21 11:12:10 +07:00
										 |  |  |     UINT rd_count = 0; | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +07:00
										 |  |  |     while ( (FR_OK == f_read(&f_src, buf, sizeof(buf), &rd_count)) && (rd_count > 0) ) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-11-21 11:12:10 +07:00
										 |  |  |       UINT wr_count = 0; | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if ( FR_OK != f_write(&f_dst, buf, rd_count, &wr_count) ) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         printf("cannot write to '%s'\r\n", dst); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   f_close(&f_src); | 
					
						
							|  |  |  |   f_close(&f_dst); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-11-19 15:27:07 +07:00
										 |  |  |   (void) cli; (void) context; | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   uint16_t argc = embeddedCliGetTokenCount(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // only support 1 argument
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  |   if ( argc > 1 ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("invalid arguments\r\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // default is current directory
 | 
					
						
							|  |  |  |   const char* dpath = "."; | 
					
						
							|  |  |  |   if (argc) dpath = args; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DIR dir; | 
					
						
							|  |  |  |   if ( FR_OK != f_opendir(&dir, dpath) ) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  |     printf("cannot access '%s': No such file or directory\r\n", dpath); | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   FILINFO fno; | 
					
						
							|  |  |  |   while( (f_readdir(&dir, &fno) == FR_OK) && (fno.fname[0] != 0) ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if ( fno.fname[0] != '.' ) // ignore . and .. entry
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if ( fno.fattrib & AM_DIR ) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         // directory
 | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  |         printf("/%s\r\n", fno.fname); | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |       }else | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  |         printf("%-40s", fno.fname); | 
					
						
							|  |  |  |         if (fno.fsize < 1024) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           printf("%lu B\r\n", fno.fsize); | 
					
						
							|  |  |  |         }else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           printf("%lu KB\r\n", fno.fsize / 1024); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-11-19 13:44:07 +07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   f_closedir(&dir); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-21 11:52:51 +07:00
										 |  |  | void cli_cmd_pwd(EmbeddedCli *cli, char *args, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) cli; (void) context; | 
					
						
							|  |  |  |   uint16_t argc = embeddedCliGetTokenCount(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (argc != 0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("invalid arguments\r\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   char path[256]; | 
					
						
							|  |  |  |   if (FR_OK != f_getcwd(path, sizeof(path))) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("cannot get current working directory\r\n"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   puts(path); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  | void cli_cmd_mkdir(EmbeddedCli *cli, char *args, void *context) | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-11-19 15:27:07 +07:00
										 |  |  |   (void) cli; (void) context; | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   uint16_t argc = embeddedCliGetTokenCount(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // only support 1 argument
 | 
					
						
							|  |  |  |   if ( argc != 1 ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("invalid arguments\r\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // default is current directory
 | 
					
						
							|  |  |  |   const char* dpath = args; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  |   if ( FR_OK != f_mkdir(dpath) ) | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-11-19 15:37:23 +07:00
										 |  |  |     printf("%s: cannot create this directory\r\n", dpath); | 
					
						
							| 
									
										
										
										
											2022-11-19 13:56:33 +07:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-11-19 15:53:55 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | void cli_cmd_mv(EmbeddedCli *cli, char *args, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) cli; (void) context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint16_t argc = embeddedCliGetTokenCount(args); | 
					
						
							|  |  |  |   if ( argc != 2 ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("invalid arguments\r\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // default is current directory
 | 
					
						
							|  |  |  |   const char* src = embeddedCliGetToken(args, 1); | 
					
						
							|  |  |  |   const char* dst = embeddedCliGetToken(args, 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( FR_OK != f_rename(src, dst) ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("cannot mv %s to %s\r\n", src, dst); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-11-21 11:24:58 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | void cli_cmd_rm(EmbeddedCli *cli, char *args, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   (void) cli; (void) context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uint16_t argc = embeddedCliGetTokenCount(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // need at least 1 argument
 | 
					
						
							|  |  |  |   if ( argc == 0 ) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     printf("invalid arguments\r\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for(uint16_t i=0; i<argc; i++) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const char* fpath = embeddedCliGetToken(args, i+1); // token count from 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( FR_OK != f_unlink(fpath) ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       printf("cannot remove '%s': No such file or directory\r\n", fpath); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |