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 16:37:58 2011 +0000
Revision:
2:5db90410bb90
Parent:
1:bb08a84162b7

        

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