Просмотр исходного кода

add scsi write10 & test unit ready
done copy command
implement get_fattime using __DATE__ and number of calls

hathach 12 лет назад
Родитель
Сommit
9d60db0f9f

+ 32 - 66
demos/host/host_os_none/host_os_none.uvopt

@@ -135,7 +135,7 @@
         <SetRegEntry>
           <Number>0</Number>
           <Key>DLGUARM</Key>
-          <Name>(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)</Name>
+          <Name></Name>
         </SetRegEntry>
         <SetRegEntry>
           <Number>0</Number>
@@ -158,24 +158,7 @@
           <Name>-O975 -S0 -C0 -FO7 -FD10000000 -FC800 -FN2 -FF0LPC18xx43xx_512_BA -FS01A000000 -FL080000 -FF1LPC18xx43xx_512_BB -FS11B000000 -FL180000)</Name>
         </SetRegEntry>
       </TargetDriverDllRegistry>
-      <Breakpoint>
-        <Bp>
-          <Number>0</Number>
-          <Type>0</Type>
-          <LineNumber>269</LineNumber>
-          <EnabledFlag>1</EnabledFlag>
-          <Address>0</Address>
-          <ByteObject>0</ByteObject>
-          <HtxType>0</HtxType>
-          <ManyObjects>0</ManyObjects>
-          <SizeOfObject>0</SizeOfObject>
-          <BreakByAccess>0</BreakByAccess>
-          <BreakIfRCount>0</BreakIfRCount>
-          <Filename>C:\Users\hathach\Dropbox\tinyusb\workspace\tinyusb\demos\host\src\cli.c</Filename>
-          <ExecCommand></ExecCommand>
-          <Expression></Expression>
-        </Bp>
-      </Breakpoint>
+      <Breakpoint/>
       <WatchWindow1>
         <Ww>
           <count>0</count>
@@ -387,24 +370,7 @@
           <Name>-O975 -S0 -C0 -FO7 -FD10000000 -FC800 -FN2 -FF0LPC18xx43xx_512_BA -FS01A000000 -FL080000 -FF1LPC18xx43xx_512_BB -FS11B000000 -FL180000)</Name>
         </SetRegEntry>
       </TargetDriverDllRegistry>
-      <Breakpoint>
-        <Bp>
-          <Number>0</Number>
-          <Type>0</Type>
-          <LineNumber>269</LineNumber>
-          <EnabledFlag>1</EnabledFlag>
-          <Address>0</Address>
-          <ByteObject>0</ByteObject>
-          <HtxType>0</HtxType>
-          <ManyObjects>0</ManyObjects>
-          <SizeOfObject>0</SizeOfObject>
-          <BreakByAccess>0</BreakByAccess>
-          <BreakIfRCount>0</BreakIfRCount>
-          <Filename>C:\Users\hathach\Dropbox\tinyusb\workspace\tinyusb\demos\host\src\cli.c</Filename>
-          <ExecCommand></ExecCommand>
-          <Expression></Expression>
-        </Bp>
-      </Breakpoint>
+      <Breakpoint/>
       <WatchWindow1>
         <Ww>
           <count>0</count>
@@ -458,10 +424,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>1</ColumnNumber>
+      <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>195</TopLine>
-      <CurrentLine>200</CurrentLine>
+      <TopLine>1</TopLine>
+      <CurrentLine>1</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\src\main.c</PathWithFileName>
       <FilenameWithoutPath>main.c</FilenameWithoutPath>
@@ -476,7 +442,7 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>94</TopLine>
+      <TopLine>125</TopLine>
       <CurrentLine>145</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\src\cdc_serial_app.c</PathWithFileName>
@@ -492,7 +458,7 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>136</TopLine>
+      <TopLine>167</TopLine>
       <CurrentLine>180</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\src\keyboard_app.c</PathWithFileName>
@@ -508,7 +474,7 @@
       <Focus>0</Focus>
       <ColumnNumber>44</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>120</TopLine>
+      <TopLine>121</TopLine>
       <CurrentLine>127</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\src\mouse_app.c</PathWithFileName>
