USB CDC (serial) and USB MSC (strage) Composite Device. http://mbed.org/users/okini3939/notebook/USB_Device/

Dependencies:   ChaNFSSD mbed ChaNFS

Committer:
okini3939
Date:
Fri Dec 23 15:39:13 2011 +0000
Revision:
1:bb08a84162b7
Child:
2:5db90410bb90

        

Who changed what in which revision?

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