USB MSD HID composite device hello world

Dependencies:   USBDevice mbed

Committer:
samux
Date:
Mon Jan 21 12:03:05 2013 +0000
Revision:
0:61e5ecd27a36
USB MSD HID composite device hello world

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 0:61e5ecd27a36 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
samux 0:61e5ecd27a36 2 *
samux 0:61e5ecd27a36 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
samux 0:61e5ecd27a36 4 * and associated documentation files (the "Software"), to deal in the Software without
samux 0:61e5ecd27a36 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
samux 0:61e5ecd27a36 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
samux 0:61e5ecd27a36 7 * Software is furnished to do so, subject to the following conditions:
samux 0:61e5ecd27a36 8 *
samux 0:61e5ecd27a36 9 * The above copyright notice and this permission notice shall be included in all copies or
samux 0:61e5ecd27a36 10 * substantial portions of the Software.
samux 0:61e5ecd27a36 11 *
samux 0:61e5ecd27a36 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
samux 0:61e5ecd27a36 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
samux 0:61e5ecd27a36 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
samux 0:61e5ecd27a36 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
samux 0:61e5ecd27a36 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
samux 0:61e5ecd27a36 17 */
samux 0:61e5ecd27a36 18
samux 0:61e5ecd27a36 19
samux 0:61e5ecd27a36 20 #ifndef USBMSD_HID_H
samux 0:61e5ecd27a36 21 #define USBMSD_HID_H
samux 0:61e5ecd27a36 22
samux 0:61e5ecd27a36 23 /* These headers are included for child class. */
samux 0:61e5ecd27a36 24 #include "USBEndpoints.h"
samux 0:61e5ecd27a36 25 #include "USBDescriptor.h"
samux 0:61e5ecd27a36 26 #include "USBDevice_Types.h"
samux 0:61e5ecd27a36 27 #include "USBHID_Types.h"
samux 0:61e5ecd27a36 28
samux 0:61e5ecd27a36 29 #include "USBDevice.h"
samux 0:61e5ecd27a36 30
samux 0:61e5ecd27a36 31 /**
samux 0:61e5ecd27a36 32 * USBMSD class: generic class in order to use all kinds of blocks storage chip
samux 0:61e5ecd27a36 33 *
samux 0:61e5ecd27a36 34 * Introduction
samux 0:61e5ecd27a36 35 *
samux 0:61e5ecd27a36 36 * The USBMSD implements the MSD protocol. It permits to access a memory chip (flash, sdcard,...)
samux 0:61e5ecd27a36 37 * from a computer over USB. But this class doesn't work standalone, you need to subclass this class
samux 0:61e5ecd27a36 38 * and define virtual functions which are called in USBMSD.
samux 0:61e5ecd27a36 39 *
samux 0:61e5ecd27a36 40 * How to use this class with your chip ?
samux 0:61e5ecd27a36 41 *
samux 0:61e5ecd27a36 42 * You have to inherit and define some pure virtual functions (mandatory step):
samux 0:61e5ecd27a36 43 * - virtual int disk_read(char * data, int block): function to read a block
samux 0:61e5ecd27a36 44 * - virtual int disk_write(const char * data, int block): function to write a block
samux 0:61e5ecd27a36 45 * - virtual int disk_initialize(): function to initialize the memory
samux 0:61e5ecd27a36 46 * - virtual int disk_sectors(): return the number of blocks
samux 0:61e5ecd27a36 47 * - virtual int disk_size(): return the memory size
samux 0:61e5ecd27a36 48 * - 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)
samux 0:61e5ecd27a36 49 *
samux 0:61e5ecd27a36 50 * All functions names are compatible with the fat filesystem library. So you can imagine using your own class with
samux 0:61e5ecd27a36 51 * USBMSD and the fat filesystem library in the same program. Just be careful because there are two different parts which
samux 0:61e5ecd27a36 52 * will access the sd card. You can do a master/slave system using the disk_status method.
samux 0:61e5ecd27a36 53 *
samux 0:61e5ecd27a36 54 * Once these functions defined, you can call connect() (at the end of the constructor of your class for instance)
samux 0:61e5ecd27a36 55 * of USBMSD to connect your mass storage device. connect() will first call disk_status() to test the status of the disk.
samux 0:61e5ecd27a36 56 * If disk_status() returns 1 (disk not initialized), then disk_initialize() is called. After this step, connect() will collect information
samux 0:61e5ecd27a36 57 * such as the number of blocks and the memory size.
samux 0:61e5ecd27a36 58 */
samux 0:61e5ecd27a36 59 class USBMSD_HID: public USBDevice {
samux 0:61e5ecd27a36 60 public:
samux 0:61e5ecd27a36 61
samux 0:61e5ecd27a36 62 /**
samux 0:61e5ecd27a36 63 * Constructor
samux 0:61e5ecd27a36 64 *
samux 0:61e5ecd27a36 65 * @param vendor_id Your vendor_id
samux 0:61e5ecd27a36 66 * @param product_id Your product_id
samux 0:61e5ecd27a36 67 * @param product_release Your preoduct_release
samux 0:61e5ecd27a36 68 * @param output_report_length Maximum length of a sent report (up to 64 bytes) (default: 64 bytes)
samux 0:61e5ecd27a36 69 * @param input_report_length Maximum length of a received report (up to 64 bytes) (default: 64 bytes)
samux 0:61e5ecd27a36 70 */
samux 0:61e5ecd27a36 71 USBMSD_HID(uint8_t output_report_length = 64, uint8_t input_report_length = 64, uint16_t vendor_id = 0x0853, uint16_t product_id = 0x0654, uint16_t product_release = 0x0001);
samux 0:61e5ecd27a36 72
samux 0:61e5ecd27a36 73 /**
samux 0:61e5ecd27a36 74 * Connect the USB MSD device. Establish disk initialization before really connect the device.
samux 0:61e5ecd27a36 75 *
samux 0:61e5ecd27a36 76 * @returns true if successful
samux 0:61e5ecd27a36 77 */
samux 0:61e5ecd27a36 78 bool connect();
samux 0:61e5ecd27a36 79
samux 0:61e5ecd27a36 80 /**
samux 0:61e5ecd27a36 81 * Send a Report. warning: blocking
samux 0:61e5ecd27a36 82 *
samux 0:61e5ecd27a36 83 * @param report Report which will be sent (a report is defined by all data and the length)
samux 0:61e5ecd27a36 84 * @returns true if successful
samux 0:61e5ecd27a36 85 */
samux 0:61e5ecd27a36 86 bool send(HID_REPORT *report);
samux 0:61e5ecd27a36 87
samux 0:61e5ecd27a36 88
samux 0:61e5ecd27a36 89 /**
samux 0:61e5ecd27a36 90 * Send a Report. warning: non blocking
samux 0:61e5ecd27a36 91 *
samux 0:61e5ecd27a36 92 * @param report Report which will be sent (a report is defined by all data and the length)
samux 0:61e5ecd27a36 93 * @returns true if successful
samux 0:61e5ecd27a36 94 */
samux 0:61e5ecd27a36 95 bool sendNB(HID_REPORT *report);
samux 0:61e5ecd27a36 96
samux 0:61e5ecd27a36 97 /**
samux 0:61e5ecd27a36 98 * Read a report: blocking
samux 0:61e5ecd27a36 99 *
samux 0:61e5ecd27a36 100 * @param report pointer to the report to fill
samux 0:61e5ecd27a36 101 * @returns true if successful
samux 0:61e5ecd27a36 102 */
samux 0:61e5ecd27a36 103 bool read(HID_REPORT * report);
samux 0:61e5ecd27a36 104
samux 0:61e5ecd27a36 105 /**
samux 0:61e5ecd27a36 106 * Read a report: non blocking
samux 0:61e5ecd27a36 107 *
samux 0:61e5ecd27a36 108 * @param report pointer to the report to fill
samux 0:61e5ecd27a36 109 * @returns true if successful
samux 0:61e5ecd27a36 110 */
samux 0:61e5ecd27a36 111 bool readNB(HID_REPORT * report);
samux 0:61e5ecd27a36 112
samux 0:61e5ecd27a36 113
samux 0:61e5ecd27a36 114 protected:
samux 0:61e5ecd27a36 115
samux 0:61e5ecd27a36 116 uint16_t reportLength;
samux 0:61e5ecd27a36 117
samux 0:61e5ecd27a36 118 /*
samux 0:61e5ecd27a36 119 * Get the Report descriptor
samux 0:61e5ecd27a36 120 *
samux 0:61e5ecd27a36 121 * @returns pointer to the report descriptor
samux 0:61e5ecd27a36 122 */
samux 0:61e5ecd27a36 123 virtual uint8_t * reportDesc();
samux 0:61e5ecd27a36 124
samux 0:61e5ecd27a36 125 /*
samux 0:61e5ecd27a36 126 * Get the length of the report descriptor
samux 0:61e5ecd27a36 127 *
samux 0:61e5ecd27a36 128 * @returns the length of the report descriptor
samux 0:61e5ecd27a36 129 */
samux 0:61e5ecd27a36 130 virtual uint16_t reportDescLength();
samux 0:61e5ecd27a36 131
samux 0:61e5ecd27a36 132 /*
samux 0:61e5ecd27a36 133 * read a block on a storage chip
samux 0:61e5ecd27a36 134 *
samux 0:61e5ecd27a36 135 * @param data pointer where will be stored read data
samux 0:61e5ecd27a36 136 * @param block block number
samux 0:61e5ecd27a36 137 * @returns 0 if successful
samux 0:61e5ecd27a36 138 */
samux 0:61e5ecd27a36 139 virtual int disk_read(uint8_t * data, uint64_t block) = 0;
samux 0:61e5ecd27a36 140
samux 0:61e5ecd27a36 141 /*
samux 0:61e5ecd27a36 142 * write a block on a storage chip
samux 0:61e5ecd27a36 143 *
samux 0:61e5ecd27a36 144 * @param data data to write
samux 0:61e5ecd27a36 145 * @param block block number
samux 0:61e5ecd27a36 146 * @returns 0 if successful
samux 0:61e5ecd27a36 147 */
samux 0:61e5ecd27a36 148 virtual int disk_write(const uint8_t * data, uint64_t block) = 0;
samux 0:61e5ecd27a36 149
samux 0:61e5ecd27a36 150 /*
samux 0:61e5ecd27a36 151 * Disk initilization
samux 0:61e5ecd27a36 152 */
samux 0:61e5ecd27a36 153 virtual int disk_initialize() = 0;
samux 0:61e5ecd27a36 154
samux 0:61e5ecd27a36 155 /*
samux 0:61e5ecd27a36 156 * Return the number of blocks
samux 0:61e5ecd27a36 157 *
samux 0:61e5ecd27a36 158 * @returns number of blocks
samux 0:61e5ecd27a36 159 */
samux 0:61e5ecd27a36 160 virtual uint64_t disk_sectors() = 0;
samux 0:61e5ecd27a36 161
samux 0:61e5ecd27a36 162 /*
samux 0:61e5ecd27a36 163 * Return memory size
samux 0:61e5ecd27a36 164 *
samux 0:61e5ecd27a36 165 * @returns memory size
samux 0:61e5ecd27a36 166 */
samux 0:61e5ecd27a36 167 virtual uint64_t disk_size() = 0;
samux 0:61e5ecd27a36 168
samux 0:61e5ecd27a36 169
samux 0:61e5ecd27a36 170 /*
samux 0:61e5ecd27a36 171 * To check the status of the storage chip
samux 0:61e5ecd27a36 172 *
samux 0:61e5ecd27a36 173 * @returns status: 0: OK, 1: disk not initialized, 2: no medium in the drive, 4: write protected
samux 0:61e5ecd27a36 174 */
samux 0:61e5ecd27a36 175 virtual int disk_status() = 0;
samux 0:61e5ecd27a36 176
samux 0:61e5ecd27a36 177 /*
samux 0:61e5ecd27a36 178 * Get string product descriptor
samux 0:61e5ecd27a36 179 *
samux 0:61e5ecd27a36 180 * @returns pointer to the string product descriptor
samux 0:61e5ecd27a36 181 */
samux 0:61e5ecd27a36 182 virtual uint8_t * stringIproductDesc();
samux 0:61e5ecd27a36 183
samux 0:61e5ecd27a36 184 virtual uint8_t * deviceDesc();
samux 0:61e5ecd27a36 185
samux 0:61e5ecd27a36 186 /*
samux 0:61e5ecd27a36 187 * Get string interface descriptor
samux 0:61e5ecd27a36 188 *
samux 0:61e5ecd27a36 189 * @returns pointer to the string interface descriptor
samux 0:61e5ecd27a36 190 */
samux 0:61e5ecd27a36 191 virtual uint8_t * stringIinterfaceDesc();
samux 0:61e5ecd27a36 192
samux 0:61e5ecd27a36 193 /*
samux 0:61e5ecd27a36 194 * Get configuration descriptor
samux 0:61e5ecd27a36 195 *
samux 0:61e5ecd27a36 196 * @returns pointer to the configuration descriptor
samux 0:61e5ecd27a36 197 */
samux 0:61e5ecd27a36 198 virtual uint8_t * configurationDesc();
samux 0:61e5ecd27a36 199
samux 0:61e5ecd27a36 200 /*
samux 0:61e5ecd27a36 201 * Callback called when a packet is received
samux 0:61e5ecd27a36 202 */
samux 0:61e5ecd27a36 203 virtual bool EP2_OUT_callback();
samux 0:61e5ecd27a36 204
samux 0:61e5ecd27a36 205 /*
samux 0:61e5ecd27a36 206 * Callback called when a packet has been sent
samux 0:61e5ecd27a36 207 */
samux 0:61e5ecd27a36 208 virtual bool EP2_IN_callback();
samux 0:61e5ecd27a36 209
samux 0:61e5ecd27a36 210 /*
samux 0:61e5ecd27a36 211 * Set configuration of device. Add endpoints
samux 0:61e5ecd27a36 212 */
samux 0:61e5ecd27a36 213 virtual bool USBCallback_setConfiguration(uint8_t configuration);
samux 0:61e5ecd27a36 214
samux 0:61e5ecd27a36 215 /*
samux 0:61e5ecd27a36 216 * Callback called to process class specific requests
samux 0:61e5ecd27a36 217 */
samux 0:61e5ecd27a36 218 virtual bool USBCallback_request();
samux 0:61e5ecd27a36 219
samux 0:61e5ecd27a36 220
samux 0:61e5ecd27a36 221 private:
samux 0:61e5ecd27a36 222
samux 0:61e5ecd27a36 223 // MSC Bulk-only Stage
samux 0:61e5ecd27a36 224 enum Stage {
samux 0:61e5ecd27a36 225 READ_CBW, // wait a CBW
samux 0:61e5ecd27a36 226 ERROR, // error
samux 0:61e5ecd27a36 227 PROCESS_CBW, // process a CBW request
samux 0:61e5ecd27a36 228 SEND_CSW, // send a CSW
samux 0:61e5ecd27a36 229 WAIT_CSW, // wait that a CSW has been effectively sent
samux 0:61e5ecd27a36 230 };
samux 0:61e5ecd27a36 231
samux 0:61e5ecd27a36 232 // Bulk-only CBW
samux 0:61e5ecd27a36 233 typedef __packed struct {
samux 0:61e5ecd27a36 234 uint32_t Signature;
samux 0:61e5ecd27a36 235 uint32_t Tag;
samux 0:61e5ecd27a36 236 uint32_t DataLength;
samux 0:61e5ecd27a36 237 uint8_t Flags;
samux 0:61e5ecd27a36 238 uint8_t LUN;
samux 0:61e5ecd27a36 239 uint8_t CBLength;
samux 0:61e5ecd27a36 240 uint8_t CB[16];
samux 0:61e5ecd27a36 241 } CBW;
samux 0:61e5ecd27a36 242
samux 0:61e5ecd27a36 243 // Bulk-only CSW
samux 0:61e5ecd27a36 244 typedef __packed struct {
samux 0:61e5ecd27a36 245 uint32_t Signature;
samux 0:61e5ecd27a36 246 uint32_t Tag;
samux 0:61e5ecd27a36 247 uint32_t DataResidue;
samux 0:61e5ecd27a36 248 uint8_t Status;
samux 0:61e5ecd27a36 249 } CSW;
samux 0:61e5ecd27a36 250
samux 0:61e5ecd27a36 251 //state of the bulk-only state machine
samux 0:61e5ecd27a36 252 Stage stage;
samux 0:61e5ecd27a36 253
samux 0:61e5ecd27a36 254 // current CBW
samux 0:61e5ecd27a36 255 CBW cbw;
samux 0:61e5ecd27a36 256
samux 0:61e5ecd27a36 257 // CSW which will be sent
samux 0:61e5ecd27a36 258 CSW csw;
samux 0:61e5ecd27a36 259
samux 0:61e5ecd27a36 260 // addr where will be read or written data
samux 0:61e5ecd27a36 261 uint32_t addr;
samux 0:61e5ecd27a36 262
samux 0:61e5ecd27a36 263 // length of a reading or writing
samux 0:61e5ecd27a36 264 uint32_t length;
samux 0:61e5ecd27a36 265
samux 0:61e5ecd27a36 266 // memory OK (after a memoryVerify)
samux 0:61e5ecd27a36 267 bool memOK;
samux 0:61e5ecd27a36 268
samux 0:61e5ecd27a36 269 // cache in RAM before writing in memory. Useful also to read a block.
samux 0:61e5ecd27a36 270 uint8_t * page;
samux 0:61e5ecd27a36 271
samux 0:61e5ecd27a36 272 int BlockSize;
samux 0:61e5ecd27a36 273 uint64_t MemorySize;
samux 0:61e5ecd27a36 274 uint64_t BlockCount;
samux 0:61e5ecd27a36 275
samux 0:61e5ecd27a36 276 void CBWDecode(uint8_t * buf, uint16_t size);
samux 0:61e5ecd27a36 277 void sendCSW (void);
samux 0:61e5ecd27a36 278 bool inquiryRequest (void);
samux 0:61e5ecd27a36 279 bool write (uint8_t * buf, uint16_t size);
samux 0:61e5ecd27a36 280 bool readFormatCapacity();
samux 0:61e5ecd27a36 281 bool readCapacity (void);
samux 0:61e5ecd27a36 282 bool infoTransfer (void);
samux 0:61e5ecd27a36 283 void memoryRead (void);
samux 0:61e5ecd27a36 284 bool modeSense6 (void);
samux 0:61e5ecd27a36 285 void testUnitReady (void);
samux 0:61e5ecd27a36 286 bool requestSense (void);
samux 0:61e5ecd27a36 287 void memoryVerify (uint8_t * buf, uint16_t size);
samux 0:61e5ecd27a36 288 void memoryWrite (uint8_t * buf, uint16_t size);
samux 0:61e5ecd27a36 289 void reset();
samux 0:61e5ecd27a36 290 void fail();
samux 0:61e5ecd27a36 291
samux 0:61e5ecd27a36 292 HID_REPORT outputReport;
samux 0:61e5ecd27a36 293 uint8_t output_length;
samux 0:61e5ecd27a36 294 uint8_t input_length;
samux 0:61e5ecd27a36 295 };
samux 0:61e5ecd27a36 296
samux 0:61e5ecd27a36 297 #endif