USB Host Driver with Socket Modem support. Works with revision 323 of mbed-src but broken with any later version.

Dependencies:   FATFileSystem

Fork of F401RE-USBHost by Norimasa Okamoto

Committer:
va009039
Date:
Mon Feb 03 13:00:16 2014 +0000
Revision:
9:7f9f64cf5ded
Parent:
8:6463cd1964c0
Child:
10:40c7f6788902
add interrupt write transfer.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 7:9a20482c9a7a 1 // Simple USBHost for FRDM-KL46Z
va009039 7:9a20482c9a7a 2 #include "USBHost.h"
va009039 7:9a20482c9a7a 3 #include <algorithm>
va009039 7:9a20482c9a7a 4
va009039 7:9a20482c9a7a 5 USBHost* USBHost::inst = NULL;
va009039 7:9a20482c9a7a 6
va009039 7:9a20482c9a7a 7 USBHost* USBHost::getHostInst()
va009039 7:9a20482c9a7a 8 {
va009039 7:9a20482c9a7a 9 if (inst == NULL) {
va009039 7:9a20482c9a7a 10 inst = new USBHost();
va009039 7:9a20482c9a7a 11 inst->init();
va009039 7:9a20482c9a7a 12 }
va009039 7:9a20482c9a7a 13 return inst;
va009039 7:9a20482c9a7a 14 }
va009039 7:9a20482c9a7a 15
va009039 9:7f9f64cf5ded 16 void USBHost::poll()
va009039 9:7f9f64cf5ded 17 {
va009039 9:7f9f64cf5ded 18 if (inst) {
va009039 9:7f9f64cf5ded 19 inst->task();
va009039 9:7f9f64cf5ded 20 }
va009039 9:7f9f64cf5ded 21 }
va009039 9:7f9f64cf5ded 22
va009039 7:9a20482c9a7a 23 USBHost::USBHost() {
va009039 7:9a20482c9a7a 24 }
va009039 7:9a20482c9a7a 25
va009039 8:6463cd1964c0 26 /* virtual */ bool USBHost::addDevice(int hub, int port, bool lowSpeed) {
va009039 8:6463cd1964c0 27 USBDeviceConnected* dev = new USBDeviceConnected;
va009039 8:6463cd1964c0 28 USBEndpoint* ep = new USBEndpoint;
va009039 8:6463cd1964c0 29 ep->setDevice(dev);
va009039 8:6463cd1964c0 30 dev->init(hub, port, lowSpeed);
va009039 8:6463cd1964c0 31 dev->setAddress(0);
va009039 8:6463cd1964c0 32 dev->setEpCtl(ep);
va009039 8:6463cd1964c0 33 uint8_t desc[18];
va009039 7:9a20482c9a7a 34 wait_ms(100);
va009039 8:6463cd1964c0 35
va009039 8:6463cd1964c0 36 int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8);
va009039 8:6463cd1964c0 37 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 8:6463cd1964c0 38 USB_DBG_HEX(desc, 8);
va009039 7:9a20482c9a7a 39 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
va009039 7:9a20482c9a7a 40 ep->setSize(dev_desc->bMaxPacketSize);
va009039 7:9a20482c9a7a 41
va009039 8:6463cd1964c0 42 int new_addr = USBDeviceConnected::getNewAddress();
va009039 8:6463cd1964c0 43 rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0);
va009039 8:6463cd1964c0 44 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 8:6463cd1964c0 45 dev->setAddress(new_addr);
va009039 7:9a20482c9a7a 46 wait_ms(100);
va009039 8:6463cd1964c0 47
va009039 8:6463cd1964c0 48 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
va009039 8:6463cd1964c0 49 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 8:6463cd1964c0 50 USB_DBG_HEX(desc, sizeof(desc));
va009039 7:9a20482c9a7a 51
va009039 8:6463cd1964c0 52 dev->setVid(dev_desc->idVendor);
va009039 8:6463cd1964c0 53 dev->setPid(dev_desc->idProduct);
va009039 8:6463cd1964c0 54 dev->setClass(dev_desc->bDeviceClass);
va009039 9:7f9f64cf5ded 55 USB_INFO("hub: %d port: %d speed: %s vid: %04x pid: %04x class: %02x addr: %d",
va009039 8:6463cd1964c0 56 hub, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(),
va009039 8:6463cd1964c0 57 dev->getAddress());
va009039 8:6463cd1964c0 58
va009039 9:7f9f64cf5ded 59 DeviceLists.push(dev);
va009039 8:6463cd1964c0 60
va009039 8:6463cd1964c0 61 if (dev->getClass() == HUB_CLASS) {
va009039 8:6463cd1964c0 62 const int config = 1;
va009039 8:6463cd1964c0 63 int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
va009039 8:6463cd1964c0 64 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 8:6463cd1964c0 65 wait_ms(100);
va009039 8:6463cd1964c0 66 Hub(dev);
va009039 7:9a20482c9a7a 67 }
va009039 8:6463cd1964c0 68 return true;
va009039 8:6463cd1964c0 69 }
va009039 7:9a20482c9a7a 70
va009039 8:6463cd1964c0 71 // enumerate a device with the control USBEndpoint
va009039 8:6463cd1964c0 72 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator)
va009039 8:6463cd1964c0 73 {
va009039 8:6463cd1964c0 74 if (dev->getClass() == HUB_CLASS) { // skip hub class
va009039 8:6463cd1964c0 75 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 76 }
va009039 8:6463cd1964c0 77 uint8_t desc[18];
va009039 8:6463cd1964c0 78 USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
va009039 8:6463cd1964c0 79 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 8:6463cd1964c0 80 USB_DBG_HEX(desc, sizeof(desc));
va009039 8:6463cd1964c0 81 if (rc != USB_TYPE_OK) {
va009039 8:6463cd1964c0 82 return rc;
va009039 8:6463cd1964c0 83 }
va009039 8:6463cd1964c0 84 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
va009039 8:6463cd1964c0 85 dev->setClass(dev_desc->bDeviceClass);
va009039 8:6463cd1964c0 86 pEnumerator->setVidPid(dev->getVid(), dev->getPid());
va009039 7:9a20482c9a7a 87
va009039 8:6463cd1964c0 88 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4);
va009039 8:6463cd1964c0 89 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 7:9a20482c9a7a 90 USB_DBG_HEX(desc, 4);
va009039 7:9a20482c9a7a 91
va009039 7:9a20482c9a7a 92 int TotalLength = desc[2]|desc[3]<<8;
va009039 7:9a20482c9a7a 93 uint8_t* buf = new uint8_t[TotalLength];
va009039 8:6463cd1964c0 94 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength);
va009039 8:6463cd1964c0 95 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 8:6463cd1964c0 96 //USB_DBG_HEX(buf, TotalLength);
va009039 8:6463cd1964c0 97
va009039 8:6463cd1964c0 98 // Parse the configuration descriptor
va009039 8:6463cd1964c0 99 parseConfDescr(dev, buf, TotalLength, pEnumerator);
va009039 8:6463cd1964c0 100 delete[] buf;
va009039 8:6463cd1964c0 101 // only set configuration if not enumerated before
va009039 8:6463cd1964c0 102 if (!dev->isEnumerated()) {
va009039 8:6463cd1964c0 103 USB_DBG("Set configuration 1 on dev: %p", dev);
va009039 8:6463cd1964c0 104 // sixth step: set configuration (only 1 supported)
va009039 8:6463cd1964c0 105 int config = 1;
va009039 8:6463cd1964c0 106 USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
va009039 8:6463cd1964c0 107 if (res != USB_TYPE_OK) {
va009039 8:6463cd1964c0 108 USB_DBG("SET CONF FAILED");
va009039 8:6463cd1964c0 109 return res;
va009039 8:6463cd1964c0 110 }
va009039 8:6463cd1964c0 111 // Some devices may require this delay
va009039 8:6463cd1964c0 112 wait_ms(100);
va009039 8:6463cd1964c0 113 dev->setEnumerated();
va009039 8:6463cd1964c0 114 // Now the device is enumerated!
va009039 8:6463cd1964c0 115 USB_DBG("dev %p is enumerated", dev);
va009039 7:9a20482c9a7a 116 }
va009039 8:6463cd1964c0 117 return USB_TYPE_OK;
va009039 8:6463cd1964c0 118 }
va009039 7:9a20482c9a7a 119
va009039 8:6463cd1964c0 120 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
va009039 8:6463cd1964c0 121 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator)
va009039 8:6463cd1964c0 122 {
va009039 8:6463cd1964c0 123 uint32_t index = 0;
va009039 8:6463cd1964c0 124 uint32_t len_desc = 0;
va009039 8:6463cd1964c0 125 uint8_t id = 0;
va009039 8:6463cd1964c0 126 USBEndpoint * ep = NULL;
va009039 8:6463cd1964c0 127 uint8_t intf_nb = 0;
va009039 8:6463cd1964c0 128 bool parsing_intf = false;
va009039 8:6463cd1964c0 129 uint8_t current_intf = 0;
va009039 8:6463cd1964c0 130 EndpointDescriptor* ep_desc;
va009039 8:6463cd1964c0 131
va009039 8:6463cd1964c0 132 while (index < len) {
va009039 8:6463cd1964c0 133 len_desc = conf_descr[index];
va009039 8:6463cd1964c0 134 id = conf_descr[index+1];
va009039 9:7f9f64cf5ded 135 USB_DBG_HEX(conf_descr+index, len_desc);
va009039 8:6463cd1964c0 136 switch (id) {
va009039 8:6463cd1964c0 137 case CONFIGURATION_DESCRIPTOR:
va009039 8:6463cd1964c0 138 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]);
va009039 8:6463cd1964c0 139 dev->setNbIntf(conf_descr[4]);
va009039 8:6463cd1964c0 140 break;
va009039 8:6463cd1964c0 141 case INTERFACE_DESCRIPTOR:
va009039 8:6463cd1964c0 142 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) {
va009039 9:7f9f64cf5ded 143 intf_nb++;
va009039 9:7f9f64cf5ded 144 current_intf = conf_descr[index + 2];
va009039 9:7f9f64cf5ded 145 dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
va009039 9:7f9f64cf5ded 146 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]);
va009039 8:6463cd1964c0 147 parsing_intf = true;
va009039 8:6463cd1964c0 148 } else {
va009039 8:6463cd1964c0 149 parsing_intf = false;
va009039 7:9a20482c9a7a 150 }
va009039 8:6463cd1964c0 151 break;
va009039 8:6463cd1964c0 152 case ENDPOINT_DESCRIPTOR:
va009039 8:6463cd1964c0 153 ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index);
va009039 8:6463cd1964c0 154 if (parsing_intf && (intf_nb <= MAX_INTF) ) {
va009039 9:7f9f64cf5ded 155 ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03);
va009039 9:7f9f64cf5ded 156 ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT;
va009039 9:7f9f64cf5ded 157 if(pEnumerator->useEndpoint(current_intf, type, dir)) {
va009039 9:7f9f64cf5ded 158 ep = new USBEndpoint;
va009039 9:7f9f64cf5ded 159 ep->setDevice(dev);
va009039 9:7f9f64cf5ded 160 ep->setType(type);
va009039 9:7f9f64cf5ded 161 ep->setAddress(ep_desc->bEndpointAddress);
va009039 9:7f9f64cf5ded 162 ep->setSize(ep_desc->wMaxPacketSize);
va009039 9:7f9f64cf5ded 163 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev);
va009039 9:7f9f64cf5ded 164 dev->addEndpoint(current_intf, ep);
va009039 8:6463cd1964c0 165 }
va009039 8:6463cd1964c0 166 }
va009039 8:6463cd1964c0 167 break;
va009039 8:6463cd1964c0 168 case HID_DESCRIPTOR:
va009039 8:6463cd1964c0 169 //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
va009039 8:6463cd1964c0 170 break;
va009039 8:6463cd1964c0 171 default:
va009039 8:6463cd1964c0 172 break;
va009039 7:9a20482c9a7a 173 }
va009039 8:6463cd1964c0 174 index += len_desc;
va009039 7:9a20482c9a7a 175 }
va009039 7:9a20482c9a7a 176 }
va009039 7:9a20482c9a7a 177
va009039 7:9a20482c9a7a 178 USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
va009039 7:9a20482c9a7a 179 SETUP_PACKET setup = {requestType, request, value, index};
va009039 8:6463cd1964c0 180 int result = ControlRead(dev, &setup, buf, len);
va009039 8:6463cd1964c0 181 //USB_DBG2("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 182 return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 183 }
va009039 7:9a20482c9a7a 184
va009039 7:9a20482c9a7a 185 USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
va009039 7:9a20482c9a7a 186 SETUP_PACKET setup = {requestType, request, value, index};
va009039 8:6463cd1964c0 187 int result = ControlWrite(dev, &setup, buf, len);
va009039 7:9a20482c9a7a 188 if (result >= 0) {
va009039 7:9a20482c9a7a 189 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 190 }
va009039 7:9a20482c9a7a 191 USB_DBG("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 192 USB_DBG_HEX(buf, len);
va009039 7:9a20482c9a7a 193 return USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 194 }
va009039 7:9a20482c9a7a 195
va009039 9:7f9f64cf5ded 196 USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
va009039 9:7f9f64cf5ded 197 if (blocking == false) {
va009039 9:7f9f64cf5ded 198 ep->setType(BULK_ENDPOINT);
va009039 9:7f9f64cf5ded 199 ep->setBuffer(buf, len);
va009039 9:7f9f64cf5ded 200 ep_queue.push(ep);
va009039 9:7f9f64cf5ded 201 return USB_TYPE_PROCESSING;
va009039 9:7f9f64cf5ded 202 }
va009039 9:7f9f64cf5ded 203 int result = bulkReadBLOCK(ep, buf, len, -1);
va009039 7:9a20482c9a7a 204 if (result >= 0) {
va009039 7:9a20482c9a7a 205 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 206 }
va009039 7:9a20482c9a7a 207 //USB_DBG2("result=%d %02x", result, host->LastStatus);
va009039 7:9a20482c9a7a 208 return USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 209 }
va009039 7:9a20482c9a7a 210
va009039 9:7f9f64cf5ded 211 USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
va009039 7:9a20482c9a7a 212 USB_TEST_ASSERT(blocking);
va009039 9:7f9f64cf5ded 213 int result = bulkWriteNB(ep, buf, len);
va009039 7:9a20482c9a7a 214 if (result >= 0) {
va009039 7:9a20482c9a7a 215 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 216 }
va009039 7:9a20482c9a7a 217 USB_DBG2("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 218 return USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 219 }
va009039 7:9a20482c9a7a 220
va009039 9:7f9f64cf5ded 221 USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
va009039 9:7f9f64cf5ded 222 if (blocking == false) {
va009039 9:7f9f64cf5ded 223 ep->setType(INTERRUPT_ENDPOINT);
va009039 9:7f9f64cf5ded 224 ep->setBuffer(buf, len);
va009039 9:7f9f64cf5ded 225 ep_queue.push(ep);
va009039 9:7f9f64cf5ded 226 return USB_TYPE_PROCESSING;
va009039 7:9a20482c9a7a 227 }
va009039 9:7f9f64cf5ded 228 interruptReadNB(ep, buf, len);
va009039 9:7f9f64cf5ded 229 return USB_TYPE_OK;
va009039 9:7f9f64cf5ded 230 }
va009039 9:7f9f64cf5ded 231
va009039 9:7f9f64cf5ded 232 USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
va009039 9:7f9f64cf5ded 233 USB_TEST_ASSERT(blocking);
va009039 9:7f9f64cf5ded 234 interruptWriteNB(ep, buf, len);
va009039 9:7f9f64cf5ded 235 return USB_TYPE_OK;
va009039 9:7f9f64cf5ded 236 }
va009039 9:7f9f64cf5ded 237
va009039 9:7f9f64cf5ded 238 USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
va009039 9:7f9f64cf5ded 239 if (blocking == false) {
va009039 9:7f9f64cf5ded 240 ep->setType(ISOCHRONOUS_ENDPOINT);
va009039 9:7f9f64cf5ded 241 ep->setBuffer(buf, len);
va009039 9:7f9f64cf5ded 242 ep_queue.push(ep);
va009039 9:7f9f64cf5ded 243 return USB_TYPE_PROCESSING;
va009039 9:7f9f64cf5ded 244 }
va009039 9:7f9f64cf5ded 245 isochronousReadNB(ep, buf, len);
va009039 9:7f9f64cf5ded 246 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 247 }
va009039 7:9a20482c9a7a 248
va009039 8:6463cd1964c0 249 int USBHost::ControlRead(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) {
va009039 8:6463cd1964c0 250 USB_TEST_ASSERT(dev);
va009039 8:6463cd1964c0 251 USBEndpoint* ep = dev->getEpCtl();
va009039 8:6463cd1964c0 252 USB_TEST_ASSERT(ep);
va009039 8:6463cd1964c0 253 setAddr(dev->getAddress(), dev->getSpeed());
va009039 7:9a20482c9a7a 254 token_setup(ep, setup, size); // setup stage
va009039 7:9a20482c9a7a 255 if (LastStatus != ACK) {
va009039 7:9a20482c9a7a 256 USB_DBG("setup %02x", LastStatus);
va009039 7:9a20482c9a7a 257 return -1;
va009039 7:9a20482c9a7a 258 }
va009039 7:9a20482c9a7a 259 int read_len = 0;
va009039 7:9a20482c9a7a 260 while(read_len < size) {
va009039 7:9a20482c9a7a 261 int size2 = std::min(size-read_len, ep->getSize());
va009039 7:9a20482c9a7a 262 int result = token_in(ep, data+read_len, size2);
va009039 7:9a20482c9a7a 263 //USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 264 if (result < 0) {
va009039 7:9a20482c9a7a 265 USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus);
va009039 7:9a20482c9a7a 266 return result;
va009039 7:9a20482c9a7a 267 }
va009039 7:9a20482c9a7a 268 read_len += result;
va009039 7:9a20482c9a7a 269 if (result < ep->getSize()) {
va009039 7:9a20482c9a7a 270 break;
va009039 7:9a20482c9a7a 271 }
va009039 7:9a20482c9a7a 272 }
va009039 7:9a20482c9a7a 273 ep->setData01(DATA1);
va009039 7:9a20482c9a7a 274 int result = token_out(ep); // status stage
va009039 7:9a20482c9a7a 275 if (result < 0) {
va009039 7:9a20482c9a7a 276 USB_DBG("status token_out %02x", LastStatus);
va009039 7:9a20482c9a7a 277 if (LastStatus == STALL) {
va009039 8:6463cd1964c0 278 ep->setLengthTransferred(read_len);
va009039 7:9a20482c9a7a 279 return read_len;
va009039 7:9a20482c9a7a 280 }
va009039 7:9a20482c9a7a 281 return result;
va009039 7:9a20482c9a7a 282 }
va009039 8:6463cd1964c0 283 ep->setLengthTransferred(read_len);
va009039 7:9a20482c9a7a 284 return read_len;
va009039 7:9a20482c9a7a 285 }
va009039 7:9a20482c9a7a 286
va009039 8:6463cd1964c0 287 int USBHost::ControlWrite(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) {
va009039 8:6463cd1964c0 288 USB_TEST_ASSERT(dev);
va009039 8:6463cd1964c0 289 USBEndpoint* ep = dev->getEpCtl();
va009039 8:6463cd1964c0 290 USB_TEST_ASSERT(ep);
va009039 8:6463cd1964c0 291 setAddr(dev->getAddress(), dev->getSpeed());
va009039 7:9a20482c9a7a 292 token_setup(ep, setup, size); // setup stage
va009039 7:9a20482c9a7a 293 if (LastStatus != ACK) {
va009039 7:9a20482c9a7a 294 USB_DBG("setup %02x", LastStatus);
va009039 7:9a20482c9a7a 295 return -1;
va009039 7:9a20482c9a7a 296 }
va009039 7:9a20482c9a7a 297 int write_len = 0;
va009039 7:9a20482c9a7a 298 if (data != NULL) {
va009039 7:9a20482c9a7a 299 write_len = token_out(ep, data, size);
va009039 7:9a20482c9a7a 300 if (write_len < 0) {
va009039 7:9a20482c9a7a 301 return -1;
va009039 7:9a20482c9a7a 302 }
va009039 7:9a20482c9a7a 303 }
va009039 7:9a20482c9a7a 304 ep->setData01(DATA1);
va009039 7:9a20482c9a7a 305 int result = token_in(ep); // status stage
va009039 7:9a20482c9a7a 306 if (result < 0) {
va009039 7:9a20482c9a7a 307 USB_DBG("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 308 //return result;
va009039 7:9a20482c9a7a 309 }
va009039 8:6463cd1964c0 310 ep->setLengthTransferred(write_len);
va009039 7:9a20482c9a7a 311 return write_len;
va009039 7:9a20482c9a7a 312 }
va009039 7:9a20482c9a7a 313
va009039 9:7f9f64cf5ded 314 int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size)
va009039 9:7f9f64cf5ded 315 {
va009039 8:6463cd1964c0 316 USB_TEST_ASSERT(ep);
va009039 8:6463cd1964c0 317 USBDeviceConnected* dev = ep->getDevice();
va009039 8:6463cd1964c0 318 USB_TEST_ASSERT(dev);
va009039 8:6463cd1964c0 319 setAddr(dev->getAddress(), dev->getSpeed());
va009039 7:9a20482c9a7a 320 setEndpoint();
va009039 7:9a20482c9a7a 321 const int retryLimit = 0;
va009039 7:9a20482c9a7a 322 int read_len = 0;
va009039 7:9a20482c9a7a 323 for(int n = 0; read_len < size; n++) {
va009039 7:9a20482c9a7a 324 int size2 = std::min(size-read_len, ep->getSize());
va009039 7:9a20482c9a7a 325 int result = token_in(ep, data+read_len, size2, retryLimit);
va009039 7:9a20482c9a7a 326 if (result < 0) {
va009039 7:9a20482c9a7a 327 if (LastStatus == NAK) {
va009039 7:9a20482c9a7a 328 if (n == 0) {
va009039 7:9a20482c9a7a 329 return -1;
va009039 7:9a20482c9a7a 330 }
va009039 7:9a20482c9a7a 331 break;
va009039 7:9a20482c9a7a 332 }
va009039 8:6463cd1964c0 333 //USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 334 return result;
va009039 7:9a20482c9a7a 335 }
va009039 7:9a20482c9a7a 336 read_len += result;
va009039 7:9a20482c9a7a 337 if (result < ep->getSize()) {
va009039 7:9a20482c9a7a 338 break;
va009039 7:9a20482c9a7a 339 }
va009039 7:9a20482c9a7a 340 }
va009039 8:6463cd1964c0 341 ep->setLengthTransferred(read_len);
va009039 7:9a20482c9a7a 342 return read_len;
va009039 7:9a20482c9a7a 343 }
va009039 7:9a20482c9a7a 344
va009039 9:7f9f64cf5ded 345 int USBHost::interruptWriteNB(USBEndpoint* ep, const uint8_t* data, int size)
va009039 9:7f9f64cf5ded 346 {
va009039 9:7f9f64cf5ded 347 USB_TEST_ASSERT(ep);
va009039 9:7f9f64cf5ded 348 USBDeviceConnected* dev = ep->getDevice();
va009039 9:7f9f64cf5ded 349 USB_TEST_ASSERT(dev);
va009039 9:7f9f64cf5ded 350 setAddr(dev->getAddress(), dev->getSpeed());
va009039 9:7f9f64cf5ded 351 setEndpoint();
va009039 9:7f9f64cf5ded 352 const int retryLimit = 0;
va009039 9:7f9f64cf5ded 353 int transferred_len = 0;
va009039 9:7f9f64cf5ded 354 for(int n = 0; transferred_len < size; n++) {
va009039 9:7f9f64cf5ded 355 int size2 = std::min(size-transferred_len, ep->getSize());
va009039 9:7f9f64cf5ded 356 int result = token_out(ep, data+transferred_len, size2, retryLimit);
va009039 9:7f9f64cf5ded 357 if (result < 0) {
va009039 9:7f9f64cf5ded 358 if (LastStatus == NAK) {
va009039 9:7f9f64cf5ded 359 if (n == 0) {
va009039 9:7f9f64cf5ded 360 return -1;
va009039 9:7f9f64cf5ded 361 }
va009039 9:7f9f64cf5ded 362 break;
va009039 9:7f9f64cf5ded 363 }
va009039 9:7f9f64cf5ded 364 //USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 9:7f9f64cf5ded 365 return result;
va009039 9:7f9f64cf5ded 366 }
va009039 9:7f9f64cf5ded 367 transferred_len += result;
va009039 9:7f9f64cf5ded 368 if (result < ep->getSize()) {
va009039 9:7f9f64cf5ded 369 break;
va009039 9:7f9f64cf5ded 370 }
va009039 9:7f9f64cf5ded 371 }
va009039 9:7f9f64cf5ded 372 ep->setLengthTransferred(transferred_len);
va009039 9:7f9f64cf5ded 373 return transferred_len;
va009039 9:7f9f64cf5ded 374 }
va009039 9:7f9f64cf5ded 375
va009039 9:7f9f64cf5ded 376 int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size)
va009039 9:7f9f64cf5ded 377 {
va009039 9:7f9f64cf5ded 378 return bulkReadBLOCK(ep, data, size, 0);
va009039 9:7f9f64cf5ded 379 }
va009039 9:7f9f64cf5ded 380
va009039 9:7f9f64cf5ded 381 int USBHost::bulkReadBLOCK(USBEndpoint* ep, uint8_t* data, int size, int timeout_ms) {
va009039 8:6463cd1964c0 382 USB_TEST_ASSERT(ep);
va009039 8:6463cd1964c0 383 USBDeviceConnected* dev = ep->getDevice();
va009039 8:6463cd1964c0 384 USB_TEST_ASSERT(dev);
va009039 8:6463cd1964c0 385 setAddr(dev->getAddress());
va009039 7:9a20482c9a7a 386 setEndpoint();
va009039 7:9a20482c9a7a 387 int retryLimit = (timeout_ms == 0) ? 0 : 10;
va009039 7:9a20482c9a7a 388 int read_len = 0;
va009039 7:9a20482c9a7a 389 Timer t;
va009039 7:9a20482c9a7a 390 for(int n = 0; read_len < size; n++) {
va009039 7:9a20482c9a7a 391 int size2 = std::min(size-read_len, ep->getSize());
va009039 7:9a20482c9a7a 392 int result = token_in(ep, data+read_len, size2, retryLimit);
va009039 7:9a20482c9a7a 393 if (result < 0) {
va009039 7:9a20482c9a7a 394 if (LastStatus == NAK) {
va009039 7:9a20482c9a7a 395 if (n == 0) {
va009039 7:9a20482c9a7a 396 return -1;
va009039 7:9a20482c9a7a 397 }
va009039 7:9a20482c9a7a 398 break;
va009039 7:9a20482c9a7a 399 }
va009039 8:6463cd1964c0 400 //USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 401 return result;
va009039 7:9a20482c9a7a 402 }
va009039 7:9a20482c9a7a 403 read_len += result;
va009039 7:9a20482c9a7a 404 if (result < ep->getSize()) {
va009039 7:9a20482c9a7a 405 break;
va009039 7:9a20482c9a7a 406 }
va009039 7:9a20482c9a7a 407 if (timeout_ms > 0 && t.read_ms() > timeout_ms) {
va009039 7:9a20482c9a7a 408 USB_DBG("timeout_ms: %d", timeout_ms);
va009039 7:9a20482c9a7a 409 break;
va009039 7:9a20482c9a7a 410 }
va009039 7:9a20482c9a7a 411 }
va009039 8:6463cd1964c0 412 ep->setLengthTransferred(read_len);
va009039 7:9a20482c9a7a 413 return read_len;
va009039 7:9a20482c9a7a 414 }
va009039 7:9a20482c9a7a 415
va009039 9:7f9f64cf5ded 416 int USBHost::bulkWriteNB(USBEndpoint* ep, const uint8_t* data, int size) {
va009039 8:6463cd1964c0 417 USB_TEST_ASSERT(ep);
va009039 8:6463cd1964c0 418 USBDeviceConnected* dev = ep->getDevice();
va009039 8:6463cd1964c0 419 USB_TEST_ASSERT(dev);
va009039 8:6463cd1964c0 420 setAddr(dev->getAddress());
va009039 7:9a20482c9a7a 421 setEndpoint();
va009039 7:9a20482c9a7a 422 int write_len = 0;
va009039 7:9a20482c9a7a 423 for(int n = 0; write_len < size; n++) {
va009039 7:9a20482c9a7a 424 int size2 = std::min(size-write_len, ep->getSize());
va009039 7:9a20482c9a7a 425 int result = token_out(ep, data+write_len, size2);
va009039 7:9a20482c9a7a 426 if (result < 0) {
va009039 7:9a20482c9a7a 427 if (LastStatus == NAK) {
va009039 7:9a20482c9a7a 428 if (n == 0) {
va009039 7:9a20482c9a7a 429 return -1;
va009039 7:9a20482c9a7a 430 }
va009039 7:9a20482c9a7a 431 break;
va009039 7:9a20482c9a7a 432 }
va009039 7:9a20482c9a7a 433 USB_DBG("token_out result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 434 return result;
va009039 7:9a20482c9a7a 435 }
va009039 7:9a20482c9a7a 436 write_len += result;
va009039 7:9a20482c9a7a 437 if (result < ep->getSize()) {
va009039 7:9a20482c9a7a 438 break;
va009039 7:9a20482c9a7a 439 }
va009039 7:9a20482c9a7a 440 }
va009039 8:6463cd1964c0 441 ep->setLengthTransferred(write_len);
va009039 7:9a20482c9a7a 442 return write_len;
va009039 7:9a20482c9a7a 443 }
va009039 7:9a20482c9a7a 444
va009039 9:7f9f64cf5ded 445 int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) {
va009039 8:6463cd1964c0 446 USBDeviceConnected* dev = ep->getDevice();
va009039 8:6463cd1964c0 447 USB_TEST_ASSERT(dev);
va009039 8:6463cd1964c0 448 setAddr(dev->getAddress());
va009039 8:6463cd1964c0 449 int result = token_iso_in(ep, data, size);
va009039 8:6463cd1964c0 450 if (result >= 0) {
va009039 8:6463cd1964c0 451 ep->setLengthTransferred(result);
va009039 8:6463cd1964c0 452 }
va009039 8:6463cd1964c0 453 return result;
va009039 7:9a20482c9a7a 454 }
va009039 7:9a20482c9a7a 455
va009039 9:7f9f64cf5ded 456 void USBHost::task()
va009039 9:7f9f64cf5ded 457 {
va009039 9:7f9f64cf5ded 458 if (ep_queue.empty()) {
va009039 9:7f9f64cf5ded 459 return;
va009039 9:7f9f64cf5ded 460 }
va009039 9:7f9f64cf5ded 461 USBEndpoint* ep = ep_queue.pop();
va009039 9:7f9f64cf5ded 462 USB_TEST_ASSERT(ep);
va009039 9:7f9f64cf5ded 463 ep->setLengthTransferred(0);
va009039 9:7f9f64cf5ded 464 switch(ep->getType()) {
va009039 9:7f9f64cf5ded 465 case INTERRUPT_ENDPOINT:
va009039 9:7f9f64cf5ded 466 if (ep->getDir() == IN) {
va009039 9:7f9f64cf5ded 467 interruptReadNB(ep, ep->getBufStart(), ep->getBufSize());
va009039 9:7f9f64cf5ded 468 }
va009039 9:7f9f64cf5ded 469 break;
va009039 9:7f9f64cf5ded 470 case BULK_ENDPOINT:
va009039 9:7f9f64cf5ded 471 if (ep->getDir() == IN) {
va009039 9:7f9f64cf5ded 472 bulkReadNB(ep, ep->getBufStart(), ep->getBufSize());
va009039 9:7f9f64cf5ded 473 }
va009039 9:7f9f64cf5ded 474 break;
va009039 9:7f9f64cf5ded 475 case ISOCHRONOUS_ENDPOINT:
va009039 9:7f9f64cf5ded 476 if (ep->getDir() == IN) {
va009039 9:7f9f64cf5ded 477 isochronousReadNB(ep, ep->getBufStart(), ep->getBufSize());
va009039 9:7f9f64cf5ded 478 }
va009039 9:7f9f64cf5ded 479 break;
va009039 9:7f9f64cf5ded 480 }
va009039 9:7f9f64cf5ded 481 ep->call();
va009039 9:7f9f64cf5ded 482 }