You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
513 lines
17 KiB
513 lines
17 KiB
/*!
|
|
\file usbh_usr.c
|
|
\brief user application layer for USBFS host-mode MSC class operation
|
|
|
|
\version 2019-06-05, V1.0.0, firmware for GD32VF103
|
|
*/
|
|
|
|
/*
|
|
Copyright (c) 2019, GigaDevice Semiconductor Inc.
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
3. Neither the name of the copyright holder nor the names of its contributors
|
|
may be used to endorse or promote products derived from this software without
|
|
specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "usbh_usr.h"
|
|
#include "drv_usb_hw.h"
|
|
#include "ff.h"
|
|
#include "usbh_msc_core.h"
|
|
#include "usbh_msc_scsi.h"
|
|
#include "usbh_msc_bbb.h"
|
|
|
|
extern usb_core_driver usbh_msc_core;
|
|
|
|
FATFS fatfs;
|
|
FIL file;
|
|
|
|
uint8_t line_idx = 0;
|
|
uint8_t need_clear = 0;
|
|
uint8_t usbh_usr_application_state = USBH_USR_FS_INIT;
|
|
uint8_t WriteTextBuff[] = "GD32 Connectivity line Host Demo application using FAT_FS ";
|
|
|
|
/* points to the DEVICE_PROP structure of current device */
|
|
usbh_user_cb user_callback_funs =
|
|
{
|
|
usbh_user_init,
|
|
usbh_user_deinit,
|
|
usbh_user_device_connected,
|
|
usbh_user_device_reset,
|
|
usbh_user_device_disconnected,
|
|
usbh_user_over_current_detected,
|
|
usbh_user_device_speed_detected,
|
|
usbh_user_device_desc_available,
|
|
usbh_user_device_address_assigned,
|
|
usbh_user_configuration_descavailable,
|
|
usbh_user_manufacturer_string,
|
|
usbh_user_product_string,
|
|
usbh_user_serialnum_string,
|
|
usbh_user_enumeration_finish,
|
|
usbh_user_userinput,
|
|
usbh_usr_msc_application,
|
|
usbh_user_device_not_supported,
|
|
usbh_user_unrecovered_error
|
|
};
|
|
|
|
const uint8_t MSG_HOST_INIT[] = "> Host Library Initialized.";
|
|
const uint8_t MSG_DEV_ATTACHED[] = "> Device Attached.";
|
|
const uint8_t MSG_DEV_DISCONNECTED[] = "> Device Disconnected.";
|
|
const uint8_t MSG_DEV_ENUMERATED[] = "> Enumeration completed.";
|
|
const uint8_t MSG_DEV_HIGHSPEED[] = "> High speed device detected.";
|
|
const uint8_t MSG_DEV_FULLSPEED[] = "> Full speed device detected.";
|
|
const uint8_t MSG_DEV_LOWSPEED[] = "> Low speed device detected.";
|
|
const uint8_t MSG_DEV_ERROR[] = "> Device fault.";
|
|
|
|
const uint8_t MSG_HOST_HEADER[] = "> USBFS MSC Host";
|
|
const uint8_t MSG_HOST_FOOTER[] = "> USB Host Library v2.0.0";
|
|
|
|
const uint8_t MSG_LIB_START[] = "##### USB Host library started #####";
|
|
const uint8_t MSG_DEV_NOSUP[] = "> Device not supported.";
|
|
const uint8_t MSG_OVERCURRENT[] = "> Overcurrent detected.";
|
|
const uint8_t MSG_RESET_DEV[] = "> Reset the USB device.";
|
|
|
|
const uint8_t MSG_MSC_CLASS[] = "> Mass storage device connected.";
|
|
const uint8_t MSG_HID_CLASS[] = "> HID device connected.";
|
|
const uint8_t MSG_DISK_SIZE[] = "> Size of the disk in MBytes: ";
|
|
const uint8_t MSG_LUN[] = "> LUN Available in the device:";
|
|
const uint8_t MSG_ROOT_CONT[] = "> Exploring disk flash ...";
|
|
const uint8_t MSG_WR_PROTECT[] = "> The disk is write protected.";
|
|
const uint8_t MSG_UNREC_ERROR[] = "> UNRECOVERED ERROR STATE.";
|
|
const uint8_t MSG_FILE_NOTINIT[] = "> Cannot initialize File System.";
|
|
const uint8_t MSG_FILE_INIT[] = "> File System initialized.";
|
|
const uint8_t MSG_Write_File[] = "> Writing File to disk flash ...";
|
|
const uint8_t MSG_Write_Protect[] = "> Disk flash is write protected ";
|
|
const uint8_t MSG_NOT_WRITE[] = "> GD32.TXT CANNOT be writen.";
|
|
const uint8_t MSG_CREATE_FILE[] = "> GD32.TXT created in the disk.";
|
|
|
|
static uint8_t explore_disk (char* path, uint8_t recu_level);
|
|
|
|
/*!
|
|
\brief user operation for host-mode initialization
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_init(void)
|
|
{
|
|
static uint8_t startup = 0U;
|
|
|
|
if (0U == startup) {
|
|
startup = 1U;
|
|
|
|
//lcd_log_print((uint8_t *)MSG_LIB_START, sizeof(MSG_LIB_START) - 1, LCD_COLOR_WHITE);
|
|
|
|
//lcd_log_footer_set((uint8_t *)MSG_HOST_FOOTER, 70);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief user operation for device attached
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_device_connected(void)
|
|
{
|
|
//lcd_log_print((uint8_t *)MSG_DEV_ATTACHED, sizeof(MSG_DEV_ATTACHED) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief user operation when unrecoveredError happens
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_unrecovered_error (void)
|
|
{
|
|
//lcd_log_print((uint8_t *)MSG_UNREC_ERROR, sizeof(MSG_UNREC_ERROR) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief user operation for device disconnect event
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_device_disconnected (void)
|
|
{
|
|
//lcd_log_print((uint8_t *)MSG_DEV_DISCONNECTED, sizeof(MSG_DEV_DISCONNECTED) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief user operation for reset USB Device
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_device_reset(void)
|
|
{
|
|
//lcd_log_print((uint8_t *)MSG_RESET_DEV, sizeof(MSG_RESET_DEV) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief user operation for detectting device speed
|
|
\param[in] device_speed: device speed
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_device_speed_detected(uint32_t device_speed)
|
|
{
|
|
if (PORT_SPEED_HIGH == device_speed) {
|
|
//lcd_log_print((uint8_t *)MSG_DEV_HIGHSPEED, sizeof(MSG_DEV_HIGHSPEED) - 1, LCD_COLOR_WHITE);
|
|
} else if(PORT_SPEED_FULL == device_speed) {
|
|
//lcd_log_print((uint8_t *)MSG_DEV_FULLSPEED, sizeof(MSG_DEV_FULLSPEED) - 1, LCD_COLOR_WHITE);
|
|
} else if(PORT_SPEED_LOW == device_speed) {
|
|
//lcd_log_print((uint8_t *)MSG_DEV_LOWSPEED, sizeof(MSG_DEV_LOWSPEED) - 1, LCD_COLOR_WHITE);
|
|
} else {
|
|
//lcd_log_print((uint8_t *)MSG_DEV_ERROR, sizeof(MSG_DEV_ERROR) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief user operation when device descriptor is available
|
|
\param[in] device_desc: device descriptor
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_device_desc_available(void *device_desc)
|
|
{
|
|
uint8_t TempStr[64], str_len = 0;
|
|
usb_desc_dev *pDevStr = device_desc;
|
|
|
|
sprintf((char *)TempStr, "VID: %04Xh", (uint32_t)pDevStr->idVendor);
|
|
str_len = strlen((const char *)TempStr);
|
|
//lcd_log_print((uint8_t *)TempStr, str_len, LCD_COLOR_WHITE);
|
|
|
|
sprintf((char *)TempStr, "PID: %04Xh", (uint32_t)pDevStr->idProduct);
|
|
str_len = strlen((const char *)TempStr);
|
|
//lcd_log_print((uint8_t *)TempStr, str_len, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief usb device is successfully assigned the Address
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_device_address_assigned(void)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
\brief user operation when configuration descriptor is available
|
|
\param[in] cfg_desc: pointer to configuration descriptor
|
|
\param[in] itf_desc: pointer to interface descriptor
|
|
\param[in] ep_desc: pointer to endpoint descriptor
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_configuration_descavailable(usb_desc_config *cfg_desc,
|
|
usb_desc_itf *itf_desc,
|
|
usb_desc_ep *ep_desc)
|
|
{
|
|
usb_desc_itf *id = itf_desc;
|
|
|
|
if (0x08U == (*id).bInterfaceClass) {
|
|
//lcd_log_print((uint8_t *)MSG_MSC_CLASS, sizeof(MSG_MSC_CLASS) - 1, LCD_COLOR_WHITE);
|
|
} else if (0x03U == (*id).bInterfaceClass) {
|
|
//lcd_log_print((uint8_t *)MSG_HID_CLASS, sizeof(MSG_HID_CLASS) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief user operation when manufacturer string exists
|
|
\param[in] manufacturer_string: manufacturer string of usb device
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_manufacturer_string(void *manufacturer_string)
|
|
{
|
|
uint8_t TempStr[64], str_len = 0;
|
|
|
|
sprintf((char *)TempStr, "Manufacturer: %s", (char *)manufacturer_string);
|
|
str_len = strlen((const char *)TempStr);
|
|
//lcd_log_print((uint8_t *)TempStr, str_len, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief user operation when product string exists
|
|
\param[in] product_string: product string of usb device
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_product_string(void *product_string)
|
|
{
|
|
uint8_t TempStr[64], str_len = 0;
|
|
|
|
sprintf((char *)TempStr, "Product: %s", (char *)product_string);
|
|
str_len = strlen((const char *)TempStr);
|
|
//lcd_log_print((uint8_t *)TempStr, str_len, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief user operatin when serialNum string exists
|
|
\param[in] serial_num_string: serialNum string of usb device
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_serialnum_string(void *serial_num_string)
|
|
{
|
|
uint8_t TempStr[64], str_len = 0;
|
|
|
|
sprintf((char *)TempStr, "Serial Number: %s", (char *)serial_num_string);
|
|
str_len = strlen((const char *)TempStr);
|
|
//lcd_log_print((uint8_t *)TempStr, str_len, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief user response request is displayed to ask for application jump to class
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_enumeration_finish(void)
|
|
{
|
|
uint8_t Str1[] = "To see the disk information: ";
|
|
uint8_t Str2[] = "Press CET Key...";
|
|
|
|
//lcd_log_print((uint8_t *)MSG_DEV_ENUMERATED, sizeof(MSG_DEV_ENUMERATED) - 1, LCD_COLOR_WHITE);
|
|
//lcd_log_print((uint8_t *)Str1, sizeof(Str1) - 1, LCD_COLOR_GREEN);
|
|
//lcd_log_print((uint8_t *)Str2, sizeof(Str2) - 1, LCD_COLOR_GREEN);
|
|
}
|
|
|
|
/*!
|
|
\brief user operation when device is not supported
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_device_not_supported(void)
|
|
{
|
|
//lcd_log_print((uint8_t *)MSG_DEV_NOSUP, sizeof(MSG_DEV_NOSUP) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief user action for application state entry
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval user response for user key
|
|
*/
|
|
usbh_user_status usbh_user_userinput(void)
|
|
{
|
|
usbh_user_status usbh_usr_status = USBH_USER_NO_RESP;
|
|
|
|
return usbh_usr_status;
|
|
}
|
|
|
|
/*!
|
|
\brief user operation for device overcurrent detection event
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_over_current_detected (void)
|
|
{
|
|
//lcd_log_print((uint8_t *)MSG_OVERCURRENT, sizeof(MSG_OVERCURRENT) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/*!
|
|
\brief demo application for mass storage
|
|
\param[in] pudev: pointer to device
|
|
\param[in] id: no use here
|
|
\param[out] none
|
|
\retval status
|
|
*/
|
|
int usbh_usr_msc_application(void)
|
|
{
|
|
FRESULT res;
|
|
uint16_t bytesWritten, bytesToWrite;
|
|
|
|
uint8_t Str1[] = "> To see the root content of the disk ";
|
|
uint8_t Str2[] = "> Press C Key to write file";
|
|
uint8_t Str3[] = "> The MSC host demo is end.";
|
|
uint8_t Str4[] = "> Press CET key...";
|
|
uint8_t TempStr[64], str_len = 0;
|
|
|
|
switch(usbh_usr_application_state)
|
|
{
|
|
case USBH_USR_FS_INIT:
|
|
/* initialises the file system*/
|
|
if (FR_OK != f_mount(0, &fatfs)) {
|
|
//lcd_log_print((uint8_t *)MSG_FILE_NOTINIT, sizeof(MSG_FILE_NOTINIT) - 1, LCD_COLOR_WHITE);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
//lcd_log_print((uint8_t *)MSG_FILE_INIT, sizeof(MSG_FILE_INIT) - 1, LCD_COLOR_WHITE);
|
|
|
|
sprintf((char *)TempStr, "> Disk capacity: %ud Bytes.", \
|
|
usbh_msc_param.msc_capacity * usbh_msc_param.msc_page_len);
|
|
|
|
str_len = strlen((const char *)TempStr);
|
|
|
|
//lcd_log_print((uint8_t *)TempStr, str_len, LCD_COLOR_WHITE);
|
|
|
|
if (DISK_WRITE_PROTECTED == usbh_msc_param.msc_write_protect) {
|
|
//lcd_log_print((uint8_t *)MSG_WR_PROTECT, sizeof(MSG_WR_PROTECT) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
usbh_usr_application_state = USBH_USR_FS_READLIST;
|
|
break;
|
|
|
|
case USBH_USR_FS_READLIST:
|
|
//lcd_log_print((uint8_t *)MSG_ROOT_CONT, sizeof(MSG_ROOT_CONT) - 1, LCD_COLOR_WHITE);
|
|
//lcd_log_print((uint8_t *)Str1, sizeof(Str1) - 1, LCD_COLOR_GREEN);
|
|
//lcd_log_print((uint8_t *)Str4, sizeof(Str4) - 1, LCD_COLOR_GREEN);
|
|
|
|
//explore_disk("0:/", 1);
|
|
line_idx = 0;
|
|
usbh_usr_application_state = USBH_USR_FS_WRITEFILE;
|
|
break;
|
|
|
|
case USBH_USR_FS_WRITEFILE:
|
|
usb_mdelay(100U);
|
|
|
|
//lcd_log_print((uint8_t *)Str2, sizeof(Str2) - 1, LCD_COLOR_GREEN);
|
|
|
|
//lcd_log_print((uint8_t *)MSG_Write_File, sizeof(MSG_Write_File) - 1, LCD_COLOR_WHITE);
|
|
|
|
if (DISK_WRITE_PROTECTED == usbh_msc_param.msc_write_protect) {
|
|
//lcd_log_print((uint8_t *)MSG_Write_Protect, sizeof(MSG_Write_Protect) - 1, LCD_COLOR_WHITE);
|
|
|
|
usbh_usr_application_state = USBH_USR_FS_DEMOEND;
|
|
break;
|
|
}
|
|
|
|
/* register work area for logical drives */
|
|
f_mount(0, &fatfs);
|
|
|
|
if (FR_OK == f_open(&file, "0:GD32.TXT", FA_CREATE_ALWAYS | FA_WRITE)) {
|
|
/* write buffer to file */
|
|
bytesToWrite = sizeof(WriteTextBuff);
|
|
res = f_write (&file, WriteTextBuff, bytesToWrite, (void *)&bytesWritten);
|
|
/* EOF or error */
|
|
if ((0U == bytesWritten) || (FR_OK != res)) {
|
|
//lcd_log_print((uint8_t *)MSG_NOT_WRITE, sizeof(MSG_NOT_WRITE) - 1, LCD_COLOR_WHITE);
|
|
} else {
|
|
//lcd_log_print((uint8_t *)MSG_CREATE_FILE, sizeof(MSG_CREATE_FILE) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
/* close file and filesystem */
|
|
f_close(&file);
|
|
f_mount(0, NULL);
|
|
} else {
|
|
//lcd_log_print((uint8_t *)MSG_CREATE_FILE, sizeof(MSG_CREATE_FILE) - 1, LCD_COLOR_WHITE);
|
|
}
|
|
|
|
usbh_usr_application_state = USBH_USR_FS_DEMOEND;
|
|
//lcd_log_print((uint8_t *)Str3, sizeof(Str3) - 1, LCD_COLOR_GREEN);
|
|
break;
|
|
|
|
case USBH_USR_FS_DEMOEND:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*!
|
|
\brief displays disk content
|
|
\param[in] path: pointer to root path
|
|
\param[in] recu_level: recursive level
|
|
\param[out] none
|
|
\retval status
|
|
*/
|
|
static uint8_t explore_disk (char* path, uint8_t recu_level)
|
|
{
|
|
FRESULT res;
|
|
FILINFO fno;
|
|
DIR dir;
|
|
char *fn;
|
|
|
|
uint8_t Str2[] = "Press B Key to continue";
|
|
|
|
res = f_opendir(&dir, path);
|
|
|
|
if (res == FR_OK) {
|
|
while (usbh_msc_core.host.connect_status) {
|
|
res = f_readdir(&dir, &fno);
|
|
if (FR_OK != res || 0U == fno.fname[0]) {
|
|
break;
|
|
}
|
|
|
|
if ('.' == fno.fname[0]) {
|
|
continue;
|
|
}
|
|
|
|
fn = fno.fname;
|
|
|
|
line_idx++;
|
|
|
|
if (line_idx > 4) {
|
|
line_idx = 0;
|
|
|
|
//lcd_log_print((uint8_t *)Str2, sizeof(Str2) - 1, LCD_COLOR_GREEN);
|
|
}
|
|
|
|
if (1U == recu_level) {
|
|
uint8_t temp[] = " |__";
|
|
//lcd_log_print((uint8_t *)temp, strlen((const char *)temp), LCD_COLOR_WHITE);
|
|
} else if(2U == recu_level) {
|
|
uint8_t temp[] = " | |__";
|
|
//lcd_log_print((uint8_t *)temp, strlen((const char *)temp), LCD_COLOR_WHITE);
|
|
}
|
|
|
|
if (AM_DIR == (fno.fattrib & AM_MASK)) {
|
|
//lcd_log_print((uint8_t *)fno.fname, strlen(fno.fname), LCD_COLOR_RED);
|
|
} else {
|
|
//lcd_log_print((uint8_t *)fno.fname, strlen(fno.fname), LCD_COLOR_WHITE);
|
|
}
|
|
|
|
if ((AM_DIR == (fno.fattrib & AM_MASK)) && (1U == recu_level)) {
|
|
explore_disk(fn, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
\brief deinit user state and associated variables
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void usbh_user_deinit(void)
|
|
{
|
|
usbh_usr_application_state = USBH_USR_FS_INIT;
|
|
}
|