| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- /*
- * Copyright (c) 2025, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include "ff.h"
- #include "diskio.h"
- #include "usbd_core.h"
- #include "usb_osal.h"
- #include "usbd_mtp.h"
- FATFS s_sd_disk;
- FIL s_file;
- BYTE work[FF_MAX_SS];
- const TCHAR driver_num_buf[3] = { '0', ':', '\0' };
- const char *show_error_string(FRESULT fresult);
- static FRESULT sd_mount_fs(void)
- {
- FRESULT fresult = f_mount(&s_sd_disk, driver_num_buf, 1);
- if (fresult == FR_OK) {
- printf("SD card has been mounted successfully\n");
- } else {
- printf("Failed to mount SD card, cause: %s\n", show_error_string(fresult));
- }
- return fresult;
- }
- #if 0
- static FRESULT sd_mkfs(void)
- {
- printf("Formatting the SD card, depending on the SD card capacity, the formatting process may take a long time\n");
- FRESULT fresult = f_mkfs(driver_num_buf, NULL, work, sizeof(work));
- if (fresult != FR_OK) {
- printf("Making File system failed, cause: %s\n", show_error_string(fresult));
- } else {
- printf("Making file system is successful\n");
- }
- return fresult;
- }
- #endif
- static FRESULT sd_write_file(void)
- {
- FRESULT fresult = f_open(&s_file, "0:/readme.txt", FA_WRITE | FA_CREATE_ALWAYS);
- if (fresult != FR_OK) {
- printf("Create new file failed, cause: %d\n", show_error_string(fresult));
- } else {
- printf("Create new file successfully, status=%d\n", fresult);
- }
- char hello_str[] = "Hello, this is SD card FATFS demo\n";
- UINT byte_written;
- fresult = f_write(&s_file, hello_str, sizeof(hello_str), &byte_written);
- if (fresult != FR_OK) {
- printf("Write file failed, cause: %s\n", show_error_string(fresult));
- } else {
- printf("Write file operation is successfully\n");
- }
- f_close(&s_file);
- return fresult;
- }
- const char *show_error_string(FRESULT fresult)
- {
- const char *result_str;
- switch (fresult) {
- case FR_OK:
- result_str = "succeeded";
- break;
- case FR_DISK_ERR:
- result_str = "A hard error occurred in the low level disk I/O level";
- break;
- case FR_INT_ERR:
- result_str = "Assertion failed";
- break;
- case FR_NOT_READY:
- result_str = "The physical drive cannot work";
- break;
- case FR_NO_FILE:
- result_str = "Could not find the file";
- break;
- case FR_NO_PATH:
- result_str = "Could not find the path";
- break;
- case FR_INVALID_NAME:
- result_str = "Tha path name format is invalid";
- break;
- case FR_DENIED:
- result_str = "Access denied due to prohibited access or directory full";
- break;
- case FR_EXIST:
- result_str = "Access denied due to prohibited access";
- break;
- case FR_INVALID_OBJECT:
- result_str = "The file/directory object is invalid";
- break;
- case FR_WRITE_PROTECTED:
- result_str = "The physical drive is write protected";
- break;
- case FR_INVALID_DRIVE:
- result_str = "The logical driver number is invalid";
- break;
- case FR_NOT_ENABLED:
- result_str = "The volume has no work area";
- break;
- case FR_NO_FILESYSTEM:
- result_str = "There is no valid FAT volume";
- break;
- case FR_MKFS_ABORTED:
- result_str = "THe f_mkfs() aborted due to any problem";
- break;
- case FR_TIMEOUT:
- result_str = "Could not get a grant to access the volume within defined period";
- break;
- case FR_LOCKED:
- result_str = "The operation is rejected according to the file sharing policy";
- break;
- case FR_NOT_ENOUGH_CORE:
- result_str = "LFN working buffer could not be allocated";
- break;
- case FR_TOO_MANY_OPEN_FILES:
- result_str = "Number of open files > FF_FS_LOCK";
- break;
- case FR_INVALID_PARAMETER:
- result_str = "Given parameter is invalid";
- break;
- default:
- result_str = "Unknown error";
- break;
- }
- return result_str;
- }
- const char *usbd_mtp_fs_root_path(void)
- {
- return driver_num_buf;
- }
- const char *usbd_mtp_fs_description(void)
- {
- return "CherryUSB MTP";
- }
- int usbd_mtp_mkdir(const char *path)
- {
- FRESULT result = f_mkdir(path);
- if (result != FR_OK) {
- printf("f_mkdir failed, cause: %s\n", show_error_string(result));
- return -1;
- }
- return 0; // Directory created successfully
- }
- int usbd_mtp_rmdir(const char *path)
- {
- FRESULT result = f_rmdir(path);
- if (result != FR_OK) {
- printf("f_mkdir failed, cause: %s\n", show_error_string(result));
- return -1;
- }
- return 0; // Directory created successfully
- }
- MTP_DIR *usbd_mtp_opendir(const char *name)
- {
- FRESULT result;
- DIR *dir;
- dir = usb_osal_malloc(sizeof(DIR));
- result = f_opendir(dir, name);
- if (result != FR_OK) {
- printf("f_opendir failed, cause: %s\n", show_error_string(result));
- usb_osal_free(dir);
- return NULL; // Failed to open directory
- }
- return (MTP_DIR *)dir;
- }
- int usbd_mtp_closedir(MTP_DIR *dir)
- {
- FRESULT result;
- result = f_closedir((DIR *)dir);
- if (result != FR_OK) {
- printf("f_closedir failed, cause: %s\n", show_error_string(result));
- return -1; // Failed to close directory
- }
- usb_osal_free(dir); // Free the directory structure
- return result;
- }
- struct mtp_dirent *usbd_mtp_readdir(MTP_DIR *dir)
- {
- FILINFO fno;
- FRESULT result;
- result = f_readdir((DIR *)dir, &fno);
- if (result != FR_OK || fno.fname[0] == 0)
- return NULL;
- static struct mtp_dirent dirent;
- memset(&dirent, 0, sizeof(struct mtp_dirent));
- strncpy(dirent.d_name, fno.fname, sizeof(dirent.d_name) - 1);
- dirent.d_name[sizeof(dirent.d_name) - 1] = '\0';
- dirent.d_namlen = strlen(dirent.d_name);
- return &dirent;
- }
- #undef SS
- #if FF_MAX_SS == FF_MIN_SS
- #define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */
- #else
- #define SS(fs) ((fs)->ssize) /* Variable sector size */
- #endif
- int usbd_mtp_stat(const char *path, struct stat *buf)
- {
- FILINFO file_info;
- FRESULT result;
- FATFS *f;
- f = &s_sd_disk;
- result = f_stat(path, &file_info);
- if (result != FR_OK) {
- printf("f_stat failed, cause: %s\n", show_error_string(result));
- return -1;
- }
- buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
- S_IWUSR | S_IWGRP | S_IWOTH;
- if (file_info.fattrib & AM_DIR) {
- buf->st_mode &= ~S_IFREG;
- buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
- }
- if (file_info.fattrib & AM_RDO)
- buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
- buf->st_size = file_info.fsize;
- buf->st_blksize = f->csize * SS(f);
- if (file_info.fattrib & AM_ARC) {
- buf->st_blocks = file_info.fsize ? ((file_info.fsize - 1) / SS(f) / f->csize + 1) : 0;
- buf->st_blocks *= (buf->st_blksize / 512); // man say st_blocks is number of 512B blocks allocated
- } else {
- buf->st_blocks = f->csize;
- }
- return 0;
- }
- int usbd_mtp_statfs(const char *path, struct mtp_statfs *buf)
- {
- FATFS *f;
- FRESULT res;
- DWORD fre_clust, fre_sect, tot_sect;
- f = &s_sd_disk;
- res = f_getfree(path, &fre_clust, &f);
- if (res != FR_OK) {
- printf("f_getfree failed, cause: %s\n", show_error_string(res));
- return -1;
- }
- tot_sect = (f->n_fatent - 2) * f->csize;
- fre_sect = fre_clust * f->csize;
- buf->f_blocks = tot_sect;
- buf->f_bfree = fre_sect;
- #if FF_MAX_SS != FF_MIN_SS
- buf->f_bsize = f->ssize;
- #else
- buf->f_bsize = FF_MIN_SS;
- #endif
- return 0;
- }
- int usbd_mtp_open(const char *path, uint8_t mode)
- {
- BYTE flags;
- if (mode == O_RDONLY) {
- flags = FA_READ | FA_OPEN_EXISTING;
- } else if (mode == O_WRONLY) {
- flags = FA_WRITE | FA_OPEN_ALWAYS;
- } else if (mode == O_RDWR) {
- flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
- } else {
- return -1; // Invalid mode
- }
- FRESULT result = f_open(&s_file, path, flags);
- if (result != FR_OK) {
- printf("f_open failed, cause: %s\n", show_error_string(result));
- return -1;
- }
- return 0;
- }
- int usbd_mtp_close(int fd)
- {
- FRESULT result = f_close(&s_file);
- if (result != FR_OK) {
- printf("f_close failed, cause: %s\n", show_error_string(result));
- return -1;
- }
- return 0;
- }
- int usbd_mtp_read(int fd, void *buf, size_t len)
- {
- UINT bytes_read;
- FRESULT result = f_read(&s_file, buf, len, &bytes_read);
- if (result != FR_OK) {
- printf("f_read failed, cause: %s\n", show_error_string(result));
- return -1;
- }
- return bytes_read; // Return number of bytes read
- }
- int usbd_mtp_write(int fd, const void *buf, size_t len)
- {
- UINT bytes_written;
- FRESULT result = f_write(&s_file, buf, len, &bytes_written);
- if (result != FR_OK) {
- printf("f_write failed, cause: %s\n", show_error_string(result));
- return -1;
- }
- return bytes_written; // Return number of bytes written
- }
- int usbd_mtp_unlink(const char *path)
- {
- FRESULT result = f_unlink(path);
- if (result != FR_OK) {
- printf("f_unlink failed, cause: %s\n", show_error_string(result));
- return -1;
- }
- return 0; // File deleted successfully
- }
- void usbd_mtp_mount()
- {
- sd_mount_fs();
- // write a file to test the SD card
- sd_write_file();
- }
|