Kazuki Yamamoto / USBCDCMSC

Dependents:   USBMSD_CDC_11U35test

Committer:
k4zuki
Date:
Tue Apr 21 09:12:22 2015 +0000
Revision:
0:db88c3af3803
Child:
1:0c31d9b30900
[ FORK ] forked from okini3939/code/USB_CDC_MSD_Hello/ only USB CDC+MSD cut out

Who changed what in which revision?

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