@@ -538,10 +504,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>1</ColumnNumber>
+      <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>111</TopLine>
-      <CurrentLine>125</CurrentLine>
+      <TopLine>1</TopLine>
+      <CurrentLine>1</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\src\msc_app.c</PathWithFileName>
       <FilenameWithoutPath>msc_app.c</FilenameWithoutPath>
@@ -554,10 +520,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>24</ColumnNumber>
+      <ColumnNumber>27</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>1</TopLine>
-      <CurrentLine>11</CurrentLine>
+      <TopLine>355</TopLine>
+      <CurrentLine>367</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\src\cli.c</PathWithFileName>
       <FilenameWithoutPath>cli.c</FilenameWithoutPath>
@@ -596,7 +562,7 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>139</TopLine>
+      <TopLine>140</TopLine>
       <CurrentLine>142</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\bsp\boards\embedded_artists\board_ea4357.c</PathWithFileName>
@@ -612,7 +578,7 @@
       <Focus>0</Focus>
       <ColumnNumber>6</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>95</TopLine>
+      <TopLine>125</TopLine>
       <CurrentLine>135</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\bsp\boards\printf_retarget.c</PathWithFileName>
@@ -748,7 +714,7 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>25</TopLine>
+      <TopLine>56</TopLine>
       <CurrentLine>76</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\tinyusb\tusb.c</PathWithFileName>
@@ -812,7 +778,7 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>483</TopLine>
+      <TopLine>491</TopLine>
       <CurrentLine>501</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\tinyusb\host\usbh.c</PathWithFileName>
@@ -826,10 +792,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>0</ColumnNumber>
+      <ColumnNumber>38</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>602</TopLine>
-      <CurrentLine>605</CurrentLine>
+      <TopLine>479</TopLine>
+      <CurrentLine>484</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\tinyusb\host\ehci\ehci.c</PathWithFileName>
       <FilenameWithoutPath>ehci.c</FilenameWithoutPath>
@@ -986,10 +952,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>0</ColumnNumber>
+      <ColumnNumber>1</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>1</TopLine>
-      <CurrentLine>1</CurrentLine>
+      <TopLine>110</TopLine>
+      <CurrentLine>118</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\tinyusb\class\msc_host.c</PathWithFileName>
       <FilenameWithoutPath>msc_host.c</FilenameWithoutPath>
@@ -1012,7 +978,7 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>548</TopLine>
+      <TopLine>549</TopLine>
       <CurrentLine>553</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\bsp\lpc43xx\CMSIS_LPC43xx_DriverLib\src\lpc43xx_uart.c</PathWithFileName>
@@ -1114,10 +1080,10 @@
       <FileType>2</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>0</ColumnNumber>
+      <ColumnNumber>26</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>140</TopLine>
-      <CurrentLine>158</CurrentLine>
+      <TopLine>145</TopLine>
+      <CurrentLine>154</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\bsp\lpc43xx\startup_keil\startup_LPC43xx.s</PathWithFileName>
       <FilenameWithoutPath>startup_LPC43xx.s</FilenameWithoutPath>
@@ -1138,10 +1104,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>46</ColumnNumber>
+      <ColumnNumber>45</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>17</TopLine>
-      <CurrentLine>30</CurrentLine>
+      <TopLine>1</TopLine>
+      <CurrentLine>10</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\vendor\fatfs\diskio.c</PathWithFileName>
       <FilenameWithoutPath>diskio.c</FilenameWithoutPath>

+ 101 - 31
demos/host/src/cli.c

@@ -57,26 +57,39 @@ 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(ls      , cli_cmd_list     , "list items in current directory") \
-    ENTRY(cd      , cli_cmd_changedir, "change current directory")        \
-    ENTRY(cat     , cli_cmd_cat      , "display contents of a text file") \
+    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 text 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 const *);
+    cli_error_t function(char *);
 
 CLI_COMMAND_TABLE(CLI_PROTOTYPE_EXPAND);
 
@@ -116,38 +129,38 @@ char const* const cli_description_tbl[] =
 #define CMD_LOOKUP_EXPAND(command, function, description)\
   [CLI_CMDTYPE_##command] = function,\
 
-typedef cli_error_t (* const cli_cmdfunc_t)(char const *);
+typedef cli_error_t (* const cli_cmdfunc_t)(char *);
 static cli_cmdfunc_t cli_command_tbl[] =
 {
   CLI_COMMAND_TABLE(CMD_LOOKUP_EXPAND)
 };
 
-
-
-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_FAILED       ] = "failed to execute"
-};
-
 //--------------------------------------------------------------------+
 // 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];
 
 //--------------------------------------------------------------------+
 // 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);
