akcelerometr i czujnik swiatla

Dependencies:   MAG3110 MMA8451Q SLCD- TSI USBDevice mbed

Committer:
zochmen
Date:
Wed Apr 16 12:20:13 2014 +0000
Revision:
0:9f7e045dcaa5
akcelerometr; czujnika swiatla;

Who changed what in which revision?

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