Mistake on this page?
Report an issue in GitHub or email us
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 "drivers/internal/PolledQueue.h"
26 #include "drivers/internal/Task.h"
27 #include "BlockDevice.h"
28 #include "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  */
64 class USBMSD: public USBDevice {
65 public:
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(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, 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  */
118  void disconnect();
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  */
137  bool media_removed();
138 
139 protected:
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 
187 private:
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;
264  events::Task<void()> _configure_task;
265 
266  BlockDevice *_bd;
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
bool connect()
Connect the USB MSD device.
A hardware device capable of writing and reading blocks.
Definition: BlockDevice.h:47
void process()
Perform USB processing.
USBMSD class: generic class in order to use all kinds of blocks storage chip.
Definition: USBMSD.h:64
Abstract interface to physical USB hardware.
Definition: USBPhy.h:82
PolledQueue.
Definition: PolledQueue.h:36
USBMSD(BlockDevice *bd, bool connect_blocking=true, uint16_t vendor_id=0x0703, uint16_t product_id=0x0104, uint16_t product_release=0x0001)
Constructor.
The Mutex class is used to synchronize the execution of threads.
Definition: Mutex.h:70
bool media_removed()
Check if MSD device was removed/unmounted on the host side.
Core USB Device driver.
Definition: USBDevice.h:38
void attach(mbed::Callback< void()> cb)
Called when USBMSD needs to perform processing.
virtual ~USBMSD()
Destroy this object.
Callback class based on template specialization.
Definition: Callback.h:53
void disconnect()
Disconnect the USB MSD device.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.