+  printf("\n%s %c%s\n$ ",
+         (volume_label[0] !=0) ? volume_label : "No Label",
+         'E'+cli_buffer[0]-'0',
+         cli_buffer+1);
+
+  memclr_(cli_buffer, CLI_MAX_BUFFER);
+}
 
 void cli_init(void)
 {
   memclr_(cli_buffer, CLI_MAX_BUFFER);
+  f_getlabel(NULL, volume_label, NULL);
 }
 
 void cli_poll(char ch)
@@ -192,11 +205,7 @@ void cli_poll(char ch)
     if (CLI_ERROR_NONE != error)  puts(cli_error_message[error]); // error message output if any
 
     //------------- print out current path -------------//
-    f_getcwd(cli_buffer, CLI_MAX_BUFFER);
-    printf("\nMSC %c%s\n$ ",
-           'E'+cli_buffer[0]-'0',
-           cli_buffer+1);
-    memclr_(cli_buffer, CLI_MAX_BUFFER);
+    cli_command_prompt();
   }
   else if (ch=='\t') // \t may be used for auto-complete later
   {
@@ -207,7 +216,7 @@ void cli_poll(char ch)
 //--------------------------------------------------------------------+
 // UNKNOWN Command
 //--------------------------------------------------------------------+
-cli_error_t cli_cmd_unknown(char const * para)
+cli_error_t cli_cmd_unknown(char * para)
 {
   puts("unknown command, please type \"help\" for list of supported commands");
   return CLI_ERROR_NONE;
@@ -216,7 +225,7 @@ cli_error_t cli_cmd_unknown(char const * para)
 //--------------------------------------------------------------------+
 // HELP command
 //--------------------------------------------------------------------+
-cli_error_t cli_cmd_help(char const * para)
+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++)
@@ -227,10 +236,18 @@ cli_error_t cli_cmd_help(char const * para)
   return CLI_ERROR_NONE;
 }
 
+//--------------------------------------------------------------------+
+// Clear Screen Command
+//--------------------------------------------------------------------+
+cli_error_t cli_cmd_clear(char* p_para)
+{
+  printf(ANSI_ERASE_SCREEN(2));
+}
+
 //--------------------------------------------------------------------+
 // LS Command
 //--------------------------------------------------------------------+
-cli_error_t cli_cmd_list(const char * p_para)
+cli_error_t cli_cmd_list(char * p_para)
 {
   if ( strlen(p_para) == 0 ) // list current directory
   {
@@ -253,7 +270,7 @@ cli_error_t cli_cmd_list(const char * p_para)
           printf("/%s", p_name);
         }else
         {
-          printf("%-50s%d KB", p_name, dir_entry.fsize / 1000);
+          printf("%-40s%d KB", p_name, dir_entry.fsize / 1000);
         }
         putchar('\n');
       }
@@ -271,7 +288,7 @@ cli_error_t cli_cmd_list(const char * p_para)
 //--------------------------------------------------------------------+
 // CD Command
 //--------------------------------------------------------------------+
