diff options
Diffstat (limited to 'lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/msc_disk.c')
-rw-r--r-- | lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/msc_disk.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/msc_disk.c b/lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/msc_disk.c new file mode 100644 index 000000000..70fd43b31 --- /dev/null +++ b/lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/msc_disk.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * The MIT License (MIT) | ||
3 | * | ||
4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | * of this software and associated documentation files (the "Software"), to deal | ||
8 | * in the Software without restriction, including without limitation the rights | ||
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | * copies of the Software, and to permit persons to whom the Software is | ||
11 | * furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in | ||
14 | * all copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
22 | * THE SOFTWARE. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include "tusb.h" | ||
27 | |||
28 | #if CFG_TUD_MSC | ||
29 | |||
30 | // Some MCU doesn't have enough 8KB SRAM to store the whole disk | ||
31 | // We will use Flash as read-only disk with board that has | ||
32 | // CFG_EXAMPLE_MSC_READONLY defined | ||
33 | |||
34 | #define README_CONTENTS \ | ||
35 | "This is tinyusb's MassStorage Class demo.\r\n\r\n\ | ||
36 | If you find any bugs or get any questions, feel free to file an\r\n\ | ||
37 | issue at github.com/hathach/tinyusb" | ||
38 | |||
39 | enum | ||
40 | { | ||
41 | DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount | ||
42 | DISK_BLOCK_SIZE = 512 | ||
43 | }; | ||
44 | |||
45 | #ifdef CFG_EXAMPLE_MSC_READONLY | ||
46 | const | ||
47 | #endif | ||
48 | uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = | ||
49 | { | ||
50 | //------------- Block0: Boot Sector -------------// | ||
51 | // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; | ||
52 | // sector_per_cluster = 1; reserved_sectors = 1; | ||
53 | // fat_num = 1; fat12_root_entry_num = 16; | ||
54 | // sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0; | ||
55 | // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; | ||
56 | // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC"; | ||
57 | // FAT magic code at offset 510-511 | ||
58 | { | ||
59 | 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, | ||
60 | 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
61 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' , | ||
62 | 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, | ||
63 | |||
64 | // Zero up to 2 last bytes of FAT magic code | ||
65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
70 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
72 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
73 | |||
74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
80 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
81 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
82 | |||
83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
84 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
86 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
88 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
89 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
90 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
91 | |||
92 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
93 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
95 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA | ||
96 | }, | ||
97 | |||
98 | //------------- Block1: FAT12 Table -------------// | ||
99 | { | ||
100 | 0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file | ||
101 | }, | ||
102 | |||
103 | //------------- Block2: Root Directory -------------// | ||
104 | { | ||
105 | // first entry is volume label | ||
106 | 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00, | ||
107 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
108 | // second entry is readme file | ||
109 | 'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D, | ||
110 | 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, | ||
111 | sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes) | ||
112 | }, | ||
113 | |||
114 | //------------- Block3: Readme Content -------------// | ||
115 | README_CONTENTS | ||
116 | }; | ||
117 | |||
118 | // Invoked when received SCSI_CMD_INQUIRY | ||
119 | // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively | ||
120 | void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) | ||
121 | { | ||
122 | (void) lun; | ||
123 | |||
124 | const char vid[] = "TinyUSB"; | ||
125 | const char pid[] = "Mass Storage"; | ||
126 | const char rev[] = "1.0"; | ||
127 | |||
128 | memcpy(vendor_id , vid, strlen(vid)); | ||
129 | memcpy(product_id , pid, strlen(pid)); | ||
130 | memcpy(product_rev, rev, strlen(rev)); | ||
131 | } | ||
132 | |||
133 | // Invoked when received Test Unit Ready command. | ||
134 | // return true allowing host to read/write this LUN e.g SD card inserted | ||
135 | bool tud_msc_test_unit_ready_cb(uint8_t lun) | ||
136 | { | ||
137 | (void) lun; | ||
138 | |||
139 | return true; // RAM disk is always ready | ||
140 | } | ||
141 | |||
142 | // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size | ||
143 | // Application update block count and block size | ||
144 | void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) | ||
145 | { | ||
146 | (void) lun; | ||
147 | |||
148 | *block_count = DISK_BLOCK_NUM; | ||
149 | *block_size = DISK_BLOCK_SIZE; | ||
150 | } | ||
151 | |||
152 | // Invoked when received Start Stop Unit command | ||
153 | // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage | ||
154 | // - Start = 1 : active mode, if load_eject = 1 : load disk storage | ||
155 | bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) | ||
156 | { | ||
157 | (void) lun; | ||
158 | (void) power_condition; | ||
159 | |||
160 | if ( load_eject ) | ||
161 | { | ||
162 | if (start) | ||
163 | { | ||
164 | // load disk storage | ||
165 | }else | ||
166 | { | ||
167 | // unload disk storage | ||
168 | } | ||
169 | } | ||
170 | |||
171 | return true; | ||
172 | } | ||
173 | |||
174 | // Callback invoked when received READ10 command. | ||
175 | // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. | ||
176 | int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) | ||
177 | { | ||
178 | (void) lun; | ||
179 | |||
180 | uint8_t const* addr = msc_disk[lba] + offset; | ||
181 | memcpy(buffer, addr, bufsize); | ||
182 | |||
183 | return bufsize; | ||
184 | } | ||
185 | |||
186 | // Callback invoked when received WRITE10 command. | ||
187 | // Process data in buffer to disk's storage and return number of written bytes | ||
188 | int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) | ||
189 | { | ||
190 | (void) lun; | ||
191 | |||
192 | #ifndef CFG_EXAMPLE_MSC_READONLY | ||
193 | uint8_t* addr = msc_disk[lba] + offset; | ||
194 | memcpy(addr, buffer, bufsize); | ||
195 | #else | ||
196 | (void) lba; (void) offset; (void) buffer; | ||
197 | #endif | ||
198 | |||
199 | return bufsize; | ||
200 | } | ||
201 | |||
202 | // Callback invoked when received an SCSI command not in built-in list below | ||
203 | // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE | ||
204 | // - READ10 and WRITE10 has their own callbacks | ||
205 | int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) | ||
206 | { | ||
207 | // read10 & write10 has their own callback and MUST not be handled here | ||
208 | |||
209 | void const* response = NULL; | ||
210 | uint16_t resplen = 0; | ||
211 | |||
212 | // most scsi handled is input | ||
213 | bool in_xfer = true; | ||
214 | |||
215 | switch (scsi_cmd[0]) | ||
216 | { | ||
217 | case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: | ||
218 | // Host is about to read/write etc ... better not to disconnect disk | ||
219 | resplen = 0; | ||
220 | break; | ||
221 | |||
222 | default: | ||
223 | // Set Sense = Invalid Command Operation | ||
224 | tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); | ||
225 | |||
226 | // negative means error -> tinyusb could stall and/or response with failed status | ||
227 | resplen = -1; | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | // return resplen must not larger than bufsize | ||
232 | if ( resplen > bufsize ) resplen = bufsize; | ||
233 | |||
234 | if ( response && (resplen > 0) ) | ||
235 | { | ||
236 | if(in_xfer) | ||
237 | { | ||
238 | memcpy(buffer, response, resplen); | ||
239 | }else | ||
240 | { | ||
241 | // SCSI output | ||
242 | } | ||
243 | } | ||
244 | |||
245 | return resplen; | ||
246 | } | ||
247 | |||
248 | #endif | ||