Mbed OS Reference
Loading...
Searching...
No Matches
USBMSD.h
1/*
2 * Copyright (c) 2018-2019, Arm Limited and affiliates.
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef USBMSD_H
19#define USBMSD_H
20
21/* These headers are included for child class. */
22#include "USBDescriptor.h"
23#include "USBDevice_Types.h"
24#include "platform/Callback.h"
25#include "usb/internal/PolledQueue.h"
26#include "usb/internal/Task.h"
27#include "BlockDevice.h"
28#include "rtos/Mutex.h"
29
30#include "USBDevice.h"
31
32/**
33 * \defgroup drivers_USBMSD USBMSD class
34 * \ingroup drivers-public-api-usb
35 * @{
36 */
37
38/**
39 * USBMSD class: generic class in order to use all kinds of blocks storage chip
40 *
41 * Introduction
42 *
43 * USBMSD implements the MSD protocol. It permits to access a block device (flash, SD Card,...)
44 * from a computer over USB.
45 *
46 * @code
47 * #include "mbed.h"
48 * #include "SDBlockDevice.h"
49 * #include "USBMSD.h"
50 *
51 * SDBlockDevice sd(PTE3, PTE1, PTE2, PTE4);
52 * USBMSD usb(&sd);
53 *
54 * int main() {
55 *
56 * while(true) {
57 * usb.process();
58 * }
59 *
60 * return 0;
61 * }
62 * @endcode
63 */
64class USBMSD: public USBDevice {
65public:
66
67 /**
68 * Constructor
69 *
70 * This creates a new USBMSD object with the given block device. Connect must be called
71 * for the block device to connect.
72 *
73 * @param bd BlockDevice to mount as a USB drive
74 * @param connect_blocking true to perform a blocking connect, false to start in a disconnected state
75 * @param vendor_id Your vendor_id
76 * @param product_id Your product_id
77 * @param product_release Your preoduct_release
78 */
79 USBMSD(mbed::BlockDevice *bd, bool connect_blocking = true, uint16_t vendor_id = 0x0703, uint16_t product_id = 0x0104, uint16_t product_release = 0x0001);
80
81 /**
82 * Fully featured constructor
83 *
84 * Construct this object with the supplied USBPhy and parameters. The user
85 * this object is responsible for calling connect() or init().
86 *
87 * @note Derived classes must use this constructor and call init() or
88 * connect() themselves. Derived classes should also call deinit() in
89 * their destructor. This ensures that no interrupts can occur when the
90 * object is partially constructed or destroyed.
91 *
92 * @param phy USB phy to use
93 * @param bd BlockDevice to mount as a USB drive
94 * @param vendor_id Your vendor_id
95 * @param product_id Your product_id
96 * @param product_release Your preoduct_release
97 */
98 USBMSD(USBPhy *phy, mbed::BlockDevice *bd, uint16_t vendor_id, uint16_t product_id, uint16_t product_release);
99
100 /**
101 * Destroy this object
102 *
103 * Any classes which inherit from this class must call disconnect
104 * before this destructor runs.
105 */
106 virtual ~USBMSD();
107
108 /**
109 * Connect the USB MSD device.
110 *
111 * @returns true if successful
112 */
113 bool connect();
114
115 /**
116 * Disconnect the USB MSD device.
117 */
119
120 /**
121 * Perform USB processing
122 */
123 void process();
124
125 /**
126 * Called when USBMSD needs to perform processing
127 *
128 * @param cb Callback called when USBMSD needs process() to be called
129 */
130 void attach(mbed::Callback<void()> cb);
131
132 /**
133 * Check if MSD device was removed/unmounted on the host side.
134 *
135 * @returns true if device was removed/unmounted on the host side
136 */
138
139protected:
140
141 /*
142 * read one or more blocks on a storage chip
143 *
144 * @param data pointer where will be stored read data
145 * @param block starting block number
146 * @param count number of blocks to read
147 * @returns 0 if successful
148 */
149 virtual int disk_read(uint8_t *data, uint64_t block, uint8_t count);
150
151 /*
152 * write one or more blocks on a storage chip
153 *
154 * @param data data to write
155 * @param block starting block number
156 * @param count number of blocks to write
157 * @returns 0 if successful
158 */
159 virtual int disk_write(const uint8_t *data, uint64_t block, uint8_t count);
160
161 /*
162 * Disk initilization
163 */
164 virtual int disk_initialize();
165
166 /*
167 * Return the number of blocks
168 *
169 * @returns number of blocks
170 */
171 virtual uint64_t disk_sectors();
172
173 /*
174 * Return memory size
175 *
176 * @returns memory size
177 */
178 virtual uint64_t disk_size();
179
180 /*
181 * To check the status of the storage chip
182 *
183 * @returns status: 0: OK, 1: disk not initialized, 2: no medium in the drive, 4: write protected
184 */
185 virtual int disk_status();
186
187private:
188
189 // MSC Bulk-only Stage
190 enum Stage {
191 READ_CBW, // wait a CBW
192 ERROR, // error
193 PROCESS_CBW, // process a CBW request
194 SEND_CSW, // send a CSW
195 };
196
197 // Bulk-only CBW
198 typedef MBED_PACKED(struct)
199 {
200 uint32_t Signature;
201 uint32_t Tag;
202 uint32_t DataLength;
203 uint8_t Flags;
204 uint8_t LUN;
205 uint8_t CBLength;
206 uint8_t CB[16];
207 } CBW;
208
209 // Bulk-only CSW
210 typedef MBED_PACKED(struct)
211 {
212 uint32_t Signature;
213 uint32_t Tag;
214 uint32_t DataResidue;
215 uint8_t Status;
216 } CSW;
217
218 // If this class has been initialized
219 bool _initialized;
220
221 // If msd device has been unmounted by host
222 volatile bool _media_removed;
223
224 //state of the bulk-only state machine
225 Stage _stage;
226
227 // current CBW
228 CBW _cbw;
229
230 // CSW which will be sent
231 CSW _csw;
232
233 // addr where will be read or written data
234 uint32_t _addr;
235
236 // length of a reading or writing
237 uint32_t _length;
238
239 // memory OK (after a memoryVerify)
240 bool _mem_ok;
241
242 // cache in RAM before writing in memory. Useful also to read a block.
243 uint8_t *_page;
244
245 int _block_size;
246 uint64_t _memory_size;
247 uint64_t _block_count;
248
249 // endpoints
250 usb_ep_t _bulk_in;
251 usb_ep_t _bulk_out;
252 uint8_t _bulk_in_buf[64];
253 uint8_t _bulk_out_buf[64];
254 bool _out_ready;
255 bool _in_ready;
256 uint32_t _bulk_out_size;
257
258 // Interrupt to thread deferral
259 events::PolledQueue _queue;
260 events::Task<void()> _in_task;
261 events::Task<void()> _out_task;
262 events::Task<void()> _reset_task;
263 events::Task<void(const setup_packet_t *)> _control_task;
264 events::Task<void()> _configure_task;
265
267 rtos::Mutex _mutex_init;
268 rtos::Mutex _mutex;
269
270 // space for config descriptor
271 uint8_t _configuration_descriptor[32];
272
273 virtual const uint8_t *string_iproduct_desc();
274 virtual const uint8_t *string_iinterface_desc();
275 virtual const uint8_t *configuration_desc(uint8_t index);
276 virtual void callback_set_configuration(uint8_t configuration);
277 virtual void callback_set_interface(uint16_t interface, uint8_t alternate);
278 virtual void callback_state_change(DeviceState new_state);
279 virtual void callback_request(const setup_packet_t *setup);
280 virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted);
281
282 void _isr_out();
283 void _isr_in();
284
285 void _out();
286 void _in();
287 void _reset();
288 void _control(const setup_packet_t *request);
289 void _configure();
290
291 void _init();
292 void _process();
293 void _write_next(uint8_t *data, uint32_t size);
294 void _read_next();
295
296 void CBWDecode(uint8_t *buf, uint16_t size);
297 void sendCSW(void);
298 bool inquiryRequest(void);
299 bool write(uint8_t *buf, uint16_t size);
300 bool readFormatCapacity();
301 bool readCapacity(void);
302 bool infoTransfer(void);
303 void memoryRead(void);
304 bool modeSense6(void);
305 bool modeSense10(void);
306 void testUnitReady(void);
307 bool requestSense(void);
308 void memoryVerify(uint8_t *buf, uint16_t size);
309 void memoryWrite(uint8_t *buf, uint16_t size);
310 void msd_reset();
311 void fail();
312};
313
314/** @}*/
315
316#endif
Core USB Device driver.
Definition: USBDevice.h:38
USBMSD class: generic class in order to use all kinds of blocks storage chip.
Definition: USBMSD.h:64
void attach(mbed::Callback< void()> cb)
Called when USBMSD needs to perform processing.
USBMSD(mbed::BlockDevice *bd, bool connect_blocking=true, uint16_t vendor_id=0x0703, uint16_t product_id=0x0104, uint16_t product_release=0x0001)
Constructor.
void process()
Perform USB processing.
void disconnect()
Disconnect the USB MSD device.
bool connect()
Connect the USB MSD device.
bool media_removed()
Check if MSD device was removed/unmounted on the host side.
USBMSD(USBPhy *phy, mbed::BlockDevice *bd, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
Fully featured constructor.
virtual ~USBMSD()
Destroy this object.
Abstract interface to physical USB hardware.
Definition: USBPhy.h:82
PolledQueue.
Definition: PolledQueue.h:37
A hardware device capable of writing and reading blocks.
Definition: BlockDevice.h:53
Callback class based on template specialization.
Definition: Callback.h:53
The Mutex class is used to synchronize the execution of threads.
Definition: Mutex.h:70
#define MBED_PACKED(struct)
MBED_PACKED Pack a structure, preventing any padding from being added between fields.