-cli_error_t cli_cmd_changedir(const char * p_para)
+cli_error_t cli_cmd_changedir(char * p_para)
 {
   if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA;
 
@@ -286,7 +303,7 @@ cli_error_t cli_cmd_changedir(const char * p_para)
 //--------------------------------------------------------------------+
 // CAT Command
 //--------------------------------------------------------------------+
-cli_error_t cli_cmd_cat(const char *p_para)
+cli_error_t cli_cmd_cat(char *p_para)
 {
   if ( strlen(p_para) == 0 ) return CLI_ERROR_INVALID_PARA;
 
@@ -325,4 +342,57 @@ cli_error_t cli_cmd_cat(const char *p_para)
   return CLI_ERROR_NONE;
 }
 
+//--------------------------------------------------------------------+
+// Make Directory command
+//--------------------------------------------------------------------+
+//--------------------------------------------------------------------+
+// 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;
+
+  //------------- 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

+ 0 - 2
demos/host/src/main.c

@@ -125,8 +125,6 @@ int main(void)
 
   tusb_init();
 
-  cli_init();
-
   //------------- application task init -------------//
   (void) osal_task_create( OSAL_TASK_REF(led_blinking_task) );
 

+ 5 - 6
demos/host/src/msc_app.c

@@ -89,24 +89,23 @@ void tusbh_msc_mounted_cb(uint8_t dev_addr)
 
   if ( disk_is_ready(0) )
   {
-    if ( f_mount(0, &fatfs[dev_addr-1]) != FR_OK )
+    if ( f_mount(0, &fatfs[dev_addr-1]) != FR_OK ) // TODO multiple volume
     {
       puts("mount failed");
       return;
     }
 
-    char volume_label[20] = {0};
-    f_getlabel(NULL, volume_label, NULL);
-    printf("Label: %s\n\n", volume_label);
-
     f_chdrive(dev_addr-1); // change to newly mounted drive
     f_chdir("/"); // root as current dir
-    printf("MSC %c:/\n$ ", 'E'+dev_addr-1);
+
+    cli_init();
+    cli_command_prompt();
   }
 }
 
 void tusbh_msc_unmounted_isr(uint8_t dev_addr)
 {
+  // unmount disk
   disk_state = STA_NOINIT;
   puts("--");
 }

+ 1 - 1
tests/lpc18xx_43xx/test/host/msc/msch_callback.h

@@ -54,7 +54,7 @@
 
 void tusbh_msc_mounted_cb(uint8_t dev_addr);
 void tusbh_msc_unmounted_isr(uint8_t dev_addr);
-void tusbh_msc_isr(uint8_t dev_addr, tusb_event_t event);
+void tusbh_msc_isr(uint8_t dev_addr, tusb_event_t event, uint32_t xferred_bytes);
 
 
 #ifdef __cplusplus

+ 9 - 0
tinyusb/class/msc.h

@@ -119,6 +119,15 @@ STATIC_ASSERT(sizeof(msc_cmd_status_wrapper_t) == 13, "size is not correct");
 //--------------------------------------------------------------------+
 // SCSI Primary Command (SPC-4)
 //--------------------------------------------------------------------+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t cmd_code;
+  uint8_t lun;
+  uint8_t reserved[3];
+  uint8_t control;
+} scsi_test_unit_ready_t;
+
+STATIC_ASSERT(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct");
+
 typedef ATTR_PACKED_STRUCT(struct) {
   uint8_t cmd_code;
   uint8_t reserved1;

+ 43 - 3
tinyusb/class/msc_host.c

@@ -116,8 +116,19 @@ static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t
 static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) ATTR_WARN_UNUSED_RESULT;
 static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer)
 {
-  ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
-  ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_in , p_buffer, p_msch->cbw.xfer_bytes) );
+  if ( NULL != p_buffer)
+  { // there is data phase
+    if (p_msch->cbw.flags & TUSB_DIR_DEV_TO_HOST_MASK)
+    {
+      ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
+      ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_in , p_buffer, p_msch->cbw.xfer_bytes) );
+    }else
+    {
+      ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_out, &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t)) );
+      ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out , p_buffer, p_msch->cbw.xfer_bytes, false) );
+    }
+  }
+
   ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , &p_msch->csw, sizeof(msc_cmd_status_wrapper_t), true) );
 
   return TUSB_ERROR_NONE;
@@ -198,6 +209,33 @@ tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_d
   return TUSB_ERROR_NONE;
 }
 
+tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun,  msc_cmd_status_wrapper_t * p_csw)
+{
+  msch_interface_t* p_msch = &msch_data[dev_addr-1];
+
+  //------------- Command Block Wrapper -------------//
+  msc_cbw_add_signature(&p_msch->cbw, lun);
+
+  p_msch->cbw.xfer_bytes = 0; // Number of bytes
+  p_msch->cbw.flags      = TUSB_DIR_HOST_TO_DEV;
+  p_msch->cbw.cmd_len    = sizeof(scsi_test_unit_ready_t);
+
+  //------------- SCSI command -------------//
+  scsi_test_unit_ready_t cmd_test_unit_ready =
+  {
+      .cmd_code = SCSI_CMD_TEST_UNIT_READY,
+      .lun      = lun // according to wiki
+  };
+
+  memcpy(p_msch->cbw.command, &cmd_test_unit_ready, p_msch->cbw.cmd_len);
+
+  // TODO MSCH refractor test uinit ready
+  ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
+  ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , p_csw, sizeof(msc_cmd_status_wrapper_t), true) );
+
+  return TUSB_ERROR_NONE;
+}
+
 tusb_error_t  tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count)
 {
   msch_interface_t* p_msch = &msch_data[dev_addr-1];
@@ -232,7 +270,7 @@ tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, u
   msc_cbw_add_signature(&p_msch->cbw, lun);
 
   p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes
-  p_msch->cbw.flags      = TUSB_DIR_DEV_TO_HOST_MASK;
+  p_msch->cbw.flags      = TUSB_DIR_HOST_TO_DEV;
   p_msch->cbw.cmd_len    = sizeof(scsi_write10_t);
 
   //------------- SCSI command -------------//
@@ -355,6 +393,8 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con
   msch_data[dev_addr-1].last_lba   = __be2le( ((scsi_read_capacity10_data_t*)msch_buffer)->last_lba );
   msch_data[dev_addr-1].block_size = (uint16_t) __be2le( ((scsi_read_capacity10_data_t*)msch_buffer)->block_size );
 
+  osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
+
   msch_data[dev_addr-1].is_initialized = true;
   tusbh_msc_mounted_cb(dev_addr);
 

+ 1 - 1
tinyusb/class/msc_host.h

@@ -67,8 +67,8 @@ tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint
 tusb_error_t tusbh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT;
 tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT;
 tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) ATTR_WARN_UNUSED_RESULT;
+tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_cmd_status_wrapper_t * p_csw) ATTR_WARN_UNUSED_RESULT; // TODO to be refractor
 
-//tusb_error_t  tusbh_msc_test_unit_ready(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
 //tusb_error_t  tusbh_msc_inquiry(uint8_t dev_addr, scsi_inquiry_data_t * p_inquiry_data) ATTR_WARN_UNUSED_RESULT;
 //tusb_error_t  tusbh_msc_read_capacity10(uint8_t dev_addr, scsi_read_capacity10_t * p_buffer) ATTR_WARN_UNUSED_RESULT;
 

+ 107 - 32
vendor/fatfs/diskio.c

@@ -56,6 +56,19 @@
 //--------------------------------------------------------------------+
 // IMPLEMENTATION
 //--------------------------------------------------------------------+
+static tusb_error_t wait_for_io_complete(uint8_t usb_addr)
+{
+  #if TUSB_CFG_OS == TUSB_OS_NONE
+  while ( tusbh_msc_status(usb_addr) == TUSB_INTERFACE_STATUS_BUSY )
+  {
+    // timeout here
+  }
+  return tusbh_msc_status(usb_addr) == TUSB_INTERFACE_STATUS_READY ? RES_OK : RES_ERROR;
+#else
+  #error semaphore instead of blocking
+#endif
+
+}
 
 //pdrv Specifies the physical drive number.
 DSTATUS disk_initialize ( BYTE pdrv )
@@ -80,51 +93,113 @@ DSTATUS disk_status (BYTE pdrv)
 DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, BYTE count)
 {
   uint8_t usb_addr = pdrv+1;
-  tusbh_msc_read10(usb_addr, 0, buff, sector, count);
+  
+	if ( TUSB_ERROR_NONE != tusbh_msc_read10(usb_addr, 0, buff, sector, count) )		return RES_ERROR;
 
-#if TUSB_CFG_OS == TUSB_OS_NONE
-  while ( tusbh_msc_status(usb_addr) == TUSB_INTERFACE_STATUS_BUSY )
-  {
-    // timeout here
-  }
-  return tusbh_msc_status(usb_addr) == TUSB_INTERFACE_STATUS_READY ? RES_OK : RES_ERROR;
-#else
-  #error semaphore instead of blocking
-#endif
-
-  return RES_ERROR;
+	return wait_for_io_complete(usb_addr);
 }
 
 
 DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, BYTE count)
 {
+  uint8_t usb_addr = pdrv+1;
+
+	if ( TUSB_ERROR_NONE != tusbh_msc_write10(usb_addr, 0, buff, sector, count) )		return RES_ERROR;
 
+	return wait_for_io_complete(usb_addr);
 }
 
