/* * Copyright (c) 2022-2023 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * */ #include "usbd_core.h" #include "usbd_msc.h" #define MSC_IN_EP 0x81 #define MSC_OUT_EP 0x02 #define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN) #ifdef CONFIG_USB_HS #define MSC_MAX_MPS 512 #else #define MSC_MAX_MPS 64 #endif const uint8_t msc_ram_descriptor[] = { USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01), USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02), /* * string0 descriptor */ USB_LANGID_INIT(USBD_LANGID_STRING), /* * string1 descriptor */ 0x14, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 'C', 0x00, /* wcChar0 */ 'h', 0x00, /* wcChar1 */ 'e', 0x00, /* wcChar2 */ 'r', 0x00, /* wcChar3 */ 'r', 0x00, /* wcChar4 */ 'y', 0x00, /* wcChar5 */ 'U', 0x00, /* wcChar6 */ 'S', 0x00, /* wcChar7 */ 'B', 0x00, /* wcChar8 */ /* * string2 descriptor */ 0x26, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 'C', 0x00, /* wcChar0 */ 'h', 0x00, /* wcChar1 */ 'e', 0x00, /* wcChar2 */ 'r', 0x00, /* wcChar3 */ 'r', 0x00, /* wcChar4 */ 'y', 0x00, /* wcChar5 */ 'U', 0x00, /* wcChar6 */ 'S', 0x00, /* wcChar7 */ 'B', 0x00, /* wcChar8 */ ' ', 0x00, /* wcChar9 */ 'M', 0x00, /* wcChar10 */ 'S', 0x00, /* wcChar11 */ 'C', 0x00, /* wcChar12 */ ' ', 0x00, /* wcChar13 */ 'D', 0x00, /* wcChar14 */ 'E', 0x00, /* wcChar15 */ 'M', 0x00, /* wcChar16 */ 'O', 0x00, /* wcChar17 */ /* * string3 descriptor */ 0x16, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ '2', 0x00, /* wcChar0 */ '0', 0x00, /* wcChar1 */ '2', 0x00, /* wcChar2 */ '2', 0x00, /* wcChar3 */ '1', 0x00, /* wcChar4 */ '2', 0x00, /* wcChar5 */ '3', 0x00, /* wcChar6 */ '4', 0x00, /* wcChar7 */ '5', 0x00, /* wcChar8 */ '6', 0x00, /* wcChar9 */ #ifdef CONFIG_USB_HS /* * device qualifier descriptor */ 0x0a, USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, #endif 0x00 }; static void usbd_event_handler(uint8_t busid, uint8_t event) { (void)busid; switch (event) { case USBD_EVENT_RESET: break; case USBD_EVENT_CONNECTED: break; case USBD_EVENT_DISCONNECTED: break; case USBD_EVENT_RESUME: break; case USBD_EVENT_SUSPEND: break; case USBD_EVENT_CONFIGURED: break; case USBD_EVENT_SET_REMOTE_WAKEUP: break; case USBD_EVENT_CLR_REMOTE_WAKEUP: break; default: break; } } /* Some MCU doesn't have enough 8KB SRAM to store the whole disk * We will use Flash as read-only disk with board that has * CFG_EXAMPLE_MSC_READONLY defined */ #define README_CONTENTS \ "This is CherryUSB's MassStorage Class demo.\r\n" enum { DISK_BLOCK_NUM = 64, /* 8KB is the smallest size that windows allow to mount, set to 32KB */ DISK_BLOCK_SIZE = 512 }; #ifdef CFG_EXAMPLE_MSC_READONLY const #endif uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { /*------------- Block0: Boot Sector -------------*/ /* byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; * sector_per_cluster = 1; reserved_sectors = 1; * fat_num = 1; fat12_root_entry_num = 16; * sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0; * drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; * filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "Hpmicro MSC"; */ /* FAT magic code at offset 510-511 */ { 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'H', 'P', 'M', 'i', 'c', 'r', 'o', ' ', 'M', 'S', 'C', 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, /* Zero up to 2 last bytes of FAT magic code */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA }, /*------------- Block1: FAT12 Table -------------*/ { 0xF8, 0xFF, 0xFF, 0xFF, 0x0F /* first 2 entries must be F8FF, third entry is cluster end of readme file */ }, /*------------- Block2: Root Directory -------------*/ { /* first entry is volume label */ 'H', 'P', 'M', 'i', 'c', 'r', 'o', ' ', 'M', 'S', 'C', 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* second entry is readme file */ 'R', 'E', 'A', 'D', 'M', 'E', ' ', ' ', 'T', 'X', 'T', 0x20, 0x00, 0xC6, 0x52, 0x6D, 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 /* readme's files size (4 Bytes) */ }, /*------------- Block3: Readme Content -------------*/ README_CONTENTS }; void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size) { (void)busid; (void)lun; *block_num = DISK_BLOCK_NUM; *block_size = DISK_BLOCK_SIZE; } int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length) { (void)busid; (void)lun; if (sector < DISK_BLOCK_NUM) memcpy(buffer, &msc_disk[sector][0], length); return 0; } int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length) { (void)busid; (void)lun; if (sector < DISK_BLOCK_NUM) memcpy(&msc_disk[sector][0], buffer, length); return 0; } /* function ------------------------------------------------------------------*/ /** * @brief msc ram init * @pre none * @param[in] none * @retval none */ struct usbd_interface intf0; void msc_ram_init(uint8_t busid, uint32_t reg_base) { usbd_desc_register(busid, msc_ram_descriptor); usbd_add_interface(busid, usbd_msc_init_intf(busid, &intf0, MSC_OUT_EP, MSC_IN_EP)); usbd_initialize(busid, reg_base, usbd_event_handler); }