Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBMSD.h Source File

USBMSD.h

00001 /* Copyright (c) 2010-2011 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 
00020 #ifndef USBMSD_H
00021 #define USBMSD_H
00022 
00023 #include "USB.h"
00024 
00025 /* These headers are included for child class. */
00026 #include "USBEndpoints.h"
00027 #include "USBDescriptor.h"
00028 #include "USBDevice_Types.h"
00029 
00030 #include "USBDevice.h"
00031 
00032 #include "disk.h"
00033 
00034 #include "Module.h"
00035 
00036 /**
00037  * USBMSD class: generic class in order to use all kinds of blocks storage chip
00038  *
00039  * Introduction
00040  *
00041  * The USBMSD implements the MSD protocol. It permits to access a memory chip (flash, sdcard,...)
00042  * from a computer over USB. But this class doesn't work standalone, you need to subclass this class
00043  * and define virtual functions which are called in USBMSD.
00044  *
00045  * How to use this class with your chip ?
00046  *
00047  * You have to inherit and define some pure virtual functions (mandatory step):
00048  *   - virtual int disk_read(char * data, int block): function to read a block
00049  *   - virtual int disk_write(const char * data, int block): function to write a block
00050  *   - virtual int disk_initialize(): function to initialize the memory
00051  *   - virtual int disk_sectors(): return the number of blocks
00052  *   - virtual int disk_size(): return the memory size
00053  *   - virtual int disk_status(): return the status of the storage chip (0: OK, 1: not initialized, 2: no medium in the drive, 4: write protection)
00054  *
00055  * All functions names are compatible with the fat filesystem library. So you can imagine using your own class with
00056  * USBMSD and the fat filesystem library in the same program. Just be careful because there are two different parts which
00057  * will access the sd card. You can do a master/slave system using the disk_status method.
00058  *
00059  * Once these functions defined, you can call connect() (at the end of the constructor of your class for instance)
00060  * of USBMSD to connect your mass storage device. connect() will first call disk_status() to test the status of the disk.
00061  * If disk_status() returns 1 (disk not initialized), then disk_initialize() is called. After this step, connect() will collect information
00062  * such as the number of blocks and the memory size.
00063  */
00064 
00065 class USBMSD: public USB_State_Receiver, public USB_Endpoint_Receiver, public Module {
00066 public:
00067 
00068     /**
00069     * Constructor
00070     *
00071     * @param vendor_id Your vendor_id
00072     * @param product_id Your product_id
00073     * @param product_release Your preoduct_release
00074     */
00075     USBMSD(USB *, MSD_Disk *);
00076 
00077     /**
00078     * Connect the USB MSD device. Establish disk initialization before really connect the device.
00079     *
00080     * @returns true if successful
00081     */
00082     bool connect();
00083 
00084     bool USBEvent_Request(CONTROL_TRANSFER&);
00085     bool USBEvent_RequestComplete(CONTROL_TRANSFER&, uint8_t *, uint32_t);
00086     bool USBEvent_EPIn(uint8_t, uint8_t);
00087     bool USBEvent_EPOut(uint8_t, uint8_t);
00088     bool USBEvent_busReset(void);
00089     bool USBEvent_connectStateChanged(bool connected);
00090     bool USBEvent_suspendStateChanged(bool suspended);
00091 
00092     virtual void on_module_loaded(void);
00093 
00094     // USB descriptors
00095     usbdesc_interface MSC_Interface;
00096     usbdesc_endpoint  MSC_BulkOut;
00097     usbdesc_endpoint  MSC_BulkIn;
00098 
00099     usbdesc_string_l(12) MSC_Description;
00100 
00101     // Bulk-only CBW
00102     typedef struct __attribute__ ((packed)) {
00103         uint32_t Signature;
00104         uint32_t Tag;
00105         uint32_t DataLength;
00106         uint8_t  Flags;
00107         uint8_t  LUN;
00108         uint8_t  CBLength;
00109         uint8_t  CB[16];
00110     } CBW;
00111 
00112     // Bulk-only CSW
00113     typedef struct __attribute__ ((packed)) {
00114         uint32_t Signature;
00115         uint32_t Tag;
00116         uint32_t DataResidue;
00117         uint8_t  Status;
00118     } CSW;
00119 
00120 private:
00121     // parent USB composite device manager
00122     USB *usb;
00123 
00124     // disk
00125     MSD_Disk *disk;
00126 
00127     // MSC Bulk-only Stage
00128     enum Stage {
00129         READ_CBW,     // wait a CBW
00130         ERROR,        // error
00131         PROCESS_CBW,  // process a CBW request
00132         SEND_CSW,     // send a CSW
00133         WAIT_CSW,     // wait that a CSW has been effectively sent
00134     };
00135 
00136     //state of the bulk-only state machine
00137     Stage stage;
00138 
00139     // current CBW
00140     CBW cbw;
00141 
00142     // CSW which will be sent
00143     CSW csw;
00144 
00145     // addr where will be read or written data
00146 //     uint32_t addr;
00147 
00148     // transitioning to block-based logic
00149     uint32_t lba;
00150     uint16_t addr_in_block;
00151 
00152     // length of a reading or writing
00153     uint32_t length;
00154 
00155     // number of blocks to transfer
00156     uint32_t blocks;
00157 
00158     // memory OK (after a memoryVerify)
00159     bool memOK;
00160 
00161     // cache in RAM before writing in memory. Useful also to read a block.
00162     uint8_t * page;
00163 
00164     // USB packet buffer
00165     uint8_t buffer[MAX_PACKET_SIZE_EPBULK];
00166 
00167     uint32_t BlockSize;
00168 //     uint32_t MemorySize;
00169     uint32_t BlockCount;
00170 
00171     void CBWDecode(uint8_t * buf, uint16_t size);
00172     void sendCSW (void);
00173     bool inquiryRequest (void);
00174     bool write (uint8_t * buf, uint16_t size);
00175     bool readFormatCapacity();
00176     bool readCapacity (void);
00177     bool infoTransfer (void);
00178     void memoryRead (void);
00179     bool modeSense6 (void);
00180     void testUnitReady (void);
00181     bool requestSense (void);
00182     void memoryVerify (uint8_t * buf, uint16_t size);
00183     void memoryWrite (uint8_t * buf, uint16_t size);
00184     void reset();
00185     void fail();
00186 };
00187 
00188 #endif