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
internal/types/WiconnectSocket.cpp@21:17bb3eddcbae, 2014-08-26 (annotated)
- 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?
User | Revision | Line number | New 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 |