ok

Dependents:   USB_CDC_MSD_Hello

Committer:
sherckuith
Date:
Fri Aug 24 02:01:52 2012 +0000
Revision:
0:8db2bcdf4574
[mbed] converted /USB_CDC_MSD_Hello/USBCDCMSC

Who changed what in which revision?

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