Kazuki Yamamoto / USBCDCMSC

Dependents:   USBMSD_CDC_11U35test

Committer:
k4zuki
Date:
Tue Apr 21 16:42:12 2015 +0000
Revision:
1:0c31d9b30900
Parent:
0:db88c3af3803
Child:
2:8f01347859d0
[ FIX ] End Point was wrong in both macro and function definition

Who changed what in which revision?

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