Usb read

Dependencies:   FATFileSystem

Fork of F401RE-USBHost by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost.cpp Source File

USBHost.cpp

00001 // Simple USBHost for FRDM-KL46Z
00002 #include "USBHost.h"
00003 #include <algorithm>
00004 
00005 USBHost* USBHost::inst = NULL;
00006 
00007 USBHost* USBHost::getHostInst()
00008 {
00009     if (inst == NULL) {
00010         inst = new USBHost();
00011         inst->init();
00012     }
00013     return inst;
00014 }
00015 
00016 void USBHost::poll()
00017 {
00018     if (inst) {
00019         inst->task();
00020     }
00021 }
00022 
00023 USBHost::USBHost() {
00024 }
00025 
00026 /* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) {
00027     USBDeviceConnected* dev = new USBDeviceConnected;
00028     USBEndpoint* ep = new USBEndpoint(dev);
00029     dev->init(0, port, lowSpeed);
00030     dev->setAddress(0);
00031     dev->setEpCtl(ep);
00032     uint8_t desc[18];
00033     wait_ms(100);
00034 
00035     int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8);
00036     USB_TEST_ASSERT(rc == USB_TYPE_OK);
00037     if (rc != USB_TYPE_OK) {
00038         USB_ERR("ADD DEVICE FAILD");
00039     }
00040     USB_DBG_HEX(desc, 8);
00041     DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
00042     ep->setSize(dev_desc->bMaxPacketSize);
00043 
00044     int new_addr = USBDeviceConnected::getNewAddress();
00045     rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0);
00046     USB_TEST_ASSERT(rc == USB_TYPE_OK);
00047     dev->setAddress(new_addr);
00048     wait_ms(100);
00049 
00050     rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
00051     USB_TEST_ASSERT(rc == USB_TYPE_OK);
00052     USB_DBG_HEX(desc, sizeof(desc));
00053 
00054     dev->setVid(dev_desc->idVendor);
00055     dev->setPid(dev_desc->idProduct);
00056     dev->setClass(dev_desc->bDeviceClass);
00057     USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d",
00058         parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(),
00059         dev->getAddress());
00060 
00061     DeviceLists.push_back(dev);
00062 
00063     if (dev->getClass() == HUB_CLASS) {
00064         const int config = 1;
00065         int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
00066         USB_TEST_ASSERT(rc == USB_TYPE_OK);
00067         wait_ms(100);
00068         Hub(dev);
00069     }
00070     return true;
00071 }
00072 
00073 // enumerate a device with the control USBEndpoint
00074 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator)
00075 {
00076     if (dev->getClass() == HUB_CLASS) { // skip hub class
00077         return USB_TYPE_OK;
00078     }
00079     uint8_t desc[18];
00080     USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
00081     USB_TEST_ASSERT(rc == USB_TYPE_OK);
00082     USB_DBG_HEX(desc, sizeof(desc));
00083     if (rc != USB_TYPE_OK) {
00084         return rc;
00085     }
00086     DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
00087     dev->setClass(dev_desc->bDeviceClass);
00088     pEnumerator->setVidPid(dev->getVid(), dev->getPid());
00089 
00090     rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4);
00091     USB_TEST_ASSERT(rc == USB_TYPE_OK);
00092     USB_DBG_HEX(desc, 4);
00093 
00094     int TotalLength = desc[2]|desc[3]<<8;
00095     uint8_t* buf = new uint8_t[TotalLength];
00096     rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength);
00097     USB_TEST_ASSERT(rc == USB_TYPE_OK);
00098     //USB_DBG_HEX(buf, TotalLength);
00099 
00100     // Parse the configuration descriptor
00101     parseConfDescr(dev, buf, TotalLength, pEnumerator);
00102     delete[] buf;
00103     // only set configuration if not enumerated before
00104     if (!dev->isEnumerated()) {
00105         USB_DBG("Set configuration 1 on dev: %p", dev);
00106         // sixth step: set configuration (only 1 supported)
00107         int config = 1;
00108         USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
00109         if (res != USB_TYPE_OK) {
00110             USB_ERR("SET CONF FAILED");
00111             return res;
00112         }
00113         // Some devices may require this delay
00114         wait_ms(100);
00115         dev->setEnumerated();
00116         // Now the device is enumerated!
00117         USB_DBG("dev %p is enumerated", dev);
00118     }
00119     return USB_TYPE_OK;
00120 }
00121 
00122 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
00123 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator)
00124 {
00125     uint32_t index = 0;
00126     uint32_t len_desc = 0;
00127     uint8_t id = 0;
00128     USBEndpoint * ep = NULL;
00129     uint8_t intf_nb = 0;
00130     bool parsing_intf = false;
00131     uint8_t current_intf = 0;
00132     EndpointDescriptor* ep_desc;
00133 
00134     while (index < len) {
00135         len_desc = conf_descr[index];
00136         id = conf_descr[index+1];
00137         USB_DBG_HEX(conf_descr+index, len_desc);
00138         switch (id) {
00139             case CONFIGURATION_DESCRIPTOR:
00140                 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]);
00141                 dev->setNbIntf(conf_descr[4]);
00142                 break;
00143             case INTERFACE_DESCRIPTOR:
00144                 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) {
00145                     intf_nb++;
00146                     current_intf = conf_descr[index + 2];
00147                     dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
00148                     USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]);
00149                     parsing_intf = true;
00150                 } else {
00151                     parsing_intf = false;
00152                 }
00153                 break;
00154             case ENDPOINT_DESCRIPTOR:
00155                 ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index);
00156                 if (parsing_intf && (intf_nb <= MAX_INTF) ) {
00157                     ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03);
00158                     ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT;
00159                     if(pEnumerator->useEndpoint(current_intf, type, dir)) {
00160                         ep = new USBEndpoint(dev);
00161                         ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress);
00162                         USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev);
00163                         dev->addEndpoint(current_intf, ep);
00164                     }
00165                 }
00166                 break;
00167             case HID_DESCRIPTOR:
00168                 //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
00169                 break;
00170             default:
00171                 break;
00172         }
00173         index += len_desc;
00174     }
00175 }
00176 
00177 USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
00178     SETUP_PACKET setup = {requestType, request, value, index};
00179     int result = ControlRead(dev, &setup, buf, len);
00180     //USB_DBG2("result=%d %02x", result, LastStatus);
00181     return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR;
00182 }
00183 
00184 USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
00185     SETUP_PACKET setup = {requestType, request, value, index};
00186     int result = ControlWrite(dev, &setup, buf, len);
00187     if (result >= 0) {
00188         return USB_TYPE_OK;
00189     }
00190     USB_DBG("result=%d %02x", result, LastStatus);
00191     USB_DBG_HEX(buf, len);
00192     return USB_TYPE_ERROR;
00193 }
00194 
00195 USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
00196     if (blocking == false) {
00197         ep->setBuffer(buf, len);
00198         ep_queue.push(ep);
00199         return USB_TYPE_PROCESSING;
00200     }
00201     int result = bulkReadBLOCK(ep, buf, len, -1);
00202     if (result >= 0) {
00203         return USB_TYPE_OK;
00204     }
00205     //USB_DBG2("result=%d %02x", result, host->LastStatus);
00206     return USB_TYPE_ERROR;
00207 }
00208 
00209 USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
00210     USB_TEST_ASSERT(blocking);
00211     int result = bulkWriteNB(ep, buf, len);
00212     if (result >= 0) {
00213         return USB_TYPE_OK;
00214     }
00215     USB_DBG2("result=%d %02x", result, LastStatus);
00216     return USB_TYPE_ERROR;
00217 }
00218 
00219 USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
00220     if (blocking == false) {
00221         ep->setBuffer(buf, len);
00222         ep_queue.push(ep);
00223         return USB_TYPE_PROCESSING;
00224     }
00225     interruptReadNB(ep, buf, len);
00226     return USB_TYPE_OK;
00227 }
00228 
00229 USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
00230     USB_TEST_ASSERT(blocking);
00231     interruptWriteNB(ep, buf, len);
00232     return USB_TYPE_OK;
00233 }
00234 
00235 USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
00236     if (blocking == false) {
00237         ep->setBuffer(buf, len);
00238         ep_queue.push(ep);
00239         return USB_TYPE_PROCESSING;
00240     }
00241     isochronousReadNB(ep, buf, len);
00242     return USB_TYPE_OK;
00243 }
00244 
00245 int USBHost::ControlRead(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) {
00246     USB_TEST_ASSERT(dev);
00247     USBEndpoint* ep = dev->getEpCtl();
00248     USB_TEST_ASSERT(ep);
00249     setAddr(dev->getAddress(), dev->getSpeed());
00250     token_setup(ep, setup, size); // setup stage
00251     if (LastStatus != ACK) {
00252         USB_DBG("setup %02x", LastStatus);
00253         return -1;
00254     }
00255     int read_len = 0;
00256     while(read_len < size) {
00257         int size2 = std::min(size-read_len, ep->getSize());
00258         int result = token_in(ep, data+read_len, size2);
00259         //USB_DBG("token_in result=%d %02x", result, LastStatus);
00260         if (result < 0) {
00261             USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus);
00262             return result;
00263         }
00264         read_len += result;
00265         if (result < ep->getSize()) {
00266             break;
00267         }
00268     }    
00269     ep->setData01(DATA1);
00270     int result = token_out(ep); // status stage
00271     if (result < 0) {
00272         USB_DBG("status token_out %02x", LastStatus);
00273         if (LastStatus == STALL) {
00274             ep->setLengthTransferred(read_len);
00275             return read_len;
00276         }
00277         return result;
00278     }
00279     ep->setLengthTransferred(read_len);
00280     return read_len;
00281 }
00282 
00283 int USBHost::ControlWrite(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) {
00284     USB_TEST_ASSERT(dev);
00285     USBEndpoint* ep = dev->getEpCtl();
00286     USB_TEST_ASSERT(ep);
00287     setAddr(dev->getAddress(), dev->getSpeed());
00288     token_setup(ep, setup, size); // setup stage
00289     if (LastStatus != ACK) {
00290         USB_DBG("setup %02x", LastStatus);
00291         return -1;
00292     }
00293     int write_len = 0;
00294     if (data != NULL) {
00295         write_len = token_out(ep, data, size);
00296         if (write_len < 0) {
00297             return -1;
00298         }
00299     }
00300     ep->setData01(DATA1);
00301     int result = token_in(ep); // status stage
00302     if (result < 0) {
00303         USB_DBG("result=%d %02x", result, LastStatus);
00304         //return result;
00305     }
00306     ep->setLengthTransferred(write_len);
00307     return write_len;
00308 }
00309 
00310 int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size)
00311 {
00312     USB_TEST_ASSERT(ep);
00313     USBDeviceConnected* dev = ep->getDevice();
00314     USB_TEST_ASSERT(dev);
00315     setAddr(dev->getAddress(), dev->getSpeed());
00316     setEndpoint();
00317     const int retryLimit = 0;
00318     int read_len = 0;
00319     for(int n = 0; read_len < size; n++) {
00320         int size2 = std::min(size-read_len, ep->getSize());
00321         int result = token_in(ep, data+read_len, size2, retryLimit);
00322         if (result < 0) {
00323             if (LastStatus == NAK) {
00324                 if (n == 0) {
00325                     return -1;
00326                 }
00327                 break;
00328             }
00329             //USB_DBG("token_in result=%d %02x", result, LastStatus);
00330             return result;
00331         }
00332         read_len += result;
00333         if (result < ep->getSize()) {
00334             break;
00335         }
00336     }
00337     ep->setLengthTransferred(read_len);
00338     return read_len;
00339 }
00340 
00341 int USBHost::interruptWriteNB(USBEndpoint* ep, const uint8_t* data, int size)
00342 {
00343     USB_TEST_ASSERT(ep);
00344     USBDeviceConnected* dev = ep->getDevice();
00345     USB_TEST_ASSERT(dev);
00346     setAddr(dev->getAddress(), dev->getSpeed());
00347     setEndpoint();
00348     const int retryLimit = 0;
00349     int transferred_len = 0;
00350     for(int n = 0; transferred_len < size; n++) {
00351         int size2 = std::min(size-transferred_len, ep->getSize());
00352         int result = token_out(ep, data+transferred_len, size2, retryLimit);
00353         if (result < 0) {
00354             if (LastStatus == NAK) {
00355                 if (n == 0) {
00356                     return -1;
00357                 }
00358                 break;
00359             }
00360             //USB_DBG("token_in result=%d %02x", result, LastStatus);
00361             return result;
00362         }
00363         transferred_len += result;
00364         if (result < ep->getSize()) {
00365             break;
00366         }
00367     }
00368     ep->setLengthTransferred(transferred_len);
00369     return transferred_len;
00370 }
00371 
00372 int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size)
00373 {
00374     return bulkReadBLOCK(ep, data, size, 0);
00375 }
00376 
00377 int USBHost::bulkReadBLOCK(USBEndpoint* ep, uint8_t* data, int size, int timeout_ms) {
00378     USB_TEST_ASSERT(ep);
00379     USBDeviceConnected* dev = ep->getDevice();
00380     USB_TEST_ASSERT(dev);
00381     setAddr(dev->getAddress());
00382     setEndpoint();
00383     int retryLimit = (timeout_ms == 0) ? 0 : 10;
00384     int read_len = 0;
00385     Timer t;
00386     for(int n = 0; read_len < size; n++) {
00387         int size2 = std::min(size-read_len, ep->getSize());
00388         int result = token_in(ep, data+read_len, size2, retryLimit);
00389         if (result < 0) {
00390             if (LastStatus == NAK) {
00391                 if (n == 0) {
00392                     return -1;
00393                 }
00394                 break;
00395             }
00396             //USB_DBG("token_in result=%d %02x", result, LastStatus);
00397             return result;
00398         }
00399         read_len += result;
00400         if (result < ep->getSize()) {
00401             break;
00402         }
00403         if (timeout_ms > 0 && t.read_ms() > timeout_ms) {
00404             USB_DBG("timeout_ms: %d", timeout_ms);
00405             break;
00406         }
00407     }
00408     ep->setLengthTransferred(read_len);
00409     return read_len;
00410 }
00411 
00412 int USBHost::bulkWriteNB(USBEndpoint* ep, const uint8_t* data, int size) {
00413     USB_TEST_ASSERT(ep);
00414     USBDeviceConnected* dev = ep->getDevice();
00415     USB_TEST_ASSERT(dev);
00416     setAddr(dev->getAddress());
00417     setEndpoint();
00418     int write_len = 0;
00419     for(int n = 0; write_len < size; n++) {
00420         int size2 = std::min(size-write_len, ep->getSize());
00421         int result = token_out(ep, data+write_len, size2);
00422         if (result < 0) {
00423             if (LastStatus == NAK) {
00424                 if (n == 0) {
00425                     return -1;
00426                 }
00427                 break;
00428             }
00429             USB_DBG("token_out result=%d %02x", result, LastStatus);
00430             return result;
00431         }
00432         write_len += result;
00433         if (result < ep->getSize()) {
00434             break;
00435         }
00436     }
00437     ep->setLengthTransferred(write_len);
00438     return write_len;
00439 }
00440 
00441 int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) {
00442     USBDeviceConnected* dev = ep->getDevice();
00443     USB_TEST_ASSERT(dev);
00444     setAddr(dev->getAddress());
00445     int result = token_iso_in(ep, data, size);
00446     if (result >= 0) {
00447          ep->setLengthTransferred(result);
00448     }
00449     return result;
00450 }
00451 
00452 void USBHost::task()
00453 {
00454     if (ep_queue.empty()) {
00455         return;
00456     }
00457     USBEndpoint* ep = ep_queue.pop();
00458     USB_TEST_ASSERT(ep);
00459     ep->setLengthTransferred(0);
00460     switch(ep->getType()) {
00461         case INTERRUPT_ENDPOINT:
00462             if (ep->getDir() == IN) {
00463                 interruptReadNB(ep, ep->getBufStart(), ep->getBufSize());
00464             }
00465             break;
00466         case BULK_ENDPOINT:
00467             if (ep->getDir() == IN) {
00468                 bulkReadNB(ep, ep->getBufStart(), ep->getBufSize());
00469             }
00470             break;
00471         case ISOCHRONOUS_ENDPOINT:
00472             if (ep->getDir() == IN) {
00473                 isochronousReadNB(ep, ep->getBufStart(), ep->getBufSize());
00474             }
00475             break;
00476     }
00477     ep->call();
00478 }