Simple USBHost library for Nucleo F446RE/F411RE/F401RE FRDM-KL46Z/KL25Z/F64F LPC4088/LPC1768

Dependencies:   FATFileSystem

Dependents:   F401RE-BTstack_example F401RE-USBHostMSD_HelloWorld

Fork of KL46Z-USBHost by Norimasa Okamoto

簡易USBホストライブラリです。
official-USBHostの下位互換で対応プログラムを僅かな修正で動かすことが出来ます。

Platforms

  • Nucleo F446RE
  • Nucleo F411RE
  • Nucleo F401RE
  • FRDM-K64F
  • FRDM-KL46Z
  • FRDM-KL25Z
  • LPC4088
  • LPC1768

Nucleo F446RE/F411RE/F401REのUSB接続方法

ST morphoUSB
U5V (CN10-8)VBUS (1 RED)
PA11 (CN10-14)DM  (2 WHITE)
PA12 (CN10-12)DP  (3 GREEN)
GND (CN10-20)GND (4 BLACK)

Examples

Import programF446RE-USBHostMouse_HelloWorld

USBHostMouse Hello World for ST-Nucleo-F446RE

Import programF401RE-USBHostMSD_HelloWorld

Simple USBHost MSD(USB flash drive) for Nucleo F401RE/FRDM-KL46Z test program

Import programF401RE-USBHostC270_example

Simple USBHost WebCam test program

Import programK64F_USBHostC270_example

Simple USBHost C270 example

Import programF401RE-BTstack_example

BTstack for Nucleo F401RE/FRDM-KL46Z example program

Import programUSBHostRSSI_example

Bluetooth device discovery example program.

Import programKL46Z-USBHostGPS_HelloWorld

Simple USBHost GPS Dongle Receiver for FRDM-KL46Z test program

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 }