Webcam Server.

Dependencies:   uvchost FatFileSystem mbed HTTPServer NetServicesMin

Committer:
va009039
Date:
Tue Aug 14 03:42:12 2012 +0000
Revision:
1:7a4f2c038803
Parent:
0:2b4ea8a138e5
supported LogitechC270 and Safari

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:2b4ea8a138e5 1 #include "msc.h"
va009039 0:2b4ea8a138e5 2 //#define __DEBUG
va009039 0:2b4ea8a138e5 3 #include "mydbg.h"
va009039 0:2b4ea8a138e5 4 #include "Utils.h"
va009039 0:2b4ea8a138e5 5
va009039 0:2b4ea8a138e5 6 //#define WRITE_PROTECT
va009039 0:2b4ea8a138e5 7
va009039 0:2b4ea8a138e5 8 msc::msc(const char* name, int drive): FATFileSystem(name)
va009039 0:2b4ea8a138e5 9 {
va009039 0:2b4ea8a138e5 10 DBG("drive=%d\n", drive);
va009039 0:2b4ea8a138e5 11 m_name = name;
va009039 0:2b4ea8a138e5 12 m_drive = drive;
va009039 0:2b4ea8a138e5 13 DBG_ASSERT(sizeof(CBW) == 31);
va009039 0:2b4ea8a138e5 14 DBG_ASSERT(sizeof(CSW) == 13);
va009039 0:2b4ea8a138e5 15 m_numBlocks = 0;
va009039 0:2b4ea8a138e5 16 m_BlockSize = 0;
va009039 0:2b4ea8a138e5 17 m_lun = 0;
va009039 0:2b4ea8a138e5 18 m_interface = 0;
va009039 0:2b4ea8a138e5 19 m_pDev = NULL;
va009039 0:2b4ea8a138e5 20 m_pEpBulkIn = NULL;
va009039 0:2b4ea8a138e5 21 m_pEpBulkOut = NULL;
va009039 0:2b4ea8a138e5 22 }
va009039 0:2b4ea8a138e5 23
va009039 0:2b4ea8a138e5 24 int msc::disk_initialize()
va009039 0:2b4ea8a138e5 25 {
va009039 0:2b4ea8a138e5 26 DBG("m_BlockSize=%d\n", m_BlockSize);
va009039 0:2b4ea8a138e5 27 if (m_BlockSize != 512) {
va009039 0:2b4ea8a138e5 28 return 1;
va009039 0:2b4ea8a138e5 29 }
va009039 0:2b4ea8a138e5 30 return 0;
va009039 0:2b4ea8a138e5 31 }
va009039 0:2b4ea8a138e5 32
va009039 0:2b4ea8a138e5 33 int msc::disk_write(const char *buffer, int block_number)
va009039 0:2b4ea8a138e5 34 {
va009039 0:2b4ea8a138e5 35 DBG("buffer=%p block_number=%d\n", buffer, block_number);
va009039 0:2b4ea8a138e5 36 int ret = MS_BulkSend(block_number, 1, (uint8_t*)buffer);
va009039 0:2b4ea8a138e5 37 if (ret >= 0) {
va009039 0:2b4ea8a138e5 38 return 0;
va009039 0:2b4ea8a138e5 39 }
va009039 0:2b4ea8a138e5 40 return 1;
va009039 0:2b4ea8a138e5 41 }
va009039 0:2b4ea8a138e5 42
va009039 0:2b4ea8a138e5 43 int msc::disk_read(char *buffer, int block_number)
va009039 0:2b4ea8a138e5 44 {
va009039 0:2b4ea8a138e5 45 DBG("buffer=%p block_number=%d\n", buffer, block_number);
va009039 0:2b4ea8a138e5 46 int ret = MS_BulkRecv(block_number, 1, (uint8_t*)buffer);
va009039 0:2b4ea8a138e5 47 if (ret >= 0) {
va009039 0:2b4ea8a138e5 48 return 0;
va009039 0:2b4ea8a138e5 49 }
va009039 0:2b4ea8a138e5 50 return 1;
va009039 0:2b4ea8a138e5 51 }
va009039 0:2b4ea8a138e5 52
va009039 0:2b4ea8a138e5 53 int msc::disk_status()
va009039 0:2b4ea8a138e5 54 {
va009039 0:2b4ea8a138e5 55 DBG("\n");
va009039 0:2b4ea8a138e5 56 return 0;
va009039 0:2b4ea8a138e5 57 }
va009039 0:2b4ea8a138e5 58
va009039 0:2b4ea8a138e5 59 int msc::disk_sync()
va009039 0:2b4ea8a138e5 60 {
va009039 0:2b4ea8a138e5 61 DBG("\n");
va009039 0:2b4ea8a138e5 62 return 0;
va009039 0:2b4ea8a138e5 63 }
va009039 0:2b4ea8a138e5 64
va009039 0:2b4ea8a138e5 65 int msc::disk_sectors()
va009039 0:2b4ea8a138e5 66 {
va009039 0:2b4ea8a138e5 67 DBG("m_numBlocks=%d\n", m_numBlocks);
va009039 0:2b4ea8a138e5 68 return m_numBlocks;
va009039 0:2b4ea8a138e5 69 }
va009039 0:2b4ea8a138e5 70
va009039 0:2b4ea8a138e5 71 int msc::setup(int timeout)
va009039 0:2b4ea8a138e5 72 {
va009039 0:2b4ea8a138e5 73 for(int i = 0; i < 2; i++) {
va009039 0:2b4ea8a138e5 74 m_pDev = m_pHost->getDeviceByClass(0x08, m_drive); // USB Mass Storage Class
va009039 0:2b4ea8a138e5 75 if (m_pDev || i > 0) {
va009039 0:2b4ea8a138e5 76 break;
va009039 0:2b4ea8a138e5 77 }
va009039 0:2b4ea8a138e5 78 UsbErr rc = Usb_poll();
va009039 0:2b4ea8a138e5 79 if (rc == USBERR_PROCESSING) {
va009039 0:2b4ea8a138e5 80 VERBOSE("%p USBERR_PROCESSING\n", this);
va009039 0:2b4ea8a138e5 81 return -1;
va009039 0:2b4ea8a138e5 82 }
va009039 0:2b4ea8a138e5 83 }
va009039 0:2b4ea8a138e5 84 DBG("m_pDev=%p\n", m_pDev);
va009039 0:2b4ea8a138e5 85 if (m_pDev == NULL) {
va009039 0:2b4ea8a138e5 86 VERBOSE("%p MSC DISK(%d) NOT FOUND\n", this, m_drive);
va009039 0:2b4ea8a138e5 87 return -1;
va009039 0:2b4ea8a138e5 88 }
va009039 0:2b4ea8a138e5 89 DBG_ASSERT(m_pDev);
va009039 0:2b4ea8a138e5 90
va009039 0:2b4ea8a138e5 91 ParseConfiguration();
va009039 0:2b4ea8a138e5 92
va009039 0:2b4ea8a138e5 93 GetMaxLUN();
va009039 0:2b4ea8a138e5 94
va009039 0:2b4ea8a138e5 95 int retry = 0;
va009039 0:2b4ea8a138e5 96 Timer t;
va009039 0:2b4ea8a138e5 97 t.start();
va009039 0:2b4ea8a138e5 98 t.reset();
va009039 0:2b4ea8a138e5 99 while(t.read_ms() < timeout) {
va009039 0:2b4ea8a138e5 100 DBG("retry=%d t=%d\n", retry, t.read_ms());
va009039 0:2b4ea8a138e5 101 if (retry > 80) {
va009039 0:2b4ea8a138e5 102 return -1;
va009039 0:2b4ea8a138e5 103 }
va009039 0:2b4ea8a138e5 104 int rc = TestUnitReady();
va009039 0:2b4ea8a138e5 105 DBG("TestUnitReady(): %d\n", rc);
va009039 0:2b4ea8a138e5 106 if (rc == USBERR_OK) {
va009039 0:2b4ea8a138e5 107 DBG("m_CSW.bCSWStatus: %02X\n", m_CSW.bCSWStatus);
va009039 0:2b4ea8a138e5 108 if (m_CSW.bCSWStatus == 0x00) {
va009039 0:2b4ea8a138e5 109 break;
va009039 0:2b4ea8a138e5 110 }
va009039 0:2b4ea8a138e5 111 }
va009039 0:2b4ea8a138e5 112 GetSenseInfo();
va009039 0:2b4ea8a138e5 113 retry++;
va009039 0:2b4ea8a138e5 114 wait_ms(50);
va009039 0:2b4ea8a138e5 115 }
va009039 0:2b4ea8a138e5 116 if (t.read_ms() >= timeout) {
va009039 0:2b4ea8a138e5 117 return -1;
va009039 0:2b4ea8a138e5 118 }
va009039 0:2b4ea8a138e5 119 ReadCapacity();
va009039 0:2b4ea8a138e5 120 Inquire();
va009039 0:2b4ea8a138e5 121 return 0;
va009039 0:2b4ea8a138e5 122 }
va009039 0:2b4ea8a138e5 123 void msc::_test()
va009039 0:2b4ea8a138e5 124 {
va009039 0:2b4ea8a138e5 125 ReadCapacity();
va009039 0:2b4ea8a138e5 126
va009039 0:2b4ea8a138e5 127 char buf[512];
va009039 0:2b4ea8a138e5 128 for(int block = 0; block < m_numBlocks; block++) {
va009039 0:2b4ea8a138e5 129 DBG("block=%d\n", block);
va009039 0:2b4ea8a138e5 130 disk_read(buf, block);
va009039 0:2b4ea8a138e5 131 }
va009039 0:2b4ea8a138e5 132 exit(1);
va009039 0:2b4ea8a138e5 133 }
va009039 0:2b4ea8a138e5 134
va009039 0:2b4ea8a138e5 135 int msc::ParseConfiguration()
va009039 0:2b4ea8a138e5 136 {
va009039 0:2b4ea8a138e5 137 UsbErr rc;
va009039 0:2b4ea8a138e5 138 uint8_t ConfigDesc[9];
va009039 0:2b4ea8a138e5 139 int index = 0;
va009039 0:2b4ea8a138e5 140 DBG_ASSERT(m_pDev);
va009039 0:2b4ea8a138e5 141 rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, ConfigDesc, sizeof(ConfigDesc));
va009039 0:2b4ea8a138e5 142 DBG_ASSERT(rc == USBERR_OK);
va009039 0:2b4ea8a138e5 143 DBG_BYTES("ConfigDescriptor 9bytes", ConfigDesc, sizeof(ConfigDesc));
va009039 0:2b4ea8a138e5 144 DBG_ASSERT(ConfigDesc[0] == 9);
va009039 0:2b4ea8a138e5 145 DBG_ASSERT(ConfigDesc[1] == 0x02);
va009039 0:2b4ea8a138e5 146 int wTotalLength = *((uint16_t*)&ConfigDesc[2]);
va009039 0:2b4ea8a138e5 147 DBG("TotalLength: %d\n", wTotalLength);
va009039 0:2b4ea8a138e5 148 int bConfigValue = ConfigDesc[5];
va009039 0:2b4ea8a138e5 149 DBG_ASSERT(bConfigValue == 1);
va009039 0:2b4ea8a138e5 150 DBG("ConfigValue: %d\n", bConfigValue);
va009039 0:2b4ea8a138e5 151 DBG("MaxPower: %d mA\n", ConfigDesc[8]*2);
va009039 0:2b4ea8a138e5 152
va009039 0:2b4ea8a138e5 153 uint8_t* buf = new uint8_t[wTotalLength];
va009039 0:2b4ea8a138e5 154 DBG_ASSERT(buf);
va009039 0:2b4ea8a138e5 155 rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength);
va009039 0:2b4ea8a138e5 156 DBG_ASSERT(rc == USBERR_OK);
va009039 0:2b4ea8a138e5 157 DBG_ASSERT(ConfigDesc[1] == 0x02);
va009039 0:2b4ea8a138e5 158 for (int pos = 0; pos < wTotalLength; pos += buf[pos]) {
va009039 0:2b4ea8a138e5 159 DBG_BYTES("CFG", buf+pos, buf[pos]);
va009039 0:2b4ea8a138e5 160 int type = buf[pos+1];
va009039 0:2b4ea8a138e5 161 if (USB_DESCRIPTOR_TYPE_INTERFACE == type) { // 0x04
va009039 0:2b4ea8a138e5 162 DBG("InterfaceNumber: %d\n", buf[pos+2]);
va009039 0:2b4ea8a138e5 163 DBG("AlternateSetting: %d\n", buf[pos+3]);
va009039 0:2b4ea8a138e5 164 DBG("NumEndpoint: %d\n", buf[pos+4]);
va009039 0:2b4ea8a138e5 165 DBG("InterfaceClass: %02X\n", buf[pos+5]);
va009039 0:2b4ea8a138e5 166 DBG("InterfaceSubClass: %02X\n", buf[pos+6]);
va009039 0:2b4ea8a138e5 167 DBG("InterfaceProtocol: %02X\n", buf[pos+7]);
va009039 0:2b4ea8a138e5 168 DBG_ASSERT(buf[pos+6] == 0x06); // SCSI
va009039 0:2b4ea8a138e5 169 DBG_ASSERT(buf[pos+7] == 0x50); // bulk only
va009039 0:2b4ea8a138e5 170 }
va009039 0:2b4ea8a138e5 171 if (USB_DESCRIPTOR_TYPE_ENDPOINT == type) {
va009039 0:2b4ea8a138e5 172 DBG_ASSERT(buf[pos] == 7);
va009039 0:2b4ea8a138e5 173 uint8_t att = buf[pos+3];
va009039 0:2b4ea8a138e5 174 if (att == 2) { // bulk
va009039 0:2b4ea8a138e5 175 uint8_t ep = buf[pos+2];
va009039 0:2b4ea8a138e5 176 bool dir = ep & 0x80; // true=IN
va009039 0:2b4ea8a138e5 177 uint16_t size = LE16(buf+pos+4);
va009039 0:2b4ea8a138e5 178 DBG("EndpointAddress: %02X\n", ep);
va009039 0:2b4ea8a138e5 179 DBG("Attribute: %02X\n", att);
va009039 0:2b4ea8a138e5 180 DBG("MaxPacketSize: %d\n", size);
va009039 0:2b4ea8a138e5 181 UsbEndpoint* pEp = new UsbEndpoint(m_pDev, ep, dir, USB_BULK, size);
va009039 0:2b4ea8a138e5 182 DBG_ASSERT(pEp);
va009039 0:2b4ea8a138e5 183 if (dir) {
va009039 0:2b4ea8a138e5 184 m_pEpBulkIn = pEp;
va009039 0:2b4ea8a138e5 185 } else {
va009039 0:2b4ea8a138e5 186 m_pEpBulkOut = pEp;
va009039 0:2b4ea8a138e5 187 }
va009039 0:2b4ea8a138e5 188 }
va009039 0:2b4ea8a138e5 189 }
va009039 0:2b4ea8a138e5 190 }
va009039 0:2b4ea8a138e5 191 delete[] buf;
va009039 0:2b4ea8a138e5 192 DBG_ASSERT(m_pEpBulkIn);
va009039 0:2b4ea8a138e5 193 DBG_ASSERT(m_pEpBulkOut);
va009039 0:2b4ea8a138e5 194 return 0;
va009039 0:2b4ea8a138e5 195 }
va009039 0:2b4ea8a138e5 196
va009039 0:2b4ea8a138e5 197 int msc::BulkOnlyMassStorageReset()
va009039 0:2b4ea8a138e5 198 {
va009039 0:2b4ea8a138e5 199 DBG_ASSERT(m_pDev);
va009039 0:2b4ea8a138e5 200 UsbErr rc = m_pDev->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0);
va009039 0:2b4ea8a138e5 201 DBG_ASSERT(rc == USBERR_OK);
va009039 0:2b4ea8a138e5 202 return rc;
va009039 0:2b4ea8a138e5 203 }
va009039 0:2b4ea8a138e5 204
va009039 0:2b4ea8a138e5 205 int msc::GetMaxLUN()
va009039 0:2b4ea8a138e5 206 {
va009039 0:2b4ea8a138e5 207 DBG_ASSERT(m_interface == 0);
va009039 0:2b4ea8a138e5 208 uint8_t temp[1];
va009039 0:2b4ea8a138e5 209 DBG_ASSERT(m_pDev);
va009039 0:2b4ea8a138e5 210 UsbErr rc = m_pDev->controlReceive(0xa1, 0xfe, 0x0000, m_interface, temp, sizeof(temp));
va009039 0:2b4ea8a138e5 211 DBG_ASSERT(rc == USBERR_OK);
va009039 0:2b4ea8a138e5 212 DBG_BYTES("GetMaxLUN", temp, sizeof(temp));
va009039 0:2b4ea8a138e5 213 m_MaxLUN = temp[0];
va009039 0:2b4ea8a138e5 214 DBG_ASSERT(m_MaxLUN <= 15);
va009039 0:2b4ea8a138e5 215 return rc;
va009039 0:2b4ea8a138e5 216 }
va009039 0:2b4ea8a138e5 217
va009039 0:2b4ea8a138e5 218
va009039 0:2b4ea8a138e5 219 int msc::TestUnitReady()
va009039 0:2b4ea8a138e5 220 {
va009039 0:2b4ea8a138e5 221 const uint8_t cdb[6] = {SCSI_CMD_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00};
va009039 0:2b4ea8a138e5 222 m_CBW.dCBWDataTraansferLength = 0;
va009039 0:2b4ea8a138e5 223 m_CBW.bmCBWFlags = 0x00;
va009039 0:2b4ea8a138e5 224 CommandTransport(cdb, sizeof(cdb));
va009039 0:2b4ea8a138e5 225 StatusTransport();
va009039 0:2b4ea8a138e5 226 return 0;
va009039 0:2b4ea8a138e5 227 }
va009039 0:2b4ea8a138e5 228
va009039 0:2b4ea8a138e5 229 int msc::GetSenseInfo()
va009039 0:2b4ea8a138e5 230 {
va009039 0:2b4ea8a138e5 231 const uint8_t cdb[6] = {SCSI_CMD_REQUEST_SENSE, 0x00, 0x00, 0x00, 18, 0x00};
va009039 0:2b4ea8a138e5 232 m_CBW.dCBWDataTraansferLength = 18;
va009039 0:2b4ea8a138e5 233 m_CBW.bmCBWFlags = 0x80; // data In
va009039 0:2b4ea8a138e5 234 CommandTransport(cdb, sizeof(cdb));
va009039 0:2b4ea8a138e5 235
va009039 0:2b4ea8a138e5 236 uint8_t buf[18];
va009039 0:2b4ea8a138e5 237 _bulkRecv(buf, sizeof(buf));
va009039 0:2b4ea8a138e5 238 DBG_HEX(buf, sizeof(buf));
va009039 0:2b4ea8a138e5 239
va009039 0:2b4ea8a138e5 240 StatusTransport();
va009039 0:2b4ea8a138e5 241 DBG_ASSERT(m_CSW.bCSWStatus == 0x00);
va009039 0:2b4ea8a138e5 242 return 0;
va009039 0:2b4ea8a138e5 243 }
va009039 0:2b4ea8a138e5 244
va009039 0:2b4ea8a138e5 245 int msc::ReadCapacity()
va009039 0:2b4ea8a138e5 246 {
va009039 0:2b4ea8a138e5 247 const uint8_t cdb[10] = {SCSI_CMD_READ_CAPACITY, 0x00, 0x00, 0x00, 0x00,
va009039 0:2b4ea8a138e5 248 0x00, 0x00, 0x00, 0x00, 0x00};
va009039 0:2b4ea8a138e5 249 m_CBW.dCBWDataTraansferLength = 8;
va009039 0:2b4ea8a138e5 250 m_CBW.bmCBWFlags = 0x80; // data In
va009039 0:2b4ea8a138e5 251 CommandTransport(cdb, sizeof(cdb));
va009039 0:2b4ea8a138e5 252
va009039 0:2b4ea8a138e5 253 uint8_t buf[8];
va009039 0:2b4ea8a138e5 254 int rc = _bulkRecv(buf, sizeof(buf));
va009039 0:2b4ea8a138e5 255 DBG_ASSERT(rc >= 0);
va009039 0:2b4ea8a138e5 256 DBG_HEX(buf, sizeof(buf));
va009039 0:2b4ea8a138e5 257
va009039 0:2b4ea8a138e5 258 StatusTransport();
va009039 0:2b4ea8a138e5 259 DBG_ASSERT(m_CSW.bCSWStatus == 0x00);
va009039 0:2b4ea8a138e5 260
va009039 0:2b4ea8a138e5 261 m_numBlocks = BE32(buf);
va009039 0:2b4ea8a138e5 262 m_BlockSize = BE32(buf+4);
va009039 0:2b4ea8a138e5 263 DBG("m_numBlocks=%d m_BlockSize=%d\n", m_numBlocks, m_BlockSize);
va009039 0:2b4ea8a138e5 264 DBG_ASSERT(m_BlockSize == 512);
va009039 0:2b4ea8a138e5 265 DBG_ASSERT(m_numBlocks > 0);
va009039 0:2b4ea8a138e5 266 return 0;
va009039 0:2b4ea8a138e5 267 }
va009039 0:2b4ea8a138e5 268
va009039 0:2b4ea8a138e5 269 int msc::Inquire()
va009039 0:2b4ea8a138e5 270 {
va009039 0:2b4ea8a138e5 271 const uint8_t cdb[6] = {SCSI_CMD_INQUIRY, 0x00, 0x00, 0x00, 36, 0x00};
va009039 0:2b4ea8a138e5 272 m_CBW.dCBWDataTraansferLength = 36;
va009039 0:2b4ea8a138e5 273 m_CBW.bmCBWFlags = 0x80; // data In
va009039 0:2b4ea8a138e5 274 CommandTransport(cdb, sizeof(cdb));
va009039 0:2b4ea8a138e5 275
va009039 0:2b4ea8a138e5 276 uint8_t buf[36];
va009039 0:2b4ea8a138e5 277 _bulkRecv(buf, sizeof(buf));
va009039 0:2b4ea8a138e5 278 DBG_HEX(buf, sizeof(buf));
va009039 0:2b4ea8a138e5 279
va009039 0:2b4ea8a138e5 280 StatusTransport();
va009039 0:2b4ea8a138e5 281 return 0;
va009039 0:2b4ea8a138e5 282 }
va009039 0:2b4ea8a138e5 283
va009039 0:2b4ea8a138e5 284 int msc::MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer)
va009039 0:2b4ea8a138e5 285 {
va009039 0:2b4ea8a138e5 286 DBG_ASSERT(m_BlockSize == 512);
va009039 0:2b4ea8a138e5 287 DBG_ASSERT(num_blocks == 1);
va009039 0:2b4ea8a138e5 288 DBG_ASSERT(user_buffer);
va009039 0:2b4ea8a138e5 289 uint8_t cdb[10] = {SCSI_CMD_READ_10, 0x00, 0x00, 0x00, 0x00,
va009039 0:2b4ea8a138e5 290 0x00, 0x00, 0x00, 0x00, 0x00};
va009039 0:2b4ea8a138e5 291 BE32(block_number, cdb+2);
va009039 0:2b4ea8a138e5 292 BE16(num_blocks, cdb+7);
va009039 0:2b4ea8a138e5 293 uint32_t len = m_BlockSize * num_blocks;
va009039 0:2b4ea8a138e5 294 DBG_ASSERT(len <= 512);
va009039 0:2b4ea8a138e5 295 m_CBW.dCBWDataTraansferLength = len;
va009039 0:2b4ea8a138e5 296 m_CBW.bmCBWFlags = 0x80; // data In
va009039 0:2b4ea8a138e5 297 CommandTransport(cdb, sizeof(cdb));
va009039 0:2b4ea8a138e5 298
va009039 0:2b4ea8a138e5 299 int ret = _bulkRecv(user_buffer, len);
va009039 0:2b4ea8a138e5 300 //DBG_HEX(user_buffer, len);
va009039 0:2b4ea8a138e5 301
va009039 0:2b4ea8a138e5 302 StatusTransport();
va009039 0:2b4ea8a138e5 303 DBG_ASSERT(m_CSW.bCSWStatus == 0x00);
va009039 0:2b4ea8a138e5 304 return ret;
va009039 0:2b4ea8a138e5 305 }
va009039 0:2b4ea8a138e5 306
va009039 0:2b4ea8a138e5 307 int msc::MS_BulkSend(uint32_t block_number, int num_blocks, uint8_t* user_buffer)
va009039 0:2b4ea8a138e5 308 {
va009039 0:2b4ea8a138e5 309 #ifdef WRITE_PROTECT
va009039 0:2b4ea8a138e5 310 return 0;
va009039 0:2b4ea8a138e5 311 #else
va009039 0:2b4ea8a138e5 312 DBG_ASSERT(num_blocks == 1);
va009039 0:2b4ea8a138e5 313 DBG_ASSERT(user_buffer);
va009039 0:2b4ea8a138e5 314 uint8_t cdb[10] = {SCSI_CMD_WRITE_10, 0x00, 0x00, 0x00, 0x00,
va009039 0:2b4ea8a138e5 315 0x00, 0x00, 0x00, 0x00, 0x00};
va009039 0:2b4ea8a138e5 316 BE32(block_number, cdb+2);
va009039 0:2b4ea8a138e5 317 BE16(num_blocks, cdb+7);
va009039 0:2b4ea8a138e5 318 uint32_t len = m_BlockSize * num_blocks;
va009039 0:2b4ea8a138e5 319 DBG_ASSERT(len <= 512);
va009039 0:2b4ea8a138e5 320 m_CBW.dCBWDataTraansferLength = len;
va009039 0:2b4ea8a138e5 321 m_CBW.bmCBWFlags = 0x00; // data Out
va009039 0:2b4ea8a138e5 322 CommandTransport(cdb, sizeof(cdb));
va009039 0:2b4ea8a138e5 323
va009039 0:2b4ea8a138e5 324 int ret = _bulkSend(user_buffer, len);
va009039 0:2b4ea8a138e5 325 //DBG_HEX(user_buffer, len);
va009039 0:2b4ea8a138e5 326
va009039 0:2b4ea8a138e5 327 StatusTransport();
va009039 0:2b4ea8a138e5 328 DBG_ASSERT(m_CSW.bCSWStatus == 0x00);
va009039 0:2b4ea8a138e5 329 return ret;
va009039 0:2b4ea8a138e5 330 #endif //WRITE_PROTECT
va009039 0:2b4ea8a138e5 331 }
va009039 0:2b4ea8a138e5 332
va009039 0:2b4ea8a138e5 333 int msc::CommandTransport(const uint8_t* cdb, int size)
va009039 0:2b4ea8a138e5 334 {
va009039 0:2b4ea8a138e5 335 DBG_ASSERT(cdb);
va009039 0:2b4ea8a138e5 336 DBG_ASSERT(size >= 6);
va009039 0:2b4ea8a138e5 337 DBG_ASSERT(size <= 16);
va009039 0:2b4ea8a138e5 338 m_CBW.bCBWLUN = m_lun;
va009039 0:2b4ea8a138e5 339 m_CBW.bCBWCBLength = size;
va009039 0:2b4ea8a138e5 340 memcpy(m_CBW.CBWCB, cdb, size);
va009039 0:2b4ea8a138e5 341
va009039 0:2b4ea8a138e5 342 m_CBW.dCBWSignature = 0x43425355;
va009039 0:2b4ea8a138e5 343 m_CBW.dCBWTag = m_tag++;
va009039 0:2b4ea8a138e5 344 m_CBW.bCBWLUN = 0;
va009039 0:2b4ea8a138e5 345 //DBG_HEX((uint8_t*)&m_CBW, sizeof(CBW));
va009039 0:2b4ea8a138e5 346 int rc = _bulkSend((uint8_t*)&m_CBW, sizeof(CBW));
va009039 0:2b4ea8a138e5 347 return rc;
va009039 0:2b4ea8a138e5 348 }
va009039 0:2b4ea8a138e5 349
va009039 0:2b4ea8a138e5 350 int msc::StatusTransport()
va009039 0:2b4ea8a138e5 351 {
va009039 0:2b4ea8a138e5 352 DBG_ASSERT(sizeof(CSW) == 13);
va009039 0:2b4ea8a138e5 353 int rc = _bulkRecv((uint8_t*)&m_CSW, sizeof(CSW));
va009039 0:2b4ea8a138e5 354 //DBG_HEX((uint8_t*)&m_CSW, sizeof(CSW));
va009039 0:2b4ea8a138e5 355 DBG_ASSERT(m_CSW.dCSWSignature == 0x53425355);
va009039 0:2b4ea8a138e5 356 DBG_ASSERT(m_CSW.dCSWTag == m_CBW.dCBWTag);
va009039 0:2b4ea8a138e5 357 DBG_ASSERT(m_CSW.dCSWDataResidue == 0);
va009039 0:2b4ea8a138e5 358 return rc;
va009039 0:2b4ea8a138e5 359 }
va009039 0:2b4ea8a138e5 360
va009039 0:2b4ea8a138e5 361 int msc::_bulkRecv(uint8_t* buf, int size)
va009039 0:2b4ea8a138e5 362 {
va009039 0:2b4ea8a138e5 363 UsbErr rc = m_pEpBulkIn->transfer(buf, size);
va009039 0:2b4ea8a138e5 364 DBG_ASSERT(rc == USBERR_PROCESSING);
va009039 0:2b4ea8a138e5 365 while(m_pEpBulkIn->status() == USBERR_PROCESSING){
va009039 0:2b4ea8a138e5 366 wait_us(1);
va009039 0:2b4ea8a138e5 367 }
va009039 0:2b4ea8a138e5 368 int ret = m_pEpBulkIn->status();
va009039 0:2b4ea8a138e5 369 if (ret >= 0) {
va009039 0:2b4ea8a138e5 370 return ret;
va009039 0:2b4ea8a138e5 371 }
va009039 0:2b4ea8a138e5 372 DBG("buf=%p size=%d ret=%d\n", buf, size, ret);
va009039 0:2b4ea8a138e5 373 return ret;
va009039 0:2b4ea8a138e5 374 }
va009039 0:2b4ea8a138e5 375
va009039 0:2b4ea8a138e5 376 int msc::_bulkSend(uint8_t* buf, int size)
va009039 0:2b4ea8a138e5 377 {
va009039 0:2b4ea8a138e5 378 DBG_ASSERT(m_pEpBulkOut);
va009039 0:2b4ea8a138e5 379 UsbErr rc = m_pEpBulkOut->transfer(buf, size);
va009039 0:2b4ea8a138e5 380 DBG_ASSERT(rc == USBERR_PROCESSING);
va009039 0:2b4ea8a138e5 381 while(m_pEpBulkOut->status() == USBERR_PROCESSING){
va009039 0:2b4ea8a138e5 382 wait_us(1);
va009039 0:2b4ea8a138e5 383 }
va009039 0:2b4ea8a138e5 384 int ret = m_pEpBulkOut->status();
va009039 0:2b4ea8a138e5 385 if (ret >= 0) {
va009039 0:2b4ea8a138e5 386 return ret;
va009039 0:2b4ea8a138e5 387 }
va009039 0:2b4ea8a138e5 388 DBG("buf=%p size=%d ret=%d\n", buf, size, ret);
va009039 0:2b4ea8a138e5 389 return ret;
va009039 0:2b4ea8a138e5 390 }