Simple USBHost library for STM32F746NG Discovery board. Only either the Fastspeed or the Highspeed port can be used( not both together)

Dependents:   DISCO-F746NG_USB_Host

Fork of KL46Z-USBHost by Norimasa Okamoto

Committer:
va009039
Date:
Fri Jan 31 13:45:07 2014 +0000
Revision:
8:6463cd1964c0
Parent:
7:9a20482c9a7a
Child:
9:7f9f64cf5ded
USB hub support.

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