Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
USBMSD.h
00001 /* 00002 * Copyright (c) 2018-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #ifndef USBMSD_H 00019 #define USBMSD_H 00020 00021 /* These headers are included for child class. */ 00022 #include "USBDescriptor.h" 00023 #include "USBDevice_Types.h" 00024 #include "platform/Callback.h" 00025 #include "drivers/internal/PolledQueue.h" 00026 #include "drivers/internal/Task.h" 00027 #include "BlockDevice.h" 00028 #include "Mutex.h" 00029 00030 #include "USBDevice.h" 00031 00032 /** 00033 * \defgroup drivers_USBMSD USBMSD class 00034 * \ingroup drivers-public-api-usb 00035 * @{ 00036 */ 00037 00038 /** 00039 * USBMSD class: generic class in order to use all kinds of blocks storage chip 00040 * 00041 * Introduction 00042 * 00043 * USBMSD implements the MSD protocol. It permits to access a block device (flash, SD Card,...) 00044 * from a computer over USB. 00045 * 00046 * @code 00047 * #include "mbed.h" 00048 * #include "SDBlockDevice.h" 00049 * #include "USBMSD.h" 00050 * 00051 * SDBlockDevice sd(PTE3, PTE1, PTE2, PTE4); 00052 * USBMSD usb(&sd); 00053 * 00054 * int main() { 00055 * 00056 * while(true) { 00057 * usb.process(); 00058 * } 00059 * 00060 * return 0; 00061 * } 00062 * @endcode 00063 */ 00064 class USBMSD: public USBDevice { 00065 public: 00066 00067 /** 00068 * Constructor 00069 * 00070 * This creates a new USBMSD object with the given block device. Connect must be called 00071 * for the block device to connect. 00072 * 00073 * @param bd BlockDevice to mount as a USB drive 00074 * @param connect_blocking true to perform a blocking connect, false to start in a disconnected state 00075 * @param vendor_id Your vendor_id 00076 * @param product_id Your product_id 00077 * @param product_release Your preoduct_release 00078 */ 00079 USBMSD(BlockDevice *bd, bool connect_blocking = true, uint16_t vendor_id = 0x0703, uint16_t product_id = 0x0104, uint16_t product_release = 0x0001); 00080 00081 /** 00082 * Fully featured constructor 00083 * 00084 * Construct this object with the supplied USBPhy and parameters. The user 00085 * this object is responsible for calling connect() or init(). 00086 * 00087 * @note Derived classes must use this constructor and call init() or 00088 * connect() themselves. Derived classes should also call deinit() in 00089 * their destructor. This ensures that no interrupts can occur when the 00090 * object is partially constructed or destroyed. 00091 * 00092 * @param phy USB phy to use 00093 * @param bd BlockDevice to mount as a USB drive 00094 * @param vendor_id Your vendor_id 00095 * @param product_id Your product_id 00096 * @param product_release Your preoduct_release 00097 */ 00098 USBMSD(USBPhy *phy, BlockDevice *bd, uint16_t vendor_id, uint16_t product_id, uint16_t product_release); 00099 00100 /** 00101 * Destroy this object 00102 * 00103 * Any classes which inherit from this class must call disconnect 00104 * before this destructor runs. 00105 */ 00106 virtual ~USBMSD(); 00107 00108 /** 00109 * Connect the USB MSD device. 00110 * 00111 * @returns true if successful 00112 */ 00113 bool connect(); 00114 00115 /** 00116 * Disconnect the USB MSD device. 00117 */ 00118 void disconnect(); 00119 00120 /** 00121 * Perform USB processing 00122 */ 00123 void process(); 00124 00125 /** 00126 * Called when USBMSD needs to perform processing 00127 * 00128 * @param cb Callback called when USBMSD needs process() to be called 00129 */ 00130 void attach(mbed::Callback<void()> cb); 00131 00132 /** 00133 * Check if MSD device was removed/unmounted on the host side. 00134 * 00135 * @returns true if device was removed/unmounted on the host side 00136 */ 00137 bool media_removed(); 00138 00139 protected: 00140 00141 /* 00142 * read one or more blocks on a storage chip 00143 * 00144 * @param data pointer where will be stored read data 00145 * @param block starting block number 00146 * @param count number of blocks to read 00147 * @returns 0 if successful 00148 */ 00149 virtual int disk_read(uint8_t *data, uint64_t block, uint8_t count); 00150 00151 /* 00152 * write one or more blocks on a storage chip 00153 * 00154 * @param data data to write 00155 * @param block starting block number 00156 * @param count number of blocks to write 00157 * @returns 0 if successful 00158 */ 00159 virtual int disk_write(const uint8_t *data, uint64_t block, uint8_t count); 00160 00161 /* 00162 * Disk initilization 00163 */ 00164 virtual int disk_initialize(); 00165 00166 /* 00167 * Return the number of blocks 00168 * 00169 * @returns number of blocks 00170 */ 00171 virtual uint64_t disk_sectors(); 00172 00173 /* 00174 * Return memory size 00175 * 00176 * @returns memory size 00177 */ 00178 virtual uint64_t disk_size(); 00179 00180 /* 00181 * To check the status of the storage chip 00182 * 00183 * @returns status: 0: OK, 1: disk not initialized, 2: no medium in the drive, 4: write protected 00184 */ 00185 virtual int disk_status(); 00186 00187 private: 00188 00189 // MSC Bulk-only Stage 00190 enum Stage { 00191 READ_CBW, // wait a CBW 00192 ERROR, // error 00193 PROCESS_CBW, // process a CBW request 00194 SEND_CSW, // send a CSW 00195 }; 00196 00197 // Bulk-only CBW 00198 typedef MBED_PACKED(struct) 00199 { 00200 uint32_t Signature; 00201 uint32_t Tag; 00202 uint32_t DataLength; 00203 uint8_t Flags; 00204 uint8_t LUN; 00205 uint8_t CBLength; 00206 uint8_t CB[16]; 00207 } CBW; 00208 00209 // Bulk-only CSW 00210 typedef MBED_PACKED(struct) 00211 { 00212 uint32_t Signature; 00213 uint32_t Tag; 00214 uint32_t DataResidue; 00215 uint8_t Status; 00216 } CSW; 00217 00218 // If this class has been initialized 00219 bool _initialized; 00220 00221 // If msd device has been unmounted by host 00222 volatile bool _media_removed; 00223 00224 //state of the bulk-only state machine 00225 Stage _stage; 00226 00227 // current CBW 00228 CBW _cbw; 00229 00230 // CSW which will be sent 00231 CSW _csw; 00232 00233 // addr where will be read or written data 00234 uint32_t _addr; 00235 00236 // length of a reading or writing 00237 uint32_t _length; 00238 00239 // memory OK (after a memoryVerify) 00240 bool _mem_ok; 00241 00242 // cache in RAM before writing in memory. Useful also to read a block. 00243 uint8_t *_page; 00244 00245 int _block_size; 00246 uint64_t _memory_size; 00247 uint64_t _block_count; 00248 00249 // endpoints 00250 usb_ep_t _bulk_in; 00251 usb_ep_t _bulk_out; 00252 uint8_t _bulk_in_buf[64]; 00253 uint8_t _bulk_out_buf[64]; 00254 bool _out_ready; 00255 bool _in_ready; 00256 uint32_t _bulk_out_size; 00257 00258 // Interrupt to thread deferral 00259 events::PolledQueue _queue; 00260 events::Task<void()> _in_task; 00261 events::Task<void()> _out_task; 00262 events::Task<void()> _reset_task; 00263 events::Task<void(const setup_packet_t *)> _control_task; 00264 events::Task<void()> _configure_task; 00265 00266 BlockDevice *_bd; 00267 rtos::Mutex _mutex_init; 00268 rtos::Mutex _mutex; 00269 00270 // space for config descriptor 00271 uint8_t _configuration_descriptor[32]; 00272 00273 virtual const uint8_t *string_iproduct_desc(); 00274 virtual const uint8_t *string_iinterface_desc(); 00275 virtual const uint8_t *configuration_desc(uint8_t index); 00276 virtual void callback_set_configuration(uint8_t configuration); 00277 virtual void callback_set_interface(uint16_t interface, uint8_t alternate); 00278 virtual void callback_state_change(DeviceState new_state); 00279 virtual void callback_request(const setup_packet_t *setup); 00280 virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted); 00281 00282 void _isr_out(); 00283 void _isr_in(); 00284 00285 void _out(); 00286 void _in(); 00287 void _reset(); 00288 void _control(const setup_packet_t *request); 00289 void _configure(); 00290 00291 void _init(); 00292 void _process(); 00293 void _write_next(uint8_t *data, uint32_t size); 00294 void _read_next(); 00295 00296 void CBWDecode(uint8_t *buf, uint16_t size); 00297 void sendCSW(void); 00298 bool inquiryRequest(void); 00299 bool write(uint8_t *buf, uint16_t size); 00300 bool readFormatCapacity(); 00301 bool readCapacity(void); 00302 bool infoTransfer(void); 00303 void memoryRead(void); 00304 bool modeSense6(void); 00305 bool modeSense10(void); 00306 void testUnitReady(void); 00307 bool requestSense(void); 00308 void memoryVerify(uint8_t *buf, uint16_t size); 00309 void memoryWrite(uint8_t *buf, uint16_t size); 00310 void msd_reset(); 00311 void fail(); 00312 }; 00313 00314 /** @}*/ 00315 00316 #endif
Generated on Tue Jul 12 2022 13:55:03 by