+/* [IN] Drive number */
+/* [IN] Control command code */
+/* [I/O] Parameter and data buffer */
+msc_cmd_status_wrapper_t temp_csw TUSB_CFG_ATTR_USBRAM; // TODO MSCH test unit ready refractor
 DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff)
 {
+  if (cmd != CTRL_SYNC) return RES_ERROR;
 
+  uint8_t usb_addr = pdrv+1;
+
+  do {
+    memclr_(&temp_csw, sizeof(msc_cmd_status_wrapper_t));
+
+    if ( TUSB_ERROR_NONE != tusbh_msc_test_unit_ready(usb_addr, 0, &temp_csw) )		return RES_ERROR;
+    wait_for_io_complete(usb_addr);
+
+  } while( temp_csw.status != 0 ); // wait unitl unit is ready
+
+  return RES_OK;
 }
 
-//DWORD get_fattime (void)
-//{
-//  union {
-//    struct {
-//      DWORD second       : 5;
-//      DWORD minute       : 6;
-//      DWORD hour         : 5;
-//      DWORD day_in_month : 5;
-//      DWORD month        : 4;
-//      DWORD year         : 7;
-//    };
-//
-//    DWORD value
-//  } timestamp =
-//  {
-//      .year = (2013-1980),
-//      .month = 10,
-//      .day_in_month = 21,
-//  };
-//}
+static inline uint8_t month2number(char* p_ch) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline uint8_t month2number(char* p_ch)
+{
+  uint8_t const * const month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+  for(uint8_t i=0; i<12; i++)
+  {
+    if ( strncmp(p_ch, month_str[i], 3) == 0 ) return i+1;
+  }
+
+  return 1;
+}
+
+static inline uint8_t c2i(char ch) ATTR_CONST ATTR_ALWAYS_INLINE;
+static inline uint8_t c2i(char ch)
+{
+  return ch - '0';
+}
+
+DWORD get_fattime (void)
+{
+  union {
+    struct {
+      DWORD second       : 5;
+      DWORD minute       : 6;
+      DWORD hour         : 5;
+      DWORD day_in_month : 5;
+      DWORD month        : 4;
+      DWORD year         : 7;
+    };
+
+    DWORD value;
+  } timestamp;
+
+  //------------- Date is compiled date-------------//
+  char compile_date[] = __DATE__; // eg. "Sep 26 2013"
+  char* p_ch;
+
+  p_ch = strtok (compile_date, " ");
+  timestamp.month = month2number(p_ch);
+
+  p_ch = strtok (NULL, " ");
+  timestamp.day_in_month = 10*c2i(p_ch[0])+ c2i(p_ch[1]);
+
+  p_ch = strtok (NULL, " ");
+  timestamp.year = 1000*c2i(p_ch[0]) + 100*c2i(p_ch[1]) + 10*c2i(p_ch[2]) + c2i(p_ch[3]) - 1980;
+
+  //------------- Time each time this function call --> sec ++ -------------//
+  static uint8_t sec = 0;
+  static uint8_t min = 0;
+  static uint8_t hour = 0;
+
+  if (++sec >= 60)
+  {
+    sec = 0;
+    if (++min >= 60)
+    {
+      min = 0;
+      if (++hour >= 24)
+      {
+        hour = 0; // assume demo wont call this function more than 24*60*60 times
+      }
+    }
+  }
+
+  timestamp.hour   = hour;
+  timestamp.minute = min;
+  timestamp.second = sec;
+
+  return timestamp.value;
+}
 
 #endif

+ 1 - 1
vendor/fatfs/ffconf.h

@@ -20,7 +20,7 @@
 /  data transfer. This reduces memory consumption 512 bytes each file object. */
 
 
-#define _FS_READONLY	1	/* 0:Read/Write or 1:Read only */
+#define _FS_READONLY	0	/* 0:Read/Write or 1:Read only */
 /* Setting _FS_READONLY to 1 defines read only configuration. This removes
 /  writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
 /  f_truncate and useless f_getfree. */