MCUXpresso_MIMXRT1052xxxxB/boards/evkbimxrt1050/usb_examples/usb_pin_detect_hid_msd/freertos/host_msd_fatfs.c
2022-04-08 22:46:35 +08:00

1080 lines
33 KiB
C

/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016, 2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include "usb_host_config.h"
#include "usb_host.h"
#include "usb_host_msd.h"
#include "host_msd_fatfs.h"
#include "host_app.h"
#include "ff.h"
#include "diskio.h"
#include "fsl_device_registers.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#if MSD_FATFS_THROUGHPUT_TEST_ENABLE
#include "fsl_device_registers.h"
#define THROUGHPUT_BUFFER_SIZE (64 * 1024) /* throughput test buffer */
#define MCU_CORE_CLOCK (120000000) /* mcu core clock, user need to configure it. */
#endif /* MSD_FATFS_THROUGHPUT_TEST_ENABLE */
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief host msd control transfer callback.
*
* This function is used as callback function for control transfer .
*
* @param param the host msd fatfs instance pointer.
* @param data data buffer pointer.
* @param dataLength data length.
* @status transfer result status.
*/
void USB_HostMsdControlCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status);
/*!
* @brief msd fatfs test code execute done.
*/
static void USB_HostMsdFatfsTestDone(void);
#if ((defined MSD_FATFS_THROUGHPUT_TEST_ENABLE) && (MSD_FATFS_THROUGHPUT_TEST_ENABLE))
/*!
* @brief host msd fatfs throughput test.
*
* @param msdFatfsInstance the host fatfs instance pointer.
*/
static void USB_HostMsdFatfsThroughputTest(usb_host_msd_fatfs_instance_t *msdFatfsInstance);
#else
/*!
* @brief display file information.
*/
static void USB_HostMsdFatfsDisplayFileInfo(FILINFO *fileInfo);
/*!
* @brief list files and sub-directory in one directory, the function don't check all sub-directories recursively.
*/
static FRESULT USB_HostMsdFatfsListDirectory(const TCHAR *path);
/*!
* @brief forward function pointer for fatfs f_forward function.
*
* @param data_ptr forward data pointer.
* @param dataLength data length.
*/
#if _USE_FORWARD && _FS_TINY
static uint32_t USB_HostMsdFatfsForward(const uint8_t *data_ptr, uint32_t dataLength);
#endif
/*!
* @brief host msd fatfs test.
*
* This function implements msd fatfs test.
*
* @param msdFatfsInstance the host fatfs instance pointer.
*/
static void USB_HostMsdFatfsTest(usb_host_msd_fatfs_instance_t *msdFatfsInstance);
#endif /* MSD_FATFS_THROUGHPUT_TEST_ENABLE */
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
extern usb_status_t USB_HostTestModeInit(usb_device_handle deviceHandle);
#endif
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief msd class handle array for fatfs */
extern usb_host_class_handle g_UsbFatfsClassHandle;
usb_host_msd_fatfs_instance_t g_MsdFatfsInstance; /* global msd fatfs instance */
static FATFS fatfs;
/* control transfer on-going state. It should set to 1 when start control transfer, it is set to 0 in the callback */
volatile uint8_t controlIng;
/* control transfer callback status */
volatile usb_status_t controlStatus;
#if MSD_FATFS_THROUGHPUT_TEST_ENABLE
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint32_t testThroughputBuffer[THROUGHPUT_BUFFER_SIZE / 4]; /* the buffer for throughput test */
uint32_t testSizeArray[] = {20 * 1024, 20 * 1024}; /* test time and test size (uint: K)*/
#else
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t testBuffer[(FF_MAX_SS > 256) ? FF_MAX_SS : 256]; /* normal test buffer */
#endif /* MSD_FATFS_THROUGHPUT_TEST_ENABLE */
/*******************************************************************************
* Code
******************************************************************************/
void USB_HostMsdControlCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{
usb_host_msd_fatfs_instance_t *msdFatfsInstance = (usb_host_msd_fatfs_instance_t *)param;
if (msdFatfsInstance->runWaitState == kUSB_HostMsdRunWaitSetInterface) /* set interface finish */
{
msdFatfsInstance->runWaitState = kUSB_HostMsdRunIdle;
msdFatfsInstance->runState = kUSB_HostMsdRunMassStorageTest;
}
controlIng = 0;
controlStatus = status;
}
static void USB_HostMsdFatfsTestDone(void)
{
usb_echo("............................test done......................\r\n");
}
#if ((defined MSD_FATFS_THROUGHPUT_TEST_ENABLE) && (MSD_FATFS_THROUGHPUT_TEST_ENABLE))
static void USB_HostMsdFatfsThroughputTest(usb_host_msd_fatfs_instance_t *msdFatfsInstance)
{
uint64_t totalTime;
FRESULT fatfsCode;
FIL file;
uint32_t resultSize;
uint32_t testSize;
uint8_t testIndex;
char test_file_name[30];
/* time delay (~100ms) */
for (resultSize = 0; resultSize < 400000; ++resultSize)
{
__NOP();
}
usb_echo("............................fatfs test.....................\r\n");
CoreDebug->DEMCR |= (1 << CoreDebug_DEMCR_TRCENA_Pos);
for (testSize = 0; testSize < (THROUGHPUT_BUFFER_SIZE / 4); ++testSize)
{
testThroughputBuffer[testSize] = testSize;
}
sprintf(test_file_name, "%c:", USBDISK + '0');
fatfsCode = f_mount(&fatfs, test_file_name, 1);
if (fatfsCode)
{
usb_echo("fatfs mount error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
sprintf(test_file_name, "%c:/thput.dat", USBDISK + '0');
usb_echo("throughput test:\r\n");
for (testIndex = 0; testIndex < (sizeof(testSizeArray) / 4); ++testIndex)
{
fatfsCode = f_unlink(test_file_name); /* delete the file if it is existed */
if ((fatfsCode != FR_OK) && (fatfsCode != FR_NO_FILE))
{
USB_HostMsdFatfsTestDone();
return;
}
fatfsCode = f_open(&file, test_file_name, FA_WRITE | FA_READ | FA_CREATE_ALWAYS); /* create one new file */
if (fatfsCode)
{
USB_HostMsdFatfsTestDone();
return;
}
totalTime = 0;
testSize = testSizeArray[testIndex] * 1024;
while (testSize)
{
if (msdFatfsInstance->deviceState != kStatus_DEV_Attached)
{
USB_HostMsdFatfsTestDone();
return;
}
DWT->CYCCNT = 0;
DWT->CTRL |= (1 << DWT_CTRL_CYCCNTENA_Pos);
fatfsCode = f_write(&file, testThroughputBuffer, THROUGHPUT_BUFFER_SIZE, &resultSize);
if (fatfsCode)
{
usb_echo("write error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
totalTime += DWT->CYCCNT;
DWT->CTRL &= ~(1 << DWT_CTRL_CYCCNTENA_Pos);
testSize -= THROUGHPUT_BUFFER_SIZE;
}
testSize = testSizeArray[testIndex];
usb_echo(" write %dKB data the speed is %d KB/s\r\n", testSize,
(uint32_t)((uint64_t)testSize * (uint64_t)MCU_CORE_CLOCK / (uint64_t)totalTime));
fatfsCode = f_lseek(&file, 0);
if (fatfsCode)
{
USB_HostMsdFatfsTestDone();
return;
}
totalTime = 0;
testSize = testSizeArray[testIndex] * 1024;
while (testSize)
{
if (msdFatfsInstance->deviceState != kStatus_DEV_Attached)
{
USB_HostMsdFatfsTestDone();
return;
}
DWT->CYCCNT = 0;
DWT->CTRL |= (1 << DWT_CTRL_CYCCNTENA_Pos);
fatfsCode = f_read(&file, testThroughputBuffer, THROUGHPUT_BUFFER_SIZE, &resultSize);
if (fatfsCode)
{
usb_echo("read error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
totalTime += DWT->CYCCNT;
DWT->CTRL &= ~(1 << DWT_CTRL_CYCCNTENA_Pos);
testSize -= THROUGHPUT_BUFFER_SIZE;
}
testSize = testSizeArray[testIndex];
usb_echo(" read %dKB data the speed is %d KB/s\r\n", testSize,
(uint32_t)((uint64_t)testSize * (uint64_t)MCU_CORE_CLOCK / (uint64_t)totalTime));
fatfsCode = f_close(&file);
if (fatfsCode)
{
USB_HostMsdFatfsTestDone();
return;
}
}
USB_HostMsdFatfsTestDone();
}
#else
static void USB_HostMsdFatfsDisplayFileInfo(FILINFO *fileInfo)
{
char *fileName;
#if _USE_LFN
fileName = (fileInfo->lfname[0] ? fileInfo->lfname : fileInfo->fname;
#else
fileName = fileInfo->fname;
#endif /* _USE_LFN */
/* note: if this file/directory don't have one attribute, '_' replace the attribute letter ('R' - readonly, 'H' - hide, 'S' - system) */
usb_echo(" %s - %c%c%c - %s - %dBytes - %d-%d-%d %d:%d:%d\r\n", (fileInfo->fattrib & AM_DIR) ? "dir" : "fil",
(fileInfo->fattrib & AM_RDO) ? 'R' : '_',
(fileInfo->fattrib & AM_HID) ? 'H' : '_',
(fileInfo->fattrib & AM_SYS) ? 'S' : '_',
fileName,
(fileInfo->fsize),
(uint32_t)((fileInfo->fdate >> 9) + 1980) /* year */,
(uint32_t)((fileInfo->fdate >> 5) & 0x000Fu) /* month */,
(uint32_t)(fileInfo->fdate & 0x001Fu) /* day */,
(uint32_t)((fileInfo->ftime >> 11) & 0x0000001Fu) /* hour */,
(uint32_t)((fileInfo->ftime >> 5) & 0x0000003Fu) /* minute */,
(uint32_t)(fileInfo->ftime & 0x0000001Fu) /* second */
);
}
static FRESULT USB_HostMsdFatfsListDirectory(const TCHAR *path)
{
FRESULT fatfsCode = FR_OK;
FILINFO fileInfo;
DIR dir;
uint8_t outputLabel = 0;
#if _USE_LFN
static uint8_t fileNameBuffer[_MAX_LFN];
fileInfo.lfname = fileNameBuffer;
fileInfo.lfsize = _MAX_LFN;
#endif /* _USE_LFN */
fatfsCode = f_opendir(&dir, path);
if (fatfsCode)
{
return fatfsCode;
}
while (1)
{
fatfsCode = f_readdir(&dir, &fileInfo);
if ((fatfsCode) || (!fileInfo.fname[0]))
{
break;
}
outputLabel = 1;
USB_HostMsdFatfsDisplayFileInfo(&fileInfo);
}
if (!outputLabel)
{
usb_echo("\r\n");
}
return fatfsCode;
}
#if _USE_FORWARD && _FS_TINY
static uint32_t USB_HostMsdFatfsForward(const uint8_t *data, uint32_t dataLength)
{
uint32_t resultCount = dataLength;
if (dataLength == 0)
{
return 1;
}
else
{
do
{
usb_echo("%c", *data);
data++;
resultCount--;
} while (resultCount);
return dataLength;
}
}
#endif
static void USB_HostMsdFatfsTest(usb_host_msd_fatfs_instance_t *msdFatfsInstance)
{
FRESULT fatfsCode;
FATFS *fs;
FIL file;
FILINFO fileInfo;
uint32_t freeClusterNumber;
uint32_t index;
uint32_t resultSize;
char *testString;
uint8_t driverNumberBuffer[3];
#if _USE_LFN
static uint8_t fileNameBuffer[_MAX_LFN];
fileInfo.lfname = fileNameBuffer;
fileInfo.lfsize = _MAX_LFN;
#endif /* _USE_LFN */
/* time delay */
for (freeClusterNumber = 0; freeClusterNumber < 10000; ++freeClusterNumber)
{
__NOP();
}
usb_echo("............................fatfs test.....................\r\n");
usb_echo("fatfs mount as logiacal driver %d......", USBDISK);
sprintf((char *)&driverNumberBuffer[0], "%c:", USBDISK + '0');
fatfsCode = f_mount(&fatfs, (char const *)&driverNumberBuffer[0], 0);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
#if (FF_FS_RPATH >= 2)
fatfsCode = f_chdrive((char const *)&driverNumberBuffer[0]);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
#endif
#if FF_USE_MKFS
MKFS_PARM formatOptions;
formatOptions.fmt = FM_SFD | FM_ANY;
usb_echo("test f_mkfs......");
fatfsCode = f_mkfs((char const *)&driverNumberBuffer[0], &formatOptions, testBuffer, FF_MAX_SS);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
#endif /* FF_USE_MKFS */
usb_echo("test f_getfree:\r\n");
fatfsCode = f_getfree((char const *)&driverNumberBuffer[0], (DWORD *)&freeClusterNumber, &fs);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
if (fs->fs_type == FS_FAT12)
{
usb_echo(" FAT type = FAT12\r\n");
}
else if (fs->fs_type == FS_FAT16)
{
usb_echo(" FAT type = FAT16\r\n");
}
else
{
usb_echo(" FAT type = FAT32\r\n");
}
usb_echo(" bytes per cluster = %d; number of clusters=%lu \r\n", fs->csize * 512, fs->n_fatent - 2);
usb_echo(" The free size: %dKB, the total size:%dKB\r\n", (freeClusterNumber * (fs->csize) / 2),
((fs->n_fatent - 2) * (fs->csize) / 2));
usb_echo("directory operation:\r\n");
usb_echo("list root directory:\r\n");
fatfsCode = USB_HostMsdFatfsListDirectory((char const *)&driverNumberBuffer[0]);
if (fatfsCode)
{
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("create directory \"dir_1\"......");
fatfsCode = f_mkdir(_T("1:/dir_1"));
if (fatfsCode)
{
if (fatfsCode == FR_EXIST)
{
usb_echo("directory exist\r\n");
}
else
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
}
else
{
usb_echo("success\r\n");
}
usb_echo("create directory \"dir_2\"......");
fatfsCode = f_mkdir(_T("1:/dir_2"));
if (fatfsCode)
{
if (fatfsCode == FR_EXIST)
{
usb_echo("directory exist\r\n");
}
else
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
}
else
{
usb_echo("success\r\n");
}
usb_echo("create sub directory \"dir_2/sub_1\"......");
fatfsCode = f_mkdir(_T("1:/dir_1/sub_1"));
if (fatfsCode)
{
if (fatfsCode == FR_EXIST)
{
usb_echo("directory exist\r\n");
}
else
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
}
else
{
usb_echo("success\r\n");
}
usb_echo("list root directory:\r\n");
fatfsCode = USB_HostMsdFatfsListDirectory(_T("1:"));
if (fatfsCode)
{
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("list directory \"dir_1\":\r\n");
fatfsCode = USB_HostMsdFatfsListDirectory(_T("1:/dir_1"));
if (fatfsCode)
{
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("rename directory \"dir_1/sub_1\" to \"dir_1/sub_2\"......");
fatfsCode = f_rename(_T("1:/dir_1/sub_1"), _T("1:/dir_1/sub_2"));
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("delete directory \"dir_1/sub_2\"......");
fatfsCode = f_unlink(_T("1:/dir_1/sub_2"));
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
#if (FF_FS_RPATH >= 2)
usb_echo("get current directory......");
fatfsCode = f_getcwd((TCHAR *)&testBuffer[0], 256);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("%s\r\n", testBuffer);
usb_echo("change current directory to \"dir_1\"......");
fatfsCode = f_chdir(_T("dir_1"));
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("list current directory:\r\n");
fatfsCode = USB_HostMsdFatfsListDirectory(_T("."));
if (fatfsCode)
{
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("get current directory......");
fatfsCode = f_getcwd((TCHAR *)&testBuffer[0], 256);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("%s\r\n", testBuffer);
#endif
usb_echo("get directory \"dir_1\" information:\r\n");
fatfsCode = f_stat(_T("1:/dir_1"), &fileInfo);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
USB_HostMsdFatfsDisplayFileInfo(&fileInfo);
usb_echo("change \"dir_1\" timestamp to 2015.10.1, 12:30:0......");
fileInfo.fdate = ((2015 - 1980) << 9 | 10 << 5 | 1); /* 2015.10.1 */
fileInfo.ftime = (12 << 11 | 30 << 5); /* 12:30:00 */
fatfsCode = f_utime(_T("1:/dir_1"), &fileInfo);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("get directory \"dir_1\" information:\r\n");
fatfsCode = f_stat(_T("1:/dir_1"), &fileInfo);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
USB_HostMsdFatfsDisplayFileInfo(&fileInfo);
usb_echo("file operation:\r\n");
usb_echo("create file \"f_1.dat\"......");
fatfsCode = f_open(&file, _T("1:/f_1.dat"), FA_WRITE | FA_READ | FA_CREATE_ALWAYS);
if (fatfsCode)
{
if (fatfsCode == FR_EXIST)
{
usb_echo("file exist\r\n");
}
else
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
}
else
{
usb_echo("success\r\n");
}
usb_echo("test f_write......");
for (index = 0; index < 58; ++index)
{
testBuffer[index] = 'A' + index;
}
testBuffer[58] = '\r';
testBuffer[59] = '\n';
fatfsCode = f_write(&file, testBuffer, 60, (UINT *)&resultSize);
if ((fatfsCode) || (resultSize != 60))
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
fatfsCode = f_sync(&file);
if (fatfsCode)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("test f_printf......");
if (f_printf(&file, _T("%s\r\n"), "f_printf test") == EOF)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
fatfsCode = f_sync(&file);
if (fatfsCode)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("test f_puts......");
if (f_puts(_T("f_put test\r\n"), &file) == EOF)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
fatfsCode = f_sync(&file);
if (fatfsCode)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("test f_putc......");
testString = "f_putc test\r\n";
while (*testString)
{
if (f_putc(*testString, &file) == EOF)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
testString++;
}
fatfsCode = f_sync(&file);
if (fatfsCode)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("test f_seek......");
fatfsCode = f_lseek(&file, 0);
if (fatfsCode)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("test f_gets......");
testString = f_gets((TCHAR *)&testBuffer[0], 10, &file);
usb_echo("%s\r\n", testString);
usb_echo("test f_read......");
fatfsCode = f_read(&file, testBuffer, 10, (UINT *)&resultSize);
if (fatfsCode)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
testBuffer[resultSize] = 0;
usb_echo("%s\r\n", testBuffer);
#if _USE_FORWARD && _FS_TINY
usb_echo("test f_forward......");
fatfsCode = f_forward(&file, USB_HostMsdFatfsForward, 10, &resultSize);
if (fatfsCode)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("\r\n");
#endif
usb_echo("test f_truncate......");
fatfsCode = f_truncate(&file);
if (fatfsCode)
{
usb_echo("error\r\n");
f_close(&file);
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("test f_close......");
fatfsCode = f_close(&file);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("get file \"f_1.dat\" information:\r\n");
fatfsCode = f_stat(_T("1:/f_1.dat"), &fileInfo);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
USB_HostMsdFatfsDisplayFileInfo(&fileInfo);
usb_echo("change \"f_1.dat\" timestamp to 2015.10.1, 12:30:0......");
fileInfo.fdate = ((uint32_t)(2015 - 1980) << 9 | 10 << 5 | 1); /* 2015.10.1 */
fileInfo.ftime = (12 << 11 | 30 << 5); /* 12:30:00 */
fatfsCode = f_utime(_T("1:/f_1.dat"), &fileInfo);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("change \"f_1.dat\" to readonly......");
fatfsCode = f_chmod(_T("1:/f_1.dat"), AM_RDO, AM_RDO);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("get file \"f_1.dat\" information:\r\n");
fatfsCode = f_stat(_T("1:/f_1.dat"), &fileInfo);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
USB_HostMsdFatfsDisplayFileInfo(&fileInfo);
usb_echo("remove \"f_1.dat\" readonly attribute......");
fatfsCode = f_chmod(_T("1:/f_1.dat"), 0, AM_RDO);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
usb_echo("get file \"f_1.dat\" information:\r\n");
fatfsCode = f_stat(_T("1:/f_1.dat"), &fileInfo);
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
USB_HostMsdFatfsDisplayFileInfo(&fileInfo);
usb_echo("rename \"f_1.dat\" to \"f_2.dat\"......");
fatfsCode = f_rename(_T("1:/f_1.dat"), _T("1:/f_2.dat"));
if (fatfsCode)
{
if (fatfsCode == FR_EXIST)
{
usb_echo("file exist\r\n");
}
else
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
}
else
{
usb_echo("success\r\n");
}
usb_echo("delete \"f_2.dat\"......");
fatfsCode = f_unlink(_T("1:/f_2.dat"));
if (fatfsCode)
{
usb_echo("error\r\n");
USB_HostMsdFatfsTestDone();
return;
}
usb_echo("success\r\n");
USB_HostMsdFatfsTestDone();
}
#endif /* MSD_FATFS_THROUGHPUT_TEST_ENABLE */
void USB_HostMsdTask(void *arg)
{
usb_status_t status;
usb_host_msd_fatfs_instance_t *msdFatfsInstance = (usb_host_msd_fatfs_instance_t *)arg;
if (msdFatfsInstance->deviceState != msdFatfsInstance->prevDeviceState)
{
msdFatfsInstance->prevDeviceState = msdFatfsInstance->deviceState;
switch (msdFatfsInstance->deviceState)
{
case kStatus_DEV_Idle:
break;
case kStatus_DEV_Attached: /* deivce is attached and numeration is done */
status = USB_HostMsdInit(msdFatfsInstance->deviceHandle,
&msdFatfsInstance->classHandle); /* msd class initialization */
g_UsbFatfsClassHandle = msdFatfsInstance->classHandle;
if (status != kStatus_USB_Success)
{
usb_echo("usb host msd init fail\r\n");
return;
}
msdFatfsInstance->runState = kUSB_HostMsdRunSetInterface;
break;
case kStatus_DEV_Detached: /* device is detached */
msdFatfsInstance->deviceState = kStatus_DEV_Idle;
msdFatfsInstance->runState = kUSB_HostMsdRunIdle;
USB_HostMsdDeinit(msdFatfsInstance->deviceHandle,
msdFatfsInstance->classHandle); /* msd class de-initialization */
msdFatfsInstance->classHandle = NULL;
usb_echo("mass storage device detached\r\n");
break;
default:
break;
}
}
/* run state */
switch (msdFatfsInstance->runState)
{
case kUSB_HostMsdRunIdle:
break;
case kUSB_HostMsdRunSetInterface: /* set msd interface */
msdFatfsInstance->runState = kUSB_HostMsdRunIdle;
msdFatfsInstance->runWaitState = kUSB_HostMsdRunWaitSetInterface;
status = USB_HostMsdSetInterface(msdFatfsInstance->classHandle, msdFatfsInstance->interfaceHandle, 0,
USB_HostMsdControlCallback, msdFatfsInstance);
if (status != kStatus_USB_Success)
{
usb_echo("set interface fail\r\n");
}
break;
case kUSB_HostMsdRunMassStorageTest: /* set interface succeed */
#if ((defined MSD_FATFS_THROUGHPUT_TEST_ENABLE) && (MSD_FATFS_THROUGHPUT_TEST_ENABLE))
USB_HostMsdFatfsThroughputTest(msdFatfsInstance); /* test throughput */
#else
USB_HostMsdFatfsTest(msdFatfsInstance); /* test msd device */
#endif /* MSD_FATFS_THROUGHPUT_TEST_ENABLE */
msdFatfsInstance->runState = kUSB_HostMsdRunIdle;
break;
default:
break;
}
}
usb_status_t USB_HostMsdEvent(usb_device_handle deviceHandle,
usb_host_configuration_handle configurationHandle,
uint32_t eventCode)
{
usb_status_t status = kStatus_USB_Success;
usb_host_configuration_t *configuration;
uint8_t interfaceIndex;
usb_host_interface_t *interface;
uint32_t infoValue = 0U;
uint8_t id;
switch (eventCode)
{
case kUSB_HostEventAttach:
/* judge whether is configurationHandle supported */
configuration = (usb_host_configuration_t *)configurationHandle;
for (interfaceIndex = 0; interfaceIndex < configuration->interfaceCount; ++interfaceIndex)
{
interface = &configuration->interfaceList[interfaceIndex];
id = interface->interfaceDesc->bInterfaceClass;
if (id != USB_HOST_MSD_CLASS_CODE)
{
continue;
}
id = interface->interfaceDesc->bInterfaceSubClass;
if ((id != USB_HOST_MSD_SUBCLASS_CODE_UFI) && (id != USB_HOST_MSD_SUBCLASS_CODE_SCSI))
{
continue;
}
id = interface->interfaceDesc->bInterfaceProtocol;
if (id != USB_HOST_MSD_PROTOCOL_BULK)
{
continue;
}
else
{
if (g_MsdFatfsInstance.deviceState == kStatus_DEV_Idle)
{
/* the interface is supported by the application */
g_MsdFatfsInstance.deviceHandle = deviceHandle;
g_MsdFatfsInstance.interfaceHandle = interface;
g_MsdFatfsInstance.configHandle = configurationHandle;
return kStatus_USB_Success;
}
else
{
continue;
}
}
}
status = kStatus_USB_NotSupported;
break;
case kUSB_HostEventNotSupported:
break;
case kUSB_HostEventEnumerationDone:
if (g_MsdFatfsInstance.configHandle == configurationHandle)
{
if ((g_MsdFatfsInstance.deviceHandle != NULL) && (g_MsdFatfsInstance.interfaceHandle != NULL))
{
/* the device enumeration is done */
if (g_MsdFatfsInstance.deviceState == kStatus_DEV_Idle)
{
g_MsdFatfsInstance.deviceState = kStatus_DEV_Attached;
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &infoValue);
usb_echo("mass storage device attached:pid=0x%x", infoValue);
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &infoValue);
usb_echo("vid=0x%x ", infoValue);
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &infoValue);
usb_echo("address=%d\r\n", infoValue);
}
else
{
usb_echo("not idle msd instance\r\n");
status = kStatus_USB_Error;
}
}
}
break;
case kUSB_HostEventDetach:
if (g_MsdFatfsInstance.configHandle == configurationHandle)
{
/* the device is detached */
g_UsbFatfsClassHandle = NULL;
g_MsdFatfsInstance.configHandle = NULL;
if (g_MsdFatfsInstance.deviceState != kStatus_DEV_Idle)
{
g_MsdFatfsInstance.deviceState = kStatus_DEV_Detached;
}
}
break;
default:
break;
}
return status;
}
#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
usb_status_t USB_HostTestEvent(usb_device_handle deviceHandle,
usb_host_configuration_handle configurationHandle,
uint32_t eventCode)
{
/* process the same supported device that is identified by configurationHandle */
static usb_host_configuration_handle s_ConfigHandle = NULL;
static usb_device_handle s_DeviceHandle = NULL;
static usb_host_interface_handle s_InterfaceHandle = NULL;
usb_status_t status = kStatus_USB_Success;
usb_host_configuration_t *configuration;
uint8_t interfaceIndex;
usb_host_interface_t *interface;
uint32_t id;
switch (eventCode)
{
case kUSB_HostEventAttach:
/* judge whether is configurationHandle supported */
configuration = (usb_host_configuration_t *)configurationHandle;
for (interfaceIndex = 0; interfaceIndex < configuration->interfaceCount; ++interfaceIndex)
{
interface = &configuration->interfaceList[interfaceIndex];
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &id);
if (id == 0x1a0a) /* certification Vendor ID */
{
usb_echo("cetification test device VID match\r\n");
s_DeviceHandle = deviceHandle;
s_InterfaceHandle = interface;
s_ConfigHandle = configurationHandle;
return kStatus_USB_Success;
}
}
status = kStatus_USB_NotSupported;
break;
case kUSB_HostEventNotSupported:
usb_echo("Unsupported Device\r\n");
break;
case kUSB_HostEventEnumerationDone:
if (s_ConfigHandle == configurationHandle)
{
USB_HostTestModeInit(s_DeviceHandle);
}
break;
case kUSB_HostEventDetach:
if (s_ConfigHandle == configurationHandle)
{
usb_echo("PET test device detach\r\n");
USB_HostCloseDeviceInterface(s_DeviceHandle, s_InterfaceHandle);
/* the device is detached */
s_DeviceHandle = NULL;
s_InterfaceHandle = NULL;
s_ConfigHandle = NULL;
}
break;
default:
break;
}
return status;
}
#endif