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:
Tue Jan 28 06:50:12 2014 +0000
Revision:
7:9a20482c9a7a
Child:
8:6463cd1964c0
Control transfer status stage must set DATA1.

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 7:9a20482c9a7a 23 #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 24 #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
va009039 7:9a20482c9a7a 25
va009039 7:9a20482c9a7a 26 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0);
va009039 7:9a20482c9a7a 27
va009039 7:9a20482c9a7a 28 USBHost* USBHost::inst = NULL;
va009039 7:9a20482c9a7a 29
va009039 7:9a20482c9a7a 30 USBHost* USBHost::getHostInst()
va009039 7:9a20482c9a7a 31 {
va009039 7:9a20482c9a7a 32 if (inst == NULL) {
va009039 7:9a20482c9a7a 33 inst = new USBHost();
va009039 7:9a20482c9a7a 34 inst->init();
va009039 7:9a20482c9a7a 35 }
va009039 7:9a20482c9a7a 36 return inst;
va009039 7:9a20482c9a7a 37 }
va009039 7:9a20482c9a7a 38
va009039 7:9a20482c9a7a 39 USBHost::USBHost() {
va009039 7:9a20482c9a7a 40 }
va009039 7:9a20482c9a7a 41
va009039 7:9a20482c9a7a 42 /* virtual */ bool USBHost::enumeration() {
va009039 7:9a20482c9a7a 43 USBEndpoint* ep = &ep_ctl_in_out;
va009039 7:9a20482c9a7a 44 uint8_t desc[64];
va009039 7:9a20482c9a7a 45 ep->setAddress(0);
va009039 7:9a20482c9a7a 46 ep->setSize(8); // max packet size
va009039 7:9a20482c9a7a 47 dev.addr = 0;
va009039 7:9a20482c9a7a 48 wait_ms(100);
va009039 7:9a20482c9a7a 49 SETUP_PACKET setup_get_descriptor = {0x80, GET_DESCRIPTOR, 1<<8, 0, 0};
va009039 7:9a20482c9a7a 50 int result = ControlRead(&setup_get_descriptor, desc, ep->getSize());
va009039 7:9a20482c9a7a 51 if (result < ep->getSize()) {
va009039 7:9a20482c9a7a 52 USB_DBG("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 53 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 54 return false;
va009039 7:9a20482c9a7a 55 }
va009039 7:9a20482c9a7a 56 USB_DBG_HEX(desc, result);
va009039 7:9a20482c9a7a 57 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 58 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
va009039 7:9a20482c9a7a 59 ep->setSize(dev_desc->bMaxPacketSize);
va009039 7:9a20482c9a7a 60
va009039 7:9a20482c9a7a 61 SETUP_PACKET setup_set_address = {0x00, SET_ADDRESS, 1, 0, 0};
va009039 7:9a20482c9a7a 62 result = ControlWrite(&setup_set_address);
va009039 7:9a20482c9a7a 63 if (result < 0) {
va009039 7:9a20482c9a7a 64 USB_DBG("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 65 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 66 return false;
va009039 7:9a20482c9a7a 67 }
va009039 7:9a20482c9a7a 68 wait_ms(100);
va009039 7:9a20482c9a7a 69 dev.addr = 1;
va009039 7:9a20482c9a7a 70
va009039 7:9a20482c9a7a 71 result = ControlRead(&setup_get_descriptor, desc, sizeof(desc));
va009039 7:9a20482c9a7a 72 if (result < 8) {
va009039 7:9a20482c9a7a 73 USB_DBG("result=%d", result);
va009039 7:9a20482c9a7a 74 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 75 return false;
va009039 7:9a20482c9a7a 76 }
va009039 7:9a20482c9a7a 77 USB_DBG_HEX(desc, result);
va009039 7:9a20482c9a7a 78 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 79
va009039 7:9a20482c9a7a 80 dev.vid = dev_desc->idVendor;
va009039 7:9a20482c9a7a 81 dev.pid = dev_desc->idProduct;
va009039 7:9a20482c9a7a 82 USB_INFO("USB VID: %04x, PID: %04x\n", dev.vid, dev.pid);
va009039 7:9a20482c9a7a 83 if (dev_desc->bDeviceClass == HUB_CLASS) {
va009039 7:9a20482c9a7a 84 USB_INFO("USB hub not supported.\n\n");
va009039 7:9a20482c9a7a 85 exit(1);
va009039 7:9a20482c9a7a 86 }
va009039 7:9a20482c9a7a 87
va009039 7:9a20482c9a7a 88 setup_get_descriptor.wValue = 2<<8; // config descriptor
va009039 7:9a20482c9a7a 89 result = ControlRead(&setup_get_descriptor, desc, 4);
va009039 7:9a20482c9a7a 90 if (result != 4) {
va009039 7:9a20482c9a7a 91 USB_DBG("result=%d", result);
va009039 7:9a20482c9a7a 92 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 93 return false;
va009039 7:9a20482c9a7a 94 }
va009039 7:9a20482c9a7a 95 USB_DBG_HEX(desc, 4);
va009039 7:9a20482c9a7a 96 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 97
va009039 7:9a20482c9a7a 98 int TotalLength = desc[2]|desc[3]<<8;
va009039 7:9a20482c9a7a 99 uint8_t* buf = new uint8_t[TotalLength];
va009039 7:9a20482c9a7a 100 result = ControlRead(&setup_get_descriptor, buf, TotalLength);
va009039 7:9a20482c9a7a 101 if (result != TotalLength) {
va009039 7:9a20482c9a7a 102 USB_DBG("result=%d TotalLength=%d %02x", result, TotalLength, LastStatus);
va009039 7:9a20482c9a7a 103 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 104 return false;
va009039 7:9a20482c9a7a 105 }
va009039 7:9a20482c9a7a 106 USB_DBG_HEX(buf, TotalLength);
va009039 7:9a20482c9a7a 107 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 108
va009039 7:9a20482c9a7a 109 for(int i = 0; i < TotalLength; ) {
va009039 7:9a20482c9a7a 110 int Length = buf[i];
va009039 7:9a20482c9a7a 111 uint8_t DescriptorType = buf[i+1];
va009039 7:9a20482c9a7a 112 if (DescriptorType == 0x05) { // endpoint
va009039 7:9a20482c9a7a 113 EndpointDescriptor* desc = reinterpret_cast<EndpointDescriptor*>(buf+i);
va009039 7:9a20482c9a7a 114 USBEndpoint* ep = NULL;
va009039 7:9a20482c9a7a 115 if (desc->bmAttributes == 0x03) { // interrupt
va009039 7:9a20482c9a7a 116 if (desc->bEndpointAddress & 0x80) {
va009039 7:9a20482c9a7a 117 ep = &ep_int_in;
va009039 7:9a20482c9a7a 118 }
va009039 7:9a20482c9a7a 119 } else if (desc->bmAttributes == 0x02) { // bulk
va009039 7:9a20482c9a7a 120 ep = (desc->bEndpointAddress & 0x80) ? &ep_bulk_in : &ep_bulk_out;
va009039 7:9a20482c9a7a 121 }
va009039 7:9a20482c9a7a 122 if (ep) {
va009039 7:9a20482c9a7a 123 ep->setAddress(desc->bEndpointAddress);
va009039 7:9a20482c9a7a 124 ep->setSize(desc->wMaxPacketSize);
va009039 7:9a20482c9a7a 125 }
va009039 7:9a20482c9a7a 126 }
va009039 7:9a20482c9a7a 127 USB_DBG_HEX(buf+i, Length);
va009039 7:9a20482c9a7a 128 i += Length;
va009039 7:9a20482c9a7a 129 }
va009039 7:9a20482c9a7a 130 delete[] buf;
va009039 7:9a20482c9a7a 131
va009039 7:9a20482c9a7a 132 // config = 1
va009039 7:9a20482c9a7a 133 SETUP_PACKET setup_set_config = {0x00, SET_CONFIGURATION, 1, 0, 0};
va009039 7:9a20482c9a7a 134 result = ControlWrite(&setup_set_config);
va009039 7:9a20482c9a7a 135 if (result < 0) {
va009039 7:9a20482c9a7a 136 USB_DBG("set config: %02x", LastStatus);
va009039 7:9a20482c9a7a 137 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 138 if (lowSpeed && LastStatus == STALL) { // TODO:
va009039 7:9a20482c9a7a 139 wait_ms(100);
va009039 7:9a20482c9a7a 140 return true;
va009039 7:9a20482c9a7a 141 }
va009039 7:9a20482c9a7a 142 return false;
va009039 7:9a20482c9a7a 143 }
va009039 7:9a20482c9a7a 144 wait_ms(100);
va009039 7:9a20482c9a7a 145 return true;
va009039 7:9a20482c9a7a 146 }
va009039 7:9a20482c9a7a 147
va009039 7:9a20482c9a7a 148 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 149 SETUP_PACKET setup = {requestType, request, value, index};
va009039 7:9a20482c9a7a 150 int result = ControlRead(&setup, buf, len);
va009039 7:9a20482c9a7a 151 USB_DBG2("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 152 return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 153 }
va009039 7:9a20482c9a7a 154
va009039 7:9a20482c9a7a 155 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 156 SETUP_PACKET setup = {requestType, request, value, index};
va009039 7:9a20482c9a7a 157 int result = ControlWrite(&setup, buf, len);
va009039 7:9a20482c9a7a 158 if (result >= 0) {
va009039 7:9a20482c9a7a 159 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 160 }
va009039 7:9a20482c9a7a 161 USB_DBG("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 162 USB_DBG_ERRSTAT();
va009039 7:9a20482c9a7a 163 USB_DBG_HEX(buf, len);
va009039 7:9a20482c9a7a 164 return USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 165 }
va009039 7:9a20482c9a7a 166
va009039 7:9a20482c9a7a 167 USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
va009039 7:9a20482c9a7a 168 USB_TEST_ASSERT(blocking);
va009039 7:9a20482c9a7a 169 int result = BulkRead(buf, len);
va009039 7:9a20482c9a7a 170 if (result >= 0) {
va009039 7:9a20482c9a7a 171 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 172 }
va009039 7:9a20482c9a7a 173 //USB_DBG2("result=%d %02x", result, host->LastStatus);
va009039 7:9a20482c9a7a 174 return USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 175 }
va009039 7:9a20482c9a7a 176
va009039 7:9a20482c9a7a 177 USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
va009039 7:9a20482c9a7a 178 USB_TEST_ASSERT(blocking);
va009039 7:9a20482c9a7a 179 int result = BulkWrite(buf, len);
va009039 7:9a20482c9a7a 180 if (result >= 0) {
va009039 7:9a20482c9a7a 181 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 182 }
va009039 7:9a20482c9a7a 183 USB_DBG2("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 184 return USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 185 }
va009039 7:9a20482c9a7a 186
va009039 7:9a20482c9a7a 187 USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
va009039 7:9a20482c9a7a 188 USB_TEST_ASSERT(blocking);
va009039 7:9a20482c9a7a 189 int result = InterruptRead(buf, len);
va009039 7:9a20482c9a7a 190 if (result >= 0) {
va009039 7:9a20482c9a7a 191 return USB_TYPE_OK;
va009039 7:9a20482c9a7a 192 }
va009039 7:9a20482c9a7a 193 return USB_TYPE_ERROR;
va009039 7:9a20482c9a7a 194 }
va009039 7:9a20482c9a7a 195
va009039 7:9a20482c9a7a 196 int USBHost::ControlRead(SETUP_PACKET* setup, uint8_t* data, int size) {
va009039 7:9a20482c9a7a 197 USBEndpoint* ep = &ep_ctl_in_out;
va009039 7:9a20482c9a7a 198 setAddr(dev.addr);
va009039 7:9a20482c9a7a 199 token_setup(ep, setup, size); // setup stage
va009039 7:9a20482c9a7a 200 if (LastStatus != ACK) {
va009039 7:9a20482c9a7a 201 USB_DBG("setup %02x", LastStatus);
va009039 7:9a20482c9a7a 202 return -1;
va009039 7:9a20482c9a7a 203 }
va009039 7:9a20482c9a7a 204 int read_len = 0;
va009039 7:9a20482c9a7a 205 while(read_len < size) {
va009039 7:9a20482c9a7a 206 int size2 = std::min(size-read_len, ep->getSize());
va009039 7:9a20482c9a7a 207 int result = token_in(ep, data+read_len, size2);
va009039 7:9a20482c9a7a 208 //USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 209 if (result < 0) {
va009039 7:9a20482c9a7a 210 USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus);
va009039 7:9a20482c9a7a 211 return result;
va009039 7:9a20482c9a7a 212 }
va009039 7:9a20482c9a7a 213 read_len += result;
va009039 7:9a20482c9a7a 214 if (result < ep->getSize()) {
va009039 7:9a20482c9a7a 215 break;
va009039 7:9a20482c9a7a 216 }
va009039 7:9a20482c9a7a 217 }
va009039 7:9a20482c9a7a 218 ep->setData01(DATA1);
va009039 7:9a20482c9a7a 219 int result = token_out(ep); // status stage
va009039 7:9a20482c9a7a 220 if (result < 0) {
va009039 7:9a20482c9a7a 221 USB_DBG("status token_out %02x", LastStatus);
va009039 7:9a20482c9a7a 222 if (LastStatus == STALL) {
va009039 7:9a20482c9a7a 223 return read_len;
va009039 7:9a20482c9a7a 224 }
va009039 7:9a20482c9a7a 225 return result;
va009039 7:9a20482c9a7a 226 }
va009039 7:9a20482c9a7a 227 return read_len;
va009039 7:9a20482c9a7a 228 }
va009039 7:9a20482c9a7a 229
va009039 7:9a20482c9a7a 230 int USBHost::ControlWrite(SETUP_PACKET* setup, uint8_t* data, int size) {
va009039 7:9a20482c9a7a 231 USBEndpoint* ep = &ep_ctl_in_out;
va009039 7:9a20482c9a7a 232 setAddr(dev.addr);
va009039 7:9a20482c9a7a 233 token_setup(ep, setup, size); // setup stage
va009039 7:9a20482c9a7a 234 if (LastStatus != ACK) {
va009039 7:9a20482c9a7a 235 USB_DBG("setup %02x", LastStatus);
va009039 7:9a20482c9a7a 236 return -1;
va009039 7:9a20482c9a7a 237 }
va009039 7:9a20482c9a7a 238 int write_len = 0;
va009039 7:9a20482c9a7a 239 if (data != NULL) {
va009039 7:9a20482c9a7a 240 write_len = token_out(ep, data, size);
va009039 7:9a20482c9a7a 241 if (write_len < 0) {
va009039 7:9a20482c9a7a 242 return -1;
va009039 7:9a20482c9a7a 243 }
va009039 7:9a20482c9a7a 244 }
va009039 7:9a20482c9a7a 245 ep->setData01(DATA1);
va009039 7:9a20482c9a7a 246 int result = token_in(ep); // status stage
va009039 7:9a20482c9a7a 247 if (result < 0) {
va009039 7:9a20482c9a7a 248 USB_DBG("result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 249 //return result;
va009039 7:9a20482c9a7a 250 }
va009039 7:9a20482c9a7a 251 return write_len;
va009039 7:9a20482c9a7a 252 }
va009039 7:9a20482c9a7a 253
va009039 7:9a20482c9a7a 254 int USBHost::InterruptRead(uint8_t* data, int size) {
va009039 7:9a20482c9a7a 255 USBEndpoint* ep = &ep_int_in;
va009039 7:9a20482c9a7a 256 setAddr(dev.addr);
va009039 7:9a20482c9a7a 257 setEndpoint();
va009039 7:9a20482c9a7a 258 const int retryLimit = 0;
va009039 7:9a20482c9a7a 259 int read_len = 0;
va009039 7:9a20482c9a7a 260 for(int n = 0; read_len < size; n++) {
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, retryLimit);
va009039 7:9a20482c9a7a 263 if (result < 0) {
va009039 7:9a20482c9a7a 264 if (LastStatus == NAK) {
va009039 7:9a20482c9a7a 265 if (n == 0) {
va009039 7:9a20482c9a7a 266 return -1;
va009039 7:9a20482c9a7a 267 }
va009039 7:9a20482c9a7a 268 break;
va009039 7:9a20482c9a7a 269 }
va009039 7:9a20482c9a7a 270 USB_DBG("token_in result=%d %02x", result, 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 return read_len;
va009039 7:9a20482c9a7a 279 }
va009039 7:9a20482c9a7a 280
va009039 7:9a20482c9a7a 281 int USBHost::BulkRead(uint8_t* data, int size, int timeout_ms) {
va009039 7:9a20482c9a7a 282 USBEndpoint* ep = &ep_bulk_in;
va009039 7:9a20482c9a7a 283 setAddr(dev.addr);
va009039 7:9a20482c9a7a 284 setEndpoint();
va009039 7:9a20482c9a7a 285 int retryLimit = (timeout_ms == 0) ? 0 : 10;
va009039 7:9a20482c9a7a 286 int read_len = 0;
va009039 7:9a20482c9a7a 287 Timer t;
va009039 7:9a20482c9a7a 288 for(int n = 0; read_len < size; n++) {
va009039 7:9a20482c9a7a 289 int size2 = std::min(size-read_len, ep->getSize());
va009039 7:9a20482c9a7a 290 int result = token_in(ep, data+read_len, size2, retryLimit);
va009039 7:9a20482c9a7a 291 if (result < 0) {
va009039 7:9a20482c9a7a 292 if (LastStatus == NAK) {
va009039 7:9a20482c9a7a 293 if (n == 0) {
va009039 7:9a20482c9a7a 294 return -1;
va009039 7:9a20482c9a7a 295 }
va009039 7:9a20482c9a7a 296 break;
va009039 7:9a20482c9a7a 297 }
va009039 7:9a20482c9a7a 298 USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 299 return result;
va009039 7:9a20482c9a7a 300 }
va009039 7:9a20482c9a7a 301 read_len += result;
va009039 7:9a20482c9a7a 302 if (result < ep->getSize()) {
va009039 7:9a20482c9a7a 303 break;
va009039 7:9a20482c9a7a 304 }
va009039 7:9a20482c9a7a 305 if (timeout_ms > 0 && t.read_ms() > timeout_ms) {
va009039 7:9a20482c9a7a 306 USB_DBG("timeout_ms: %d", timeout_ms);
va009039 7:9a20482c9a7a 307 break;
va009039 7:9a20482c9a7a 308 }
va009039 7:9a20482c9a7a 309 }
va009039 7:9a20482c9a7a 310 return read_len;
va009039 7:9a20482c9a7a 311 }
va009039 7:9a20482c9a7a 312
va009039 7:9a20482c9a7a 313 int USBHost::BulkWrite(const uint8_t* data, int size) {
va009039 7:9a20482c9a7a 314 USBEndpoint* ep = &ep_bulk_out;
va009039 7:9a20482c9a7a 315 setAddr(dev.addr);
va009039 7:9a20482c9a7a 316 setEndpoint();
va009039 7:9a20482c9a7a 317 int write_len = 0;
va009039 7:9a20482c9a7a 318 for(int n = 0; write_len < size; n++) {
va009039 7:9a20482c9a7a 319 int size2 = std::min(size-write_len, ep->getSize());
va009039 7:9a20482c9a7a 320 int result = token_out(ep, data+write_len, size2);
va009039 7:9a20482c9a7a 321 if (result < 0) {
va009039 7:9a20482c9a7a 322 if (LastStatus == NAK) {
va009039 7:9a20482c9a7a 323 if (n == 0) {
va009039 7:9a20482c9a7a 324 return -1;
va009039 7:9a20482c9a7a 325 }
va009039 7:9a20482c9a7a 326 break;
va009039 7:9a20482c9a7a 327 }
va009039 7:9a20482c9a7a 328 USB_DBG("token_out result=%d %02x", result, LastStatus);
va009039 7:9a20482c9a7a 329 return result;
va009039 7:9a20482c9a7a 330 }
va009039 7:9a20482c9a7a 331 write_len += result;
va009039 7:9a20482c9a7a 332 if (result < ep->getSize()) {
va009039 7:9a20482c9a7a 333 break;
va009039 7:9a20482c9a7a 334 }
va009039 7:9a20482c9a7a 335 }
va009039 7:9a20482c9a7a 336 return write_len;
va009039 7:9a20482c9a7a 337 }
va009039 7:9a20482c9a7a 338
va009039 7:9a20482c9a7a 339 int USBHost::IsochronousRead(USBEndpoint* ep, uint8_t* data, int size) {
va009039 7:9a20482c9a7a 340 setAddr(dev.addr);
va009039 7:9a20482c9a7a 341 return token_iso_in(ep, data, size);
va009039 7:9a20482c9a7a 342 }
va009039 7:9a20482c9a7a 343