USB device stack - modified

Dependents:   shaun_larada

Fork of USBDevice by mbed official

Committer:
setcom_001
Date:
Mon Jul 22 21:16:27 2013 +0000
Revision:
12:a9671b78d24e
docs update

Who changed what in which revision?

UserRevisionLine numberNew contents of line
setcom_001 12:a9671b78d24e 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
setcom_001 12:a9671b78d24e 2 *
setcom_001 12:a9671b78d24e 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
setcom_001 12:a9671b78d24e 4 * and associated documentation files (the "Software"), to deal in the Software without
setcom_001 12:a9671b78d24e 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
setcom_001 12:a9671b78d24e 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
setcom_001 12:a9671b78d24e 7 * Software is furnished to do so, subject to the following conditions:
setcom_001 12:a9671b78d24e 8 *
setcom_001 12:a9671b78d24e 9 * The above copyright notice and this permission notice shall be included in all copies or
setcom_001 12:a9671b78d24e 10 * substantial portions of the Software.
setcom_001 12:a9671b78d24e 11 *
setcom_001 12:a9671b78d24e 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
setcom_001 12:a9671b78d24e 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
setcom_001 12:a9671b78d24e 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
setcom_001 12:a9671b78d24e 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
setcom_001 12:a9671b78d24e 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
setcom_001 12:a9671b78d24e 17 */
setcom_001 12:a9671b78d24e 18
setcom_001 12:a9671b78d24e 19 #include "stdint.h"
setcom_001 12:a9671b78d24e 20 #include "USBMSD.h"
setcom_001 12:a9671b78d24e 21
setcom_001 12:a9671b78d24e 22 #define DISK_OK 0x00
setcom_001 12:a9671b78d24e 23 #define NO_INIT 0x01
setcom_001 12:a9671b78d24e 24 #define NO_DISK 0x02
setcom_001 12:a9671b78d24e 25 #define WRITE_PROTECT 0x04
setcom_001 12:a9671b78d24e 26
setcom_001 12:a9671b78d24e 27 #define CBW_Signature 0x43425355
setcom_001 12:a9671b78d24e 28 #define CSW_Signature 0x53425355
setcom_001 12:a9671b78d24e 29
setcom_001 12:a9671b78d24e 30 // SCSI Commands
setcom_001 12:a9671b78d24e 31 #define TEST_UNIT_READY 0x00
setcom_001 12:a9671b78d24e 32 #define REQUEST_SENSE 0x03
setcom_001 12:a9671b78d24e 33 #define FORMAT_UNIT 0x04
setcom_001 12:a9671b78d24e 34 #define INQUIRY 0x12
setcom_001 12:a9671b78d24e 35 #define MODE_SELECT6 0x15
setcom_001 12:a9671b78d24e 36 #define MODE_SENSE6 0x1A
setcom_001 12:a9671b78d24e 37 #define START_STOP_UNIT 0x1B
setcom_001 12:a9671b78d24e 38 #define MEDIA_REMOVAL 0x1E
setcom_001 12:a9671b78d24e 39 #define READ_FORMAT_CAPACITIES 0x23
setcom_001 12:a9671b78d24e 40 #define READ_CAPACITY 0x25
setcom_001 12:a9671b78d24e 41 #define READ10 0x28
setcom_001 12:a9671b78d24e 42 #define WRITE10 0x2A
setcom_001 12:a9671b78d24e 43 #define VERIFY10 0x2F
setcom_001 12:a9671b78d24e 44 #define READ12 0xA8
setcom_001 12:a9671b78d24e 45 #define WRITE12 0xAA
setcom_001 12:a9671b78d24e 46 #define MODE_SELECT10 0x55
setcom_001 12:a9671b78d24e 47 #define MODE_SENSE10 0x5A
setcom_001 12:a9671b78d24e 48
setcom_001 12:a9671b78d24e 49 // MSC class specific requests
setcom_001 12:a9671b78d24e 50 #define MSC_REQUEST_RESET 0xFF
setcom_001 12:a9671b78d24e 51 #define MSC_REQUEST_GET_MAX_LUN 0xFE
setcom_001 12:a9671b78d24e 52
setcom_001 12:a9671b78d24e 53 #define DEFAULT_CONFIGURATION (1)
setcom_001 12:a9671b78d24e 54
setcom_001 12:a9671b78d24e 55 // max packet size
setcom_001 12:a9671b78d24e 56 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK
setcom_001 12:a9671b78d24e 57
setcom_001 12:a9671b78d24e 58 // CSW Status
setcom_001 12:a9671b78d24e 59 enum Status
setcom_001 12:a9671b78d24e 60 {
setcom_001 12:a9671b78d24e 61 CSW_PASSED,
setcom_001 12:a9671b78d24e 62 CSW_FAILED,
setcom_001 12:a9671b78d24e 63 CSW_ERROR,
setcom_001 12:a9671b78d24e 64 };
setcom_001 12:a9671b78d24e 65
setcom_001 12:a9671b78d24e 66
setcom_001 12:a9671b78d24e 67 USBMSD::USBMSD( uint16_t vendor_id, uint16_t product_id, uint16_t product_release ): USBDevice( vendor_id, product_id, product_release )
setcom_001 12:a9671b78d24e 68 {
setcom_001 12:a9671b78d24e 69 }
setcom_001 12:a9671b78d24e 70
setcom_001 12:a9671b78d24e 71
setcom_001 12:a9671b78d24e 72
setcom_001 12:a9671b78d24e 73 // Called in ISR context to process a class specific request
setcom_001 12:a9671b78d24e 74 bool USBMSD::USBCallback_request( void )
setcom_001 12:a9671b78d24e 75 {
setcom_001 12:a9671b78d24e 76 bool success = false;
setcom_001 12:a9671b78d24e 77 CONTROL_TRANSFER *transfer = getTransferPtr();
setcom_001 12:a9671b78d24e 78 static uint8_t maxLUN[1] = {0};
setcom_001 12:a9671b78d24e 79
setcom_001 12:a9671b78d24e 80 if ( transfer->setup.bmRequestType.Type == CLASS_TYPE )
setcom_001 12:a9671b78d24e 81 {
setcom_001 12:a9671b78d24e 82 switch ( transfer->setup.bRequest )
setcom_001 12:a9671b78d24e 83 {
setcom_001 12:a9671b78d24e 84 case MSC_REQUEST_RESET:
setcom_001 12:a9671b78d24e 85 reset();
setcom_001 12:a9671b78d24e 86 success = true;
setcom_001 12:a9671b78d24e 87 break;
setcom_001 12:a9671b78d24e 88
setcom_001 12:a9671b78d24e 89 case MSC_REQUEST_GET_MAX_LUN:
setcom_001 12:a9671b78d24e 90 transfer->remaining = 1;
setcom_001 12:a9671b78d24e 91 transfer->ptr = maxLUN;
setcom_001 12:a9671b78d24e 92 transfer->direction = DEVICE_TO_HOST;
setcom_001 12:a9671b78d24e 93 success = true;
setcom_001 12:a9671b78d24e 94 break;
setcom_001 12:a9671b78d24e 95
setcom_001 12:a9671b78d24e 96 default:
setcom_001 12:a9671b78d24e 97 break;
setcom_001 12:a9671b78d24e 98 }
setcom_001 12:a9671b78d24e 99 }
setcom_001 12:a9671b78d24e 100
setcom_001 12:a9671b78d24e 101 return success;
setcom_001 12:a9671b78d24e 102 }
setcom_001 12:a9671b78d24e 103
setcom_001 12:a9671b78d24e 104
setcom_001 12:a9671b78d24e 105 bool USBMSD::connect()
setcom_001 12:a9671b78d24e 106 {
setcom_001 12:a9671b78d24e 107 //disk initialization
setcom_001 12:a9671b78d24e 108 if ( disk_status() & NO_INIT )
setcom_001 12:a9671b78d24e 109 {
setcom_001 12:a9671b78d24e 110 if ( disk_initialize() )
setcom_001 12:a9671b78d24e 111 {
setcom_001 12:a9671b78d24e 112 return false;
setcom_001 12:a9671b78d24e 113 }
setcom_001 12:a9671b78d24e 114 }
setcom_001 12:a9671b78d24e 115
setcom_001 12:a9671b78d24e 116 // get number of blocks
setcom_001 12:a9671b78d24e 117 BlockCount = disk_sectors();
setcom_001 12:a9671b78d24e 118 // get memory size
setcom_001 12:a9671b78d24e 119 MemorySize = disk_size();
setcom_001 12:a9671b78d24e 120
setcom_001 12:a9671b78d24e 121 if ( BlockCount >= 0 )
setcom_001 12:a9671b78d24e 122 {
setcom_001 12:a9671b78d24e 123 BlockSize = MemorySize / BlockCount;
setcom_001 12:a9671b78d24e 124
setcom_001 12:a9671b78d24e 125 if ( BlockSize != 0 )
setcom_001 12:a9671b78d24e 126 {
setcom_001 12:a9671b78d24e 127 page = ( uint8_t * )malloc( BlockSize * sizeof( uint8_t ) );
setcom_001 12:a9671b78d24e 128
setcom_001 12:a9671b78d24e 129 if ( page == NULL )
setcom_001 12:a9671b78d24e 130 {
setcom_001 12:a9671b78d24e 131 return false;
setcom_001 12:a9671b78d24e 132 }
setcom_001 12:a9671b78d24e 133 }
setcom_001 12:a9671b78d24e 134 }
setcom_001 12:a9671b78d24e 135 else
setcom_001 12:a9671b78d24e 136 {
setcom_001 12:a9671b78d24e 137 return false;
setcom_001 12:a9671b78d24e 138 }
setcom_001 12:a9671b78d24e 139
setcom_001 12:a9671b78d24e 140 //connect the device
setcom_001 12:a9671b78d24e 141 USBDevice::connect();
setcom_001 12:a9671b78d24e 142 return true;
setcom_001 12:a9671b78d24e 143 }
setcom_001 12:a9671b78d24e 144
setcom_001 12:a9671b78d24e 145
setcom_001 12:a9671b78d24e 146 void USBMSD::reset()
setcom_001 12:a9671b78d24e 147 {
setcom_001 12:a9671b78d24e 148 stage = READ_CBW;
setcom_001 12:a9671b78d24e 149 }
setcom_001 12:a9671b78d24e 150
setcom_001 12:a9671b78d24e 151
setcom_001 12:a9671b78d24e 152 // Called in ISR context called when a data is received
setcom_001 12:a9671b78d24e 153 bool USBMSD::EP2_OUT_callback()
setcom_001 12:a9671b78d24e 154 {
setcom_001 12:a9671b78d24e 155 uint32_t size = 0;
setcom_001 12:a9671b78d24e 156 uint8_t buf[MAX_PACKET_SIZE_EPBULK];
setcom_001 12:a9671b78d24e 157 readEP( EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK );
setcom_001 12:a9671b78d24e 158
setcom_001 12:a9671b78d24e 159 switch ( stage )
setcom_001 12:a9671b78d24e 160 {
setcom_001 12:a9671b78d24e 161 // the device has to decode the CBW received
setcom_001 12:a9671b78d24e 162 case READ_CBW:
setcom_001 12:a9671b78d24e 163 CBWDecode( buf, size );
setcom_001 12:a9671b78d24e 164 break;
setcom_001 12:a9671b78d24e 165
setcom_001 12:a9671b78d24e 166 // the device has to receive data from the host
setcom_001 12:a9671b78d24e 167 case PROCESS_CBW:
setcom_001 12:a9671b78d24e 168 switch ( cbw.CB[0] )
setcom_001 12:a9671b78d24e 169 {
setcom_001 12:a9671b78d24e 170 case WRITE10:
setcom_001 12:a9671b78d24e 171 case WRITE12:
setcom_001 12:a9671b78d24e 172 memoryWrite( buf, size );
setcom_001 12:a9671b78d24e 173 break;
setcom_001 12:a9671b78d24e 174
setcom_001 12:a9671b78d24e 175 case VERIFY10:
setcom_001 12:a9671b78d24e 176 memoryVerify( buf, size );
setcom_001 12:a9671b78d24e 177 break;
setcom_001 12:a9671b78d24e 178 }
setcom_001 12:a9671b78d24e 179
setcom_001 12:a9671b78d24e 180 break;
setcom_001 12:a9671b78d24e 181
setcom_001 12:a9671b78d24e 182 // an error has occured: stall endpoint and send CSW
setcom_001 12:a9671b78d24e 183 default:
setcom_001 12:a9671b78d24e 184 stallEndpoint( EPBULK_OUT );
setcom_001 12:a9671b78d24e 185 csw.Status = CSW_ERROR;
setcom_001 12:a9671b78d24e 186 sendCSW();
setcom_001 12:a9671b78d24e 187 break;
setcom_001 12:a9671b78d24e 188 }
setcom_001 12:a9671b78d24e 189
setcom_001 12:a9671b78d24e 190 //reactivate readings on the OUT bulk endpoint
setcom_001 12:a9671b78d24e 191 readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
setcom_001 12:a9671b78d24e 192 return true;
setcom_001 12:a9671b78d24e 193 }
setcom_001 12:a9671b78d24e 194
setcom_001 12:a9671b78d24e 195 // Called in ISR context when a data has been transferred
setcom_001 12:a9671b78d24e 196 bool USBMSD::EP2_IN_callback()
setcom_001 12:a9671b78d24e 197 {
setcom_001 12:a9671b78d24e 198 switch ( stage )
setcom_001 12:a9671b78d24e 199 {
setcom_001 12:a9671b78d24e 200 // the device has to send data to the host
setcom_001 12:a9671b78d24e 201 case PROCESS_CBW:
setcom_001 12:a9671b78d24e 202 switch ( cbw.CB[0] )
setcom_001 12:a9671b78d24e 203 {
setcom_001 12:a9671b78d24e 204 case READ10:
setcom_001 12:a9671b78d24e 205 case READ12:
setcom_001 12:a9671b78d24e 206 memoryRead();
setcom_001 12:a9671b78d24e 207 break;
setcom_001 12:a9671b78d24e 208 }
setcom_001 12:a9671b78d24e 209
setcom_001 12:a9671b78d24e 210 break;
setcom_001 12:a9671b78d24e 211
setcom_001 12:a9671b78d24e 212 //the device has to send a CSW
setcom_001 12:a9671b78d24e 213 case SEND_CSW:
setcom_001 12:a9671b78d24e 214 sendCSW();
setcom_001 12:a9671b78d24e 215 break;
setcom_001 12:a9671b78d24e 216
setcom_001 12:a9671b78d24e 217 // an error has occured
setcom_001 12:a9671b78d24e 218 case ERROR:
setcom_001 12:a9671b78d24e 219 stallEndpoint( EPBULK_IN );
setcom_001 12:a9671b78d24e 220 sendCSW();
setcom_001 12:a9671b78d24e 221 break;
setcom_001 12:a9671b78d24e 222
setcom_001 12:a9671b78d24e 223 // the host has received the CSW -> we wait a CBW
setcom_001 12:a9671b78d24e 224 case WAIT_CSW:
setcom_001 12:a9671b78d24e 225 stage = READ_CBW;
setcom_001 12:a9671b78d24e 226 break;
setcom_001 12:a9671b78d24e 227 }
setcom_001 12:a9671b78d24e 228
setcom_001 12:a9671b78d24e 229 return true;
setcom_001 12:a9671b78d24e 230 }
setcom_001 12:a9671b78d24e 231
setcom_001 12:a9671b78d24e 232
setcom_001 12:a9671b78d24e 233 void USBMSD::memoryWrite ( uint8_t *buf, uint16_t size )
setcom_001 12:a9671b78d24e 234 {
setcom_001 12:a9671b78d24e 235 if ( ( addr + size ) > MemorySize )
setcom_001 12:a9671b78d24e 236 {
setcom_001 12:a9671b78d24e 237 size = MemorySize - addr;
setcom_001 12:a9671b78d24e 238 stage = ERROR;
setcom_001 12:a9671b78d24e 239 stallEndpoint( EPBULK_OUT );
setcom_001 12:a9671b78d24e 240 }
setcom_001 12:a9671b78d24e 241
setcom_001 12:a9671b78d24e 242 // we fill an array in RAM of 1 block before writing it in memory
setcom_001 12:a9671b78d24e 243 for ( int i = 0; i < size; i++ )
setcom_001 12:a9671b78d24e 244 {
setcom_001 12:a9671b78d24e 245 page[addr % BlockSize + i] = buf[i];
setcom_001 12:a9671b78d24e 246 }
setcom_001 12:a9671b78d24e 247
setcom_001 12:a9671b78d24e 248 // if the array is filled, write it in memory
setcom_001 12:a9671b78d24e 249 if ( !( ( addr + size ) % BlockSize ) )
setcom_001 12:a9671b78d24e 250 {
setcom_001 12:a9671b78d24e 251 if ( !( disk_status() & WRITE_PROTECT ) )
setcom_001 12:a9671b78d24e 252 {
setcom_001 12:a9671b78d24e 253 disk_write( ( const char * )page, addr / BlockSize );
setcom_001 12:a9671b78d24e 254 }
setcom_001 12:a9671b78d24e 255 }
setcom_001 12:a9671b78d24e 256
setcom_001 12:a9671b78d24e 257 addr += size;
setcom_001 12:a9671b78d24e 258 length -= size;
setcom_001 12:a9671b78d24e 259 csw.DataResidue -= size;
setcom_001 12:a9671b78d24e 260
setcom_001 12:a9671b78d24e 261 if ( ( !length ) || ( stage != PROCESS_CBW ) )
setcom_001 12:a9671b78d24e 262 {
setcom_001 12:a9671b78d24e 263 csw.Status = ( stage == ERROR ) ? CSW_FAILED : CSW_PASSED;
setcom_001 12:a9671b78d24e 264 sendCSW();
setcom_001 12:a9671b78d24e 265 }
setcom_001 12:a9671b78d24e 266 }
setcom_001 12:a9671b78d24e 267
setcom_001 12:a9671b78d24e 268 void USBMSD::memoryVerify ( uint8_t *buf, uint16_t size )
setcom_001 12:a9671b78d24e 269 {
setcom_001 12:a9671b78d24e 270 uint32_t n;
setcom_001 12:a9671b78d24e 271
setcom_001 12:a9671b78d24e 272 if ( ( addr + size ) > MemorySize )
setcom_001 12:a9671b78d24e 273 {
setcom_001 12:a9671b78d24e 274 size = MemorySize - addr;
setcom_001 12:a9671b78d24e 275 stage = ERROR;
setcom_001 12:a9671b78d24e 276 stallEndpoint( EPBULK_OUT );
setcom_001 12:a9671b78d24e 277 }
setcom_001 12:a9671b78d24e 278
setcom_001 12:a9671b78d24e 279 // beginning of a new block -> load a whole block in RAM
setcom_001 12:a9671b78d24e 280 if ( !( addr % BlockSize ) )
setcom_001 12:a9671b78d24e 281 {
setcom_001 12:a9671b78d24e 282 disk_read( ( char * )page, addr / BlockSize );
setcom_001 12:a9671b78d24e 283 }
setcom_001 12:a9671b78d24e 284
setcom_001 12:a9671b78d24e 285 // info are in RAM -> no need to re-read memory
setcom_001 12:a9671b78d24e 286 for ( n = 0; n < size; n++ )
setcom_001 12:a9671b78d24e 287 {
setcom_001 12:a9671b78d24e 288 if ( page[addr % BlockSize + n] != buf[n] )
setcom_001 12:a9671b78d24e 289 {
setcom_001 12:a9671b78d24e 290 memOK = false;
setcom_001 12:a9671b78d24e 291 break;
setcom_001 12:a9671b78d24e 292 }
setcom_001 12:a9671b78d24e 293 }
setcom_001 12:a9671b78d24e 294
setcom_001 12:a9671b78d24e 295 addr += size;
setcom_001 12:a9671b78d24e 296 length -= size;
setcom_001 12:a9671b78d24e 297 csw.DataResidue -= size;
setcom_001 12:a9671b78d24e 298
setcom_001 12:a9671b78d24e 299 if ( !length || ( stage != PROCESS_CBW ) )
setcom_001 12:a9671b78d24e 300 {
setcom_001 12:a9671b78d24e 301 csw.Status = ( memOK && ( stage == PROCESS_CBW ) ) ? CSW_PASSED : CSW_FAILED;
setcom_001 12:a9671b78d24e 302 sendCSW();
setcom_001 12:a9671b78d24e 303 }
setcom_001 12:a9671b78d24e 304 }
setcom_001 12:a9671b78d24e 305
setcom_001 12:a9671b78d24e 306
setcom_001 12:a9671b78d24e 307 bool USBMSD::inquiryRequest ( void )
setcom_001 12:a9671b78d24e 308 {
setcom_001 12:a9671b78d24e 309 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01,
setcom_001 12:a9671b78d24e 310 36 - 4, 0x80, 0x00, 0x00,
setcom_001 12:a9671b78d24e 311 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G',
setcom_001 12:a9671b78d24e 312 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ',
setcom_001 12:a9671b78d24e 313 '1', '.', '0', ' ',
setcom_001 12:a9671b78d24e 314 };
setcom_001 12:a9671b78d24e 315
setcom_001 12:a9671b78d24e 316 if ( !write( inquiry, sizeof( inquiry ) ) )
setcom_001 12:a9671b78d24e 317 {
setcom_001 12:a9671b78d24e 318 return false;
setcom_001 12:a9671b78d24e 319 }
setcom_001 12:a9671b78d24e 320
setcom_001 12:a9671b78d24e 321 return true;
setcom_001 12:a9671b78d24e 322 }
setcom_001 12:a9671b78d24e 323
setcom_001 12:a9671b78d24e 324
setcom_001 12:a9671b78d24e 325 bool USBMSD::readFormatCapacity()
setcom_001 12:a9671b78d24e 326 {
setcom_001 12:a9671b78d24e 327 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08,
setcom_001 12:a9671b78d24e 328 ( BlockCount >> 24 ) & 0xff,
setcom_001 12:a9671b78d24e 329 ( BlockCount >> 16 ) & 0xff,
setcom_001 12:a9671b78d24e 330 ( BlockCount >> 8 ) & 0xff,
setcom_001 12:a9671b78d24e 331 ( BlockCount >> 0 ) & 0xff,
setcom_001 12:a9671b78d24e 332
setcom_001 12:a9671b78d24e 333 0x02,
setcom_001 12:a9671b78d24e 334 ( BlockSize >> 16 ) & 0xff,
setcom_001 12:a9671b78d24e 335 ( BlockSize >> 8 ) & 0xff,
setcom_001 12:a9671b78d24e 336 ( BlockSize >> 0 ) & 0xff,
setcom_001 12:a9671b78d24e 337 };
setcom_001 12:a9671b78d24e 338
setcom_001 12:a9671b78d24e 339 if ( !write( capacity, sizeof( capacity ) ) )
setcom_001 12:a9671b78d24e 340 {
setcom_001 12:a9671b78d24e 341 return false;
setcom_001 12:a9671b78d24e 342 }
setcom_001 12:a9671b78d24e 343
setcom_001 12:a9671b78d24e 344 return true;
setcom_001 12:a9671b78d24e 345 }
setcom_001 12:a9671b78d24e 346
setcom_001 12:a9671b78d24e 347
setcom_001 12:a9671b78d24e 348 bool USBMSD::readCapacity ( void )
setcom_001 12:a9671b78d24e 349 {
setcom_001 12:a9671b78d24e 350 uint8_t capacity[] =
setcom_001 12:a9671b78d24e 351 {
setcom_001 12:a9671b78d24e 352 ( ( BlockCount - 1 ) >> 24 ) & 0xff,
setcom_001 12:a9671b78d24e 353 ( ( BlockCount - 1 ) >> 16 ) & 0xff,
setcom_001 12:a9671b78d24e 354 ( ( BlockCount - 1 ) >> 8 ) & 0xff,
setcom_001 12:a9671b78d24e 355 ( ( BlockCount - 1 ) >> 0 ) & 0xff,
setcom_001 12:a9671b78d24e 356
setcom_001 12:a9671b78d24e 357 ( BlockSize >> 24 ) & 0xff,
setcom_001 12:a9671b78d24e 358 ( BlockSize >> 16 ) & 0xff,
setcom_001 12:a9671b78d24e 359 ( BlockSize >> 8 ) & 0xff,
setcom_001 12:a9671b78d24e 360 ( BlockSize >> 0 ) & 0xff,
setcom_001 12:a9671b78d24e 361 };
setcom_001 12:a9671b78d24e 362
setcom_001 12:a9671b78d24e 363 if ( !write( capacity, sizeof( capacity ) ) )
setcom_001 12:a9671b78d24e 364 {
setcom_001 12:a9671b78d24e 365 return false;
setcom_001 12:a9671b78d24e 366 }
setcom_001 12:a9671b78d24e 367
setcom_001 12:a9671b78d24e 368 return true;
setcom_001 12:a9671b78d24e 369 }
setcom_001 12:a9671b78d24e 370
setcom_001 12:a9671b78d24e 371 bool USBMSD::write ( uint8_t *buf, uint16_t size )
setcom_001 12:a9671b78d24e 372 {
setcom_001 12:a9671b78d24e 373 if ( size >= cbw.DataLength )
setcom_001 12:a9671b78d24e 374 {
setcom_001 12:a9671b78d24e 375 size = cbw.DataLength;
setcom_001 12:a9671b78d24e 376 }
setcom_001 12:a9671b78d24e 377
setcom_001 12:a9671b78d24e 378 stage = SEND_CSW;
setcom_001 12:a9671b78d24e 379
setcom_001 12:a9671b78d24e 380 if ( !writeNB( EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK ) )
setcom_001 12:a9671b78d24e 381 {
setcom_001 12:a9671b78d24e 382 return false;
setcom_001 12:a9671b78d24e 383 }
setcom_001 12:a9671b78d24e 384
setcom_001 12:a9671b78d24e 385 csw.DataResidue -= size;
setcom_001 12:a9671b78d24e 386 csw.Status = CSW_PASSED;
setcom_001 12:a9671b78d24e 387 return true;
setcom_001 12:a9671b78d24e 388 }
setcom_001 12:a9671b78d24e 389
setcom_001 12:a9671b78d24e 390
setcom_001 12:a9671b78d24e 391 bool USBMSD::modeSense6 ( void )
setcom_001 12:a9671b78d24e 392 {
setcom_001 12:a9671b78d24e 393 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 };
setcom_001 12:a9671b78d24e 394
setcom_001 12:a9671b78d24e 395 if ( !write( sense6, sizeof( sense6 ) ) )
setcom_001 12:a9671b78d24e 396 {
setcom_001 12:a9671b78d24e 397 return false;
setcom_001 12:a9671b78d24e 398 }
setcom_001 12:a9671b78d24e 399
setcom_001 12:a9671b78d24e 400 return true;
setcom_001 12:a9671b78d24e 401 }
setcom_001 12:a9671b78d24e 402
setcom_001 12:a9671b78d24e 403 void USBMSD::sendCSW()
setcom_001 12:a9671b78d24e 404 {
setcom_001 12:a9671b78d24e 405 csw.Signature = CSW_Signature;
setcom_001 12:a9671b78d24e 406 writeNB( EPBULK_IN, ( uint8_t * )&csw, sizeof( CSW ), MAX_PACKET_SIZE_EPBULK );
setcom_001 12:a9671b78d24e 407 stage = WAIT_CSW;
setcom_001 12:a9671b78d24e 408 }
setcom_001 12:a9671b78d24e 409
setcom_001 12:a9671b78d24e 410 bool USBMSD::requestSense ( void )
setcom_001 12:a9671b78d24e 411 {
setcom_001 12:a9671b78d24e 412 uint8_t request_sense[] =
setcom_001 12:a9671b78d24e 413 {
setcom_001 12:a9671b78d24e 414 0x70,
setcom_001 12:a9671b78d24e 415 0x00,
setcom_001 12:a9671b78d24e 416 0x05, // Sense Key: illegal request
setcom_001 12:a9671b78d24e 417 0x00,
setcom_001 12:a9671b78d24e 418 0x00,
setcom_001 12:a9671b78d24e 419 0x00,
setcom_001 12:a9671b78d24e 420 0x00,
setcom_001 12:a9671b78d24e 421 0x0A,
setcom_001 12:a9671b78d24e 422 0x00,
setcom_001 12:a9671b78d24e 423 0x00,
setcom_001 12:a9671b78d24e 424 0x00,
setcom_001 12:a9671b78d24e 425 0x00,
setcom_001 12:a9671b78d24e 426 0x30,
setcom_001 12:a9671b78d24e 427 0x01,
setcom_001 12:a9671b78d24e 428 0x00,
setcom_001 12:a9671b78d24e 429 0x00,
setcom_001 12:a9671b78d24e 430 0x00,
setcom_001 12:a9671b78d24e 431 0x00,
setcom_001 12:a9671b78d24e 432 };
setcom_001 12:a9671b78d24e 433
setcom_001 12:a9671b78d24e 434 if ( !write( request_sense, sizeof( request_sense ) ) )
setcom_001 12:a9671b78d24e 435 {
setcom_001 12:a9671b78d24e 436 return false;
setcom_001 12:a9671b78d24e 437 }
setcom_001 12:a9671b78d24e 438
setcom_001 12:a9671b78d24e 439 return true;
setcom_001 12:a9671b78d24e 440 }
setcom_001 12:a9671b78d24e 441
setcom_001 12:a9671b78d24e 442 void USBMSD::fail()
setcom_001 12:a9671b78d24e 443 {
setcom_001 12:a9671b78d24e 444 csw.Status = CSW_FAILED;
setcom_001 12:a9671b78d24e 445 sendCSW();
setcom_001 12:a9671b78d24e 446 }
setcom_001 12:a9671b78d24e 447
setcom_001 12:a9671b78d24e 448
setcom_001 12:a9671b78d24e 449 void USBMSD::CBWDecode( uint8_t *buf, uint16_t size )
setcom_001 12:a9671b78d24e 450 {
setcom_001 12:a9671b78d24e 451 if ( size == sizeof( cbw ) )
setcom_001 12:a9671b78d24e 452 {
setcom_001 12:a9671b78d24e 453 memcpy( ( uint8_t * )&cbw, buf, size );
setcom_001 12:a9671b78d24e 454
setcom_001 12:a9671b78d24e 455 if ( cbw.Signature == CBW_Signature )
setcom_001 12:a9671b78d24e 456 {
setcom_001 12:a9671b78d24e 457 csw.Tag = cbw.Tag;
setcom_001 12:a9671b78d24e 458 csw.DataResidue = cbw.DataLength;
setcom_001 12:a9671b78d24e 459
setcom_001 12:a9671b78d24e 460 if ( ( cbw.CBLength < 1 ) || ( cbw.CBLength > 16 ) )
setcom_001 12:a9671b78d24e 461 {
setcom_001 12:a9671b78d24e 462 fail();
setcom_001 12:a9671b78d24e 463 }
setcom_001 12:a9671b78d24e 464 else
setcom_001 12:a9671b78d24e 465 {
setcom_001 12:a9671b78d24e 466 switch ( cbw.CB[0] )
setcom_001 12:a9671b78d24e 467 {
setcom_001 12:a9671b78d24e 468 case TEST_UNIT_READY:
setcom_001 12:a9671b78d24e 469 testUnitReady();
setcom_001 12:a9671b78d24e 470 break;
setcom_001 12:a9671b78d24e 471
setcom_001 12:a9671b78d24e 472 case REQUEST_SENSE:
setcom_001 12:a9671b78d24e 473 requestSense();
setcom_001 12:a9671b78d24e 474 break;
setcom_001 12:a9671b78d24e 475
setcom_001 12:a9671b78d24e 476 case INQUIRY:
setcom_001 12:a9671b78d24e 477 inquiryRequest();
setcom_001 12:a9671b78d24e 478 break;
setcom_001 12:a9671b78d24e 479
setcom_001 12:a9671b78d24e 480 case MODE_SENSE6:
setcom_001 12:a9671b78d24e 481 modeSense6();
setcom_001 12:a9671b78d24e 482 break;
setcom_001 12:a9671b78d24e 483
setcom_001 12:a9671b78d24e 484 case READ_FORMAT_CAPACITIES:
setcom_001 12:a9671b78d24e 485 readFormatCapacity();
setcom_001 12:a9671b78d24e 486 break;
setcom_001 12:a9671b78d24e 487
setcom_001 12:a9671b78d24e 488 case READ_CAPACITY:
setcom_001 12:a9671b78d24e 489 readCapacity();
setcom_001 12:a9671b78d24e 490 break;
setcom_001 12:a9671b78d24e 491
setcom_001 12:a9671b78d24e 492 case READ10:
setcom_001 12:a9671b78d24e 493 case READ12:
setcom_001 12:a9671b78d24e 494 if ( infoTransfer() )
setcom_001 12:a9671b78d24e 495 {
setcom_001 12:a9671b78d24e 496 if ( ( cbw.Flags & 0x80 ) )
setcom_001 12:a9671b78d24e 497 {
setcom_001 12:a9671b78d24e 498 stage = PROCESS_CBW;
setcom_001 12:a9671b78d24e 499 memoryRead();
setcom_001 12:a9671b78d24e 500 }
setcom_001 12:a9671b78d24e 501 else
setcom_001 12:a9671b78d24e 502 {
setcom_001 12:a9671b78d24e 503 stallEndpoint( EPBULK_OUT );
setcom_001 12:a9671b78d24e 504 csw.Status = CSW_ERROR;
setcom_001 12:a9671b78d24e 505 sendCSW();
setcom_001 12:a9671b78d24e 506 }
setcom_001 12:a9671b78d24e 507 }
setcom_001 12:a9671b78d24e 508
setcom_001 12:a9671b78d24e 509 break;
setcom_001 12:a9671b78d24e 510
setcom_001 12:a9671b78d24e 511 case WRITE10:
setcom_001 12:a9671b78d24e 512 case WRITE12:
setcom_001 12:a9671b78d24e 513 if ( infoTransfer() )
setcom_001 12:a9671b78d24e 514 {
setcom_001 12:a9671b78d24e 515 if ( !( cbw.Flags & 0x80 ) )
setcom_001 12:a9671b78d24e 516 {
setcom_001 12:a9671b78d24e 517 stage = PROCESS_CBW;
setcom_001 12:a9671b78d24e 518 }
setcom_001 12:a9671b78d24e 519 else
setcom_001 12:a9671b78d24e 520 {
setcom_001 12:a9671b78d24e 521 stallEndpoint( EPBULK_IN );
setcom_001 12:a9671b78d24e 522 csw.Status = CSW_ERROR;
setcom_001 12:a9671b78d24e 523 sendCSW();
setcom_001 12:a9671b78d24e 524 }
setcom_001 12:a9671b78d24e 525 }
setcom_001 12:a9671b78d24e 526
setcom_001 12:a9671b78d24e 527 break;
setcom_001 12:a9671b78d24e 528
setcom_001 12:a9671b78d24e 529 case VERIFY10:
setcom_001 12:a9671b78d24e 530 if ( !( cbw.CB[1] & 0x02 ) )
setcom_001 12:a9671b78d24e 531 {
setcom_001 12:a9671b78d24e 532 csw.Status = CSW_PASSED;
setcom_001 12:a9671b78d24e 533 sendCSW();
setcom_001 12:a9671b78d24e 534 break;
setcom_001 12:a9671b78d24e 535 }
setcom_001 12:a9671b78d24e 536
setcom_001 12:a9671b78d24e 537 if ( infoTransfer() )
setcom_001 12:a9671b78d24e 538 {
setcom_001 12:a9671b78d24e 539 if ( !( cbw.Flags & 0x80 ) )
setcom_001 12:a9671b78d24e 540 {
setcom_001 12:a9671b78d24e 541 stage = PROCESS_CBW;
setcom_001 12:a9671b78d24e 542 memOK = true;
setcom_001 12:a9671b78d24e 543 }
setcom_001 12:a9671b78d24e 544 else
setcom_001 12:a9671b78d24e 545 {
setcom_001 12:a9671b78d24e 546 stallEndpoint( EPBULK_IN );
setcom_001 12:a9671b78d24e 547 csw.Status = CSW_ERROR;
setcom_001 12:a9671b78d24e 548 sendCSW();
setcom_001 12:a9671b78d24e 549 }
setcom_001 12:a9671b78d24e 550 }
setcom_001 12:a9671b78d24e 551
setcom_001 12:a9671b78d24e 552 break;
setcom_001 12:a9671b78d24e 553
setcom_001 12:a9671b78d24e 554 default:
setcom_001 12:a9671b78d24e 555 fail();
setcom_001 12:a9671b78d24e 556 break;
setcom_001 12:a9671b78d24e 557 }
setcom_001 12:a9671b78d24e 558 }
setcom_001 12:a9671b78d24e 559 }
setcom_001 12:a9671b78d24e 560 }
setcom_001 12:a9671b78d24e 561 }
setcom_001 12:a9671b78d24e 562
setcom_001 12:a9671b78d24e 563 void USBMSD::testUnitReady ( void )
setcom_001 12:a9671b78d24e 564 {
setcom_001 12:a9671b78d24e 565 if ( cbw.DataLength != 0 )
setcom_001 12:a9671b78d24e 566 {
setcom_001 12:a9671b78d24e 567 if ( ( cbw.Flags & 0x80 ) != 0 )
setcom_001 12:a9671b78d24e 568 {
setcom_001 12:a9671b78d24e 569 stallEndpoint( EPBULK_IN );
setcom_001 12:a9671b78d24e 570 }
setcom_001 12:a9671b78d24e 571 else
setcom_001 12:a9671b78d24e 572 {
setcom_001 12:a9671b78d24e 573 stallEndpoint( EPBULK_OUT );
setcom_001 12:a9671b78d24e 574 }
setcom_001 12:a9671b78d24e 575 }
setcom_001 12:a9671b78d24e 576
setcom_001 12:a9671b78d24e 577 csw.Status = CSW_PASSED;
setcom_001 12:a9671b78d24e 578 sendCSW();
setcom_001 12:a9671b78d24e 579 }
setcom_001 12:a9671b78d24e 580
setcom_001 12:a9671b78d24e 581
setcom_001 12:a9671b78d24e 582 void USBMSD::memoryRead ( void )
setcom_001 12:a9671b78d24e 583 {
setcom_001 12:a9671b78d24e 584 uint32_t n;
setcom_001 12:a9671b78d24e 585 n = ( length > MAX_PACKET ) ? MAX_PACKET : length;
setcom_001 12:a9671b78d24e 586
setcom_001 12:a9671b78d24e 587 if ( ( addr + n ) > MemorySize )
setcom_001 12:a9671b78d24e 588 {
setcom_001 12:a9671b78d24e 589 n = MemorySize - addr;
setcom_001 12:a9671b78d24e 590 stage = ERROR;
setcom_001 12:a9671b78d24e 591 }
setcom_001 12:a9671b78d24e 592
setcom_001 12:a9671b78d24e 593 // we read an entire block
setcom_001 12:a9671b78d24e 594 if ( !( addr % BlockSize ) )
setcom_001 12:a9671b78d24e 595 {
setcom_001 12:a9671b78d24e 596 disk_read( ( char * )page, addr / BlockSize );
setcom_001 12:a9671b78d24e 597 }
setcom_001 12:a9671b78d24e 598
setcom_001 12:a9671b78d24e 599 // write data which are in RAM
setcom_001 12:a9671b78d24e 600 writeNB( EPBULK_IN, &page[addr % BlockSize], n, MAX_PACKET_SIZE_EPBULK );
setcom_001 12:a9671b78d24e 601 addr += n;
setcom_001 12:a9671b78d24e 602 length -= n;
setcom_001 12:a9671b78d24e 603 csw.DataResidue -= n;
setcom_001 12:a9671b78d24e 604
setcom_001 12:a9671b78d24e 605 if ( !length || ( stage != PROCESS_CBW ) )
setcom_001 12:a9671b78d24e 606 {
setcom_001 12:a9671b78d24e 607 csw.Status = ( stage == PROCESS_CBW ) ? CSW_PASSED : CSW_FAILED;
setcom_001 12:a9671b78d24e 608 stage = ( stage == PROCESS_CBW ) ? SEND_CSW : stage;
setcom_001 12:a9671b78d24e 609 }
setcom_001 12:a9671b78d24e 610 }
setcom_001 12:a9671b78d24e 611
setcom_001 12:a9671b78d24e 612
setcom_001 12:a9671b78d24e 613 bool USBMSD::infoTransfer ( void )
setcom_001 12:a9671b78d24e 614 {
setcom_001 12:a9671b78d24e 615 uint32_t n;
setcom_001 12:a9671b78d24e 616 // Logical Block Address of First Block
setcom_001 12:a9671b78d24e 617 n = ( cbw.CB[2] << 24 ) | ( cbw.CB[3] << 16 ) | ( cbw.CB[4] << 8 ) | ( cbw.CB[5] << 0 );
setcom_001 12:a9671b78d24e 618 addr = n * BlockSize;
setcom_001 12:a9671b78d24e 619
setcom_001 12:a9671b78d24e 620 // Number of Blocks to transfer
setcom_001 12:a9671b78d24e 621 switch ( cbw.CB[0] )
setcom_001 12:a9671b78d24e 622 {
setcom_001 12:a9671b78d24e 623 case READ10:
setcom_001 12:a9671b78d24e 624 case WRITE10:
setcom_001 12:a9671b78d24e 625 case VERIFY10:
setcom_001 12:a9671b78d24e 626 n = ( cbw.CB[7] << 8 ) | ( cbw.CB[8] << 0 );
setcom_001 12:a9671b78d24e 627 break;
setcom_001 12:a9671b78d24e 628
setcom_001 12:a9671b78d24e 629 case READ12:
setcom_001 12:a9671b78d24e 630 case WRITE12:
setcom_001 12:a9671b78d24e 631 n = ( cbw.CB[6] << 24 ) | ( cbw.CB[7] << 16 ) | ( cbw.CB[8] << 8 ) | ( cbw.CB[9] << 0 );
setcom_001 12:a9671b78d24e 632 break;
setcom_001 12:a9671b78d24e 633 }
setcom_001 12:a9671b78d24e 634
setcom_001 12:a9671b78d24e 635 length = n * BlockSize;
setcom_001 12:a9671b78d24e 636
setcom_001 12:a9671b78d24e 637 if ( !cbw.DataLength ) // host requests no data
setcom_001 12:a9671b78d24e 638 {
setcom_001 12:a9671b78d24e 639 csw.Status = CSW_FAILED;
setcom_001 12:a9671b78d24e 640 sendCSW();
setcom_001 12:a9671b78d24e 641 return false;
setcom_001 12:a9671b78d24e 642 }
setcom_001 12:a9671b78d24e 643
setcom_001 12:a9671b78d24e 644 if ( cbw.DataLength != length )
setcom_001 12:a9671b78d24e 645 {
setcom_001 12:a9671b78d24e 646 if ( ( cbw.Flags & 0x80 ) != 0 )
setcom_001 12:a9671b78d24e 647 {
setcom_001 12:a9671b78d24e 648 stallEndpoint( EPBULK_IN );
setcom_001 12:a9671b78d24e 649 }
setcom_001 12:a9671b78d24e 650 else
setcom_001 12:a9671b78d24e 651 {
setcom_001 12:a9671b78d24e 652 stallEndpoint( EPBULK_OUT );
setcom_001 12:a9671b78d24e 653 }
setcom_001 12:a9671b78d24e 654
setcom_001 12:a9671b78d24e 655 csw.Status = CSW_FAILED;
setcom_001 12:a9671b78d24e 656 sendCSW();
setcom_001 12:a9671b78d24e 657 return false;
setcom_001 12:a9671b78d24e 658 }
setcom_001 12:a9671b78d24e 659
setcom_001 12:a9671b78d24e 660 return true;
setcom_001 12:a9671b78d24e 661 }
setcom_001 12:a9671b78d24e 662
setcom_001 12:a9671b78d24e 663
setcom_001 12:a9671b78d24e 664
setcom_001 12:a9671b78d24e 665
setcom_001 12:a9671b78d24e 666
setcom_001 12:a9671b78d24e 667 // Called in ISR context
setcom_001 12:a9671b78d24e 668 // Set configuration. Return false if the
setcom_001 12:a9671b78d24e 669 // configuration is not supported.
setcom_001 12:a9671b78d24e 670 bool USBMSD::USBCallback_setConfiguration( uint8_t configuration )
setcom_001 12:a9671b78d24e 671 {
setcom_001 12:a9671b78d24e 672 if ( configuration != DEFAULT_CONFIGURATION )
setcom_001 12:a9671b78d24e 673 {
setcom_001 12:a9671b78d24e 674 return false;
setcom_001 12:a9671b78d24e 675 }
setcom_001 12:a9671b78d24e 676
setcom_001 12:a9671b78d24e 677 // Configure endpoints > 0
setcom_001 12:a9671b78d24e 678 addEndpoint( EPBULK_IN, MAX_PACKET_SIZE_EPBULK );
setcom_001 12:a9671b78d24e 679 addEndpoint( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
setcom_001 12:a9671b78d24e 680 //activate readings
setcom_001 12:a9671b78d24e 681 readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
setcom_001 12:a9671b78d24e 682 return true;
setcom_001 12:a9671b78d24e 683 }
setcom_001 12:a9671b78d24e 684
setcom_001 12:a9671b78d24e 685
setcom_001 12:a9671b78d24e 686 uint8_t *USBMSD::stringIinterfaceDesc()
setcom_001 12:a9671b78d24e 687 {
setcom_001 12:a9671b78d24e 688 static uint8_t stringIinterfaceDescriptor[] =
setcom_001 12:a9671b78d24e 689 {
setcom_001 12:a9671b78d24e 690 0x08, //bLength
setcom_001 12:a9671b78d24e 691 STRING_DESCRIPTOR, //bDescriptorType 0x03
setcom_001 12:a9671b78d24e 692 'M', 0, 'S', 0, 'D', 0 //bString iInterface - MSD
setcom_001 12:a9671b78d24e 693 };
setcom_001 12:a9671b78d24e 694 return stringIinterfaceDescriptor;
setcom_001 12:a9671b78d24e 695 }
setcom_001 12:a9671b78d24e 696
setcom_001 12:a9671b78d24e 697 uint8_t *USBMSD::stringIproductDesc()
setcom_001 12:a9671b78d24e 698 {
setcom_001 12:a9671b78d24e 699 static uint8_t stringIproductDescriptor[] =
setcom_001 12:a9671b78d24e 700 {
setcom_001 12:a9671b78d24e 701 0x12, //bLength
setcom_001 12:a9671b78d24e 702 STRING_DESCRIPTOR, //bDescriptorType 0x03
setcom_001 12:a9671b78d24e 703 'M', 0, 'b', 0, 'e', 0, 'd', 0, ' ', 0, 'M', 0, 'S', 0, 'D', 0 //bString iProduct - Mbed Audio
setcom_001 12:a9671b78d24e 704 };
setcom_001 12:a9671b78d24e 705 return stringIproductDescriptor;
setcom_001 12:a9671b78d24e 706 }
setcom_001 12:a9671b78d24e 707
setcom_001 12:a9671b78d24e 708
setcom_001 12:a9671b78d24e 709 uint8_t *USBMSD::configurationDesc()
setcom_001 12:a9671b78d24e 710 {
setcom_001 12:a9671b78d24e 711 static uint8_t configDescriptor[] =
setcom_001 12:a9671b78d24e 712 {
setcom_001 12:a9671b78d24e 713
setcom_001 12:a9671b78d24e 714 // Configuration 1
setcom_001 12:a9671b78d24e 715 9, // bLength
setcom_001 12:a9671b78d24e 716 2, // bDescriptorType
setcom_001 12:a9671b78d24e 717 LSB( 9 + 9 + 7 + 7 ), // wTotalLength
setcom_001 12:a9671b78d24e 718 MSB( 9 + 9 + 7 + 7 ),
setcom_001 12:a9671b78d24e 719 0x01, // bNumInterfaces
setcom_001 12:a9671b78d24e 720 0x01, // bConfigurationValue: 0x01 is used to select this configuration
setcom_001 12:a9671b78d24e 721 0x00, // iConfiguration: no string to describe this configuration
setcom_001 12:a9671b78d24e 722 0xC0, // bmAttributes
setcom_001 12:a9671b78d24e 723 100, // bMaxPower, device power consumption is 100 mA
setcom_001 12:a9671b78d24e 724
setcom_001 12:a9671b78d24e 725 // Interface 0, Alternate Setting 0, MSC Class
setcom_001 12:a9671b78d24e 726 9, // bLength
setcom_001 12:a9671b78d24e 727 4, // bDescriptorType
setcom_001 12:a9671b78d24e 728 0x00, // bInterfaceNumber
setcom_001 12:a9671b78d24e 729 0x00, // bAlternateSetting
setcom_001 12:a9671b78d24e 730 0x02, // bNumEndpoints
setcom_001 12:a9671b78d24e 731 0x08, // bInterfaceClass
setcom_001 12:a9671b78d24e 732 0x06, // bInterfaceSubClass
setcom_001 12:a9671b78d24e 733 0x50, // bInterfaceProtocol
setcom_001 12:a9671b78d24e 734 0x04, // iInterface
setcom_001 12:a9671b78d24e 735
setcom_001 12:a9671b78d24e 736 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
setcom_001 12:a9671b78d24e 737 7, // bLength
setcom_001 12:a9671b78d24e 738 5, // bDescriptorType
setcom_001 12:a9671b78d24e 739 PHY_TO_DESC( EPBULK_IN ), // bEndpointAddress
setcom_001 12:a9671b78d24e 740 0x02, // bmAttributes (0x02=bulk)
setcom_001 12:a9671b78d24e 741 LSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (LSB)
setcom_001 12:a9671b78d24e 742 MSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (MSB)
setcom_001 12:a9671b78d24e 743 0, // bInterval
setcom_001 12:a9671b78d24e 744
setcom_001 12:a9671b78d24e 745 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
setcom_001 12:a9671b78d24e 746 7, // bLength
setcom_001 12:a9671b78d24e 747 5, // bDescriptorType
setcom_001 12:a9671b78d24e 748 PHY_TO_DESC( EPBULK_OUT ), // bEndpointAddress
setcom_001 12:a9671b78d24e 749 0x02, // bmAttributes (0x02=bulk)
setcom_001 12:a9671b78d24e 750 LSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (LSB)
setcom_001 12:a9671b78d24e 751 MSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (MSB)
setcom_001 12:a9671b78d24e 752 0 // bInterval
setcom_001 12:a9671b78d24e 753 };
setcom_001 12:a9671b78d24e 754 return configDescriptor;
setcom_001 12:a9671b78d24e 755 }
setcom_001 12:a9671b78d24e 756