Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBMSD.h Source File

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