Kazuki Yamamoto / USBCDCMSC

Dependents:   USBMSD_CDC_11U35test

Committer:
k4zuki
Date:
Wed Apr 22 04:54:29 2015 +0000
Revision:
2:8f01347859d0
Parent:
1:0c31d9b30900
Child:
3:178491b4d4f3
[ FIX ] some functions copied from USBCDC/USBSerial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
k4zuki 0:db88c3af3803 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
k4zuki 0:db88c3af3803 2 *
k4zuki 0:db88c3af3803 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
k4zuki 0:db88c3af3803 4 * and associated documentation files (the "Software"), to deal in the Software without
k4zuki 0:db88c3af3803 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
k4zuki 0:db88c3af3803 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
k4zuki 0:db88c3af3803 7 * Software is furnished to do so, subject to the following conditions:
k4zuki 0:db88c3af3803 8 *
k4zuki 0:db88c3af3803 9 * The above copyright notice and this permission notice shall be included in all copies or
k4zuki 0:db88c3af3803 10 * substantial portions of the Software.
k4zuki 0:db88c3af3803 11 *
k4zuki 0:db88c3af3803 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
k4zuki 0:db88c3af3803 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
k4zuki 0:db88c3af3803 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
k4zuki 0:db88c3af3803 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
k4zuki 0:db88c3af3803 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
k4zuki 0:db88c3af3803 17 */
k4zuki 0:db88c3af3803 18
k4zuki 0:db88c3af3803 19 #include "stdint.h"
k4zuki 0:db88c3af3803 20 #include "USBCDCMSC.h"
k4zuki 0:db88c3af3803 21 #include "USBEndpoints.h"
k4zuki 0:db88c3af3803 22
k4zuki 0:db88c3af3803 23 /* Bulk endpoint */
k4zuki 1:0c31d9b30900 24 #define MSDBULK_OUT (EP3OUT)
k4zuki 1:0c31d9b30900 25 #define MSDBULK_IN (EP3IN)
k4zuki 1:0c31d9b30900 26 #define MAX_PACKET_SIZE_MSDBULK (MAX_PACKET_SIZE_EP3)
k4zuki 0:db88c3af3803 27
k4zuki 0:db88c3af3803 28 static uint8_t cdc_line_coding[7]= {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08};
k4zuki 0:db88c3af3803 29
k4zuki 0:db88c3af3803 30 #define DEFAULT_CONFIGURATION (1)
k4zuki 0:db88c3af3803 31
k4zuki 0:db88c3af3803 32 #define CDC_SET_LINE_CODING 0x20
k4zuki 0:db88c3af3803 33 #define CDC_GET_LINE_CODING 0x21
k4zuki 0:db88c3af3803 34 #define CDC_SET_CONTROL_LINE_STATE 0x22
k4zuki 0:db88c3af3803 35 #define CDC_SEND_BREAK 0x23
k4zuki 0:db88c3af3803 36
k4zuki 0:db88c3af3803 37 #define MAX_CDC_REPORT_SIZE MAX_PACKET_SIZE_EPBULK
k4zuki 0:db88c3af3803 38
k4zuki 0:db88c3af3803 39
k4zuki 0:db88c3af3803 40
k4zuki 0:db88c3af3803 41 #define DISK_OK 0x00
k4zuki 0:db88c3af3803 42 #define NO_INIT 0x01
k4zuki 0:db88c3af3803 43 #define NO_DISK 0x02
k4zuki 0:db88c3af3803 44 #define WRITE_PROTECT 0x04
k4zuki 0:db88c3af3803 45
k4zuki 0:db88c3af3803 46 #define CBW_Signature 0x43425355
k4zuki 0:db88c3af3803 47 #define CSW_Signature 0x53425355
k4zuki 0:db88c3af3803 48
k4zuki 0:db88c3af3803 49 // SCSI Commands
k4zuki 0:db88c3af3803 50 #define TEST_UNIT_READY 0x00
k4zuki 0:db88c3af3803 51 #define REQUEST_SENSE 0x03
k4zuki 0:db88c3af3803 52 #define FORMAT_UNIT 0x04
k4zuki 0:db88c3af3803 53 #define INQUIRY 0x12
k4zuki 0:db88c3af3803 54 #define MODE_SELECT6 0x15
k4zuki 0:db88c3af3803 55 #define MODE_SENSE6 0x1A
k4zuki 0:db88c3af3803 56 #define START_STOP_UNIT 0x1B
k4zuki 0:db88c3af3803 57 #define MEDIA_REMOVAL 0x1E
k4zuki 0:db88c3af3803 58 #define READ_FORMAT_CAPACITIES 0x23
k4zuki 0:db88c3af3803 59 #define READ_CAPACITY 0x25
k4zuki 0:db88c3af3803 60 #define READ10 0x28
k4zuki 0:db88c3af3803 61 #define WRITE10 0x2A
k4zuki 0:db88c3af3803 62 #define VERIFY10 0x2F
k4zuki 0:db88c3af3803 63 #define READ12 0xA8
k4zuki 0:db88c3af3803 64 #define WRITE12 0xAA
k4zuki 0:db88c3af3803 65 #define MODE_SELECT10 0x55
k4zuki 0:db88c3af3803 66 #define MODE_SENSE10 0x5A
k4zuki 0:db88c3af3803 67
k4zuki 0:db88c3af3803 68 // MSC class specific requests
k4zuki 0:db88c3af3803 69 #define MSC_REQUEST_RESET 0xFF
k4zuki 0:db88c3af3803 70 #define MSC_REQUEST_GET_MAX_LUN 0xFE
k4zuki 0:db88c3af3803 71
k4zuki 0:db88c3af3803 72 #define DEFAULT_CONFIGURATION (1)
k4zuki 0:db88c3af3803 73
k4zuki 0:db88c3af3803 74 // max packet size
k4zuki 0:db88c3af3803 75 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK
k4zuki 0:db88c3af3803 76
k4zuki 0:db88c3af3803 77 // CSW Status
k4zuki 0:db88c3af3803 78 enum Status {
k4zuki 0:db88c3af3803 79 CSW_PASSED,
k4zuki 0:db88c3af3803 80 CSW_FAILED,
k4zuki 0:db88c3af3803 81 CSW_ERROR,
k4zuki 0:db88c3af3803 82 };
k4zuki 0:db88c3af3803 83
k4zuki 0:db88c3af3803 84
k4zuki 0:db88c3af3803 85 USBCDCMSC::USBCDCMSC(USBSDFileSystem *sd, uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release), cdcbuf(128), _sd(sd) {
k4zuki 0:db88c3af3803 86 cdcbreak = 0;
k4zuki 0:db88c3af3803 87 _status = NO_INIT;
k4zuki 0:db88c3af3803 88 connect();
k4zuki 0:db88c3af3803 89 // USBDevice::connect();
k4zuki 0:db88c3af3803 90 USBHAL::connect();
k4zuki 0:db88c3af3803 91 }
k4zuki 0:db88c3af3803 92
k4zuki 0:db88c3af3803 93 bool USBCDCMSC::USBCallback_request(void) {
k4zuki 0:db88c3af3803 94 /* Called in ISR context */
k4zuki 0:db88c3af3803 95
k4zuki 0:db88c3af3803 96 bool success = false;
k4zuki 0:db88c3af3803 97 CONTROL_TRANSFER * transfer = getTransferPtr();
k4zuki 0:db88c3af3803 98 static uint8_t maxLUN[1] = {0};
k4zuki 0:db88c3af3803 99
k4zuki 0:db88c3af3803 100 /* Process class-specific requests */
k4zuki 0:db88c3af3803 101
k4zuki 0:db88c3af3803 102 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
k4zuki 0:db88c3af3803 103 switch (transfer->setup.bRequest) {
k4zuki 0:db88c3af3803 104 case CDC_GET_LINE_CODING:
k4zuki 0:db88c3af3803 105 transfer->remaining = 7;
k4zuki 0:db88c3af3803 106 transfer->ptr = cdc_line_coding;
k4zuki 0:db88c3af3803 107 transfer->direction = DEVICE_TO_HOST;
k4zuki 0:db88c3af3803 108 success = true;
k4zuki 0:db88c3af3803 109 break;
k4zuki 0:db88c3af3803 110 case CDC_SET_LINE_CODING:
k4zuki 0:db88c3af3803 111 transfer->remaining = 7;
k4zuki 0:db88c3af3803 112 success = true;
k4zuki 0:db88c3af3803 113 break;
k4zuki 0:db88c3af3803 114 case CDC_SET_CONTROL_LINE_STATE:
k4zuki 0:db88c3af3803 115 success = true;
k4zuki 0:db88c3af3803 116 break;
k4zuki 0:db88c3af3803 117 case CDC_SEND_BREAK:
k4zuki 0:db88c3af3803 118 cdcbreak = 1;
k4zuki 0:db88c3af3803 119 success = true;
k4zuki 0:db88c3af3803 120 break;
k4zuki 0:db88c3af3803 121 case MSC_REQUEST_RESET:
k4zuki 0:db88c3af3803 122 reset();
k4zuki 0:db88c3af3803 123 success = true;
k4zuki 0:db88c3af3803 124 break;
k4zuki 0:db88c3af3803 125 case MSC_REQUEST_GET_MAX_LUN:
k4zuki 0:db88c3af3803 126 transfer->remaining = 1;
k4zuki 0:db88c3af3803 127 transfer->ptr = maxLUN;
k4zuki 0:db88c3af3803 128 transfer->direction = DEVICE_TO_HOST;
k4zuki 0:db88c3af3803 129 success = true;
k4zuki 0:db88c3af3803 130 break;
k4zuki 0:db88c3af3803 131 default:
k4zuki 0:db88c3af3803 132 break;
k4zuki 0:db88c3af3803 133 }
k4zuki 0:db88c3af3803 134 }
k4zuki 0:db88c3af3803 135
k4zuki 0:db88c3af3803 136 return success;
k4zuki 0:db88c3af3803 137 }
k4zuki 0:db88c3af3803 138
k4zuki 0:db88c3af3803 139
k4zuki 0:db88c3af3803 140 // Called in ISR context
k4zuki 0:db88c3af3803 141 // Set configuration. Return false if the
k4zuki 0:db88c3af3803 142 // configuration is not supported.
k4zuki 0:db88c3af3803 143 bool USBCDCMSC::USBCallback_setConfiguration(uint8_t configuration) {
k4zuki 0:db88c3af3803 144 if (configuration != DEFAULT_CONFIGURATION) {
k4zuki 0:db88c3af3803 145 return false;
k4zuki 0:db88c3af3803 146 }
k4zuki 0:db88c3af3803 147
k4zuki 0:db88c3af3803 148 // Configure endpoints > 0
k4zuki 0:db88c3af3803 149 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
k4zuki 0:db88c3af3803 150 addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
k4zuki 0:db88c3af3803 151 addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
k4zuki 0:db88c3af3803 152
k4zuki 0:db88c3af3803 153 // Configure endpoints > 0
k4zuki 0:db88c3af3803 154 addEndpoint(MSDBULK_IN, MAX_PACKET_SIZE_MSDBULK);
k4zuki 0:db88c3af3803 155 addEndpoint(MSDBULK_OUT, MAX_PACKET_SIZE_MSDBULK);
k4zuki 0:db88c3af3803 156
k4zuki 0:db88c3af3803 157 // We activate the endpoint to be able to recceive data
k4zuki 0:db88c3af3803 158 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
k4zuki 0:db88c3af3803 159
k4zuki 0:db88c3af3803 160 //activate readings
k4zuki 0:db88c3af3803 161 readStart(MSDBULK_OUT, MAX_PACKET_SIZE_MSDBULK);
k4zuki 0:db88c3af3803 162 return true;
k4zuki 0:db88c3af3803 163 }
k4zuki 0:db88c3af3803 164
k4zuki 2:8f01347859d0 165 void USBCDCMSC::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) {
k4zuki 2:8f01347859d0 166 // Request of setting line coding has 7 bytes
k4zuki 2:8f01347859d0 167 if (length != 7) {
k4zuki 2:8f01347859d0 168 return;
k4zuki 2:8f01347859d0 169 }
k4zuki 2:8f01347859d0 170
k4zuki 2:8f01347859d0 171 CONTROL_TRANSFER * transfer = getTransferPtr();
k4zuki 2:8f01347859d0 172
k4zuki 2:8f01347859d0 173 /* Process class-specific requests */
k4zuki 2:8f01347859d0 174 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
k4zuki 2:8f01347859d0 175 if (transfer->setup.bRequest == CDC_SET_LINE_CODING) {
k4zuki 2:8f01347859d0 176 if (memcmp(cdc_line_coding, buf, 7)) {
k4zuki 2:8f01347859d0 177 memcpy(cdc_line_coding, buf, 7);
k4zuki 2:8f01347859d0 178
k4zuki 2:8f01347859d0 179 int baud = buf[0] + (buf[1] << 8)
k4zuki 2:8f01347859d0 180 + (buf[2] << 16) + (buf[3] << 24);
k4zuki 2:8f01347859d0 181 int stop = buf[4];
k4zuki 2:8f01347859d0 182 int bits = buf[6];
k4zuki 2:8f01347859d0 183 int parity = buf[5];
k4zuki 2:8f01347859d0 184
k4zuki 2:8f01347859d0 185 lineCodingChanged(baud, bits, parity, stop);
k4zuki 2:8f01347859d0 186 }
k4zuki 2:8f01347859d0 187 }
k4zuki 2:8f01347859d0 188 }
k4zuki 2:8f01347859d0 189 }
k4zuki 2:8f01347859d0 190
k4zuki 2:8f01347859d0 191
k4zuki 0:db88c3af3803 192 bool USBCDCMSC::send(uint8_t * buffer, uint16_t size) {
k4zuki 0:db88c3af3803 193 return USBDevice::write(EPBULK_IN, buffer, size, MAX_CDC_REPORT_SIZE);
k4zuki 0:db88c3af3803 194 }
k4zuki 0:db88c3af3803 195
k4zuki 0:db88c3af3803 196 bool USBCDCMSC::readEP(uint8_t * buffer, uint32_t * size) {
k4zuki 0:db88c3af3803 197 if (!USBDevice::readEP(EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE))
k4zuki 0:db88c3af3803 198 return false;
k4zuki 0:db88c3af3803 199 if (!readStart(EPBULK_OUT, MAX_CDC_REPORT_SIZE))
k4zuki 0:db88c3af3803 200 return false;
k4zuki 0:db88c3af3803 201 return true;
k4zuki 0:db88c3af3803 202 }
k4zuki 0:db88c3af3803 203
k4zuki 0:db88c3af3803 204 bool USBCDCMSC::readEP_NB(uint8_t * buffer, uint32_t * size) {
k4zuki 0:db88c3af3803 205 if (!USBDevice::readEP_NB(EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE))
k4zuki 0:db88c3af3803 206 return false;
k4zuki 0:db88c3af3803 207 if (!readStart(EPBULK_OUT, MAX_CDC_REPORT_SIZE))
k4zuki 0:db88c3af3803 208 return false;
k4zuki 0:db88c3af3803 209 return true;
k4zuki 0:db88c3af3803 210 }
k4zuki 0:db88c3af3803 211
k4zuki 0:db88c3af3803 212
k4zuki 0:db88c3af3803 213 uint8_t * USBCDCMSC::deviceDesc() {
k4zuki 0:db88c3af3803 214 static uint8_t deviceDescriptor[] = {
k4zuki 0:db88c3af3803 215 18, // bLength
k4zuki 0:db88c3af3803 216 1, // bDescriptorType
k4zuki 0:db88c3af3803 217 0x10, 0x01, // bcdUSB
k4zuki 0:db88c3af3803 218 0xef, // bDeviceClass
k4zuki 0:db88c3af3803 219 0x02, // bDeviceSubClass
k4zuki 0:db88c3af3803 220 0x01, // bDeviceProtocol
k4zuki 0:db88c3af3803 221 MAX_PACKET_SIZE_EP0, // bMaxPacketSize0
k4zuki 0:db88c3af3803 222 LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
k4zuki 0:db88c3af3803 223 LSB(PRODUCT_ID), MSB(PRODUCT_ID),// idProduct
k4zuki 0:db88c3af3803 224 0x00, 0x01, // bcdDevice
k4zuki 0:db88c3af3803 225 1, // iManufacturer
k4zuki 0:db88c3af3803 226 2, // iProduct
k4zuki 0:db88c3af3803 227 3, // iSerialNumber
k4zuki 0:db88c3af3803 228 1 // bNumConfigurations
k4zuki 0:db88c3af3803 229 };
k4zuki 0:db88c3af3803 230 return deviceDescriptor;
k4zuki 0:db88c3af3803 231 }
k4zuki 0:db88c3af3803 232
k4zuki 0:db88c3af3803 233 uint8_t * USBCDCMSC::stringIinterfaceDesc() {
k4zuki 0:db88c3af3803 234 static uint8_t stringIinterfaceDescriptor[] = {
k4zuki 0:db88c3af3803 235 0x0e,
k4zuki 0:db88c3af3803 236 STRING_DESCRIPTOR,
k4zuki 0:db88c3af3803 237 'C',0,'D',0,'C',0,'M',0,'S',0,'C',0,
k4zuki 0:db88c3af3803 238 };
k4zuki 0:db88c3af3803 239 return stringIinterfaceDescriptor;
k4zuki 0:db88c3af3803 240 }
k4zuki 0:db88c3af3803 241
k4zuki 0:db88c3af3803 242 uint8_t * USBCDCMSC::stringIproductDesc() {
k4zuki 0:db88c3af3803 243 static uint8_t stringIproductDescriptor[] = {
k4zuki 0:db88c3af3803 244 0x1c,
k4zuki 0:db88c3af3803 245 STRING_DESCRIPTOR,
k4zuki 0:db88c3af3803 246 'C',0,'D',0,'C',0,'M',0,'S',0,'C',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0
k4zuki 0:db88c3af3803 247 };
k4zuki 0:db88c3af3803 248 return stringIproductDescriptor;
k4zuki 0:db88c3af3803 249 }
k4zuki 0:db88c3af3803 250
k4zuki 0:db88c3af3803 251
k4zuki 0:db88c3af3803 252 uint8_t * USBCDCMSC::configurationDesc() {
k4zuki 0:db88c3af3803 253 static uint8_t configDescriptor[] = {
k4zuki 0:db88c3af3803 254 9, // bLength;
k4zuki 0:db88c3af3803 255 2, // bDescriptorType;
k4zuki 0:db88c3af3803 256 LSB(0x62), // wTotalLength
k4zuki 0:db88c3af3803 257 MSB(0x62),
k4zuki 0:db88c3af3803 258 3, // bNumInterfaces
k4zuki 0:db88c3af3803 259 1, // bConfigurationValue
k4zuki 0:db88c3af3803 260 0, // iConfiguration
k4zuki 0:db88c3af3803 261 0xc0, // bmAttributes
k4zuki 0:db88c3af3803 262 50, // bMaxPower
k4zuki 0:db88c3af3803 263
k4zuki 0:db88c3af3803 264 // IAD
k4zuki 0:db88c3af3803 265 // 0x08, 0x0B, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00,
k4zuki 0:db88c3af3803 266 0x08, 0x0B, 0x00, 0x02, 0x02, 0x02, 0x01, 0x00,
k4zuki 0:db88c3af3803 267
k4zuki 0:db88c3af3803 268 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
k4zuki 0:db88c3af3803 269 9, // bLength
k4zuki 0:db88c3af3803 270 4, // bDescriptorType
k4zuki 0:db88c3af3803 271 0, // bInterfaceNumber
k4zuki 0:db88c3af3803 272 0, // bAlternateSetting
k4zuki 0:db88c3af3803 273 1, // bNumEndpoints
k4zuki 0:db88c3af3803 274 0x02, // bInterfaceClass
k4zuki 0:db88c3af3803 275 0x02, // bInterfaceSubClass
k4zuki 0:db88c3af3803 276 0x01, // bInterfaceProtocol
k4zuki 0:db88c3af3803 277 0, // iInterface
k4zuki 0:db88c3af3803 278
k4zuki 0:db88c3af3803 279 // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
k4zuki 0:db88c3af3803 280 5, // bFunctionLength
k4zuki 0:db88c3af3803 281 0x24, // bDescriptorType
k4zuki 0:db88c3af3803 282 0x00, // bDescriptorSubtype
k4zuki 0:db88c3af3803 283 0x10, 0x01, // bcdCDC
k4zuki 0:db88c3af3803 284
k4zuki 0:db88c3af3803 285 // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
k4zuki 0:db88c3af3803 286 5, // bFunctionLength
k4zuki 0:db88c3af3803 287 0x24, // bDescriptorType
k4zuki 0:db88c3af3803 288 0x01, // bDescriptorSubtype
k4zuki 0:db88c3af3803 289 0x03, // bmCapabilities
k4zuki 0:db88c3af3803 290 1, // bDataInterface
k4zuki 0:db88c3af3803 291
k4zuki 0:db88c3af3803 292 // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
k4zuki 0:db88c3af3803 293 4, // bFunctionLength
k4zuki 0:db88c3af3803 294 0x24, // bDescriptorType
k4zuki 0:db88c3af3803 295 0x02, // bDescriptorSubtype
k4zuki 0:db88c3af3803 296 0x06, // bmCapabilities
k4zuki 0:db88c3af3803 297
k4zuki 0:db88c3af3803 298 // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
k4zuki 0:db88c3af3803 299 5, // bFunctionLength
k4zuki 0:db88c3af3803 300 0x24, // bDescriptorType
k4zuki 0:db88c3af3803 301 0x06, // bDescriptorSubtype
k4zuki 0:db88c3af3803 302 0, // bMasterInterface
k4zuki 0:db88c3af3803 303 1, // bSlaveInterface0
k4zuki 0:db88c3af3803 304
k4zuki 0:db88c3af3803 305 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
k4zuki 0:db88c3af3803 306 ENDPOINT_DESCRIPTOR_LENGTH, // bLength
k4zuki 0:db88c3af3803 307 ENDPOINT_DESCRIPTOR, // bDescriptorType
k4zuki 0:db88c3af3803 308 PHY_TO_DESC(EPINT_IN), // bEndpointAddress
k4zuki 0:db88c3af3803 309 E_INTERRUPT, // bmAttributes (0x03=intr)
k4zuki 0:db88c3af3803 310 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
k4zuki 0:db88c3af3803 311 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
k4zuki 0:db88c3af3803 312 16, // bInterval
k4zuki 0:db88c3af3803 313
k4zuki 0:db88c3af3803 314
k4zuki 0:db88c3af3803 315
k4zuki 0:db88c3af3803 316
k4zuki 0:db88c3af3803 317 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
k4zuki 0:db88c3af3803 318 9, // bLength
k4zuki 0:db88c3af3803 319 4, // bDescriptorType
k4zuki 0:db88c3af3803 320 1, // bInterfaceNumber
k4zuki 0:db88c3af3803 321 0, // bAlternateSetting
k4zuki 0:db88c3af3803 322 2, // bNumEndpoints
k4zuki 0:db88c3af3803 323 0x0A, // bInterfaceClass
k4zuki 0:db88c3af3803 324 0x00, // bInterfaceSubClass
k4zuki 0:db88c3af3803 325 0x00, // bInterfaceProtocol
k4zuki 0:db88c3af3803 326 0, // iInterface
k4zuki 0:db88c3af3803 327
k4zuki 0:db88c3af3803 328 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
k4zuki 0:db88c3af3803 329 7, // bLength
k4zuki 0:db88c3af3803 330 5, // bDescriptorType
k4zuki 0:db88c3af3803 331 PHY_TO_DESC(EPBULK_IN), // bEndpointAddress
k4zuki 0:db88c3af3803 332 0x02, // bmAttributes (0x02=bulk)
k4zuki 0:db88c3af3803 333 LSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (LSB)
k4zuki 0:db88c3af3803 334 MSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (MSB)
k4zuki 0:db88c3af3803 335 0, // bInterval
k4zuki 0:db88c3af3803 336
k4zuki 0:db88c3af3803 337 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
k4zuki 0:db88c3af3803 338 7, // bLength
k4zuki 0:db88c3af3803 339 5, // bDescriptorType
k4zuki 0:db88c3af3803 340 PHY_TO_DESC(EPBULK_OUT),// bEndpointAddress
k4zuki 0:db88c3af3803 341 0x02, // bmAttributes (0x02=bulk)
k4zuki 0:db88c3af3803 342 LSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (LSB)
k4zuki 0:db88c3af3803 343 MSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (MSB)
k4zuki 0:db88c3af3803 344 0, // bInterval
k4zuki 0:db88c3af3803 345
k4zuki 0:db88c3af3803 346 // Interface 2, Alternate Setting 0, MSC Class
k4zuki 0:db88c3af3803 347 9, // bLength
k4zuki 0:db88c3af3803 348 4, // bDescriptorType
k4zuki 0:db88c3af3803 349 0x02, // bInterfaceNumber
k4zuki 0:db88c3af3803 350 0x00, // bAlternateSetting
k4zuki 0:db88c3af3803 351 0x02, // bNumEndpoints
k4zuki 0:db88c3af3803 352 0x08, // bInterfaceClass
k4zuki 0:db88c3af3803 353 0x06, // bInterfaceSubClass
k4zuki 0:db88c3af3803 354 0x50, // bInterfaceProtocol
k4zuki 0:db88c3af3803 355 0x04, // iInterface
k4zuki 0:db88c3af3803 356
k4zuki 0:db88c3af3803 357 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
k4zuki 0:db88c3af3803 358 7, // bLength
k4zuki 0:db88c3af3803 359 5, // bDescriptorType
k4zuki 0:db88c3af3803 360 PHY_TO_DESC(MSDBULK_IN), // bEndpointAddress
k4zuki 0:db88c3af3803 361 0x02, // bmAttributes (0x02=bulk)
k4zuki 0:db88c3af3803 362 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
k4zuki 0:db88c3af3803 363 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
k4zuki 0:db88c3af3803 364 0, // bInterval
k4zuki 0:db88c3af3803 365
k4zuki 0:db88c3af3803 366 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
k4zuki 0:db88c3af3803 367 7, // bLength
k4zuki 0:db88c3af3803 368 5, // bDescriptorType
k4zuki 0:db88c3af3803 369 PHY_TO_DESC(MSDBULK_OUT), // bEndpointAddress
k4zuki 0:db88c3af3803 370 0x02, // bmAttributes (0x02=bulk)
k4zuki 0:db88c3af3803 371 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
k4zuki 0:db88c3af3803 372 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
k4zuki 0:db88c3af3803 373 0 // bInterval
k4zuki 0:db88c3af3803 374 };
k4zuki 0:db88c3af3803 375 return configDescriptor;
k4zuki 0:db88c3af3803 376 }
k4zuki 0:db88c3af3803 377
k4zuki 0:db88c3af3803 378 int USBCDCMSC::_putc(int c) {
k4zuki 0:db88c3af3803 379 send((uint8_t *)&c, 1);
k4zuki 0:db88c3af3803 380 return 1;
k4zuki 0:db88c3af3803 381 }
k4zuki 0:db88c3af3803 382
k4zuki 0:db88c3af3803 383 int USBCDCMSC::_getc() {
k4zuki 0:db88c3af3803 384 uint8_t c;
k4zuki 0:db88c3af3803 385 while (cdcbuf.isEmpty());
k4zuki 0:db88c3af3803 386 cdcbuf.dequeue(&c);
k4zuki 0:db88c3af3803 387 return c;
k4zuki 0:db88c3af3803 388 }
k4zuki 0:db88c3af3803 389
k4zuki 0:db88c3af3803 390
k4zuki 0:db88c3af3803 391 bool USBCDCMSC::writeBlock(uint8_t * buf, uint16_t size) {
k4zuki 0:db88c3af3803 392 if(size > MAX_PACKET_SIZE_EPBULK) {
k4zuki 0:db88c3af3803 393 return false;
k4zuki 0:db88c3af3803 394 }
k4zuki 0:db88c3af3803 395 if(!send(buf, size)) {
k4zuki 0:db88c3af3803 396 return false;
k4zuki 0:db88c3af3803 397 }
k4zuki 0:db88c3af3803 398 return true;
k4zuki 0:db88c3af3803 399 }
k4zuki 0:db88c3af3803 400
k4zuki 0:db88c3af3803 401
k4zuki 0:db88c3af3803 402
k4zuki 0:db88c3af3803 403 bool USBCDCMSC::EP2_OUT_callback() {
k4zuki 0:db88c3af3803 404 uint8_t c[65];
k4zuki 0:db88c3af3803 405 uint32_t size = 0;
k4zuki 0:db88c3af3803 406
k4zuki 0:db88c3af3803 407 //we read the packet received and put it on the circular buffer
k4zuki 0:db88c3af3803 408 readEP(c, &size);
k4zuki 0:db88c3af3803 409 for (int i = 0; i < size; i++) {
k4zuki 0:db88c3af3803 410 cdcbuf.queue(c[i]);
k4zuki 0:db88c3af3803 411 }
k4zuki 0:db88c3af3803 412
k4zuki 0:db88c3af3803 413 //call a potential handler
k4zuki 0:db88c3af3803 414 rx.call();
k4zuki 0:db88c3af3803 415
k4zuki 0:db88c3af3803 416 // We reactivate the endpoint to receive next characters
k4zuki 0:db88c3af3803 417 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
k4zuki 0:db88c3af3803 418 return true;
k4zuki 0:db88c3af3803 419 }
k4zuki 0:db88c3af3803 420
k4zuki 0:db88c3af3803 421 uint8_t USBCDCMSC::available() {
k4zuki 0:db88c3af3803 422 return cdcbuf.available();
k4zuki 0:db88c3af3803 423 }
k4zuki 0:db88c3af3803 424
k4zuki 0:db88c3af3803 425
k4zuki 0:db88c3af3803 426 bool USBCDCMSC::connect() {
k4zuki 0:db88c3af3803 427
k4zuki 0:db88c3af3803 428 //disk initialization
k4zuki 0:db88c3af3803 429 if (_disk_status() & NO_INIT) {
k4zuki 0:db88c3af3803 430 if (disk_initialize()) {
k4zuki 0:db88c3af3803 431 return false;
k4zuki 0:db88c3af3803 432 }
k4zuki 0:db88c3af3803 433 }
k4zuki 0:db88c3af3803 434
k4zuki 0:db88c3af3803 435 // get number of blocks
k4zuki 0:db88c3af3803 436 BlockCount = disk_sectors();
k4zuki 0:db88c3af3803 437
k4zuki 0:db88c3af3803 438 // get memory size
k4zuki 0:db88c3af3803 439 MemorySize = disk_size();
k4zuki 0:db88c3af3803 440
k4zuki 0:db88c3af3803 441 if (BlockCount >= 0) {
k4zuki 0:db88c3af3803 442 BlockSize = MemorySize / BlockCount;
k4zuki 0:db88c3af3803 443 if (BlockSize != 0) {
k4zuki 0:db88c3af3803 444 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t));
k4zuki 0:db88c3af3803 445 if (page == NULL)
k4zuki 0:db88c3af3803 446 return false;
k4zuki 0:db88c3af3803 447 }
k4zuki 0:db88c3af3803 448 } else {
k4zuki 0:db88c3af3803 449 return false;
k4zuki 0:db88c3af3803 450 }
k4zuki 0:db88c3af3803 451
k4zuki 0:db88c3af3803 452 //connect the device
k4zuki 0:db88c3af3803 453 // USBDevice::connect();
k4zuki 0:db88c3af3803 454 return true;
k4zuki 0:db88c3af3803 455 }
k4zuki 0:db88c3af3803 456
k4zuki 0:db88c3af3803 457
k4zuki 0:db88c3af3803 458 void USBCDCMSC::reset() {
k4zuki 0:db88c3af3803 459 stage = READ_CBW;
k4zuki 0:db88c3af3803 460 }
k4zuki 0:db88c3af3803 461
k4zuki 0:db88c3af3803 462
k4zuki 0:db88c3af3803 463 // Called in ISR context called when a data is received
k4zuki 1:0c31d9b30900 464 bool USBCDCMSC::EP3_OUT_callback() {
k4zuki 0:db88c3af3803 465 uint32_t size = 0;
k4zuki 0:db88c3af3803 466 uint8_t buf[MAX_PACKET_SIZE_EPBULK];
k4zuki 0:db88c3af3803 467 USBDevice::readEP(MSDBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK);
k4zuki 0:db88c3af3803 468 switch (stage) {
k4zuki 0:db88c3af3803 469 // the device has to decode the CBW received
k4zuki 0:db88c3af3803 470 case READ_CBW:
k4zuki 0:db88c3af3803 471 CBWDecode(buf, size);
k4zuki 0:db88c3af3803 472 break;
k4zuki 0:db88c3af3803 473
k4zuki 0:db88c3af3803 474 // the device has to receive data from the host
k4zuki 0:db88c3af3803 475 case PROCESS_CBW:
k4zuki 0:db88c3af3803 476 switch (cbw.CB[0]) {
k4zuki 0:db88c3af3803 477 case WRITE10:
k4zuki 0:db88c3af3803 478 case WRITE12:
k4zuki 0:db88c3af3803 479 memoryWrite(buf, size);
k4zuki 0:db88c3af3803 480 break;
k4zuki 0:db88c3af3803 481 case VERIFY10:
k4zuki 0:db88c3af3803 482 memoryVerify(buf, size);
k4zuki 0:db88c3af3803 483 break;
k4zuki 0:db88c3af3803 484 }
k4zuki 0:db88c3af3803 485 break;
k4zuki 0:db88c3af3803 486
k4zuki 0:db88c3af3803 487 // an error has occured: stall endpoint and send CSW
k4zuki 0:db88c3af3803 488 default:
k4zuki 0:db88c3af3803 489 stallEndpoint(MSDBULK_OUT);
k4zuki 0:db88c3af3803 490 csw.Status = CSW_ERROR;
k4zuki 0:db88c3af3803 491 sendCSW();
k4zuki 0:db88c3af3803 492 break;
k4zuki 0:db88c3af3803 493 }
k4zuki 0:db88c3af3803 494
k4zuki 0:db88c3af3803 495 //reactivate readings on the OUT bulk endpoint
k4zuki 0:db88c3af3803 496 readStart(MSDBULK_OUT, MAX_PACKET_SIZE_EPBULK);
k4zuki 0:db88c3af3803 497 return true;
k4zuki 0:db88c3af3803 498 }
k4zuki 0:db88c3af3803 499
k4zuki 0:db88c3af3803 500 // Called in ISR context when a data has been transferred
k4zuki 1:0c31d9b30900 501 bool USBCDCMSC::EP3_IN_callback() {
k4zuki 0:db88c3af3803 502 switch (stage) {
k4zuki 0:db88c3af3803 503
k4zuki 0:db88c3af3803 504 // the device has to send data to the host
k4zuki 0:db88c3af3803 505 case PROCESS_CBW:
k4zuki 0:db88c3af3803 506 switch (cbw.CB[0]) {
k4zuki 0:db88c3af3803 507 case READ10:
k4zuki 0:db88c3af3803 508 case READ12:
k4zuki 0:db88c3af3803 509 memoryRead();
k4zuki 0:db88c3af3803 510 break;
k4zuki 0:db88c3af3803 511 }
k4zuki 0:db88c3af3803 512 break;
k4zuki 0:db88c3af3803 513
k4zuki 0:db88c3af3803 514 //the device has to send a CSW
k4zuki 0:db88c3af3803 515 case SEND_CSW:
k4zuki 0:db88c3af3803 516 sendCSW();
k4zuki 0:db88c3af3803 517 break;
k4zuki 0:db88c3af3803 518
k4zuki 0:db88c3af3803 519 // an error has occured
k4zuki 0:db88c3af3803 520 case ERROR:
k4zuki 0:db88c3af3803 521 stallEndpoint(MSDBULK_IN);
k4zuki 0:db88c3af3803 522 sendCSW();
k4zuki 0:db88c3af3803 523 break;
k4zuki 0:db88c3af3803 524
k4zuki 0:db88c3af3803 525 // the host has received the CSW -> we wait a CBW
k4zuki 0:db88c3af3803 526 case WAIT_CSW:
k4zuki 0:db88c3af3803 527 stage = READ_CBW;
k4zuki 0:db88c3af3803 528 break;
k4zuki 0:db88c3af3803 529 }
k4zuki 0:db88c3af3803 530 return true;
k4zuki 0:db88c3af3803 531 }
k4zuki 0:db88c3af3803 532
k4zuki 0:db88c3af3803 533
k4zuki 0:db88c3af3803 534 void USBCDCMSC::memoryWrite (uint8_t * buf, uint16_t size) {
k4zuki 0:db88c3af3803 535
k4zuki 0:db88c3af3803 536 if ((addr + size) > MemorySize) {
k4zuki 0:db88c3af3803 537 size = MemorySize - addr;
k4zuki 0:db88c3af3803 538 stage = ERROR;
k4zuki 0:db88c3af3803 539 stallEndpoint(MSDBULK_OUT);
k4zuki 0:db88c3af3803 540 }
k4zuki 0:db88c3af3803 541
k4zuki 0:db88c3af3803 542 // we fill an array in RAM of 1 block before writing it in memory
k4zuki 0:db88c3af3803 543 for (int i = 0; i < size; i++)
k4zuki 0:db88c3af3803 544 page[addr%BlockSize + i] = buf[i];
k4zuki 0:db88c3af3803 545
k4zuki 0:db88c3af3803 546 // if the array is filled, write it in memory
k4zuki 0:db88c3af3803 547 if (!((addr + size)%BlockSize)) {
k4zuki 0:db88c3af3803 548 if (!(_disk_status() & WRITE_PROTECT)) {
k4zuki 0:db88c3af3803 549 _disk_write((const uint8_t *)page, addr/BlockSize);
k4zuki 0:db88c3af3803 550 }
k4zuki 0:db88c3af3803 551 }
k4zuki 0:db88c3af3803 552
k4zuki 0:db88c3af3803 553 addr += size;
k4zuki 0:db88c3af3803 554 length -= size;
k4zuki 0:db88c3af3803 555 csw.DataResidue -= size;
k4zuki 0:db88c3af3803 556
k4zuki 0:db88c3af3803 557 if ((!length) || (stage != PROCESS_CBW)) {
k4zuki 0:db88c3af3803 558 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED;
k4zuki 0:db88c3af3803 559 sendCSW();
k4zuki 0:db88c3af3803 560 }
k4zuki 0:db88c3af3803 561 }
k4zuki 0:db88c3af3803 562
k4zuki 0:db88c3af3803 563 void USBCDCMSC::memoryVerify (uint8_t * buf, uint16_t size) {
k4zuki 0:db88c3af3803 564 uint32_t n;
k4zuki 0:db88c3af3803 565
k4zuki 0:db88c3af3803 566 if ((addr + size) > MemorySize) {
k4zuki 0:db88c3af3803 567 size = MemorySize - addr;
k4zuki 0:db88c3af3803 568 stage = ERROR;
k4zuki 0:db88c3af3803 569 stallEndpoint(MSDBULK_OUT);
k4zuki 0:db88c3af3803 570 }
k4zuki 0:db88c3af3803 571
k4zuki 0:db88c3af3803 572 // beginning of a new block -> load a whole block in RAM
k4zuki 0:db88c3af3803 573 if (!(addr%BlockSize))
k4zuki 0:db88c3af3803 574 disk_read((uint8_t *)page, addr/BlockSize);
k4zuki 0:db88c3af3803 575
k4zuki 0:db88c3af3803 576 // info are in RAM -> no need to re-read memory
k4zuki 0:db88c3af3803 577 for (n = 0; n < size; n++) {
k4zuki 0:db88c3af3803 578 if (page[addr%BlockSize + n] != buf[n]) {
k4zuki 0:db88c3af3803 579 memOK = false;
k4zuki 0:db88c3af3803 580 break;
k4zuki 0:db88c3af3803 581 }
k4zuki 0:db88c3af3803 582 }
k4zuki 0:db88c3af3803 583
k4zuki 0:db88c3af3803 584 addr += size;
k4zuki 0:db88c3af3803 585 length -= size;
k4zuki 0:db88c3af3803 586 csw.DataResidue -= size;
k4zuki 0:db88c3af3803 587
k4zuki 0:db88c3af3803 588 if ( !length || (stage != PROCESS_CBW)) {
k4zuki 0:db88c3af3803 589 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED;
k4zuki 0:db88c3af3803 590 sendCSW();
k4zuki 0:db88c3af3803 591 }
k4zuki 0:db88c3af3803 592 }
k4zuki 0:db88c3af3803 593
k4zuki 0:db88c3af3803 594
k4zuki 0:db88c3af3803 595 bool USBCDCMSC::inquiryRequest (void) {
k4zuki 0:db88c3af3803 596 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01,
k4zuki 0:db88c3af3803 597 36 - 4, 0x80, 0x00, 0x00,
k4zuki 0:db88c3af3803 598 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G',
k4zuki 0:db88c3af3803 599 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ',
k4zuki 0:db88c3af3803 600 '1', '.', '0', ' ',
k4zuki 0:db88c3af3803 601 };
k4zuki 0:db88c3af3803 602 if (!msd_write(inquiry, sizeof(inquiry))) {
k4zuki 0:db88c3af3803 603 return false;
k4zuki 0:db88c3af3803 604 }
k4zuki 0:db88c3af3803 605 return true;
k4zuki 0:db88c3af3803 606 }
k4zuki 0:db88c3af3803 607
k4zuki 0:db88c3af3803 608
k4zuki 0:db88c3af3803 609 bool USBCDCMSC::readFormatCapacity() {
k4zuki 0:db88c3af3803 610 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08,
k4zuki 0:db88c3af3803 611 (BlockCount >> 24) & 0xff,
k4zuki 0:db88c3af3803 612 (BlockCount >> 16) & 0xff,
k4zuki 0:db88c3af3803 613 (BlockCount >> 8) & 0xff,
k4zuki 0:db88c3af3803 614 (BlockCount >> 0) & 0xff,
k4zuki 0:db88c3af3803 615
k4zuki 0:db88c3af3803 616 0x02,
k4zuki 0:db88c3af3803 617 (BlockSize >> 16) & 0xff,
k4zuki 0:db88c3af3803 618 (BlockSize >> 8) & 0xff,
k4zuki 0:db88c3af3803 619 (BlockSize >> 0) & 0xff,
k4zuki 0:db88c3af3803 620 };
k4zuki 0:db88c3af3803 621 if (!msd_write(capacity, sizeof(capacity))) {
k4zuki 0:db88c3af3803 622 return false;
k4zuki 0:db88c3af3803 623 }
k4zuki 0:db88c3af3803 624 return true;
k4zuki 0:db88c3af3803 625 }
k4zuki 0:db88c3af3803 626
k4zuki 0:db88c3af3803 627
k4zuki 0:db88c3af3803 628 bool USBCDCMSC::readCapacity (void) {
k4zuki 0:db88c3af3803 629 uint8_t capacity[] = {
k4zuki 0:db88c3af3803 630 ((BlockCount - 1) >> 24) & 0xff,
k4zuki 0:db88c3af3803 631 ((BlockCount - 1) >> 16) & 0xff,
k4zuki 0:db88c3af3803 632 ((BlockCount - 1) >> 8) & 0xff,
k4zuki 0:db88c3af3803 633 ((BlockCount - 1) >> 0) & 0xff,
k4zuki 0:db88c3af3803 634
k4zuki 0:db88c3af3803 635 (BlockSize >> 24) & 0xff,
k4zuki 0:db88c3af3803 636 (BlockSize >> 16) & 0xff,
k4zuki 0:db88c3af3803 637 (BlockSize >> 8) & 0xff,
k4zuki 0:db88c3af3803 638 (BlockSize >> 0) & 0xff,
k4zuki 0:db88c3af3803 639 };
k4zuki 0:db88c3af3803 640 if (!msd_write(capacity, sizeof(capacity))) {
k4zuki 0:db88c3af3803 641 return false;
k4zuki 0:db88c3af3803 642 }
k4zuki 0:db88c3af3803 643 return true;
k4zuki 0:db88c3af3803 644 }
k4zuki 0:db88c3af3803 645
k4zuki 0:db88c3af3803 646 bool USBCDCMSC::msd_write (uint8_t * buf, uint16_t size) {
k4zuki 0:db88c3af3803 647
k4zuki 0:db88c3af3803 648 if (size >= cbw.DataLength) {
k4zuki 0:db88c3af3803 649 size = cbw.DataLength;
k4zuki 0:db88c3af3803 650 }
k4zuki 0:db88c3af3803 651 stage = SEND_CSW;
k4zuki 0:db88c3af3803 652
k4zuki 0:db88c3af3803 653 if (!writeNB(MSDBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) {
k4zuki 0:db88c3af3803 654 return false;
k4zuki 0:db88c3af3803 655 }
k4zuki 0:db88c3af3803 656
k4zuki 0:db88c3af3803 657 csw.DataResidue -= size;
k4zuki 0:db88c3af3803 658 csw.Status = CSW_PASSED;
k4zuki 0:db88c3af3803 659 return true;
k4zuki 0:db88c3af3803 660 }
k4zuki 0:db88c3af3803 661
k4zuki 0:db88c3af3803 662
k4zuki 0:db88c3af3803 663 bool USBCDCMSC::modeSense6 (void) {
k4zuki 0:db88c3af3803 664 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 };
k4zuki 0:db88c3af3803 665 if (!msd_write(sense6, sizeof(sense6))) {
k4zuki 0:db88c3af3803 666 return false;
k4zuki 0:db88c3af3803 667 }
k4zuki 0:db88c3af3803 668 return true;
k4zuki 0:db88c3af3803 669 }
k4zuki 0:db88c3af3803 670
k4zuki 0:db88c3af3803 671 void USBCDCMSC::sendCSW() {
k4zuki 0:db88c3af3803 672 csw.Signature = CSW_Signature;
k4zuki 0:db88c3af3803 673 writeNB(MSDBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK);
k4zuki 0:db88c3af3803 674 stage = WAIT_CSW;
k4zuki 0:db88c3af3803 675 }
k4zuki 0:db88c3af3803 676
k4zuki 0:db88c3af3803 677 bool USBCDCMSC::requestSense (void) {
k4zuki 0:db88c3af3803 678 uint8_t request_sense[] = {
k4zuki 0:db88c3af3803 679 0x70,
k4zuki 0:db88c3af3803 680 0x00,
k4zuki 0:db88c3af3803 681 0x05, // Sense Key: illegal request
k4zuki 0:db88c3af3803 682 0x00,
k4zuki 0:db88c3af3803 683 0x00,
k4zuki 0:db88c3af3803 684 0x00,
k4zuki 0:db88c3af3803 685 0x00,
k4zuki 0:db88c3af3803 686 0x0A,
k4zuki 0:db88c3af3803 687 0x00,
k4zuki 0:db88c3af3803 688 0x00,
k4zuki 0:db88c3af3803 689 0x00,
k4zuki 0:db88c3af3803 690 0x00,
k4zuki 0:db88c3af3803 691 0x30,
k4zuki 0:db88c3af3803 692 0x01,
k4zuki 0:db88c3af3803 693 0x00,
k4zuki 0:db88c3af3803 694 0x00,
k4zuki 0:db88c3af3803 695 0x00,
k4zuki 0:db88c3af3803 696 0x00,
k4zuki 0:db88c3af3803 697 };
k4zuki 0:db88c3af3803 698
k4zuki 0:db88c3af3803 699 if (!msd_write(request_sense, sizeof(request_sense))) {
k4zuki 0:db88c3af3803 700 return false;
k4zuki 0:db88c3af3803 701 }
k4zuki 0:db88c3af3803 702
k4zuki 0:db88c3af3803 703 return true;
k4zuki 0:db88c3af3803 704 }
k4zuki 0:db88c3af3803 705
k4zuki 0:db88c3af3803 706 void USBCDCMSC::fail() {
k4zuki 0:db88c3af3803 707 csw.Status = CSW_FAILED;
k4zuki 0:db88c3af3803 708 sendCSW();
k4zuki 0:db88c3af3803 709 }
k4zuki 0:db88c3af3803 710
k4zuki 0:db88c3af3803 711
k4zuki 0:db88c3af3803 712 void USBCDCMSC::CBWDecode(uint8_t * buf, uint16_t size) {
k4zuki 0:db88c3af3803 713 if (size == sizeof(cbw)) {
k4zuki 0:db88c3af3803 714 memcpy((uint8_t *)&cbw, buf, size);
k4zuki 0:db88c3af3803 715 if (cbw.Signature == CBW_Signature) {
k4zuki 0:db88c3af3803 716 csw.Tag = cbw.Tag;
k4zuki 0:db88c3af3803 717 csw.DataResidue = cbw.DataLength;
k4zuki 0:db88c3af3803 718 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) {
k4zuki 0:db88c3af3803 719 fail();
k4zuki 0:db88c3af3803 720 } else {
k4zuki 0:db88c3af3803 721 switch (cbw.CB[0]) {
k4zuki 0:db88c3af3803 722 case TEST_UNIT_READY:
k4zuki 0:db88c3af3803 723 testUnitReady();
k4zuki 0:db88c3af3803 724 break;
k4zuki 0:db88c3af3803 725 case REQUEST_SENSE:
k4zuki 0:db88c3af3803 726 requestSense();
k4zuki 0:db88c3af3803 727 break;
k4zuki 0:db88c3af3803 728 case INQUIRY:
k4zuki 0:db88c3af3803 729 inquiryRequest();
k4zuki 0:db88c3af3803 730 break;
k4zuki 0:db88c3af3803 731 case MODE_SENSE6:
k4zuki 0:db88c3af3803 732 modeSense6();
k4zuki 0:db88c3af3803 733 break;
k4zuki 0:db88c3af3803 734 case READ_FORMAT_CAPACITIES:
k4zuki 0:db88c3af3803 735 readFormatCapacity();
k4zuki 0:db88c3af3803 736 break;
k4zuki 0:db88c3af3803 737 case READ_CAPACITY:
k4zuki 0:db88c3af3803 738 readCapacity();
k4zuki 0:db88c3af3803 739 break;
k4zuki 0:db88c3af3803 740 case READ10:
k4zuki 0:db88c3af3803 741 case READ12:
k4zuki 0:db88c3af3803 742 if (infoTransfer()) {
k4zuki 0:db88c3af3803 743 if ((cbw.Flags & 0x80)) {
k4zuki 0:db88c3af3803 744 stage = PROCESS_CBW;
k4zuki 0:db88c3af3803 745 memoryRead();
k4zuki 0:db88c3af3803 746 } else {
k4zuki 0:db88c3af3803 747 stallEndpoint(MSDBULK_OUT);
k4zuki 0:db88c3af3803 748 csw.Status = CSW_ERROR;
k4zuki 0:db88c3af3803 749 sendCSW();
k4zuki 0:db88c3af3803 750 }
k4zuki 0:db88c3af3803 751 }
k4zuki 0:db88c3af3803 752 break;
k4zuki 0:db88c3af3803 753 case WRITE10:
k4zuki 0:db88c3af3803 754 case WRITE12:
k4zuki 0:db88c3af3803 755 if (infoTransfer()) {
k4zuki 0:db88c3af3803 756 if (!(cbw.Flags & 0x80)) {
k4zuki 0:db88c3af3803 757 stage = PROCESS_CBW;
k4zuki 0:db88c3af3803 758 } else {
k4zuki 0:db88c3af3803 759 stallEndpoint(MSDBULK_IN);
k4zuki 0:db88c3af3803 760 csw.Status = CSW_ERROR;
k4zuki 0:db88c3af3803 761 sendCSW();
k4zuki 0:db88c3af3803 762 }
k4zuki 0:db88c3af3803 763 }
k4zuki 0:db88c3af3803 764 break;
k4zuki 0:db88c3af3803 765 case VERIFY10:
k4zuki 0:db88c3af3803 766 if (!(cbw.CB[1] & 0x02)) {
k4zuki 0:db88c3af3803 767 csw.Status = CSW_PASSED;
k4zuki 0:db88c3af3803 768 sendCSW();
k4zuki 0:db88c3af3803 769 break;
k4zuki 0:db88c3af3803 770 }
k4zuki 0:db88c3af3803 771 if (infoTransfer()) {
k4zuki 0:db88c3af3803 772 if (!(cbw.Flags & 0x80)) {
k4zuki 0:db88c3af3803 773 stage = PROCESS_CBW;
k4zuki 0:db88c3af3803 774 memOK = true;
k4zuki 0:db88c3af3803 775 } else {
k4zuki 0:db88c3af3803 776 stallEndpoint(MSDBULK_IN);
k4zuki 0:db88c3af3803 777 csw.Status = CSW_ERROR;
k4zuki 0:db88c3af3803 778 sendCSW();
k4zuki 0:db88c3af3803 779 }
k4zuki 0:db88c3af3803 780 }
k4zuki 0:db88c3af3803 781 break;
k4zuki 0:db88c3af3803 782 default:
k4zuki 0:db88c3af3803 783 fail();
k4zuki 0:db88c3af3803 784 break;
k4zuki 0:db88c3af3803 785 }
k4zuki 0:db88c3af3803 786 }
k4zuki 0:db88c3af3803 787 }
k4zuki 0:db88c3af3803 788 }
k4zuki 0:db88c3af3803 789 }
k4zuki 0:db88c3af3803 790
k4zuki 0:db88c3af3803 791 void USBCDCMSC::testUnitReady (void) {
k4zuki 0:db88c3af3803 792
k4zuki 0:db88c3af3803 793 if (cbw.DataLength != 0) {
k4zuki 0:db88c3af3803 794 if ((cbw.Flags & 0x80) != 0) {
k4zuki 0:db88c3af3803 795 stallEndpoint(MSDBULK_IN);
k4zuki 0:db88c3af3803 796 } else {
k4zuki 0:db88c3af3803 797 stallEndpoint(MSDBULK_OUT);
k4zuki 0:db88c3af3803 798 }
k4zuki 0:db88c3af3803 799 }
k4zuki 0:db88c3af3803 800
k4zuki 0:db88c3af3803 801 csw.Status = CSW_PASSED;
k4zuki 0:db88c3af3803 802 sendCSW();
k4zuki 0:db88c3af3803 803 }
k4zuki 0:db88c3af3803 804
k4zuki 0:db88c3af3803 805
k4zuki 0:db88c3af3803 806 void USBCDCMSC::memoryRead (void) {
k4zuki 0:db88c3af3803 807 uint32_t n;
k4zuki 0:db88c3af3803 808
k4zuki 0:db88c3af3803 809 n = (length > MAX_PACKET) ? MAX_PACKET : length;
k4zuki 0:db88c3af3803 810
k4zuki 0:db88c3af3803 811 if ((addr + n) > MemorySize) {
k4zuki 0:db88c3af3803 812 n = MemorySize - addr;
k4zuki 0:db88c3af3803 813 stage = ERROR;
k4zuki 0:db88c3af3803 814 }
k4zuki 0:db88c3af3803 815
k4zuki 0:db88c3af3803 816 // we read an entire block
k4zuki 0:db88c3af3803 817 if (!(addr%BlockSize))
k4zuki 0:db88c3af3803 818 disk_read((uint8_t *)page, addr/BlockSize);
k4zuki 0:db88c3af3803 819
k4zuki 0:db88c3af3803 820 // write data which are in RAM
k4zuki 0:db88c3af3803 821 writeNB(MSDBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK);
k4zuki 0:db88c3af3803 822
k4zuki 0:db88c3af3803 823 addr += n;
k4zuki 0:db88c3af3803 824 length -= n;
k4zuki 0:db88c3af3803 825
k4zuki 0:db88c3af3803 826 csw.DataResidue -= n;
k4zuki 0:db88c3af3803 827
k4zuki 0:db88c3af3803 828 if ( !length || (stage != PROCESS_CBW)) {
k4zuki 0:db88c3af3803 829 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED;
k4zuki 0:db88c3af3803 830 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage;
k4zuki 0:db88c3af3803 831 }
k4zuki 0:db88c3af3803 832 }
k4zuki 0:db88c3af3803 833
k4zuki 0:db88c3af3803 834
k4zuki 0:db88c3af3803 835 bool USBCDCMSC::infoTransfer (void) {
k4zuki 0:db88c3af3803 836 uint32_t n;
k4zuki 0:db88c3af3803 837
k4zuki 0:db88c3af3803 838 // Logical Block Address of First Block
k4zuki 0:db88c3af3803 839 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0);
k4zuki 0:db88c3af3803 840
k4zuki 0:db88c3af3803 841 addr = n * BlockSize;
k4zuki 0:db88c3af3803 842
k4zuki 0:db88c3af3803 843 // Number of Blocks to transfer
k4zuki 0:db88c3af3803 844 switch (cbw.CB[0]) {
k4zuki 0:db88c3af3803 845 case READ10:
k4zuki 0:db88c3af3803 846 case WRITE10:
k4zuki 0:db88c3af3803 847 case VERIFY10:
k4zuki 0:db88c3af3803 848 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0);
k4zuki 0:db88c3af3803 849 break;
k4zuki 0:db88c3af3803 850
k4zuki 0:db88c3af3803 851 case READ12:
k4zuki 0:db88c3af3803 852 case WRITE12:
k4zuki 0:db88c3af3803 853 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0);
k4zuki 0:db88c3af3803 854 break;
k4zuki 0:db88c3af3803 855 }
k4zuki 0:db88c3af3803 856
k4zuki 0:db88c3af3803 857 length = n * BlockSize;
k4zuki 0:db88c3af3803 858
k4zuki 0:db88c3af3803 859 if (!cbw.DataLength) { // host requests no data
k4zuki 0:db88c3af3803 860 csw.Status = CSW_FAILED;
k4zuki 0:db88c3af3803 861 sendCSW();
k4zuki 0:db88c3af3803 862 return false;
k4zuki 0:db88c3af3803 863 }
k4zuki 0:db88c3af3803 864
k4zuki 0:db88c3af3803 865 if (cbw.DataLength != length) {
k4zuki 0:db88c3af3803 866 if ((cbw.Flags & 0x80) != 0) {
k4zuki 0:db88c3af3803 867 stallEndpoint(MSDBULK_IN);
k4zuki 0:db88c3af3803 868 } else {
k4zuki 0:db88c3af3803 869 stallEndpoint(MSDBULK_OUT);
k4zuki 0:db88c3af3803 870 }
k4zuki 0:db88c3af3803 871
k4zuki 0:db88c3af3803 872 csw.Status = CSW_FAILED;
k4zuki 0:db88c3af3803 873 sendCSW();
k4zuki 0:db88c3af3803 874 return false;
k4zuki 0:db88c3af3803 875 }
k4zuki 0:db88c3af3803 876
k4zuki 0:db88c3af3803 877 return true;
k4zuki 0:db88c3af3803 878 }
k4zuki 0:db88c3af3803 879
k4zuki 0:db88c3af3803 880 int USBCDCMSC::isBreak () {
k4zuki 0:db88c3af3803 881 int ret = cdcbreak;
k4zuki 0:db88c3af3803 882 cdcbreak = 0;
k4zuki 0:db88c3af3803 883 return ret;
k4zuki 0:db88c3af3803 884 }
k4zuki 0:db88c3af3803 885
k4zuki 0:db88c3af3803 886 int USBCDCMSC::disk_initialize() {
k4zuki 0:db88c3af3803 887 if (_sd->disk_initialize()) {
k4zuki 0:db88c3af3803 888 _status |= NO_DISK;
k4zuki 0:db88c3af3803 889 return 1;
k4zuki 0:db88c3af3803 890 } else {
k4zuki 0:db88c3af3803 891 _status = DISK_OK;
k4zuki 0:db88c3af3803 892 return 0;
k4zuki 0:db88c3af3803 893 }
k4zuki 0:db88c3af3803 894 }
k4zuki 0:db88c3af3803 895
k4zuki 0:db88c3af3803 896 int USBCDCMSC::_disk_write(const uint8_t *buffer, int block_number) {
k4zuki 0:db88c3af3803 897 return _sd->_disk_write(buffer, block_number,1);
k4zuki 0:db88c3af3803 898 }
k4zuki 0:db88c3af3803 899
k4zuki 0:db88c3af3803 900 int USBCDCMSC::disk_read(uint8_t *buffer, int block_number) {
k4zuki 0:db88c3af3803 901 return _sd->disk_read(buffer, block_number,1);
k4zuki 0:db88c3af3803 902 }
k4zuki 0:db88c3af3803 903
k4zuki 0:db88c3af3803 904 int USBCDCMSC::_disk_status() {
k4zuki 0:db88c3af3803 905 return _status;
k4zuki 0:db88c3af3803 906 }
k4zuki 0:db88c3af3803 907
k4zuki 0:db88c3af3803 908 int USBCDCMSC::disk_sectors() {
k4zuki 0:db88c3af3803 909 return _sd->disk_sectors();
k4zuki 0:db88c3af3803 910 }
k4zuki 0:db88c3af3803 911 int USBCDCMSC::disk_size() {
k4zuki 0:db88c3af3803 912 return _sd->disk_sectors() * 512;
k4zuki 0:db88c3af3803 913 }