convert JPEG stream data to bitmap, BaseJpegDecode example program
Dependencies: BaseJpegDecode BaseUsbHost FATFileSystem mbed-rtos mbed
JPEGデコードのサンプルプログラムです。
JPEGのMCU単位で逐次デコード出力していますので少ないRAMメモリで動かすことが出来ます。
#include "USBHostMSD.h" #include "SimpleJpegDecode.h" #include "bmp24.h" const char* INPUT_FILE = "/usb/input.jpg"; const char* OUTPUT_FILE = "/usb/output.bmp"; bmp24 bmp; RawSerial pc(USBTX, USBRX); void callbackRGB(int x, int y, uint8_t* rgb) { bmp.point(x, y, rgb); pc.printf("x=%d, y=%d, RGB=(0x%02x,0x%02x,0x%02x)\n", x, y, rgb[0], rgb[1], rgb[2]); } int main() { pc.baud(115200); USBHostMSD* msd = new USBHostMSD("usb"); if (!msd->connect()) { error("USB Flash drive not found.\n"); } SimpleJpegDecode* decode = new SimpleJpegDecode(RGB24); decode->setOnResult(callbackRGB); decode->clear(); pc.printf("input: %s\n", INPUT_FILE); FILE* fp = fopen(INPUT_FILE, "rb"); if (fp == NULL) { error("open error\n"); } while(1) { int c = fgetc(fp); if (c == EOF) { break; } decode->input(c); } fclose(fp); pc.printf("output: %s\n", OUTPUT_FILE); if (!bmp.writeFile(OUTPUT_FILE)) { error("write error\n"); } exit(1); }
UsbFlashDrive/UsbFlashDrive.cpp@0:98f918e1d528, 2013-02-02 (annotated)
- Committer:
- va009039
- Date:
- Sat Feb 02 01:25:25 2013 +0000
- Revision:
- 0:98f918e1d528
first commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 0:98f918e1d528 | 1 | // UsbFlashDrive.cpp 2013/1/25 |
va009039 | 0:98f918e1d528 | 2 | #include "mbed.h" |
va009039 | 0:98f918e1d528 | 3 | #include "rtos.h" |
va009039 | 0:98f918e1d528 | 4 | #include "BaseUsbHost.h" |
va009039 | 0:98f918e1d528 | 5 | //#define DEBUG |
va009039 | 0:98f918e1d528 | 6 | #include "BaseUsbHostDebug.h" |
va009039 | 0:98f918e1d528 | 7 | #define TEST |
va009039 | 0:98f918e1d528 | 8 | #include "BaseUsbHostTest.h" |
va009039 | 0:98f918e1d528 | 9 | #include "UsbFlashDrive.h" |
va009039 | 0:98f918e1d528 | 10 | |
va009039 | 0:98f918e1d528 | 11 | //#define WRITE_PROTECT |
va009039 | 0:98f918e1d528 | 12 | |
va009039 | 0:98f918e1d528 | 13 | |
va009039 | 0:98f918e1d528 | 14 | uint32_t BE32(uint8_t* d) |
va009039 | 0:98f918e1d528 | 15 | { |
va009039 | 0:98f918e1d528 | 16 | return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3]; |
va009039 | 0:98f918e1d528 | 17 | } |
va009039 | 0:98f918e1d528 | 18 | |
va009039 | 0:98f918e1d528 | 19 | void BE16(uint32_t n, uint8_t* d) |
va009039 | 0:98f918e1d528 | 20 | { |
va009039 | 0:98f918e1d528 | 21 | d[0] = (uint8_t)(n >> 8); |
va009039 | 0:98f918e1d528 | 22 | d[1] = (uint8_t)n; |
va009039 | 0:98f918e1d528 | 23 | } |
va009039 | 0:98f918e1d528 | 24 | |
va009039 | 0:98f918e1d528 | 25 | void BE32(uint32_t n, uint8_t* d) |
va009039 | 0:98f918e1d528 | 26 | { |
va009039 | 0:98f918e1d528 | 27 | d[0] = (uint8_t)(n >> 24); |
va009039 | 0:98f918e1d528 | 28 | d[1] = (uint8_t)(n >> 16); |
va009039 | 0:98f918e1d528 | 29 | d[2] = (uint8_t)(n >> 8); |
va009039 | 0:98f918e1d528 | 30 | d[3] = (uint8_t)n; |
va009039 | 0:98f918e1d528 | 31 | } |
va009039 | 0:98f918e1d528 | 32 | |
va009039 | 0:98f918e1d528 | 33 | UsbFlashDrive::UsbFlashDrive(const char* name, ControlEp* ctlEp): FATFileSystem(name) |
va009039 | 0:98f918e1d528 | 34 | { |
va009039 | 0:98f918e1d528 | 35 | m_name = name; |
va009039 | 0:98f918e1d528 | 36 | |
va009039 | 0:98f918e1d528 | 37 | if (ctlEp == NULL) { // root hub |
va009039 | 0:98f918e1d528 | 38 | DBG_OHCI(LPC_USB->HcRhPortStatus1); |
va009039 | 0:98f918e1d528 | 39 | TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200); |
va009039 | 0:98f918e1d528 | 40 | ctlEp = new ControlEp(); |
va009039 | 0:98f918e1d528 | 41 | TEST_ASSERT_TRUE(ctlEp); |
va009039 | 0:98f918e1d528 | 42 | } |
va009039 | 0:98f918e1d528 | 43 | |
va009039 | 0:98f918e1d528 | 44 | CTASSERT(sizeof(CBW) == 31); |
va009039 | 0:98f918e1d528 | 45 | CTASSERT(sizeof(CSW) == 13); |
va009039 | 0:98f918e1d528 | 46 | TEST_ASSERT(sizeof(CBW) == 31); |
va009039 | 0:98f918e1d528 | 47 | TEST_ASSERT(sizeof(CSW) == 13); |
va009039 | 0:98f918e1d528 | 48 | |
va009039 | 0:98f918e1d528 | 49 | m_numBlocks = 0; |
va009039 | 0:98f918e1d528 | 50 | m_BlockSize = 0; |
va009039 | 0:98f918e1d528 | 51 | m_lun = 0; |
va009039 | 0:98f918e1d528 | 52 | m_interface = 0; |
va009039 | 0:98f918e1d528 | 53 | m_pEpBulkIn = NULL; |
va009039 | 0:98f918e1d528 | 54 | m_pEpBulkOut = NULL; |
va009039 | 0:98f918e1d528 | 55 | |
va009039 | 0:98f918e1d528 | 56 | ParseConfiguration(ctlEp); |
va009039 | 0:98f918e1d528 | 57 | int rc = ctlEp->SetConfiguration(1); |
va009039 | 0:98f918e1d528 | 58 | TEST_ASSERT_EQUAL(rc, USB_OK); |
va009039 | 0:98f918e1d528 | 59 | GetMaxLUN(ctlEp); |
va009039 | 0:98f918e1d528 | 60 | setup(ctlEp); |
va009039 | 0:98f918e1d528 | 61 | } |
va009039 | 0:98f918e1d528 | 62 | |
va009039 | 0:98f918e1d528 | 63 | bool UsbFlashDrive::check(ControlEp* ctlEp) |
va009039 | 0:98f918e1d528 | 64 | { |
va009039 | 0:98f918e1d528 | 65 | if (ctlEp == NULL) { |
va009039 | 0:98f918e1d528 | 66 | return false; |
va009039 | 0:98f918e1d528 | 67 | } |
va009039 | 0:98f918e1d528 | 68 | CTASSERT(sizeof(StandardDeviceDescriptor) == 18); |
va009039 | 0:98f918e1d528 | 69 | CTASSERT(sizeof(StandardConfigurationDescriptor) == 9); |
va009039 | 0:98f918e1d528 | 70 | CTASSERT(sizeof(StandardInterfaceDescriptor) == 9); |
va009039 | 0:98f918e1d528 | 71 | TEST_ASSERT(sizeof(StandardDeviceDescriptor) == 18); |
va009039 | 0:98f918e1d528 | 72 | TEST_ASSERT(sizeof(StandardConfigurationDescriptor) == 9); |
va009039 | 0:98f918e1d528 | 73 | TEST_ASSERT(sizeof(StandardInterfaceDescriptor) == 9); |
va009039 | 0:98f918e1d528 | 74 | |
va009039 | 0:98f918e1d528 | 75 | StandardDeviceDescriptor desc; |
va009039 | 0:98f918e1d528 | 76 | int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_DEVICE, 0, reinterpret_cast<uint8_t*>(&desc), sizeof(StandardDeviceDescriptor)); |
va009039 | 0:98f918e1d528 | 77 | if (rc != USB_OK) { |
va009039 | 0:98f918e1d528 | 78 | return false; |
va009039 | 0:98f918e1d528 | 79 | } |
va009039 | 0:98f918e1d528 | 80 | if (desc.bDeviceClass == 8) { |
va009039 | 0:98f918e1d528 | 81 | return true; |
va009039 | 0:98f918e1d528 | 82 | } else if (desc.bDeviceClass != 0x00) { |
va009039 | 0:98f918e1d528 | 83 | return false; |
va009039 | 0:98f918e1d528 | 84 | } |
va009039 | 0:98f918e1d528 | 85 | uint8_t temp[4]; |
va009039 | 0:98f918e1d528 | 86 | rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp)); |
va009039 | 0:98f918e1d528 | 87 | if (rc != USB_OK) { |
va009039 | 0:98f918e1d528 | 88 | return false; |
va009039 | 0:98f918e1d528 | 89 | } |
va009039 | 0:98f918e1d528 | 90 | StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp); |
va009039 | 0:98f918e1d528 | 91 | uint8_t* buf = new uint8_t[cfg->wTotalLength]; |
va009039 | 0:98f918e1d528 | 92 | |
va009039 | 0:98f918e1d528 | 93 | rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength); |
va009039 | 0:98f918e1d528 | 94 | if (rc != USB_OK) { |
va009039 | 0:98f918e1d528 | 95 | return false; |
va009039 | 0:98f918e1d528 | 96 | } |
va009039 | 0:98f918e1d528 | 97 | DBG_HEX(buf, cfg->wTotalLength); |
va009039 | 0:98f918e1d528 | 98 | bool ret = false; |
va009039 | 0:98f918e1d528 | 99 | for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) { |
va009039 | 0:98f918e1d528 | 100 | StandardInterfaceDescriptor* desc = reinterpret_cast<StandardInterfaceDescriptor*>(buf+pos); |
va009039 | 0:98f918e1d528 | 101 | if (desc->bDescriptorType == 4) { // interface ? |
va009039 | 0:98f918e1d528 | 102 | if (desc->bInterfaceClass == 8 && desc->bInterfaceSubClass == 6 && desc->bInterfaceProtocol == 0x50) { |
va009039 | 0:98f918e1d528 | 103 | ret = true; |
va009039 | 0:98f918e1d528 | 104 | } |
va009039 | 0:98f918e1d528 | 105 | break; |
va009039 | 0:98f918e1d528 | 106 | } |
va009039 | 0:98f918e1d528 | 107 | } |
va009039 | 0:98f918e1d528 | 108 | delete[] buf; |
va009039 | 0:98f918e1d528 | 109 | return ret; |
va009039 | 0:98f918e1d528 | 110 | } |
va009039 | 0:98f918e1d528 | 111 | |
va009039 | 0:98f918e1d528 | 112 | int UsbFlashDrive::disk_initialize() |
va009039 | 0:98f918e1d528 | 113 | { |
va009039 | 0:98f918e1d528 | 114 | //DBG("m_BlockSize=%d\n", m_BlockSize); |
va009039 | 0:98f918e1d528 | 115 | if (m_BlockSize != 512) { |
va009039 | 0:98f918e1d528 | 116 | return 1; |
va009039 | 0:98f918e1d528 | 117 | } |
va009039 | 0:98f918e1d528 | 118 | return 0; |
va009039 | 0:98f918e1d528 | 119 | } |
va009039 | 0:98f918e1d528 | 120 | |
va009039 | 0:98f918e1d528 | 121 | int UsbFlashDrive::disk_write(const uint8_t* buffer, uint64_t sector) |
va009039 | 0:98f918e1d528 | 122 | { |
va009039 | 0:98f918e1d528 | 123 | m_report_disk_write++; |
va009039 | 0:98f918e1d528 | 124 | //DBG("buffer=%p block_number=%d\n", buffer, sector); |
va009039 | 0:98f918e1d528 | 125 | int ret = MS_BulkSend(sector, 1, buffer); |
va009039 | 0:98f918e1d528 | 126 | if (ret >= 0) { |
va009039 | 0:98f918e1d528 | 127 | return 0; |
va009039 | 0:98f918e1d528 | 128 | } |
va009039 | 0:98f918e1d528 | 129 | return 1; |
va009039 | 0:98f918e1d528 | 130 | } |
va009039 | 0:98f918e1d528 | 131 | |
va009039 | 0:98f918e1d528 | 132 | int UsbFlashDrive::disk_read(uint8_t* buffer, uint64_t sector) |
va009039 | 0:98f918e1d528 | 133 | { |
va009039 | 0:98f918e1d528 | 134 | m_report_disk_read++; |
va009039 | 0:98f918e1d528 | 135 | //DBG("buffer=%p block_number=%d\n", buffer, sector); |
va009039 | 0:98f918e1d528 | 136 | int ret = MS_BulkRecv(sector, 1, buffer); |
va009039 | 0:98f918e1d528 | 137 | if (ret >= 0) { |
va009039 | 0:98f918e1d528 | 138 | return 0; |
va009039 | 0:98f918e1d528 | 139 | } |
va009039 | 0:98f918e1d528 | 140 | return 1; |
va009039 | 0:98f918e1d528 | 141 | } |
va009039 | 0:98f918e1d528 | 142 | |
va009039 | 0:98f918e1d528 | 143 | int UsbFlashDrive::disk_status() |
va009039 | 0:98f918e1d528 | 144 | { |
va009039 | 0:98f918e1d528 | 145 | m_report_disk_status++; |
va009039 | 0:98f918e1d528 | 146 | return 0; |
va009039 | 0:98f918e1d528 | 147 | } |
va009039 | 0:98f918e1d528 | 148 | |
va009039 | 0:98f918e1d528 | 149 | int UsbFlashDrive::disk_sync() |
va009039 | 0:98f918e1d528 | 150 | { |
va009039 | 0:98f918e1d528 | 151 | m_report_disk_sync++; |
va009039 | 0:98f918e1d528 | 152 | return 0; |
va009039 | 0:98f918e1d528 | 153 | } |
va009039 | 0:98f918e1d528 | 154 | |
va009039 | 0:98f918e1d528 | 155 | uint64_t UsbFlashDrive::disk_sectors() |
va009039 | 0:98f918e1d528 | 156 | { |
va009039 | 0:98f918e1d528 | 157 | DBG("m_numBlocks=%d\n", m_numBlocks); |
va009039 | 0:98f918e1d528 | 158 | return m_numBlocks; |
va009039 | 0:98f918e1d528 | 159 | } |
va009039 | 0:98f918e1d528 | 160 | |
va009039 | 0:98f918e1d528 | 161 | int UsbFlashDrive::setup(ControlEp* ctlEp, int timeout) |
va009039 | 0:98f918e1d528 | 162 | { |
va009039 | 0:98f918e1d528 | 163 | |
va009039 | 0:98f918e1d528 | 164 | int retry = 0; |
va009039 | 0:98f918e1d528 | 165 | Timer t; |
va009039 | 0:98f918e1d528 | 166 | t.start(); |
va009039 | 0:98f918e1d528 | 167 | t.reset(); |
va009039 | 0:98f918e1d528 | 168 | while(t.read_ms() < timeout) { |
va009039 | 0:98f918e1d528 | 169 | DBG("retry=%d t=%d\n", retry, t.read_ms()); |
va009039 | 0:98f918e1d528 | 170 | if (retry > 80) { |
va009039 | 0:98f918e1d528 | 171 | return -1; |
va009039 | 0:98f918e1d528 | 172 | } |
va009039 | 0:98f918e1d528 | 173 | int rc = TestUnitReady(); |
va009039 | 0:98f918e1d528 | 174 | DBG("TestUnitReady(): %d\n", rc); |
va009039 | 0:98f918e1d528 | 175 | if (rc == USB_OK) { |
va009039 | 0:98f918e1d528 | 176 | DBG("m_CSW.bCSWStatus: %02X\n", m_CSW.bCSWStatus); |
va009039 | 0:98f918e1d528 | 177 | if (m_CSW.bCSWStatus == 0x00) { |
va009039 | 0:98f918e1d528 | 178 | break; |
va009039 | 0:98f918e1d528 | 179 | } |
va009039 | 0:98f918e1d528 | 180 | } |
va009039 | 0:98f918e1d528 | 181 | GetSenseInfo(); |
va009039 | 0:98f918e1d528 | 182 | retry++; |
va009039 | 0:98f918e1d528 | 183 | wait_ms(50); |
va009039 | 0:98f918e1d528 | 184 | } |
va009039 | 0:98f918e1d528 | 185 | if (t.read_ms() >= timeout) { |
va009039 | 0:98f918e1d528 | 186 | return -1; |
va009039 | 0:98f918e1d528 | 187 | } |
va009039 | 0:98f918e1d528 | 188 | ReadCapacity(); |
va009039 | 0:98f918e1d528 | 189 | Inquire(); |
va009039 | 0:98f918e1d528 | 190 | return 0; |
va009039 | 0:98f918e1d528 | 191 | } |
va009039 | 0:98f918e1d528 | 192 | |
va009039 | 0:98f918e1d528 | 193 | int UsbFlashDrive::ParseConfiguration(ControlEp* ctlEp) |
va009039 | 0:98f918e1d528 | 194 | { |
va009039 | 0:98f918e1d528 | 195 | TEST_ASSERT(ctlEp); |
va009039 | 0:98f918e1d528 | 196 | TEST_ASSERT(sizeof(StandardEndpointDescriptor) == 7); |
va009039 | 0:98f918e1d528 | 197 | uint8_t temp[4]; |
va009039 | 0:98f918e1d528 | 198 | int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp)); |
va009039 | 0:98f918e1d528 | 199 | if (rc != USB_OK) { |
va009039 | 0:98f918e1d528 | 200 | return rc; |
va009039 | 0:98f918e1d528 | 201 | } |
va009039 | 0:98f918e1d528 | 202 | StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp); |
va009039 | 0:98f918e1d528 | 203 | uint8_t* buf = new uint8_t[cfg->wTotalLength]; |
va009039 | 0:98f918e1d528 | 204 | rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength); |
va009039 | 0:98f918e1d528 | 205 | if (rc != USB_OK) { |
va009039 | 0:98f918e1d528 | 206 | return rc; |
va009039 | 0:98f918e1d528 | 207 | } |
va009039 | 0:98f918e1d528 | 208 | DBG_HEX(buf, cfg->wTotalLength); |
va009039 | 0:98f918e1d528 | 209 | for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) { |
va009039 | 0:98f918e1d528 | 210 | StandardEndpointDescriptor* desc = reinterpret_cast<StandardEndpointDescriptor*>(buf+pos); |
va009039 | 0:98f918e1d528 | 211 | if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT) { |
va009039 | 0:98f918e1d528 | 212 | if (desc->bmAttributes == 2) { // bulk |
va009039 | 0:98f918e1d528 | 213 | BulkEp* pEp = new BulkEp(ctlEp->GetAddr(), desc->bEndpointAddress, desc->wMaxPacketSize); |
va009039 | 0:98f918e1d528 | 214 | if (desc->bEndpointAddress & 0x80) { |
va009039 | 0:98f918e1d528 | 215 | m_pEpBulkIn = pEp; |
va009039 | 0:98f918e1d528 | 216 | } else { |
va009039 | 0:98f918e1d528 | 217 | m_pEpBulkOut = pEp; |
va009039 | 0:98f918e1d528 | 218 | } |
va009039 | 0:98f918e1d528 | 219 | } |
va009039 | 0:98f918e1d528 | 220 | } |
va009039 | 0:98f918e1d528 | 221 | } |
va009039 | 0:98f918e1d528 | 222 | delete[] buf; |
va009039 | 0:98f918e1d528 | 223 | if (m_pEpBulkIn && m_pEpBulkOut) { |
va009039 | 0:98f918e1d528 | 224 | return USB_OK; |
va009039 | 0:98f918e1d528 | 225 | } |
va009039 | 0:98f918e1d528 | 226 | return USB_ERROR; |
va009039 | 0:98f918e1d528 | 227 | } |
va009039 | 0:98f918e1d528 | 228 | |
va009039 | 0:98f918e1d528 | 229 | int UsbFlashDrive::BulkOnlyMassStorageReset(ControlEp* ctlEp) |
va009039 | 0:98f918e1d528 | 230 | { |
va009039 | 0:98f918e1d528 | 231 | TEST_ASSERT(ctlEp); |
va009039 | 0:98f918e1d528 | 232 | int rc = ctlEp->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); |
va009039 | 0:98f918e1d528 | 233 | TEST_ASSERT(rc == USB_OK); |
va009039 | 0:98f918e1d528 | 234 | return rc; |
va009039 | 0:98f918e1d528 | 235 | } |
va009039 | 0:98f918e1d528 | 236 | |
va009039 | 0:98f918e1d528 | 237 | int UsbFlashDrive::GetMaxLUN(ControlEp* ctlEp) |
va009039 | 0:98f918e1d528 | 238 | { |
va009039 | 0:98f918e1d528 | 239 | TEST_ASSERT(ctlEp); |
va009039 | 0:98f918e1d528 | 240 | TEST_ASSERT(m_interface == 0); |
va009039 | 0:98f918e1d528 | 241 | uint8_t temp[1]; |
va009039 | 0:98f918e1d528 | 242 | int rc = ctlEp->controlReceive(0xa1, 0xfe, 0x0000, m_interface, temp, sizeof(temp)); |
va009039 | 0:98f918e1d528 | 243 | TEST_ASSERT(rc == USB_OK); |
va009039 | 0:98f918e1d528 | 244 | DBG_BYTES("GetMaxLUN", temp, sizeof(temp)); |
va009039 | 0:98f918e1d528 | 245 | m_MaxLUN = temp[0]; |
va009039 | 0:98f918e1d528 | 246 | TEST_ASSERT(m_MaxLUN <= 15); |
va009039 | 0:98f918e1d528 | 247 | return rc; |
va009039 | 0:98f918e1d528 | 248 | } |
va009039 | 0:98f918e1d528 | 249 | |
va009039 | 0:98f918e1d528 | 250 | |
va009039 | 0:98f918e1d528 | 251 | int UsbFlashDrive::TestUnitReady() |
va009039 | 0:98f918e1d528 | 252 | { |
va009039 | 0:98f918e1d528 | 253 | const uint8_t cdb[6] = {SCSI_CMD_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00}; |
va009039 | 0:98f918e1d528 | 254 | m_CBW.dCBWDataTraansferLength = 0; |
va009039 | 0:98f918e1d528 | 255 | m_CBW.bmCBWFlags = 0x00; |
va009039 | 0:98f918e1d528 | 256 | CommandTransport(cdb, sizeof(cdb)); |
va009039 | 0:98f918e1d528 | 257 | StatusTransport(); |
va009039 | 0:98f918e1d528 | 258 | return 0; |
va009039 | 0:98f918e1d528 | 259 | } |
va009039 | 0:98f918e1d528 | 260 | |
va009039 | 0:98f918e1d528 | 261 | int UsbFlashDrive::GetSenseInfo() |
va009039 | 0:98f918e1d528 | 262 | { |
va009039 | 0:98f918e1d528 | 263 | const uint8_t cdb[6] = {SCSI_CMD_REQUEST_SENSE, 0x00, 0x00, 0x00, 18, 0x00}; |
va009039 | 0:98f918e1d528 | 264 | m_CBW.dCBWDataTraansferLength = 18; |
va009039 | 0:98f918e1d528 | 265 | m_CBW.bmCBWFlags = 0x80; // data In |
va009039 | 0:98f918e1d528 | 266 | CommandTransport(cdb, sizeof(cdb)); |
va009039 | 0:98f918e1d528 | 267 | |
va009039 | 0:98f918e1d528 | 268 | uint8_t buf[18]; |
va009039 | 0:98f918e1d528 | 269 | _bulkRecv(buf, sizeof(buf)); |
va009039 | 0:98f918e1d528 | 270 | DBG_HEX(buf, sizeof(buf)); |
va009039 | 0:98f918e1d528 | 271 | |
va009039 | 0:98f918e1d528 | 272 | StatusTransport(); |
va009039 | 0:98f918e1d528 | 273 | TEST_ASSERT(m_CSW.bCSWStatus == 0x00); |
va009039 | 0:98f918e1d528 | 274 | return 0; |
va009039 | 0:98f918e1d528 | 275 | } |
va009039 | 0:98f918e1d528 | 276 | |
va009039 | 0:98f918e1d528 | 277 | int UsbFlashDrive::ReadCapacity() |
va009039 | 0:98f918e1d528 | 278 | { |
va009039 | 0:98f918e1d528 | 279 | const uint8_t cdb[10] = {SCSI_CMD_READ_CAPACITY, 0x00, 0x00, 0x00, 0x00, |
va009039 | 0:98f918e1d528 | 280 | 0x00, 0x00, 0x00, 0x00, 0x00}; |
va009039 | 0:98f918e1d528 | 281 | m_CBW.dCBWDataTraansferLength = 8; |
va009039 | 0:98f918e1d528 | 282 | m_CBW.bmCBWFlags = 0x80; // data In |
va009039 | 0:98f918e1d528 | 283 | CommandTransport(cdb, sizeof(cdb)); |
va009039 | 0:98f918e1d528 | 284 | |
va009039 | 0:98f918e1d528 | 285 | uint8_t buf[8]; |
va009039 | 0:98f918e1d528 | 286 | int rc = _bulkRecv(buf, sizeof(buf)); |
va009039 | 0:98f918e1d528 | 287 | TEST_ASSERT(rc >= 0); |
va009039 | 0:98f918e1d528 | 288 | DBG_HEX(buf, sizeof(buf)); |
va009039 | 0:98f918e1d528 | 289 | |
va009039 | 0:98f918e1d528 | 290 | StatusTransport(); |
va009039 | 0:98f918e1d528 | 291 | TEST_ASSERT(m_CSW.bCSWStatus == 0x00); |
va009039 | 0:98f918e1d528 | 292 | |
va009039 | 0:98f918e1d528 | 293 | m_numBlocks = BE32(buf); |
va009039 | 0:98f918e1d528 | 294 | m_BlockSize = BE32(buf+4); |
va009039 | 0:98f918e1d528 | 295 | DBG("m_numBlocks=%d m_BlockSize=%d\n", m_numBlocks, m_BlockSize); |
va009039 | 0:98f918e1d528 | 296 | TEST_ASSERT(m_BlockSize == 512); |
va009039 | 0:98f918e1d528 | 297 | TEST_ASSERT(m_numBlocks > 0); |
va009039 | 0:98f918e1d528 | 298 | return 0; |
va009039 | 0:98f918e1d528 | 299 | } |
va009039 | 0:98f918e1d528 | 300 | |
va009039 | 0:98f918e1d528 | 301 | int UsbFlashDrive::Inquire() |
va009039 | 0:98f918e1d528 | 302 | { |
va009039 | 0:98f918e1d528 | 303 | const uint8_t cdb[6] = {SCSI_CMD_INQUIRY, 0x00, 0x00, 0x00, 36, 0x00}; |
va009039 | 0:98f918e1d528 | 304 | m_CBW.dCBWDataTraansferLength = 36; |
va009039 | 0:98f918e1d528 | 305 | m_CBW.bmCBWFlags = 0x80; // data In |
va009039 | 0:98f918e1d528 | 306 | CommandTransport(cdb, sizeof(cdb)); |
va009039 | 0:98f918e1d528 | 307 | |
va009039 | 0:98f918e1d528 | 308 | uint8_t buf[36]; |
va009039 | 0:98f918e1d528 | 309 | int rc = _bulkRecv(buf, sizeof(buf)); |
va009039 | 0:98f918e1d528 | 310 | TEST_ASSERT(rc >= 0); |
va009039 | 0:98f918e1d528 | 311 | DBG_HEX(buf, sizeof(buf)); |
va009039 | 0:98f918e1d528 | 312 | |
va009039 | 0:98f918e1d528 | 313 | StatusTransport(); |
va009039 | 0:98f918e1d528 | 314 | return 0; |
va009039 | 0:98f918e1d528 | 315 | } |
va009039 | 0:98f918e1d528 | 316 | |
va009039 | 0:98f918e1d528 | 317 | int UsbFlashDrive::MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer) |
va009039 | 0:98f918e1d528 | 318 | { |
va009039 | 0:98f918e1d528 | 319 | TEST_ASSERT(m_BlockSize == 512); |
va009039 | 0:98f918e1d528 | 320 | TEST_ASSERT(num_blocks == 1); |
va009039 | 0:98f918e1d528 | 321 | TEST_ASSERT(user_buffer); |
va009039 | 0:98f918e1d528 | 322 | uint8_t cdb[10] = {SCSI_CMD_READ_10, 0x00, 0x00, 0x00, 0x00, |
va009039 | 0:98f918e1d528 | 323 | 0x00, 0x00, 0x00, 0x00, 0x00}; |
va009039 | 0:98f918e1d528 | 324 | BE32(block_number, cdb+2); |
va009039 | 0:98f918e1d528 | 325 | BE16(num_blocks, cdb+7); |
va009039 | 0:98f918e1d528 | 326 | uint32_t len = m_BlockSize * num_blocks; |
va009039 | 0:98f918e1d528 | 327 | TEST_ASSERT(len <= 512); |
va009039 | 0:98f918e1d528 | 328 | m_CBW.dCBWDataTraansferLength = len; |
va009039 | 0:98f918e1d528 | 329 | m_CBW.bmCBWFlags = 0x80; // data In |
va009039 | 0:98f918e1d528 | 330 | CommandTransport(cdb, sizeof(cdb)); |
va009039 | 0:98f918e1d528 | 331 | |
va009039 | 0:98f918e1d528 | 332 | int ret = _bulkRecv(user_buffer, len); |
va009039 | 0:98f918e1d528 | 333 | //DBG_HEX(user_buffer, len); |
va009039 | 0:98f918e1d528 | 334 | |
va009039 | 0:98f918e1d528 | 335 | StatusTransport(); |
va009039 | 0:98f918e1d528 | 336 | TEST_ASSERT(m_CSW.bCSWStatus == 0x00); |
va009039 | 0:98f918e1d528 | 337 | return ret; |
va009039 | 0:98f918e1d528 | 338 | } |
va009039 | 0:98f918e1d528 | 339 | |
va009039 | 0:98f918e1d528 | 340 | int UsbFlashDrive::MS_BulkSend(uint32_t block_number, int num_blocks, const uint8_t* user_buffer) |
va009039 | 0:98f918e1d528 | 341 | { |
va009039 | 0:98f918e1d528 | 342 | #ifdef WRITE_PROTECT |
va009039 | 0:98f918e1d528 | 343 | return 0; |
va009039 | 0:98f918e1d528 | 344 | #else |
va009039 | 0:98f918e1d528 | 345 | TEST_ASSERT(num_blocks == 1); |
va009039 | 0:98f918e1d528 | 346 | TEST_ASSERT(user_buffer); |
va009039 | 0:98f918e1d528 | 347 | uint8_t cdb[10] = {SCSI_CMD_WRITE_10, 0x00, 0x00, 0x00, 0x00, |
va009039 | 0:98f918e1d528 | 348 | 0x00, 0x00, 0x00, 0x00, 0x00}; |
va009039 | 0:98f918e1d528 | 349 | BE32(block_number, cdb+2); |
va009039 | 0:98f918e1d528 | 350 | BE16(num_blocks, cdb+7); |
va009039 | 0:98f918e1d528 | 351 | uint32_t len = m_BlockSize * num_blocks; |
va009039 | 0:98f918e1d528 | 352 | TEST_ASSERT(len <= 512); |
va009039 | 0:98f918e1d528 | 353 | m_CBW.dCBWDataTraansferLength = len; |
va009039 | 0:98f918e1d528 | 354 | m_CBW.bmCBWFlags = 0x00; // data Out |
va009039 | 0:98f918e1d528 | 355 | CommandTransport(cdb, sizeof(cdb)); |
va009039 | 0:98f918e1d528 | 356 | |
va009039 | 0:98f918e1d528 | 357 | int ret = _bulkSend(user_buffer, len); |
va009039 | 0:98f918e1d528 | 358 | //DBG_HEX(user_buffer, len); |
va009039 | 0:98f918e1d528 | 359 | |
va009039 | 0:98f918e1d528 | 360 | StatusTransport(); |
va009039 | 0:98f918e1d528 | 361 | TEST_ASSERT(m_CSW.bCSWStatus == 0x00); |
va009039 | 0:98f918e1d528 | 362 | return ret; |
va009039 | 0:98f918e1d528 | 363 | #endif //WRITE_PROTECT |
va009039 | 0:98f918e1d528 | 364 | } |
va009039 | 0:98f918e1d528 | 365 | |
va009039 | 0:98f918e1d528 | 366 | int UsbFlashDrive::CommandTransport(const uint8_t* cdb, int size) |
va009039 | 0:98f918e1d528 | 367 | { |
va009039 | 0:98f918e1d528 | 368 | TEST_ASSERT(cdb); |
va009039 | 0:98f918e1d528 | 369 | TEST_ASSERT(size >= 6); |
va009039 | 0:98f918e1d528 | 370 | TEST_ASSERT(size <= 16); |
va009039 | 0:98f918e1d528 | 371 | m_CBW.bCBWLUN = m_lun; |
va009039 | 0:98f918e1d528 | 372 | m_CBW.bCBWCBLength = size; |
va009039 | 0:98f918e1d528 | 373 | memcpy(m_CBW.CBWCB, cdb, size); |
va009039 | 0:98f918e1d528 | 374 | |
va009039 | 0:98f918e1d528 | 375 | m_CBW.dCBWSignature = 0x43425355; |
va009039 | 0:98f918e1d528 | 376 | m_CBW.dCBWTag = m_tag++; |
va009039 | 0:98f918e1d528 | 377 | m_CBW.bCBWLUN = 0; |
va009039 | 0:98f918e1d528 | 378 | //DBG_HEX((uint8_t*)&m_CBW, sizeof(CBW)); |
va009039 | 0:98f918e1d528 | 379 | int rc = _bulkSend((uint8_t*)&m_CBW, sizeof(CBW)); |
va009039 | 0:98f918e1d528 | 380 | return rc; |
va009039 | 0:98f918e1d528 | 381 | } |
va009039 | 0:98f918e1d528 | 382 | |
va009039 | 0:98f918e1d528 | 383 | int UsbFlashDrive::StatusTransport() |
va009039 | 0:98f918e1d528 | 384 | { |
va009039 | 0:98f918e1d528 | 385 | TEST_ASSERT(sizeof(CSW) == 13); |
va009039 | 0:98f918e1d528 | 386 | int rc = _bulkRecv((uint8_t*)&m_CSW, sizeof(CSW)); |
va009039 | 0:98f918e1d528 | 387 | //DBG_HEX((uint8_t*)&m_CSW, sizeof(CSW)); |
va009039 | 0:98f918e1d528 | 388 | TEST_ASSERT(m_CSW.dCSWSignature == 0x53425355); |
va009039 | 0:98f918e1d528 | 389 | TEST_ASSERT(m_CSW.dCSWTag == m_CBW.dCBWTag); |
va009039 | 0:98f918e1d528 | 390 | TEST_ASSERT(m_CSW.dCSWDataResidue == 0); |
va009039 | 0:98f918e1d528 | 391 | return rc; |
va009039 | 0:98f918e1d528 | 392 | } |
va009039 | 0:98f918e1d528 | 393 | |
va009039 | 0:98f918e1d528 | 394 | int UsbFlashDrive::_bulkRecv(uint8_t* buf, int size) |
va009039 | 0:98f918e1d528 | 395 | { |
va009039 | 0:98f918e1d528 | 396 | TEST_ASSERT(m_pEpBulkIn); |
va009039 | 0:98f918e1d528 | 397 | int ret = m_pEpBulkIn->bulkReceive(buf, size); |
va009039 | 0:98f918e1d528 | 398 | return ret; |
va009039 | 0:98f918e1d528 | 399 | } |
va009039 | 0:98f918e1d528 | 400 | |
va009039 | 0:98f918e1d528 | 401 | int UsbFlashDrive::_bulkSend(const uint8_t* buf, int size) |
va009039 | 0:98f918e1d528 | 402 | { |
va009039 | 0:98f918e1d528 | 403 | TEST_ASSERT(m_pEpBulkOut); |
va009039 | 0:98f918e1d528 | 404 | int ret = m_pEpBulkOut->bulkSend(buf, size); |
va009039 | 0:98f918e1d528 | 405 | return ret; |
va009039 | 0:98f918e1d528 | 406 | } |