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