Host library for controlling a WiConnect enabled Wi-Fi module.

Dependents:   wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more

Committer:
dan_ackme
Date:
Tue Aug 26 16:38:19 2014 -0700
Revision:
21:17bb3eddcbae
Parent:
17:7268f365676b
Child:
24:e27e23297f02
Add TCP server API

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dan_ackme 17:7268f365676b 1 /**
dan_ackme 17:7268f365676b 2 * ACKme WiConnect Host Library is licensed under the BSD licence:
dan_ackme 17:7268f365676b 3 *
dan_ackme 17:7268f365676b 4 * Copyright (c)2014 ACKme Networks.
dan_ackme 17:7268f365676b 5 * All rights reserved.
dan_ackme 17:7268f365676b 6 *
dan_ackme 17:7268f365676b 7 * Redistribution and use in source and binary forms, with or without modification,
dan_ackme 17:7268f365676b 8 * are permitted provided that the following conditions are met:
dan_ackme 17:7268f365676b 9 *
dan_ackme 17:7268f365676b 10 * 1. Redistributions of source code must retain the above copyright notice,
dan_ackme 17:7268f365676b 11 * this list of conditions and the following disclaimer.
dan_ackme 17:7268f365676b 12 * 2. Redistributions in binary form must reproduce the above copyright notice,
dan_ackme 17:7268f365676b 13 * this list of conditions and the following disclaimer in the documentation
dan_ackme 17:7268f365676b 14 * and/or other materials provided with the distribution.
dan_ackme 17:7268f365676b 15 * 3. The name of the author may not be used to endorse or promote products
dan_ackme 17:7268f365676b 16 * derived from this software without specific prior written permission.
dan_ackme 17:7268f365676b 17 *
dan_ackme 17:7268f365676b 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED
dan_ackme 17:7268f365676b 19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
dan_ackme 17:7268f365676b 20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
dan_ackme 17:7268f365676b 21 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
dan_ackme 17:7268f365676b 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
dan_ackme 17:7268f365676b 23 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
dan_ackme 17:7268f365676b 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
dan_ackme 17:7268f365676b 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
dan_ackme 17:7268f365676b 26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
dan_ackme 17:7268f365676b 27 * OF SUCH DAMAGE.
dan_ackme 17:7268f365676b 28 */
dan_ackme 17:7268f365676b 29 #include <stdarg.h>
dan_ackme 17:7268f365676b 30 #include "Wiconnect.h"
dan_ackme 17:7268f365676b 31 #include "internal/common.h"
dan_ackme 17:7268f365676b 32 #include "StringUtil.h"
dan_ackme 17:7268f365676b 33
dan_ackme 17:7268f365676b 34
dan_ackme 17:7268f365676b 35 #define CHECK_CONNECTED() if(!isConnected()) return WICONNECT_NOT_CONNECTED
dan_ackme 17:7268f365676b 36
dan_ackme 17:7268f365676b 37
dan_ackme 17:7268f365676b 38 /*************************************************************************************************/
dan_ackme 17:7268f365676b 39 WiconnectSocket::WiconnectSocket(int rxBufferLen_, void *rxBuffer_, int txBufferLen_, void *txBuffer_)
dan_ackme 17:7268f365676b 40 {
dan_ackme 17:7268f365676b 41 wiconnect = Wiconnect::getInstance();
dan_ackme 17:7268f365676b 42
dan_ackme 17:7268f365676b 43 memset(&txBuffer, 0, sizeof(Buffer));
dan_ackme 17:7268f365676b 44 memset(&rxBuffer, 0, sizeof(Buffer));
dan_ackme 17:7268f365676b 45
dan_ackme 17:7268f365676b 46 txBuffer.size = !wiconnect->nonBlocking ? txBufferLen_ : 0;
dan_ackme 17:7268f365676b 47 txBuffer.buffer = (uint8_t*)txBuffer_;
dan_ackme 17:7268f365676b 48
dan_ackme 17:7268f365676b 49 rxBuffer.size = !wiconnect->nonBlocking ? rxBufferLen_ : 0;
dan_ackme 17:7268f365676b 50 rxBuffer.buffer = (uint8_t*)rxBuffer_;
dan_ackme 17:7268f365676b 51
dan_ackme 17:7268f365676b 52 if(txBuffer.size > 0)
dan_ackme 17:7268f365676b 53 {
dan_ackme 17:7268f365676b 54 if(txBuffer_ == NULL)
dan_ackme 17:7268f365676b 55 {
dan_ackme 17:7268f365676b 56 #ifdef WICONNECT_ENABLE_MALLOC
dan_ackme 17:7268f365676b 57 wiconnect_assert(wiconnect, "Socket(), malloc not defined", wiconnect->_malloc != NULL);
dan_ackme 17:7268f365676b 58 txBuffer.buffer = (uint8_t*)wiconnect->_malloc(txBufferLen_);
dan_ackme 17:7268f365676b 59 wiconnect_assert(wiconnect, "Socket(), txBuffer malloc failed", txBuffer.buffer != NULL);
dan_ackme 17:7268f365676b 60 txBuffer.allocated = true;
dan_ackme 17:7268f365676b 61 #else
dan_ackme 17:7268f365676b 62 wiconnect_assert(0);
dan_ackme 17:7268f365676b 63 #endif
dan_ackme 17:7268f365676b 64 }
dan_ackme 17:7268f365676b 65 }
dan_ackme 17:7268f365676b 66
dan_ackme 17:7268f365676b 67 if(rxBuffer.size > 0)
dan_ackme 17:7268f365676b 68 {
dan_ackme 17:7268f365676b 69 if(rxBuffer_ == NULL)
dan_ackme 17:7268f365676b 70 {
dan_ackme 17:7268f365676b 71 #ifdef WICONNECT_ENABLE_MALLOC
dan_ackme 17:7268f365676b 72 wiconnect_assert(wiconnect, "Socket(), malloc not defined", wiconnect->_malloc != NULL);
dan_ackme 17:7268f365676b 73 rxBuffer.buffer = (uint8_t*)wiconnect->_malloc(rxBufferLen_);
dan_ackme 17:7268f365676b 74 wiconnect_assert(wiconnect, "Socket(), rxBuffer malloc failed", rxBuffer.buffer != NULL);
dan_ackme 17:7268f365676b 75 rxBuffer.allocated = true;
dan_ackme 17:7268f365676b 76 #else
dan_ackme 17:7268f365676b 77 wiconnect_assert(0);
dan_ackme 17:7268f365676b 78 #endif
dan_ackme 17:7268f365676b 79 }
dan_ackme 17:7268f365676b 80 }
dan_ackme 17:7268f365676b 81
dan_ackme 17:7268f365676b 82 handle = SOCKET_INVALID_HANDLE;
dan_ackme 17:7268f365676b 83 type = SOCKET_TYPE_UNKNOWN;
dan_ackme 17:7268f365676b 84 remotePort = 0;
dan_ackme 17:7268f365676b 85 localPort = 0;
dan_ackme 17:7268f365676b 86 connected = false;
dan_ackme 17:7268f365676b 87 host[0] = 0;
dan_ackme 17:7268f365676b 88 }
dan_ackme 17:7268f365676b 89
dan_ackme 17:7268f365676b 90
dan_ackme 17:7268f365676b 91 /*************************************************************************************************/
dan_ackme 17:7268f365676b 92 WiconnectResult WiconnectSocket::init(uint8_t handle_, SocketType type_, const char *host_, uint16_t remotePort_, uint16_t localPort_)
dan_ackme 17:7268f365676b 93 {
dan_ackme 17:7268f365676b 94 handle = handle_;
dan_ackme 17:7268f365676b 95 type = type_;
dan_ackme 17:7268f365676b 96 remotePort = remotePort_;
dan_ackme 17:7268f365676b 97 localPort = localPort_;
dan_ackme 17:7268f365676b 98 connected = true;
dan_ackme 17:7268f365676b 99
dan_ackme 17:7268f365676b 100 txBuffer.ptr = txBuffer.buffer;
dan_ackme 17:7268f365676b 101 rxBuffer.ptr = rxBuffer.buffer;
dan_ackme 17:7268f365676b 102
dan_ackme 17:7268f365676b 103 strncpy(host, host_, sizeof(host)-1);
dan_ackme 17:7268f365676b 104
dan_ackme 17:7268f365676b 105 return WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 106 }
dan_ackme 17:7268f365676b 107
dan_ackme 17:7268f365676b 108 /*************************************************************************************************/
dan_ackme 17:7268f365676b 109 WiconnectSocket::~WiconnectSocket()
dan_ackme 17:7268f365676b 110 {
dan_ackme 17:7268f365676b 111 while((handle != SOCKET_INVALID_HANDLE) && (close() == WICONNECT_PROCESSING))
dan_ackme 17:7268f365676b 112 {
dan_ackme 17:7268f365676b 113 }
dan_ackme 17:7268f365676b 114
dan_ackme 17:7268f365676b 115 #ifdef WICONNECT_ENABLE_MALLOC
dan_ackme 17:7268f365676b 116 if(txBuffer.allocated && txBuffer.size > 0)
dan_ackme 17:7268f365676b 117 {
dan_ackme 17:7268f365676b 118 wiconnect_assert(wiconnect, "~Socket(), free not defined", wiconnect->_free != NULL);
dan_ackme 17:7268f365676b 119 wiconnect->_free(txBuffer.buffer);
dan_ackme 17:7268f365676b 120 }
dan_ackme 17:7268f365676b 121 if(rxBuffer.allocated && rxBuffer.size > 0)
dan_ackme 17:7268f365676b 122 {
dan_ackme 17:7268f365676b 123 wiconnect_assert(wiconnect, "~Socket(), free not defined", wiconnect->_free != NULL);
dan_ackme 17:7268f365676b 124 wiconnect->_free(rxBuffer.buffer);
dan_ackme 17:7268f365676b 125 }
dan_ackme 17:7268f365676b 126 #endif
dan_ackme 17:7268f365676b 127 }
dan_ackme 17:7268f365676b 128
dan_ackme 17:7268f365676b 129 /*************************************************************************************************/
dan_ackme 17:7268f365676b 130 bool WiconnectSocket::isConnected()
dan_ackme 17:7268f365676b 131 {
dan_ackme 17:7268f365676b 132 return connected;
dan_ackme 17:7268f365676b 133 }
dan_ackme 17:7268f365676b 134
dan_ackme 17:7268f365676b 135 /*************************************************************************************************/
dan_ackme 17:7268f365676b 136 SocketType WiconnectSocket::getType()
dan_ackme 17:7268f365676b 137 {
dan_ackme 17:7268f365676b 138 return type;
dan_ackme 17:7268f365676b 139 }
dan_ackme 17:7268f365676b 140
dan_ackme 17:7268f365676b 141 /*************************************************************************************************/
dan_ackme 17:7268f365676b 142 const char* WiconnectSocket::getHost()
dan_ackme 17:7268f365676b 143 {
dan_ackme 17:7268f365676b 144 return host;
dan_ackme 17:7268f365676b 145 }
dan_ackme 17:7268f365676b 146
dan_ackme 17:7268f365676b 147 /*************************************************************************************************/
dan_ackme 17:7268f365676b 148 uint16_t WiconnectSocket::getLocalPort()
dan_ackme 17:7268f365676b 149 {
dan_ackme 17:7268f365676b 150 return localPort;
dan_ackme 17:7268f365676b 151 }
dan_ackme 17:7268f365676b 152
dan_ackme 17:7268f365676b 153 /*************************************************************************************************/
dan_ackme 17:7268f365676b 154 uint16_t WiconnectSocket::getRemotePort()
dan_ackme 17:7268f365676b 155 {
dan_ackme 17:7268f365676b 156 return remotePort;
dan_ackme 17:7268f365676b 157 }
dan_ackme 17:7268f365676b 158
dan_ackme 17:7268f365676b 159 /*************************************************************************************************/
dan_ackme 17:7268f365676b 160 uint8_t WiconnectSocket::getHandle()
dan_ackme 17:7268f365676b 161 {
dan_ackme 17:7268f365676b 162 return handle;
dan_ackme 17:7268f365676b 163 }
dan_ackme 17:7268f365676b 164
dan_ackme 17:7268f365676b 165
dan_ackme 17:7268f365676b 166 /*************************************************************************************************/
dan_ackme 17:7268f365676b 167 WiconnectResult WiconnectSocket::close()
dan_ackme 17:7268f365676b 168 {
dan_ackme 17:7268f365676b 169 WiconnectResult result;
dan_ackme 17:7268f365676b 170 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 171 CHECK_OTHER_COMMAND_EXECUTING();
dan_ackme 17:7268f365676b 172
dan_ackme 21:17bb3eddcbae 173 result = wiconnect->sendCommand("close %d", handle);
dan_ackme 21:17bb3eddcbae 174
dan_ackme 21:17bb3eddcbae 175 if(result != WICONNECT_PROCESSING)
dan_ackme 17:7268f365676b 176 {
dan_ackme 21:17bb3eddcbae 177 connected = false;
dan_ackme 21:17bb3eddcbae 178 wiconnect->socketClosedCallback(this);
dan_ackme 17:7268f365676b 179 }
dan_ackme 17:7268f365676b 180
dan_ackme 17:7268f365676b 181 CHECK_CLEANUP_COMMAND();
dan_ackme 17:7268f365676b 182
dan_ackme 17:7268f365676b 183 return result;
dan_ackme 17:7268f365676b 184 }
dan_ackme 17:7268f365676b 185
dan_ackme 17:7268f365676b 186 /*************************************************************************************************/
dan_ackme 17:7268f365676b 187 WiconnectResult WiconnectSocket::poll(bool *rxDataAvailablePtr, bool autoClose)
dan_ackme 17:7268f365676b 188 {
dan_ackme 17:7268f365676b 189 WiconnectResult result;
dan_ackme 17:7268f365676b 190 int32_t status;
dan_ackme 17:7268f365676b 191
dan_ackme 17:7268f365676b 192 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 193 CHECK_OTHER_COMMAND_EXECUTING();
dan_ackme 17:7268f365676b 194
dan_ackme 17:7268f365676b 195 *rxDataAvailablePtr = false;
dan_ackme 17:7268f365676b 196
dan_ackme 17:7268f365676b 197 if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("poll %d", handle)))
dan_ackme 17:7268f365676b 198 {
dan_ackme 17:7268f365676b 199 if(!WICONNECT_FAILED(result, wiconnect->responseToInt32(&status)))
dan_ackme 17:7268f365676b 200 {
dan_ackme 17:7268f365676b 201 if(status > 0)
dan_ackme 17:7268f365676b 202 {
dan_ackme 17:7268f365676b 203 *rxDataAvailablePtr = true;
dan_ackme 17:7268f365676b 204 if(status == 2 && autoClose)
dan_ackme 17:7268f365676b 205 {
dan_ackme 17:7268f365676b 206 connected = false;
dan_ackme 17:7268f365676b 207 }
dan_ackme 17:7268f365676b 208 }
dan_ackme 17:7268f365676b 209 }
dan_ackme 17:7268f365676b 210 }
dan_ackme 17:7268f365676b 211
dan_ackme 17:7268f365676b 212 CHECK_CLEANUP_COMMAND();
dan_ackme 17:7268f365676b 213
dan_ackme 17:7268f365676b 214 return result;
dan_ackme 17:7268f365676b 215 }
dan_ackme 17:7268f365676b 216
dan_ackme 17:7268f365676b 217 /*************************************************************************************************/
dan_ackme 17:7268f365676b 218 WiconnectResult WiconnectSocket::write(int length, bool flush)
dan_ackme 17:7268f365676b 219 {
dan_ackme 17:7268f365676b 220 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 221
dan_ackme 17:7268f365676b 222 if( txBuffer.size == 0)
dan_ackme 17:7268f365676b 223 {
dan_ackme 17:7268f365676b 224 return WICONNECT_UNSUPPORTED;
dan_ackme 17:7268f365676b 225 }
dan_ackme 17:7268f365676b 226 else if(length > txBuffer.size)
dan_ackme 17:7268f365676b 227 {
dan_ackme 17:7268f365676b 228 return WICONNECT_OVERFLOW;
dan_ackme 17:7268f365676b 229 }
dan_ackme 17:7268f365676b 230 txBuffer.bytesPending = length;
dan_ackme 17:7268f365676b 231
dan_ackme 17:7268f365676b 232 return flush ? flushTxBuffer() : WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 233 }
dan_ackme 17:7268f365676b 234
dan_ackme 17:7268f365676b 235 /*************************************************************************************************/
dan_ackme 17:7268f365676b 236 WiconnectResult WiconnectSocket::write(const void* buffer, int length, bool flush)
dan_ackme 17:7268f365676b 237 {
dan_ackme 17:7268f365676b 238 WiconnectResult result = WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 239 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 240
dan_ackme 17:7268f365676b 241 if(txBuffer.size > 0)
dan_ackme 17:7268f365676b 242 {
dan_ackme 17:7268f365676b 243 // NOTE: txBuffer only available in blocking mode (so no need to check if a cmd is executing)
dan_ackme 17:7268f365676b 244
dan_ackme 17:7268f365676b 245 const uint8_t *src = (const uint8_t *)buffer;
dan_ackme 17:7268f365676b 246
dan_ackme 17:7268f365676b 247 while(length > 0)
dan_ackme 17:7268f365676b 248 {
dan_ackme 17:7268f365676b 249 int bytesToWrite = MIN(length, txBuffer.size - txBuffer.bytesPending);
dan_ackme 17:7268f365676b 250 uint8_t *dst = (uint8_t*)&txBuffer.buffer[txBuffer.bytesPending];
dan_ackme 17:7268f365676b 251 memcpy(dst, src, bytesToWrite);
dan_ackme 17:7268f365676b 252 txBuffer.bytesPending += bytesToWrite;
dan_ackme 17:7268f365676b 253 length -= bytesToWrite;
dan_ackme 17:7268f365676b 254 src += bytesToWrite;
dan_ackme 17:7268f365676b 255
dan_ackme 17:7268f365676b 256 if((txBuffer.bytesPending >= txBuffer.size) &&
dan_ackme 17:7268f365676b 257 WICONNECT_FAILED(result, flushTxBuffer()))
dan_ackme 17:7268f365676b 258 {
dan_ackme 17:7268f365676b 259 break;
dan_ackme 17:7268f365676b 260 }
dan_ackme 17:7268f365676b 261 }
dan_ackme 17:7268f365676b 262
dan_ackme 17:7268f365676b 263 if(flush && txBuffer.bytesPending > 0)
dan_ackme 17:7268f365676b 264 {
dan_ackme 17:7268f365676b 265 result = flushTxBuffer();
dan_ackme 17:7268f365676b 266 }
dan_ackme 17:7268f365676b 267 }
dan_ackme 17:7268f365676b 268 else
dan_ackme 17:7268f365676b 269 {
dan_ackme 17:7268f365676b 270 if(WICONNECT_IS_IDLE())
dan_ackme 17:7268f365676b 271 {
dan_ackme 17:7268f365676b 272 txBuffer.ptr = (uint8_t*)buffer;
dan_ackme 17:7268f365676b 273 txBuffer.bytesPending = length;
dan_ackme 17:7268f365676b 274 }
dan_ackme 17:7268f365676b 275
dan_ackme 17:7268f365676b 276 result = flushTxBuffer();
dan_ackme 17:7268f365676b 277 }
dan_ackme 17:7268f365676b 278
dan_ackme 17:7268f365676b 279 return result;
dan_ackme 17:7268f365676b 280 }
dan_ackme 17:7268f365676b 281
dan_ackme 17:7268f365676b 282 /*************************************************************************************************/
dan_ackme 17:7268f365676b 283 WiconnectResult WiconnectSocket::read(void* buffer, uint16_t maxLength, uint16_t *bytesRead)
dan_ackme 17:7268f365676b 284 {
dan_ackme 17:7268f365676b 285 WiconnectResult result;
dan_ackme 17:7268f365676b 286
dan_ackme 17:7268f365676b 287 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 288 CHECK_OTHER_COMMAND_EXECUTING();
dan_ackme 17:7268f365676b 289
dan_ackme 17:7268f365676b 290 if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand((char*)buffer, maxLength, "read %d %d", handle, maxLength)))
dan_ackme 17:7268f365676b 291 {
dan_ackme 17:7268f365676b 292 *bytesRead = wiconnect->getLastCommandResponseLength();
dan_ackme 17:7268f365676b 293 }
dan_ackme 17:7268f365676b 294
dan_ackme 17:7268f365676b 295 CHECK_CLEANUP_COMMAND();
dan_ackme 17:7268f365676b 296
dan_ackme 17:7268f365676b 297 return result;
dan_ackme 17:7268f365676b 298 }
dan_ackme 17:7268f365676b 299
dan_ackme 17:7268f365676b 300 /*************************************************************************************************/
dan_ackme 17:7268f365676b 301 WiconnectResult WiconnectSocket::read(uint8_t **bufferPtr, uint16_t *bytesReadPtr)
dan_ackme 17:7268f365676b 302 {
dan_ackme 17:7268f365676b 303 WiconnectResult result = WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 304
dan_ackme 17:7268f365676b 305 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 306
dan_ackme 17:7268f365676b 307 if(rxBuffer.size == 0)
dan_ackme 17:7268f365676b 308 {
dan_ackme 17:7268f365676b 309 return WICONNECT_UNSUPPORTED;
dan_ackme 17:7268f365676b 310 }
dan_ackme 17:7268f365676b 311 else if(bufferPtr != NULL && bytesReadPtr == NULL)
dan_ackme 17:7268f365676b 312 {
dan_ackme 17:7268f365676b 313 return WICONNECT_BAD_ARG;
dan_ackme 17:7268f365676b 314 }
dan_ackme 21:17bb3eddcbae 315 else if(rxBuffer.bytesPending < rxBuffer.size)
dan_ackme 17:7268f365676b 316 {
dan_ackme 21:17bb3eddcbae 317 const int bytesToRead = rxBuffer.size - rxBuffer.bytesPending;
dan_ackme 17:7268f365676b 318 char* ptr = (char*)&rxBuffer.buffer[rxBuffer.bytesPending];
dan_ackme 21:17bb3eddcbae 319 if(!WICONNECT_FAILED(result, wiconnect->sendCommand(ptr, bytesToRead, "read %d %d", handle, bytesToRead)))
dan_ackme 17:7268f365676b 320 {
dan_ackme 17:7268f365676b 321 rxBuffer.bytesPending += wiconnect->getLastCommandResponseLength();
dan_ackme 17:7268f365676b 322 }
dan_ackme 17:7268f365676b 323 }
dan_ackme 17:7268f365676b 324
dan_ackme 17:7268f365676b 325 if(bufferPtr != NULL)
dan_ackme 17:7268f365676b 326 {
dan_ackme 17:7268f365676b 327 *bufferPtr = rxBuffer.buffer;
dan_ackme 17:7268f365676b 328 *bytesReadPtr = rxBuffer.bytesPending;
dan_ackme 17:7268f365676b 329 clearRxBuffer();
dan_ackme 17:7268f365676b 330 }
dan_ackme 17:7268f365676b 331
dan_ackme 17:7268f365676b 332 return result;
dan_ackme 17:7268f365676b 333 }
dan_ackme 17:7268f365676b 334
dan_ackme 17:7268f365676b 335 /*************************************************************************************************/
dan_ackme 17:7268f365676b 336 WiconnectResult WiconnectSocket::getc(uint8_t *c)
dan_ackme 17:7268f365676b 337 {
dan_ackme 17:7268f365676b 338 WiconnectResult result;
dan_ackme 17:7268f365676b 339
dan_ackme 17:7268f365676b 340 if(rxBuffer.size == 0)
dan_ackme 17:7268f365676b 341 {
dan_ackme 17:7268f365676b 342 return WICONNECT_UNSUPPORTED;
dan_ackme 17:7268f365676b 343 }
dan_ackme 17:7268f365676b 344
dan_ackme 17:7268f365676b 345 read_data:
dan_ackme 17:7268f365676b 346 if(rxBuffer.bytesPending == 0 &&
dan_ackme 17:7268f365676b 347 WICONNECT_FAILED(result, read()))
dan_ackme 17:7268f365676b 348 {
dan_ackme 17:7268f365676b 349 return result;
dan_ackme 17:7268f365676b 350 }
dan_ackme 17:7268f365676b 351 else if(rxBuffer.ptr < &rxBuffer.buffer[rxBuffer.bytesPending])
dan_ackme 17:7268f365676b 352 {
dan_ackme 17:7268f365676b 353 *c = *rxBuffer.ptr;
dan_ackme 17:7268f365676b 354 ++rxBuffer.ptr;
dan_ackme 17:7268f365676b 355 return WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 356 }
dan_ackme 17:7268f365676b 357 else
dan_ackme 17:7268f365676b 358 {
dan_ackme 17:7268f365676b 359 clearRxBuffer();
dan_ackme 17:7268f365676b 360 goto read_data;
dan_ackme 17:7268f365676b 361 }
dan_ackme 17:7268f365676b 362 }
dan_ackme 17:7268f365676b 363
dan_ackme 17:7268f365676b 364 /*************************************************************************************************/
dan_ackme 17:7268f365676b 365 WiconnectResult WiconnectSocket::putc(uint8_t c, bool flush)
dan_ackme 17:7268f365676b 366 {
dan_ackme 17:7268f365676b 367 WiconnectResult result = WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 368 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 369
dan_ackme 17:7268f365676b 370 if(txBuffer.size == 0)
dan_ackme 17:7268f365676b 371 {
dan_ackme 17:7268f365676b 372 return WICONNECT_UNSUPPORTED;
dan_ackme 17:7268f365676b 373 }
dan_ackme 17:7268f365676b 374 else if(txBuffer.bytesPending < txBuffer.size)
dan_ackme 17:7268f365676b 375 {
dan_ackme 17:7268f365676b 376 uint8_t *ptr = (uint8_t*)&txBuffer.buffer[txBuffer.bytesPending];
dan_ackme 17:7268f365676b 377 *ptr = c;
dan_ackme 17:7268f365676b 378 ++txBuffer.bytesPending;
dan_ackme 17:7268f365676b 379
dan_ackme 17:7268f365676b 380 if(flush || txBuffer.bytesPending >= txBuffer.size)
dan_ackme 17:7268f365676b 381 {
dan_ackme 17:7268f365676b 382 result = flushTxBuffer();
dan_ackme 17:7268f365676b 383 }
dan_ackme 17:7268f365676b 384 }
dan_ackme 17:7268f365676b 385 else
dan_ackme 17:7268f365676b 386 {
dan_ackme 17:7268f365676b 387 result = WICONNECT_OVERFLOW;
dan_ackme 17:7268f365676b 388 }
dan_ackme 17:7268f365676b 389
dan_ackme 17:7268f365676b 390 return result;
dan_ackme 17:7268f365676b 391 }
dan_ackme 17:7268f365676b 392
dan_ackme 17:7268f365676b 393 /*************************************************************************************************/
dan_ackme 17:7268f365676b 394 WiconnectResult WiconnectSocket::puts(const char *s, bool flush)
dan_ackme 17:7268f365676b 395 {
dan_ackme 17:7268f365676b 396 const int len = strlen(s);
dan_ackme 17:7268f365676b 397 return write(s, len, flush);
dan_ackme 17:7268f365676b 398 }
dan_ackme 17:7268f365676b 399
dan_ackme 17:7268f365676b 400 /*************************************************************************************************/
dan_ackme 17:7268f365676b 401 WiconnectResult WiconnectSocket::printf(const char* format, ...)
dan_ackme 17:7268f365676b 402 {
dan_ackme 17:7268f365676b 403 WiconnectResult result = WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 404
dan_ackme 17:7268f365676b 405 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 406 if(txBuffer.size == 0)
dan_ackme 17:7268f365676b 407 {
dan_ackme 17:7268f365676b 408 return WICONNECT_UNSUPPORTED;
dan_ackme 17:7268f365676b 409 }
dan_ackme 17:7268f365676b 410
dan_ackme 17:7268f365676b 411 const int available = txBuffer.size - txBuffer.bytesPending;
dan_ackme 17:7268f365676b 412 char *ptr = (char*)&txBuffer.buffer[txBuffer.bytesPending];
dan_ackme 17:7268f365676b 413 va_list args;
dan_ackme 17:7268f365676b 414 va_start(args, format);
dan_ackme 17:7268f365676b 415 const int len = vsnprintf(ptr, available, format, args);
dan_ackme 17:7268f365676b 416 if(len > available)
dan_ackme 17:7268f365676b 417 {
dan_ackme 17:7268f365676b 418 return WICONNECT_OVERFLOW;
dan_ackme 17:7268f365676b 419 }
dan_ackme 17:7268f365676b 420 else
dan_ackme 17:7268f365676b 421 {
dan_ackme 17:7268f365676b 422 txBuffer.bytesPending += len;
dan_ackme 17:7268f365676b 423 }
dan_ackme 17:7268f365676b 424
dan_ackme 17:7268f365676b 425 if(txBuffer.bytesPending >= txBuffer.size)
dan_ackme 17:7268f365676b 426 {
dan_ackme 17:7268f365676b 427 result = flushTxBuffer();
dan_ackme 17:7268f365676b 428 }
dan_ackme 17:7268f365676b 429
dan_ackme 17:7268f365676b 430 return result;
dan_ackme 17:7268f365676b 431 }
dan_ackme 17:7268f365676b 432
dan_ackme 17:7268f365676b 433 /*************************************************************************************************/
dan_ackme 17:7268f365676b 434 WiconnectResult WiconnectSocket::flushTxBuffer()
dan_ackme 17:7268f365676b 435 {
dan_ackme 17:7268f365676b 436 WiconnectResult result = WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 437
dan_ackme 17:7268f365676b 438 CHECK_CONNECTED();
dan_ackme 17:7268f365676b 439 CHECK_OTHER_COMMAND_EXECUTING();
dan_ackme 17:7268f365676b 440
dan_ackme 17:7268f365676b 441 if(txBuffer.bytesPending > 0)
dan_ackme 17:7268f365676b 442 {
dan_ackme 17:7268f365676b 443 result = wiconnect->sendCommand(ReaderFunc(this, &WiconnectSocket::writeDataCallback), NULL, "write %d %d", handle, txBuffer.bytesPending);
dan_ackme 17:7268f365676b 444 }
dan_ackme 17:7268f365676b 445
dan_ackme 17:7268f365676b 446 CHECK_CLEANUP_COMMAND();
dan_ackme 17:7268f365676b 447
dan_ackme 17:7268f365676b 448 if(result != WICONNECT_PROCESSING)
dan_ackme 17:7268f365676b 449 {
dan_ackme 17:7268f365676b 450 txBuffer.ptr = txBuffer.buffer;
dan_ackme 17:7268f365676b 451 txBuffer.bytesPending = 0;
dan_ackme 17:7268f365676b 452 }
dan_ackme 17:7268f365676b 453
dan_ackme 17:7268f365676b 454 return result;
dan_ackme 17:7268f365676b 455 }
dan_ackme 17:7268f365676b 456
dan_ackme 17:7268f365676b 457 /*************************************************************************************************/
dan_ackme 17:7268f365676b 458 void WiconnectSocket::clearRxBuffer()
dan_ackme 17:7268f365676b 459 {
dan_ackme 17:7268f365676b 460 rxBuffer.bytesPending = 0;
dan_ackme 17:7268f365676b 461 rxBuffer.ptr = rxBuffer.buffer;
dan_ackme 17:7268f365676b 462 }
dan_ackme 17:7268f365676b 463
dan_ackme 17:7268f365676b 464 /*************************************************************************************************/
dan_ackme 17:7268f365676b 465 uint8_t* WiconnectSocket::getTxBuffer()
dan_ackme 17:7268f365676b 466 {
dan_ackme 17:7268f365676b 467 return txBuffer.buffer;
dan_ackme 17:7268f365676b 468 }
dan_ackme 17:7268f365676b 469 /*************************************************************************************************/
dan_ackme 17:7268f365676b 470 int WiconnectSocket::getTxBufferSize()
dan_ackme 17:7268f365676b 471 {
dan_ackme 17:7268f365676b 472 return txBuffer.size;
dan_ackme 17:7268f365676b 473 }
dan_ackme 17:7268f365676b 474 /*************************************************************************************************/
dan_ackme 17:7268f365676b 475 int WiconnectSocket::getTxBufferBytesPending()
dan_ackme 17:7268f365676b 476 {
dan_ackme 17:7268f365676b 477 return txBuffer.bytesPending;
dan_ackme 17:7268f365676b 478 }
dan_ackme 17:7268f365676b 479 /*************************************************************************************************/
dan_ackme 17:7268f365676b 480 uint8_t* WiconnectSocket::getRxBuffer()
dan_ackme 17:7268f365676b 481 {
dan_ackme 17:7268f365676b 482 return rxBuffer.buffer;
dan_ackme 17:7268f365676b 483 }
dan_ackme 17:7268f365676b 484 /*************************************************************************************************/
dan_ackme 17:7268f365676b 485 int WiconnectSocket::getRxBufferSize()
dan_ackme 17:7268f365676b 486 {
dan_ackme 17:7268f365676b 487 return rxBuffer.size;
dan_ackme 17:7268f365676b 488 }
dan_ackme 17:7268f365676b 489 /*************************************************************************************************/
dan_ackme 17:7268f365676b 490 int WiconnectSocket::getRxBufferBytesPending()
dan_ackme 17:7268f365676b 491 {
dan_ackme 17:7268f365676b 492 return rxBuffer.bytesPending;
dan_ackme 17:7268f365676b 493 }
dan_ackme 17:7268f365676b 494
dan_ackme 17:7268f365676b 495
dan_ackme 17:7268f365676b 496 /*************************************************************************************************/
dan_ackme 17:7268f365676b 497 WiconnectResult WiconnectSocket::writeDataCallback(void *user, void *data, int maxReadSize, int *bytesRead)
dan_ackme 17:7268f365676b 498 {
dan_ackme 17:7268f365676b 499 if(txBuffer.bytesPending == 0)
dan_ackme 17:7268f365676b 500 {
dan_ackme 17:7268f365676b 501 *bytesRead = EOF;
dan_ackme 17:7268f365676b 502 }
dan_ackme 17:7268f365676b 503 else
dan_ackme 17:7268f365676b 504 {
dan_ackme 17:7268f365676b 505 const int bytesToWrite = MIN(maxReadSize, txBuffer.bytesPending);
dan_ackme 17:7268f365676b 506 memcpy(data, txBuffer.ptr, bytesToWrite);
dan_ackme 17:7268f365676b 507 txBuffer.ptr += bytesToWrite;
dan_ackme 17:7268f365676b 508 txBuffer.bytesPending -= bytesToWrite;
dan_ackme 17:7268f365676b 509 *bytesRead = bytesToWrite;
dan_ackme 17:7268f365676b 510 }
dan_ackme 17:7268f365676b 511
dan_ackme 17:7268f365676b 512 return WICONNECT_SUCCESS;
dan_ackme 17:7268f365676b 513 }
dan_ackme 17:7268f365676b 514