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:
Sat Jan 25 12:51:44 2014 +0000
Revision:
3:a3872f7593e2
fix max packet size

Who changed what in which revision?

UserRevisionLine numberNew 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