Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of USBHost_DISCO-F746NG by
USBHost/USBHost.cpp@3:a3872f7593e2, 2014-01-25 (annotated)
- Committer:
- va009039
- Date:
- Sat Jan 25 12:51:44 2014 +0000
- Revision:
- 3:a3872f7593e2
fix max packet size
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 3:a3872f7593e2 | 1 | // Simple USBHost for FRDM-KL46Z |
va009039 | 3:a3872f7593e2 | 2 | #include "USBHost.h" |
va009039 | 3:a3872f7593e2 | 3 | #include <algorithm> |
va009039 | 3:a3872f7593e2 | 4 | |
va009039 | 3:a3872f7593e2 | 5 | template <bool>struct CtAssert; |
va009039 | 3:a3872f7593e2 | 6 | template <>struct CtAssert<true> {}; |
va009039 | 3:a3872f7593e2 | 7 | #define CTASSERT(A) CtAssert<A>(); |
va009039 | 3:a3872f7593e2 | 8 | |
va009039 | 3:a3872f7593e2 | 9 | |
va009039 | 3:a3872f7593e2 | 10 | #ifdef _USB_DBG |
va009039 | 3:a3872f7593e2 | 11 | #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0); |
va009039 | 3:a3872f7593e2 | 12 | #define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0); |
va009039 | 3:a3872f7593e2 | 13 | #define USB_DBG_HEX(A,B) debug_hex(A,B) |
va009039 | 3:a3872f7593e2 | 14 | #define USB_DBG_ERRSTAT() report.print_errstat(); |
va009039 | 3:a3872f7593e2 | 15 | void debug_hex(uint8_t* buf, int size); |
va009039 | 3:a3872f7593e2 | 16 | #else |
va009039 | 3:a3872f7593e2 | 17 | #define USB_DBG(...) while(0) |
va009039 | 3:a3872f7593e2 | 18 | #define USB_DBG2(...) while(0) |
va009039 | 3:a3872f7593e2 | 19 | #define USB_DBG_HEX(A,B) while(0) |
va009039 | 3:a3872f7593e2 | 20 | #define USB_DBG_ERRSTAT() while(0) |
va009039 | 3:a3872f7593e2 | 21 | #endif |
va009039 | 3:a3872f7593e2 | 22 | |
va009039 | 3:a3872f7593e2 | 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 | 3:a3872f7593e2 | 24 | #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A)) |
va009039 | 3:a3872f7593e2 | 25 | |
va009039 | 3:a3872f7593e2 | 26 | #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0); |
va009039 | 3:a3872f7593e2 | 27 | |
va009039 | 3:a3872f7593e2 | 28 | USBHost* USBHost::inst = NULL; |
va009039 | 3:a3872f7593e2 | 29 | |
va009039 | 3:a3872f7593e2 | 30 | USBHost* USBHost::getHostInst() |
va009039 | 3:a3872f7593e2 | 31 | { |
va009039 | 3:a3872f7593e2 | 32 | if (inst == NULL) { |
va009039 | 3:a3872f7593e2 | 33 | inst = new USBHost(); |
va009039 | 3:a3872f7593e2 | 34 | inst->init(); |
va009039 | 3:a3872f7593e2 | 35 | } |
va009039 | 3:a3872f7593e2 | 36 | return inst; |
va009039 | 3:a3872f7593e2 | 37 | } |
va009039 | 3:a3872f7593e2 | 38 | |
va009039 | 3:a3872f7593e2 | 39 | USBHost::USBHost() { |
va009039 | 3:a3872f7593e2 | 40 | } |
va009039 | 3:a3872f7593e2 | 41 | |
va009039 | 3:a3872f7593e2 | 42 | /* virtual */ bool USBHost::enumeration() { |
va009039 | 3:a3872f7593e2 | 43 | uint8_t desc[64]; |
va009039 | 3:a3872f7593e2 | 44 | MaxPacketSize0 = 8; |
va009039 | 3:a3872f7593e2 | 45 | dev_addr = 0; |
va009039 | 3:a3872f7593e2 | 46 | USB0->ADDR = (lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(dev_addr); |
va009039 | 3:a3872f7593e2 | 47 | wait_ms(100); |
va009039 | 3:a3872f7593e2 | 48 | SETUP_PACKET setup_get_descriptor = {0x80, GET_DESCRIPTOR, 1<<8, 0, 0}; |
va009039 | 3:a3872f7593e2 | 49 | int result = ControlRead(&setup_get_descriptor, desc, 8); |
va009039 | 3:a3872f7593e2 | 50 | if (result < 8) { |
va009039 | 3:a3872f7593e2 | 51 | USB_DBG("result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 52 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 53 | return false; |
va009039 | 3:a3872f7593e2 | 54 | } |
va009039 | 3:a3872f7593e2 | 55 | USB_DBG_HEX(desc, result); |
va009039 | 3:a3872f7593e2 | 56 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 57 | DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); |
va009039 | 3:a3872f7593e2 | 58 | MaxPacketSize0 = dev_desc->bMaxPacketSize; |
va009039 | 3:a3872f7593e2 | 59 | |
va009039 | 3:a3872f7593e2 | 60 | SETUP_PACKET setup_set_address = {0x00, SET_ADDRESS, 1, 0, 0}; |
va009039 | 3:a3872f7593e2 | 61 | result = ControlWrite(&setup_set_address); |
va009039 | 3:a3872f7593e2 | 62 | if (result < 0) { |
va009039 | 3:a3872f7593e2 | 63 | USB_DBG("result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 64 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 65 | return false; |
va009039 | 3:a3872f7593e2 | 66 | } |
va009039 | 3:a3872f7593e2 | 67 | wait_ms(100); |
va009039 | 3:a3872f7593e2 | 68 | dev_addr = 1; |
va009039 | 3:a3872f7593e2 | 69 | |
va009039 | 3:a3872f7593e2 | 70 | result = ControlRead(&setup_get_descriptor, desc, sizeof(desc)); |
va009039 | 3:a3872f7593e2 | 71 | if (result < 8) { |
va009039 | 3:a3872f7593e2 | 72 | USB_DBG("result=%d", result); |
va009039 | 3:a3872f7593e2 | 73 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 74 | return false; |
va009039 | 3:a3872f7593e2 | 75 | } |
va009039 | 3:a3872f7593e2 | 76 | USB_DBG_HEX(desc, result); |
va009039 | 3:a3872f7593e2 | 77 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 78 | |
va009039 | 3:a3872f7593e2 | 79 | USB_INFO("VID: %04x, PID: %04x\n", dev_desc->idVendor, dev_desc->idProduct); |
va009039 | 3:a3872f7593e2 | 80 | if (dev_desc->bDeviceClass == HUB_CLASS) { |
va009039 | 3:a3872f7593e2 | 81 | USB_INFO("USB hub not supported.\n\n"); |
va009039 | 3:a3872f7593e2 | 82 | exit(1); |
va009039 | 3:a3872f7593e2 | 83 | } |
va009039 | 3:a3872f7593e2 | 84 | |
va009039 | 3:a3872f7593e2 | 85 | setup_get_descriptor.wValue = 2<<8; // config descriptor |
va009039 | 3:a3872f7593e2 | 86 | result = ControlRead(&setup_get_descriptor, desc, 4); |
va009039 | 3:a3872f7593e2 | 87 | if (result != 4) { |
va009039 | 3:a3872f7593e2 | 88 | USB_DBG("result=%d", result); |
va009039 | 3:a3872f7593e2 | 89 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 90 | return false; |
va009039 | 3:a3872f7593e2 | 91 | } |
va009039 | 3:a3872f7593e2 | 92 | USB_DBG_HEX(desc, 4); |
va009039 | 3:a3872f7593e2 | 93 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 94 | |
va009039 | 3:a3872f7593e2 | 95 | int TotalLength = desc[2]|desc[3]<<8; |
va009039 | 3:a3872f7593e2 | 96 | uint8_t* buf = new uint8_t[TotalLength]; |
va009039 | 3:a3872f7593e2 | 97 | result = ControlRead(&setup_get_descriptor, buf, TotalLength); |
va009039 | 3:a3872f7593e2 | 98 | if (result != TotalLength) { |
va009039 | 3:a3872f7593e2 | 99 | USB_DBG("result=%d TotalLength=%d %02x", result, TotalLength, LastStatus); |
va009039 | 3:a3872f7593e2 | 100 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 101 | return false; |
va009039 | 3:a3872f7593e2 | 102 | } |
va009039 | 3:a3872f7593e2 | 103 | USB_DBG_HEX(buf, TotalLength); |
va009039 | 3:a3872f7593e2 | 104 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 105 | |
va009039 | 3:a3872f7593e2 | 106 | for(int i = 0; i < TotalLength; ) { |
va009039 | 3:a3872f7593e2 | 107 | int Length = buf[i]; |
va009039 | 3:a3872f7593e2 | 108 | uint8_t DescriptorType = buf[i+1]; |
va009039 | 3:a3872f7593e2 | 109 | if (DescriptorType == 0x05) { // endpoint |
va009039 | 3:a3872f7593e2 | 110 | EndpointDescriptor* desc = reinterpret_cast<EndpointDescriptor*>(buf+i); |
va009039 | 3:a3872f7593e2 | 111 | USBEndpoint* ep = NULL; |
va009039 | 3:a3872f7593e2 | 112 | if (desc->bmAttributes == 0x03) { // interrupt |
va009039 | 3:a3872f7593e2 | 113 | if (desc->bEndpointAddress & 0x80) { |
va009039 | 3:a3872f7593e2 | 114 | ep = &ep_int_in; |
va009039 | 3:a3872f7593e2 | 115 | } |
va009039 | 3:a3872f7593e2 | 116 | } else if (desc->bmAttributes == 0x02) { // bulk |
va009039 | 3:a3872f7593e2 | 117 | ep = (desc->bEndpointAddress & 0x80) ? &ep_bulk_in : &ep_bulk_out; |
va009039 | 3:a3872f7593e2 | 118 | } |
va009039 | 3:a3872f7593e2 | 119 | if (ep) { |
va009039 | 3:a3872f7593e2 | 120 | ep->setAddress(desc->bEndpointAddress); |
va009039 | 3:a3872f7593e2 | 121 | ep->setSize(desc->wMaxPacketSize); |
va009039 | 3:a3872f7593e2 | 122 | } |
va009039 | 3:a3872f7593e2 | 123 | } |
va009039 | 3:a3872f7593e2 | 124 | USB_DBG_HEX(buf+i, Length); |
va009039 | 3:a3872f7593e2 | 125 | i += Length; |
va009039 | 3:a3872f7593e2 | 126 | } |
va009039 | 3:a3872f7593e2 | 127 | delete[] buf; |
va009039 | 3:a3872f7593e2 | 128 | |
va009039 | 3:a3872f7593e2 | 129 | // config = 1 |
va009039 | 3:a3872f7593e2 | 130 | SETUP_PACKET setup_set_config = {0x00, SET_CONFIGURATION, 1, 0, 0}; |
va009039 | 3:a3872f7593e2 | 131 | result = ControlWrite(&setup_set_config); |
va009039 | 3:a3872f7593e2 | 132 | if (result < 0) { |
va009039 | 3:a3872f7593e2 | 133 | USB_DBG("set config: %02x", LastStatus); |
va009039 | 3:a3872f7593e2 | 134 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 135 | if (lowSpeed && LastStatus == STALL) { // TODO: |
va009039 | 3:a3872f7593e2 | 136 | wait_ms(100); |
va009039 | 3:a3872f7593e2 | 137 | return true; |
va009039 | 3:a3872f7593e2 | 138 | } |
va009039 | 3:a3872f7593e2 | 139 | return false; |
va009039 | 3:a3872f7593e2 | 140 | } |
va009039 | 3:a3872f7593e2 | 141 | wait_ms(100); |
va009039 | 3:a3872f7593e2 | 142 | return true; |
va009039 | 3:a3872f7593e2 | 143 | } |
va009039 | 3:a3872f7593e2 | 144 | |
va009039 | 3:a3872f7593e2 | 145 | 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 | 3:a3872f7593e2 | 146 | SETUP_PACKET setup = {requestType, request, value, index}; |
va009039 | 3:a3872f7593e2 | 147 | int result = ControlRead(&setup, buf, len); |
va009039 | 3:a3872f7593e2 | 148 | USB_DBG2("result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 149 | return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR; |
va009039 | 3:a3872f7593e2 | 150 | } |
va009039 | 3:a3872f7593e2 | 151 | |
va009039 | 3:a3872f7593e2 | 152 | 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 | 3:a3872f7593e2 | 153 | SETUP_PACKET setup = {requestType, request, value, index}; |
va009039 | 3:a3872f7593e2 | 154 | int result = ControlWrite(&setup, buf, len); |
va009039 | 3:a3872f7593e2 | 155 | if (result >= 0) { |
va009039 | 3:a3872f7593e2 | 156 | return USB_TYPE_OK; |
va009039 | 3:a3872f7593e2 | 157 | } |
va009039 | 3:a3872f7593e2 | 158 | USB_DBG("result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 159 | USB_DBG_ERRSTAT(); |
va009039 | 3:a3872f7593e2 | 160 | USB_DBG_HEX(buf, len); |
va009039 | 3:a3872f7593e2 | 161 | return USB_TYPE_ERROR; |
va009039 | 3:a3872f7593e2 | 162 | } |
va009039 | 3:a3872f7593e2 | 163 | |
va009039 | 3:a3872f7593e2 | 164 | USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { |
va009039 | 3:a3872f7593e2 | 165 | USB_TEST_ASSERT(blocking); |
va009039 | 3:a3872f7593e2 | 166 | int result = BulkRead(buf, len); |
va009039 | 3:a3872f7593e2 | 167 | if (result >= 0) { |
va009039 | 3:a3872f7593e2 | 168 | return USB_TYPE_OK; |
va009039 | 3:a3872f7593e2 | 169 | } |
va009039 | 3:a3872f7593e2 | 170 | //USB_DBG2("result=%d %02x", result, host->LastStatus); |
va009039 | 3:a3872f7593e2 | 171 | return USB_TYPE_ERROR; |
va009039 | 3:a3872f7593e2 | 172 | } |
va009039 | 3:a3872f7593e2 | 173 | |
va009039 | 3:a3872f7593e2 | 174 | USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { |
va009039 | 3:a3872f7593e2 | 175 | USB_TEST_ASSERT(blocking); |
va009039 | 3:a3872f7593e2 | 176 | int result = BulkWrite(buf, len); |
va009039 | 3:a3872f7593e2 | 177 | if (result >= 0) { |
va009039 | 3:a3872f7593e2 | 178 | return USB_TYPE_OK; |
va009039 | 3:a3872f7593e2 | 179 | } |
va009039 | 3:a3872f7593e2 | 180 | USB_DBG2("result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 181 | return USB_TYPE_ERROR; |
va009039 | 3:a3872f7593e2 | 182 | } |
va009039 | 3:a3872f7593e2 | 183 | |
va009039 | 3:a3872f7593e2 | 184 | USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { |
va009039 | 3:a3872f7593e2 | 185 | USB_TEST_ASSERT(blocking); |
va009039 | 3:a3872f7593e2 | 186 | int result = InterruptRead(buf, len); |
va009039 | 3:a3872f7593e2 | 187 | if (result >= 0) { |
va009039 | 3:a3872f7593e2 | 188 | return USB_TYPE_OK; |
va009039 | 3:a3872f7593e2 | 189 | } |
va009039 | 3:a3872f7593e2 | 190 | return USB_TYPE_ERROR; |
va009039 | 3:a3872f7593e2 | 191 | } |
va009039 | 3:a3872f7593e2 | 192 | |
va009039 | 3:a3872f7593e2 | 193 | int USBHost::ControlRead(SETUP_PACKET* setup, uint8_t* data, int size) { |
va009039 | 3:a3872f7593e2 | 194 | setAddr(dev_addr); |
va009039 | 3:a3872f7593e2 | 195 | token_setup(setup, size); // setup stage |
va009039 | 3:a3872f7593e2 | 196 | if (LastStatus != ACK) { |
va009039 | 3:a3872f7593e2 | 197 | USB_DBG("setup %02x", LastStatus); |
va009039 | 3:a3872f7593e2 | 198 | return -1; |
va009039 | 3:a3872f7593e2 | 199 | } |
va009039 | 3:a3872f7593e2 | 200 | int read_len = 0; |
va009039 | 3:a3872f7593e2 | 201 | while(read_len < size) { |
va009039 | 3:a3872f7593e2 | 202 | int size2 = std::min(size-read_len, MaxPacketSize0); |
va009039 | 3:a3872f7593e2 | 203 | int result = token_in(0, data+read_len, size2); |
va009039 | 3:a3872f7593e2 | 204 | //USB_DBG("token_in result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 205 | if (result < 0) { |
va009039 | 3:a3872f7593e2 | 206 | USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus); |
va009039 | 3:a3872f7593e2 | 207 | return result; |
va009039 | 3:a3872f7593e2 | 208 | } |
va009039 | 3:a3872f7593e2 | 209 | read_len += result; |
va009039 | 3:a3872f7593e2 | 210 | if (result < MaxPacketSize0) { |
va009039 | 3:a3872f7593e2 | 211 | break; |
va009039 | 3:a3872f7593e2 | 212 | } |
va009039 | 3:a3872f7593e2 | 213 | } |
va009039 | 3:a3872f7593e2 | 214 | int result = token_out(0); // status stage |
va009039 | 3:a3872f7593e2 | 215 | if (result < 0) { |
va009039 | 3:a3872f7593e2 | 216 | USB_DBG("status token_out %02x", LastStatus); |
va009039 | 3:a3872f7593e2 | 217 | if (LastStatus == STALL) { |
va009039 | 3:a3872f7593e2 | 218 | return read_len; |
va009039 | 3:a3872f7593e2 | 219 | } |
va009039 | 3:a3872f7593e2 | 220 | return result; |
va009039 | 3:a3872f7593e2 | 221 | } |
va009039 | 3:a3872f7593e2 | 222 | return read_len; |
va009039 | 3:a3872f7593e2 | 223 | } |
va009039 | 3:a3872f7593e2 | 224 | |
va009039 | 3:a3872f7593e2 | 225 | int USBHost::ControlWrite(SETUP_PACKET* setup, uint8_t* data, int size) { |
va009039 | 3:a3872f7593e2 | 226 | setAddr(dev_addr); |
va009039 | 3:a3872f7593e2 | 227 | token_setup(setup, size); // setup stage |
va009039 | 3:a3872f7593e2 | 228 | if (LastStatus != ACK) { |
va009039 | 3:a3872f7593e2 | 229 | USB_DBG("setup %02x", LastStatus); |
va009039 | 3:a3872f7593e2 | 230 | return -1; |
va009039 | 3:a3872f7593e2 | 231 | } |
va009039 | 3:a3872f7593e2 | 232 | int write_len = 0; |
va009039 | 3:a3872f7593e2 | 233 | if (data != NULL) { |
va009039 | 3:a3872f7593e2 | 234 | write_len = token_out(0, data, size); |
va009039 | 3:a3872f7593e2 | 235 | if (write_len < 0) { |
va009039 | 3:a3872f7593e2 | 236 | return -1; |
va009039 | 3:a3872f7593e2 | 237 | } |
va009039 | 3:a3872f7593e2 | 238 | } |
va009039 | 3:a3872f7593e2 | 239 | int result = token_in(0); // status stage |
va009039 | 3:a3872f7593e2 | 240 | if (result < 0) { |
va009039 | 3:a3872f7593e2 | 241 | USB_DBG("result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 242 | //return result; |
va009039 | 3:a3872f7593e2 | 243 | } |
va009039 | 3:a3872f7593e2 | 244 | return write_len; |
va009039 | 3:a3872f7593e2 | 245 | } |
va009039 | 3:a3872f7593e2 | 246 | |
va009039 | 3:a3872f7593e2 | 247 | int USBHost::InterruptRead(uint8_t* data, int size) { |
va009039 | 3:a3872f7593e2 | 248 | setAddr(dev_addr); |
va009039 | 3:a3872f7593e2 | 249 | setEndpoint(); |
va009039 | 3:a3872f7593e2 | 250 | const int retryLimit = 0; |
va009039 | 3:a3872f7593e2 | 251 | int max_packet_size = ep_int_in.getSize(); |
va009039 | 3:a3872f7593e2 | 252 | int read_len = 0; |
va009039 | 3:a3872f7593e2 | 253 | for(int n = 0; read_len < size; n++) { |
va009039 | 3:a3872f7593e2 | 254 | int size2 = std::min(size-read_len, max_packet_size); |
va009039 | 3:a3872f7593e2 | 255 | int result = token_in(ep_int_in.getAddress() & 0x7f, data+read_len, size2, retryLimit); |
va009039 | 3:a3872f7593e2 | 256 | if (result < 0) { |
va009039 | 3:a3872f7593e2 | 257 | if (LastStatus == NAK) { |
va009039 | 3:a3872f7593e2 | 258 | if (n == 0) { |
va009039 | 3:a3872f7593e2 | 259 | return -1; |
va009039 | 3:a3872f7593e2 | 260 | } |
va009039 | 3:a3872f7593e2 | 261 | break; |
va009039 | 3:a3872f7593e2 | 262 | } |
va009039 | 3:a3872f7593e2 | 263 | USB_DBG("token_in result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 264 | return result; |
va009039 | 3:a3872f7593e2 | 265 | } |
va009039 | 3:a3872f7593e2 | 266 | read_len += result; |
va009039 | 3:a3872f7593e2 | 267 | if (result < max_packet_size) { |
va009039 | 3:a3872f7593e2 | 268 | break; |
va009039 | 3:a3872f7593e2 | 269 | } |
va009039 | 3:a3872f7593e2 | 270 | } |
va009039 | 3:a3872f7593e2 | 271 | return read_len; |
va009039 | 3:a3872f7593e2 | 272 | } |
va009039 | 3:a3872f7593e2 | 273 | |
va009039 | 3:a3872f7593e2 | 274 | int USBHost::BulkRead(uint8_t* data, int size, int timeout_ms) { |
va009039 | 3:a3872f7593e2 | 275 | setAddr(dev_addr); |
va009039 | 3:a3872f7593e2 | 276 | setEndpoint(); |
va009039 | 3:a3872f7593e2 | 277 | int max_packet_size = ep_bulk_in.getSize(); |
va009039 | 3:a3872f7593e2 | 278 | int retryLimit = (timeout_ms == 0) ? 0 : 10; |
va009039 | 3:a3872f7593e2 | 279 | int read_len = 0; |
va009039 | 3:a3872f7593e2 | 280 | Timer t; |
va009039 | 3:a3872f7593e2 | 281 | for(int n = 0; read_len < size; n++) { |
va009039 | 3:a3872f7593e2 | 282 | int size2 = std::min(size-read_len, max_packet_size); |
va009039 | 3:a3872f7593e2 | 283 | int result = token_in(ep_bulk_in.getAddress() & 0x7f, data+read_len, size2, retryLimit); |
va009039 | 3:a3872f7593e2 | 284 | if (result < 0) { |
va009039 | 3:a3872f7593e2 | 285 | if (LastStatus == NAK) { |
va009039 | 3:a3872f7593e2 | 286 | if (n == 0) { |
va009039 | 3:a3872f7593e2 | 287 | return -1; |
va009039 | 3:a3872f7593e2 | 288 | } |
va009039 | 3:a3872f7593e2 | 289 | break; |
va009039 | 3:a3872f7593e2 | 290 | } |
va009039 | 3:a3872f7593e2 | 291 | USB_DBG("token_in result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 292 | return result; |
va009039 | 3:a3872f7593e2 | 293 | } |
va009039 | 3:a3872f7593e2 | 294 | read_len += result; |
va009039 | 3:a3872f7593e2 | 295 | if (result < max_packet_size) { |
va009039 | 3:a3872f7593e2 | 296 | break; |
va009039 | 3:a3872f7593e2 | 297 | } |
va009039 | 3:a3872f7593e2 | 298 | if (timeout_ms > 0 && t.read_ms() > timeout_ms) { |
va009039 | 3:a3872f7593e2 | 299 | USB_DBG("timeout_ms: %d", timeout_ms); |
va009039 | 3:a3872f7593e2 | 300 | break; |
va009039 | 3:a3872f7593e2 | 301 | } |
va009039 | 3:a3872f7593e2 | 302 | } |
va009039 | 3:a3872f7593e2 | 303 | return read_len; |
va009039 | 3:a3872f7593e2 | 304 | } |
va009039 | 3:a3872f7593e2 | 305 | |
va009039 | 3:a3872f7593e2 | 306 | int USBHost::BulkWrite(const uint8_t* data, int size) { |
va009039 | 3:a3872f7593e2 | 307 | setAddr(dev_addr); |
va009039 | 3:a3872f7593e2 | 308 | setEndpoint(); |
va009039 | 3:a3872f7593e2 | 309 | int max_packet_size = ep_bulk_out.getSize(); |
va009039 | 3:a3872f7593e2 | 310 | int write_len = 0; |
va009039 | 3:a3872f7593e2 | 311 | for(int n = 0; write_len < size; n++) { |
va009039 | 3:a3872f7593e2 | 312 | int size2 = std::min(size-write_len, max_packet_size); |
va009039 | 3:a3872f7593e2 | 313 | int result = token_out(ep_bulk_out.getAddress(), data+write_len, size2); |
va009039 | 3:a3872f7593e2 | 314 | if (result < 0) { |
va009039 | 3:a3872f7593e2 | 315 | if (LastStatus == NAK) { |
va009039 | 3:a3872f7593e2 | 316 | if (n == 0) { |
va009039 | 3:a3872f7593e2 | 317 | return -1; |
va009039 | 3:a3872f7593e2 | 318 | } |
va009039 | 3:a3872f7593e2 | 319 | break; |
va009039 | 3:a3872f7593e2 | 320 | } |
va009039 | 3:a3872f7593e2 | 321 | //USB_DBG("token_in result=%d %02x", result, LastStatus); |
va009039 | 3:a3872f7593e2 | 322 | return result; |
va009039 | 3:a3872f7593e2 | 323 | } |
va009039 | 3:a3872f7593e2 | 324 | write_len += result; |
va009039 | 3:a3872f7593e2 | 325 | if (result < max_packet_size) { |
va009039 | 3:a3872f7593e2 | 326 | break; |
va009039 | 3:a3872f7593e2 | 327 | } |
va009039 | 3:a3872f7593e2 | 328 | } |
va009039 | 3:a3872f7593e2 | 329 | return write_len; |
va009039 | 3:a3872f7593e2 | 330 | } |
va009039 | 3:a3872f7593e2 | 331 |