-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUSBD_User_MSC_0.c
277 lines (230 loc) · 10.8 KB
/
USBD_User_MSC_0.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*------------------------------------------------------------------------------
* MDK Middleware - Component ::USB:Device
* Copyright (c) 2004-2015 ARM Germany GmbH. All rights reserved.
*------------------------------------------------------------------------------
* Name: USBD_User_MSC_0.c
* Purpose: USB Device Mass Storage Device class (MSC) User module
* Rev.: V6.3.1
*----------------------------------------------------------------------------*/
/**
* \addtogroup usbd_mscFunctions
*
*/
//! [code_USBD_User_MSC]
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "rl_usb.h"
// If the USE_FILE_SYSTEM value is 1 then File System is used and media can
// be accessed from application code or can be accessed by USB Mass Storage
// requests, default media in that case is one selected as default in File
// System Configuration file.
// If the USE_FILE_SYSTEM value is 0 then File System is not used and media
// can only be accessed by USB Mass Storage requests, default media in that
// case is RAM memory containing dummy disk image.
#define USE_FILE_SYSTEM 0 // 1 = File System is used, 0 = File System is not used
// Definition MEDIA_DRIVE is used to define Drive to be used for media
// Available options are:
// "R:" or "R0:" if media is RAM
// "M:" or "M0:" if media is Memory Card 0
// "M1:" if media is Memory Card 1
// "N:" or "N0:" if media is NAND Flash 0
// "N1:" if media is NAND Flash 1
#define MEDIA_DRIVE "M0:"
#if (USE_FILE_SYSTEM == 1) // If File System is used
#include "rl_fs.h"
#define MEDIA_OWN_USB (1U ) // Media owned by USB (bit mask)
#define MEDIA_OWN_CHG (1U << 1) // Media ownership change requested (bit mask)
volatile uint8_t usbd_msc0_media_own; // USB MSC0 media ownership
static int32_t drv_id; // FAT drive id
static bool media_ok; // Media is initialized and ok
#else
static uint32_t memory [8192/4]; // Memory in RAM for dummy disk image
static uint32_t block_buf[ 512/4]; // Buffer for block read/write to media
extern
const uint8_t memory_disk_image[4096]; // Dummy Memory Disk Image
#endif
// Called during USBD_Initialize to initialize the USB Device MSC class instance 0.
void USBD_MSC0_Initialize (void) {
#if (USE_FILE_SYSTEM == 1) // If File System is used
uint32_t param_status;
usbd_msc0_media_own = MEDIA_OWN_USB; // Initially media is owned by USB
media_ok = false; // Current media status (not initialized = not ok)
if (finit (MEDIA_DRIVE) != fsOK) { // Initialize File System
return; // Exit if failed
}
drv_id = fs_ioc_get_id (MEDIA_DRIVE); // Get ID of media drive
if (drv_id < 0U) { return; } // If ID is invalid exit
param_status = 0U; // Parameter for function call is 0
// Initialize media
if (fs_ioc_device_ctrl (drv_id, fsDevCtrlCodeControlMedia, ¶m_status) != fsOK) {
return; // Exit if failed
}
if (fs_ioc_lock (drv_id)) { // Lock media for USB usage
return; // Exit if failed
}
media_ok = true; // Media was initialized and is ok
#else
// Copy the dummy image from code to RAM
memcpy (memory, memory_disk_image, sizeof(memory_disk_image));
#endif
}
// \brief Called during \ref USBD_Uninitialize to de-initialize the USB Device MSC class instance 0.
void USBD_MSC0_Uninitialize (void) {
// Add code for de-initialization
}
// Get cache information.
// \param[out] buffer cache buffer address.
// \param[out] size cache buffer size.
// \return true operation succeeded.
// \return false operation failed.
bool USBD_MSC0_GetCacheInfo (uint32_t *buffer, uint32_t *size) {
#if (USE_FILE_SYSTEM == 1) // If File System is used
fsIOC_Cache cache_info;
// Get cache settings of File System
if (fs_ioc_get_cache(drv_id, &cache_info) != fsOK) {
return false; // Exit if failed
}
// Use File Systems cache for MSC
*buffer = (uint32_t)cache_info.buffer;// Cache buffer from File System
*size = cache_info.size; // Cache size
#else
*buffer = (uint32_t)block_buf; // Local buffer for data
*size = sizeof(block_buf); // Size of local buffer
#endif
return true;
}
// Get media capacity.
// \param[out] block_count total number of blocks on media.
// \param[out] block_size media block size.
// \return true operation succeeded.
// \return false operation failed.
bool USBD_MSC0_GetMediaCapacity (uint32_t *block_count, uint32_t *block_size) {
#if (USE_FILE_SYSTEM == 1) // If File System is used
fsMediaInfo media_info;
// Read media information of actual media
if (fs_ioc_read_info(drv_id, &media_info) != fsOK) {
return false; // Exit if failed
}
*block_count = media_info.block_cnt; // Total number of blocks on media
*block_size = media_info.read_blen; // Block size of blocks on media
#else
*block_count = sizeof(memory)/512U; // Total number of blocks on media
*block_size = 512U; // Block size of blocks on media
#endif
return true;
}
// Read data from media.
// \param[in] lba logical address of first block to read.
// \param[in] cnt number of contiguous blocks to read from media.
// \param[out] buf data buffer for data read from media.
// \return true read succeeded.
// \return false read failed.
bool USBD_MSC0_Read (uint32_t lba, uint16_t cnt, uint8_t *buf) {
#if (USE_FILE_SYSTEM == 1) // If File System is used
// Read data directly from media
if (fs_ioc_read_sector (drv_id, lba, buf, cnt) != fsOK) {
return false;
}
#else
// Read data from dummy image in RAM
memcpy (buf, &memory[lba * (512U/4U)], cnt * 512U);
#endif
return true;
}
// Write data to media.
// \param[in] lba logical address of first block to write.
// \param[in] cnt number of contiguous blocks to write to media.
// \param[out] buf data buffer containing data to write to media.
// \return true write succeeded.
// \return false write failed.
bool USBD_MSC0_Write (uint32_t lba, uint16_t cnt, const uint8_t *buf) {
#if (USE_FILE_SYSTEM == 1) // If File System is used
// Write data directly to media
if (fs_ioc_write_sector (drv_id, lba, buf, cnt) != fsOK) {
return false;
}
#else
// Write data to image in RAM
memcpy (&memory[lba * (512U/4U)], buf, cnt * 512U);
#endif
return true;
}
// Check media presence and write protect status.
// (if media is not owned by USB it returns that media is not ready)
// \return media presence and write protected status
// - bit 1: write protect bit
// - value 1: media is write protected
// - value 0: media is not write protected
// - bit 0: media presence bit
// - value 1: media is present
// - value 0: media is not present
uint32_t USBD_MSC0_CheckMedia (void) {
#if (USE_FILE_SYSTEM == 1) // If File System is used
uint32_t param_status;
uint8_t media_state; // Bit 0. media ready, Bit 1. media write protect
static uint8_t media_ready_ex = 0U; // Previous media ready state
uint8_t own;
// Get current media status
media_state = 0U;
switch (fs_ioc_device_ctrl (drv_id, fsDevCtrlCodeCheckMedia, ¶m_status)) {
case fsOK:
if (param_status & FS_MEDIA_NOCHKMEDIA) {
// If check media not available on hardware layer
media_state = USBD_MSC_MEDIA_READY;
break;
}
if (param_status & FS_MEDIA_INSERTED) {
media_state = USBD_MSC_MEDIA_READY;
}
if (param_status & FS_MEDIA_PROTECTED) {
media_state |= USBD_MSC_MEDIA_PROTECTED;
}
break;
default:
break;
}
// Store current owner so no new request can interfere
own = usbd_msc0_media_own;
// De-initialize media according to previous owner
if (own & MEDIA_OWN_CHG) { // If owner change requested
if (own & MEDIA_OWN_USB) { // If new requested owner is USB (previous owner was File System)
funmount (MEDIA_DRIVE); // De-initialize media and dismount Drive
} else { // If new requested owner is File System (previous owner was USB)
fs_ioc_unlock (drv_id); // Un-lock media
}
}
// Initialize media according to current owner
if ((own & MEDIA_OWN_CHG) || // If owner change requested or
(media_state ^ media_ready_ex)) { // if media ready state has changed (disconnect(SD remove)/connect(SD insert))
if (media_state & USBD_MSC_MEDIA_READY) { // If media is ready
if (own & MEDIA_OWN_USB){ // If current owner is USB
media_ok = false; // Invalidate current media status (not initialized = not ok)
param_status = 0U; // Parameter for function call is 0
if (fs_ioc_device_ctrl (drv_id, fsDevCtrlCodeControlMedia, ¶m_status) == fsOK) {
// Initialization of media has succeeded
if (fs_ioc_lock (drv_id) == 0) { // If lock media for USB usage has succeeded
media_ok = true; // Media was initialized and is ok
}
}
} else { // If current owner is File System
if (fmount (MEDIA_DRIVE) == fsOK) { // Initialize media and Mount Drive for File System usage
media_ok = true; // Media was initialized and is ok
}
}
}
if (own & MEDIA_OWN_CHG) {
usbd_msc0_media_own &= ~MEDIA_OWN_CHG; // Clear request to change media owner if it was handled
}
media_ready_ex = media_state & USBD_MSC_MEDIA_READY;
}
// If media is not ok or owned by File System return that it is not ready for USB
if ((!media_ok) || (!(usbd_msc0_media_own & MEDIA_OWN_USB))) {
return 0U;
}
return media_state;
#else
return USBD_MSC_MEDIA_READY;
#endif
}
//! [code_USBD_User_MSC]