Changes to enabled on-line compiler

Committer:
JMF
Date:
Wed May 30 20:59:51 2018 +0000
Revision:
0:082731ede69f
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JMF 0:082731ede69f 1 /**
JMF 0:082731ede69f 2 * copyright (c) 2018, James Flynn
JMF 0:082731ede69f 3 * SPDX-License-Identifier: Apache-2.0
JMF 0:082731ede69f 4 */
JMF 0:082731ede69f 5
JMF 0:082731ede69f 6 /*
JMF 0:082731ede69f 7 * Licensed under the Apache License, Version 2.0 (the "License");
JMF 0:082731ede69f 8 * you may not use this file except in compliance with the License.
JMF 0:082731ede69f 9 * You may obtain a copy of the License at
JMF 0:082731ede69f 10 *
JMF 0:082731ede69f 11 * http://www.apache.org/licenses/LICENSE-2.0
JMF 0:082731ede69f 12 *
JMF 0:082731ede69f 13 * Unless required by applicable law or agreed to in writing, software
JMF 0:082731ede69f 14 * distributed under the License is distributed on an "AS IS" BASIS,
JMF 0:082731ede69f 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
JMF 0:082731ede69f 16 *
JMF 0:082731ede69f 17 * See the License for the specific language governing permissions and
JMF 0:082731ede69f 18 * limitations under the License.
JMF 0:082731ede69f 19 *
JMF 0:082731ede69f 20 */
JMF 0:082731ede69f 21
JMF 0:082731ede69f 22 /**----------------------------------------------------------
JMF 0:082731ede69f 23 * @file BG96Interface.cpp
JMF 0:082731ede69f 24 * @brief BG96 NetworkInterfaceAPI implementation for Mbed OS v5.x
JMF 0:082731ede69f 25 *
JMF 0:082731ede69f 26 * @author James Flynn
JMF 0:082731ede69f 27 *
JMF 0:082731ede69f 28 * @date 1-April-2018
JMF 0:082731ede69f 29 */
JMF 0:082731ede69f 30
JMF 0:082731ede69f 31 #include <ctype.h>
JMF 0:082731ede69f 32 #include "mbed.h"
JMF 0:082731ede69f 33 #include "BG96.h"
JMF 0:082731ede69f 34 #include "BG96Interface.h"
JMF 0:082731ede69f 35
JMF 0:082731ede69f 36 //
JMF 0:082731ede69f 37 // The driver uses a simple/basic state machine to manage receiving and transmitting
JMF 0:082731ede69f 38 // data. These are the states that are used
JMF 0:082731ede69f 39 //
JMF 0:082731ede69f 40 #define READ_INIT 10 //initialize for a read state
JMF 0:082731ede69f 41 #define READ_START 11 //start reading from the BG96
JMF 0:082731ede69f 42 #define READ_ACTIVE 12 //a read is on-going/active
JMF 0:082731ede69f 43 #define READ_DOCB 13 //need to perform a call-back on the socket
JMF 0:082731ede69f 44 #define DATA_AVAILABLE 14 //indicates that rx data is available
JMF 0:082731ede69f 45
JMF 0:082731ede69f 46 #define TX_IDLE 20 //indicates that no data is bing TX'd
JMF 0:082731ede69f 47 #define TX_STARTING 21 //indicates that TX data is starting
JMF 0:082731ede69f 48 #define TX_ACTIVE 22 //indicates that TX data is being sent
JMF 0:082731ede69f 49 #define TX_COMPLETE 23 //all TX data has been sent
JMF 0:082731ede69f 50 #define TX_DOCB 24 //indicatew we need to exeucte the call-back
JMF 0:082731ede69f 51
JMF 0:082731ede69f 52 #define BG96_READ_TIMEOUTMS 30000 //read timeout in MS
JMF 0:082731ede69f 53 #define EQ_FREQ 50 //frequency in ms to check for Tx/Rx data
JMF 0:082731ede69f 54 #define EQ_FREQ_SLOW 2000 //frequency in ms to check when in slow monitor mode
JMF 0:082731ede69f 55
JMF 0:082731ede69f 56 #define EVENT_COMPLETE 0 //signals when a TX/RX event is complete
JMF 0:082731ede69f 57 #define EVENT_GETMORE 0x01 //signals when we need additional TX/RX data
JMF 0:082731ede69f 58
JMF 0:082731ede69f 59 //
JMF 0:082731ede69f 60 // The following are only used when debug is eabled.
JMF 0:082731ede69f 61 //
JMF 0:082731ede69f 62
JMF 0:082731ede69f 63 #if MBED_CONF_APP_BG96_DEBUG == true
JMF 0:082731ede69f 64 #define debugOutput(...) _dbOut(__VA_ARGS__)
JMF 0:082731ede69f 65 #define debugDump_arry(...) _dbDump_arry(__VA_ARGS__)
JMF 0:082731ede69f 66
JMF 0:082731ede69f 67 #define dbgIO_lock dbgout_mutex.lock(); //used to prevent stdio output over-writes
JMF 0:082731ede69f 68 #define dbgIO_unlock dbgout_mutex.unlock(); //when executing--including BG96 debug output
JMF 0:082731ede69f 69
JMF 0:082731ede69f 70 /** functions to output debug data---------------------------
JMF 0:082731ede69f 71 *
JMF 0:082731ede69f 72 * @author James Flynn
JMF 0:082731ede69f 73 * @param data pointer to the data array to dump
JMF 0:082731ede69f 74 * @param size number of bytes to dump
JMF 0:082731ede69f 75 * @return void
JMF 0:082731ede69f 76 * @date 1-Feb-2018
JMF 0:082731ede69f 77 */
JMF 0:082731ede69f 78
JMF 0:082731ede69f 79
JMF 0:082731ede69f 80 void BG96Interface::_dbDump_arry( const uint8_t* data, unsigned int size )
JMF 0:082731ede69f 81 {
JMF 0:082731ede69f 82 unsigned int i, k;
JMF 0:082731ede69f 83
JMF 0:082731ede69f 84 dbgIO_lock;
JMF 0:082731ede69f 85 if( g_debug & DBGMSG_ARRY ) {
JMF 0:082731ede69f 86 for (i=0; i<size; i+=16) {
JMF 0:082731ede69f 87 printf("[BG96 Driver]:0x%04X: ",i);
JMF 0:082731ede69f 88 for (k=0; k<16; k++) {
JMF 0:082731ede69f 89 if( (i+k)<size )
JMF 0:082731ede69f 90 printf("%02X ", data[i+k]);
JMF 0:082731ede69f 91 else
JMF 0:082731ede69f 92 printf(" ");
JMF 0:082731ede69f 93 }
JMF 0:082731ede69f 94 printf(" ");
JMF 0:082731ede69f 95 for (k=0; k<16; k++) {
JMF 0:082731ede69f 96 if( (i+k)<size )
JMF 0:082731ede69f 97 printf("%c", isprint(data[i+k])? data[i+k]:'.');
JMF 0:082731ede69f 98 }
JMF 0:082731ede69f 99 printf("\n\r");
JMF 0:082731ede69f 100 }
JMF 0:082731ede69f 101 }
JMF 0:082731ede69f 102 dbgIO_unlock;
JMF 0:082731ede69f 103 }
JMF 0:082731ede69f 104
JMF 0:082731ede69f 105 void BG96Interface::_dbOut(int who, const char* format, ...)
JMF 0:082731ede69f 106 {
JMF 0:082731ede69f 107 char buffer[256];
JMF 0:082731ede69f 108 dbgIO_lock;
JMF 0:082731ede69f 109 if( who & (g_debug & (DBGMSG_DRV|DBGMSG_EQ)) ) {
JMF 0:082731ede69f 110 va_list args;
JMF 0:082731ede69f 111 va_start (args, format);
JMF 0:082731ede69f 112 printf("[BG96 Driver]: ");
JMF 0:082731ede69f 113 vsnprintf(buffer, sizeof(buffer), format, args);
JMF 0:082731ede69f 114 printf("%s",buffer);
JMF 0:082731ede69f 115 printf("\n");
JMF 0:082731ede69f 116 va_end (args);
JMF 0:082731ede69f 117 }
JMF 0:082731ede69f 118 dbgIO_unlock;
JMF 0:082731ede69f 119 }
JMF 0:082731ede69f 120
JMF 0:082731ede69f 121 #else
JMF 0:082731ede69f 122
JMF 0:082731ede69f 123 #define dbgIO_lock
JMF 0:082731ede69f 124 #define dbgIO_unlock
JMF 0:082731ede69f 125 #define debugOutput(...) {/* __VA_ARGS__ */}
JMF 0:082731ede69f 126 #define debugDump_arry(...) {/* __VA_ARGS__ */}
JMF 0:082731ede69f 127
JMF 0:082731ede69f 128 #endif //MBED_CONF_APP_BG96_DEBUG == true
JMF 0:082731ede69f 129
JMF 0:082731ede69f 130
JMF 0:082731ede69f 131 /** --------------------------------------------------------
JMF 0:082731ede69f 132 * @brief BG96Interface constructor
JMF 0:082731ede69f 133 * @param none
JMF 0:082731ede69f 134 * @retval none
JMF 0:082731ede69f 135 */
JMF 0:082731ede69f 136 BG96Interface::BG96Interface(void) :
JMF 0:082731ede69f 137 g_isInitialized(NSAPI_ERROR_NO_CONNECTION),
JMF 0:082731ede69f 138 g_bg96_queue_id(-1),
JMF 0:082731ede69f 139 scheduled_events(0),
JMF 0:082731ede69f 140 _BG96(false)
JMF 0:082731ede69f 141 {
JMF 0:082731ede69f 142 for( int i=0; i<BG96_SOCKET_COUNT; i++ ) {
JMF 0:082731ede69f 143 g_sock[i].id = -1;
JMF 0:082731ede69f 144 g_sock[i].disTO = false;
JMF 0:082731ede69f 145 g_sock[i].connected = false;
JMF 0:082731ede69f 146 g_socRx[i].m_rx_state = READ_START;
JMF 0:082731ede69f 147 g_socRx[i].m_rx_disTO = false;
JMF 0:082731ede69f 148 g_socTx[i].m_tx_state = TX_IDLE;
JMF 0:082731ede69f 149 }
JMF 0:082731ede69f 150 #if MBED_CONF_APP_BG96_DEBUG == true
JMF 0:082731ede69f 151 g_debug=0;
JMF 0:082731ede69f 152 #endif
JMF 0:082731ede69f 153 }
JMF 0:082731ede69f 154
JMF 0:082731ede69f 155 /** ----------------------------------------------------------
JMF 0:082731ede69f 156 * @brief BG96Interface destructor
JMF 0:082731ede69f 157 * @param none
JMF 0:082731ede69f 158 * @retval none
JMF 0:082731ede69f 159 */
JMF 0:082731ede69f 160 BG96Interface::~BG96Interface()
JMF 0:082731ede69f 161 {
JMF 0:082731ede69f 162 }
JMF 0:082731ede69f 163
JMF 0:082731ede69f 164 /** ----------------------------------------------------------
JMF 0:082731ede69f 165 * @brief network connect
JMF 0:082731ede69f 166 * connects to Access Point, can be called with no argument
JMF 0:082731ede69f 167 * or arguments. If none, use default APN.
JMF 0:082731ede69f 168 * @param ap: Access Point Name (APN) Name String
JMF 0:082731ede69f 169 * pass_word: Password String for AP
JMF 0:082731ede69f 170 * username: username to use for AP
JMF 0:082731ede69f 171 * @retval NSAPI Error Type
JMF 0:082731ede69f 172 */
JMF 0:082731ede69f 173 nsapi_error_t BG96Interface::connect(void)
JMF 0:082731ede69f 174 {
JMF 0:082731ede69f 175 nsapi_error_t ret = NSAPI_ERROR_OK;
JMF 0:082731ede69f 176 debugOutput(DBGMSG_DRV,"BG96Interface::connect(void) ENTER.");
JMF 0:082731ede69f 177 if( g_isInitialized == NSAPI_ERROR_NO_CONNECTION )
JMF 0:082731ede69f 178 ret = connect(DEFAULT_APN, NULL, NULL);
JMF 0:082731ede69f 179
JMF 0:082731ede69f 180 return (ret == NSAPI_ERROR_NO_CONNECTION);
JMF 0:082731ede69f 181 }
JMF 0:082731ede69f 182
JMF 0:082731ede69f 183 nsapi_error_t BG96Interface::connect(const char *apn, const char *username, const char *password)
JMF 0:082731ede69f 184 {
JMF 0:082731ede69f 185 Timer t;
JMF 0:082731ede69f 186 bool ok=false;
JMF 0:082731ede69f 187
JMF 0:082731ede69f 188 debugOutput(DBGMSG_DRV,"BG96Interface::connect(%s,%s,%s) ENTER",apn,username,password);
JMF 0:082731ede69f 189
JMF 0:082731ede69f 190 if( g_isInitialized == NSAPI_ERROR_IS_CONNECTED )
JMF 0:082731ede69f 191 ok = disconnect();
JMF 0:082731ede69f 192
JMF 0:082731ede69f 193 t.start();
JMF 0:082731ede69f 194 dbgIO_lock;
JMF 0:082731ede69f 195 while(t.read_ms() < BG96_MISC_TIMEOUT && !ok)
JMF 0:082731ede69f 196 ok = _BG96.startup();
JMF 0:082731ede69f 197 dbgIO_unlock;
JMF 0:082731ede69f 198
JMF 0:082731ede69f 199 if( ok && g_bg96_queue_id == -1)
JMF 0:082731ede69f 200 g_bg96_queue_id = _bg96_monitor.start(callback(&_bg96_queue, &EventQueue::dispatch_forever));
JMF 0:082731ede69f 201
JMF 0:082731ede69f 202 debugOutput(DBGMSG_DRV,"BG96Interface::connect EXIT");
JMF 0:082731ede69f 203
JMF 0:082731ede69f 204 return ok? set_credentials(apn, username, password) : NSAPI_ERROR_DEVICE_ERROR;
JMF 0:082731ede69f 205 }
JMF 0:082731ede69f 206
JMF 0:082731ede69f 207 /** Set the cellular network credentials --------------------
JMF 0:082731ede69f 208 *
JMF 0:082731ede69f 209 * @param apn Optional, APN of network
JMF 0:082731ede69f 210 * @param user Optional, username --not used--
JMF 0:082731ede69f 211 * @param pass Optional, password --not used--
JMF 0:082731ede69f 212 * @return nsapi_error_t
JMF 0:082731ede69f 213 */
JMF 0:082731ede69f 214 nsapi_error_t BG96Interface::set_credentials(const char *apn, const char *username, const char *password)
JMF 0:082731ede69f 215 {
JMF 0:082731ede69f 216 debugOutput(DBGMSG_DRV,"BG96Interface::set_credentials ENTER/EXIT, APN=%s, USER=%s, PASS=%s",apn,username,password);
JMF 0:082731ede69f 217 g_isInitialized = (_BG96.connect((char*)apn, (char*)username, (char*)password)==true)? NSAPI_ERROR_NO_CONNECTION : NSAPI_ERROR_IS_CONNECTED;
JMF 0:082731ede69f 218
JMF 0:082731ede69f 219 return g_isInitialized;
JMF 0:082731ede69f 220 }
JMF 0:082731ede69f 221
JMF 0:082731ede69f 222 /**----------------------------------------------------------
JMF 0:082731ede69f 223 * @brief network disconnect
JMF 0:082731ede69f 224 * disconnects from APN
JMF 0:082731ede69f 225 * @param none
JMF 0:082731ede69f 226 * @return nsapi_error_t
JMF 0:082731ede69f 227 */
JMF 0:082731ede69f 228 int BG96Interface::disconnect(void)
JMF 0:082731ede69f 229 {
JMF 0:082731ede69f 230 nsapi_error_t ret;
JMF 0:082731ede69f 231
JMF 0:082731ede69f 232 debugOutput(DBGMSG_DRV,"BG96Interface::disconnect ENTER");
JMF 0:082731ede69f 233 _bg96_queue.cancel(g_bg96_queue_id);
JMF 0:082731ede69f 234 g_bg96_queue_id = -1;
JMF 0:082731ede69f 235 g_isInitialized = NSAPI_ERROR_NO_CONNECTION;
JMF 0:082731ede69f 236 dbgIO_lock;
JMF 0:082731ede69f 237 ret = _BG96.disconnect();
JMF 0:082731ede69f 238 dbgIO_unlock;
JMF 0:082731ede69f 239 debugOutput(DBGMSG_DRV,"BG96Interface::disconnect EXIT");
JMF 0:082731ede69f 240 return ret? NSAPI_ERROR_OK:NSAPI_ERROR_DEVICE_ERROR;
JMF 0:082731ede69f 241 }
JMF 0:082731ede69f 242
JMF 0:082731ede69f 243 /**----------------------------------------------------------
JMF 0:082731ede69f 244 * @brief Get the local IP address
JMF 0:082731ede69f 245 * @param none
JMF 0:082731ede69f 246 * @retval Null-terminated representation of the local IP address
JMF 0:082731ede69f 247 * or null if not yet connected
JMF 0:082731ede69f 248 */
JMF 0:082731ede69f 249 const char *BG96Interface::get_ip_address()
JMF 0:082731ede69f 250 {
JMF 0:082731ede69f 251 static char ip[25];
JMF 0:082731ede69f 252 debugOutput(DBGMSG_DRV,"BG96Interface::get_ip_address ENTER");
JMF 0:082731ede69f 253 dbgIO_lock;
JMF 0:082731ede69f 254 const char* ptr = _BG96.getIPAddress(ip);
JMF 0:082731ede69f 255 dbgIO_unlock;
JMF 0:082731ede69f 256
JMF 0:082731ede69f 257 debugOutput(DBGMSG_DRV,"BG96Interface::get_ip_address EXIT");
JMF 0:082731ede69f 258 return ptr;
JMF 0:082731ede69f 259 }
JMF 0:082731ede69f 260
JMF 0:082731ede69f 261 /**----------------------------------------------------------
JMF 0:082731ede69f 262 * @brief Get the MAC address
JMF 0:082731ede69f 263 * @param none
JMF 0:082731ede69f 264 * @retval Null-terminated representation of the MAC address
JMF 0:082731ede69f 265 * or null if not yet connected
JMF 0:082731ede69f 266 */
JMF 0:082731ede69f 267 const char *BG96Interface::get_mac_address()
JMF 0:082731ede69f 268 {
JMF 0:082731ede69f 269 static char mac[25];
JMF 0:082731ede69f 270 debugOutput(DBGMSG_DRV,"BG96Interface::get_mac_address ENTER");
JMF 0:082731ede69f 271 dbgIO_lock;
JMF 0:082731ede69f 272 const char* ptr = _BG96.getMACAddress(mac);
JMF 0:082731ede69f 273 dbgIO_unlock;
JMF 0:082731ede69f 274 debugOutput(DBGMSG_DRV,"BG96Interface::get_mac_address EXIT");
JMF 0:082731ede69f 275 return ptr;
JMF 0:082731ede69f 276 }
JMF 0:082731ede69f 277
JMF 0:082731ede69f 278 /**----------------------------------------------------------
JMF 0:082731ede69f 279 * @brief Get Module Firmware Information
JMF 0:082731ede69f 280 * @param none
JMF 0:082731ede69f 281 * @retval Null-terminated representation of the MAC address
JMF 0:082731ede69f 282 * or null if error
JMF 0:082731ede69f 283 */
JMF 0:082731ede69f 284 const char* BG96Interface::getRevision(void)
JMF 0:082731ede69f 285 {
JMF 0:082731ede69f 286 static char str[40];
JMF 0:082731ede69f 287 dbgIO_lock;
JMF 0:082731ede69f 288 const char* ptr = _BG96.getRev(str);
JMF 0:082731ede69f 289 dbgIO_unlock;
JMF 0:082731ede69f 290 return ptr;
JMF 0:082731ede69f 291 }
JMF 0:082731ede69f 292
JMF 0:082731ede69f 293 /**----------------------------------------------------------
JMF 0:082731ede69f 294 * @brief attach function/callback to the socket
JMF 0:082731ede69f 295 * Not used
JMF 0:082731ede69f 296 * @param handle: Pointer to handle
JMF 0:082731ede69f 297 * callback: callback function pointer
JMF 0:082731ede69f 298 * data: pointer to data
JMF 0:082731ede69f 299 * @retval none
JMF 0:082731ede69f 300 */
JMF 0:082731ede69f 301 void BG96Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
JMF 0:082731ede69f 302 {
JMF 0:082731ede69f 303 BG96SOCKET *sock = (BG96SOCKET*)handle;
JMF 0:082731ede69f 304 debugOutput(DBGMSG_DRV,"ENTER/EXIT socket_attach(), socket %d attached",sock->id);
JMF 0:082731ede69f 305 sock->_callback = callback;
JMF 0:082731ede69f 306 sock->_data = data;
JMF 0:082731ede69f 307 }
JMF 0:082731ede69f 308
JMF 0:082731ede69f 309
JMF 0:082731ede69f 310 /**----------------------------------------------------------
JMF 0:082731ede69f 311 * @brief bind to a port number and address
JMF 0:082731ede69f 312 * @param handle: Pointer to socket handle
JMF 0:082731ede69f 313 * proto: address to bind to
JMF 0:082731ede69f 314 * @return nsapi_error_t
JMF 0:082731ede69f 315 */
JMF 0:082731ede69f 316 int BG96Interface::socket_bind(void *handle, const SocketAddress &address)
JMF 0:082731ede69f 317 {
JMF 0:082731ede69f 318 debugOutput(DBGMSG_DRV,"BG96Interface::socket_bind ENTER/EXIT");
JMF 0:082731ede69f 319 return socket_listen(handle, 1);
JMF 0:082731ede69f 320 }
JMF 0:082731ede69f 321
JMF 0:082731ede69f 322 /**----------------------------------------------------------
JMF 0:082731ede69f 323 * @brief start listening on a port and address
JMF 0:082731ede69f 324 * @param handle: Pointer to handle
JMF 0:082731ede69f 325 * backlog: not used (always value is 1)
JMF 0:082731ede69f 326 * @return nsapi_error_t
JMF 0:082731ede69f 327 */
JMF 0:082731ede69f 328 int BG96Interface::socket_listen(void *handle, int backlog)
JMF 0:082731ede69f 329 {
JMF 0:082731ede69f 330 BG96SOCKET *socket = (BG96SOCKET *)handle;
JMF 0:082731ede69f 331 nsapi_error_t ret = NSAPI_ERROR_OK;
JMF 0:082731ede69f 332
JMF 0:082731ede69f 333 backlog = backlog; //avoid unused error from compiler
JMF 0:082731ede69f 334 debugOutput(DBGMSG_DRV,"BG96Interface::socket_listen, socket %d listening %s ENTER",
JMF 0:082731ede69f 335 socket->id, socket->connected? "YES":"NO");
JMF 0:082731ede69f 336 if( !socket->connected ) {
JMF 0:082731ede69f 337 socket->disTO = true;
JMF 0:082731ede69f 338 _eq_schedule();
JMF 0:082731ede69f 339 }
JMF 0:082731ede69f 340 else
JMF 0:082731ede69f 341 ret = NSAPI_ERROR_NO_CONNECTION;
JMF 0:082731ede69f 342
JMF 0:082731ede69f 343 debugOutput(DBGMSG_DRV,"BG96Interface::socket_listen EXIT");
JMF 0:082731ede69f 344 return ret;
JMF 0:082731ede69f 345 }
JMF 0:082731ede69f 346
JMF 0:082731ede69f 347 /**----------------------------------------------------------
JMF 0:082731ede69f 348 * @brief Set the socket options
JMF 0:082731ede69f 349 * Not used
JMF 0:082731ede69f 350 * @param handle: Pointer to handle
JMF 0:082731ede69f 351 * level: SOL_SOCKET
JMF 0:082731ede69f 352 * optname: option name
JMF 0:082731ede69f 353 * optval: pointer to option value
JMF 0:082731ede69f 354 * optlen: option length
JMF 0:082731ede69f 355 * @return nsapi_error_t
JMF 0:082731ede69f 356 */
JMF 0:082731ede69f 357 int BG96Interface::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
JMF 0:082731ede69f 358 {
JMF 0:082731ede69f 359 BG96SOCKET *sock = (BG96SOCKET *)handle;
JMF 0:082731ede69f 360
JMF 0:082731ede69f 361 debugOutput(DBGMSG_DRV,"BG96Interface::setsockopt ENTER/EXIT");
JMF 0:082731ede69f 362 if (!optlen || !sock) {
JMF 0:082731ede69f 363 return NSAPI_ERROR_PARAMETER;
JMF 0:082731ede69f 364 }
JMF 0:082731ede69f 365
JMF 0:082731ede69f 366 if (level == NSAPI_SOCKET && sock->proto == NSAPI_TCP) {
JMF 0:082731ede69f 367 switch (optname) {
JMF 0:082731ede69f 368 case NSAPI_REUSEADDR:
JMF 0:082731ede69f 369 case NSAPI_KEEPIDLE:
JMF 0:082731ede69f 370 case NSAPI_KEEPINTVL:
JMF 0:082731ede69f 371 case NSAPI_LINGER:
JMF 0:082731ede69f 372 case NSAPI_SNDBUF:
JMF 0:082731ede69f 373 case NSAPI_ADD_MEMBERSHIP:
JMF 0:082731ede69f 374 case NSAPI_DROP_MEMBERSHIP:
JMF 0:082731ede69f 375 case NSAPI_KEEPALIVE:
JMF 0:082731ede69f 376 return NSAPI_ERROR_UNSUPPORTED;
JMF 0:082731ede69f 377
JMF 0:082731ede69f 378 case NSAPI_RCVBUF:
JMF 0:082731ede69f 379 if (optlen == sizeof(void *)) {
JMF 0:082731ede69f 380 sock->dptr_last = (void*)optval;
JMF 0:082731ede69f 381 sock->dptr_size = (unsigned)optlen;
JMF 0:082731ede69f 382 return NSAPI_ERROR_OK;
JMF 0:082731ede69f 383 }
JMF 0:082731ede69f 384 return NSAPI_ERROR_PARAMETER;
JMF 0:082731ede69f 385 }
JMF 0:082731ede69f 386 }
JMF 0:082731ede69f 387 return NSAPI_ERROR_UNSUPPORTED;
JMF 0:082731ede69f 388 }
JMF 0:082731ede69f 389
JMF 0:082731ede69f 390 /**----------------------------------------------------------
JMF 0:082731ede69f 391 * @brief Get the socket options
JMF 0:082731ede69f 392 * Not used
JMF 0:082731ede69f 393 * @param handle: Pointer to handle
JMF 0:082731ede69f 394 * level: SOL_SOCKET
JMF 0:082731ede69f 395 * optname: option name
JMF 0:082731ede69f 396 * optval: pointer to option value
JMF 0:082731ede69f 397 * optlen: pointer to option length
JMF 0:082731ede69f 398 * @return nsapi_error_t
JMF 0:082731ede69f 399 */
JMF 0:082731ede69f 400 int BG96Interface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
JMF 0:082731ede69f 401 {
JMF 0:082731ede69f 402 BG96SOCKET *sock = (BG96SOCKET *)handle;
JMF 0:082731ede69f 403
JMF 0:082731ede69f 404 debugOutput(DBGMSG_DRV,"BG96Interface::getsockopt ENTER/EXIT");
JMF 0:082731ede69f 405 if (!optval || !optlen || !sock) {
JMF 0:082731ede69f 406 return NSAPI_ERROR_PARAMETER;
JMF 0:082731ede69f 407 }
JMF 0:082731ede69f 408
JMF 0:082731ede69f 409 if (level == NSAPI_SOCKET && sock->proto == NSAPI_TCP) {
JMF 0:082731ede69f 410 switch (optname) {
JMF 0:082731ede69f 411 case NSAPI_REUSEADDR:
JMF 0:082731ede69f 412 case NSAPI_KEEPALIVE:
JMF 0:082731ede69f 413 case NSAPI_KEEPIDLE:
JMF 0:082731ede69f 414 case NSAPI_KEEPINTVL:
JMF 0:082731ede69f 415 case NSAPI_LINGER:
JMF 0:082731ede69f 416 case NSAPI_SNDBUF:
JMF 0:082731ede69f 417 case NSAPI_ADD_MEMBERSHIP:
JMF 0:082731ede69f 418 case NSAPI_DROP_MEMBERSHIP:
JMF 0:082731ede69f 419 return NSAPI_ERROR_UNSUPPORTED;
JMF 0:082731ede69f 420
JMF 0:082731ede69f 421 case NSAPI_RCVBUF:
JMF 0:082731ede69f 422 optval = sock->dptr_last;
JMF 0:082731ede69f 423 *optlen = sock->dptr_size;
JMF 0:082731ede69f 424 return NSAPI_ERROR_OK;
JMF 0:082731ede69f 425 }
JMF 0:082731ede69f 426 }
JMF 0:082731ede69f 427 return NSAPI_ERROR_UNSUPPORTED;
JMF 0:082731ede69f 428 }
JMF 0:082731ede69f 429
JMF 0:082731ede69f 430 /**----------------------------------------------------------
JMF 0:082731ede69f 431 * @brief helpe function to set debug levels. Only enabled
JMF 0:082731ede69f 432 * if debug flag set during compilation
JMF 0:082731ede69f 433 * @param int = value to set debug flag to
JMF 0:082731ede69f 434 * @retval none
JMF 0:082731ede69f 435 */
JMF 0:082731ede69f 436 void BG96Interface::doDebug( int v )
JMF 0:082731ede69f 437 {
JMF 0:082731ede69f 438 #if MBED_CONF_APP_BG96_DEBUG == true
JMF 0:082731ede69f 439 gvupdate_mutex.lock();
JMF 0:082731ede69f 440 _BG96.doDebug(v);
JMF 0:082731ede69f 441 g_debug= v;
JMF 0:082731ede69f 442 gvupdate_mutex.unlock();
JMF 0:082731ede69f 443 debugOutput(DBGMSG_DRV,"SET debug flag to 0x%02X",v);
JMF 0:082731ede69f 444 #endif
JMF 0:082731ede69f 445 }
JMF 0:082731ede69f 446
JMF 0:082731ede69f 447 /**----------------------------------------------------------
JMF 0:082731ede69f 448 * @brief open a socket handle
JMF 0:082731ede69f 449 * @param handle: Pointer to handle
JMF 0:082731ede69f 450 * proto: TCP/UDP protocol
JMF 0:082731ede69f 451 * @return nsapi_error_t
JMF 0:082731ede69f 452 */
JMF 0:082731ede69f 453 int BG96Interface::socket_open(void **handle, nsapi_protocol_t proto)
JMF 0:082731ede69f 454 {
JMF 0:082731ede69f 455 int i;
JMF 0:082731ede69f 456 nsapi_error_t ret=NSAPI_ERROR_OK;
JMF 0:082731ede69f 457
JMF 0:082731ede69f 458 debugOutput(DBGMSG_DRV,"ENTER socket_open(), protocol=%s", (proto==NSAPI_TCP)?"TCP":"UDP");
JMF 0:082731ede69f 459 gvupdate_mutex.lock();
JMF 0:082731ede69f 460 for( i=0; i<BG96_SOCKET_COUNT; i++ ) //find the next available socket...
JMF 0:082731ede69f 461 if( g_sock[i].id == -1 )
JMF 0:082731ede69f 462 break;
JMF 0:082731ede69f 463
JMF 0:082731ede69f 464 if( i == BG96_SOCKET_COUNT ) {
JMF 0:082731ede69f 465 ret = NSAPI_ERROR_NO_SOCKET;
JMF 0:082731ede69f 466 debugOutput(DBGMSG_DRV,"EXIT socket_open; NO SOCKET AVAILABLE (%d)",i);
JMF 0:082731ede69f 467 }
JMF 0:082731ede69f 468 else{
JMF 0:082731ede69f 469 debugOutput(DBGMSG_DRV,"socket_open using socket %d", i);
JMF 0:082731ede69f 470
JMF 0:082731ede69f 471 g_socTx[i].m_tx_state = TX_IDLE;
JMF 0:082731ede69f 472 g_socRx[i].m_rx_state = READ_START;
JMF 0:082731ede69f 473
JMF 0:082731ede69f 474 g_sock[i].id = i;
JMF 0:082731ede69f 475 g_sock[i].disTO = false;
JMF 0:082731ede69f 476 g_sock[i].proto = proto;
JMF 0:082731ede69f 477 g_sock[i].connected = false;
JMF 0:082731ede69f 478 g_sock[i]._callback = NULL;
JMF 0:082731ede69f 479 g_sock[i]._data = NULL;
JMF 0:082731ede69f 480 *handle = &g_sock[i];
JMF 0:082731ede69f 481 debugOutput(DBGMSG_DRV,"EXIT socket_open; Socket=%d, protocol =%s",
JMF 0:082731ede69f 482 i, (g_sock[i].proto==NSAPI_UDP)?"UDP":"TCP");
JMF 0:082731ede69f 483 }
JMF 0:082731ede69f 484 gvupdate_mutex.unlock();
JMF 0:082731ede69f 485
JMF 0:082731ede69f 486 return ret;
JMF 0:082731ede69f 487 }
JMF 0:082731ede69f 488
JMF 0:082731ede69f 489 /**----------------------------------------------------------
JMF 0:082731ede69f 490 * @brief close a socket
JMF 0:082731ede69f 491 * @param handle: Pointer to handle
JMF 0:082731ede69f 492 * @return nsapi_error_t
JMF 0:082731ede69f 493 */
JMF 0:082731ede69f 494 int BG96Interface::socket_close(void *handle)
JMF 0:082731ede69f 495 {
JMF 0:082731ede69f 496 BG96SOCKET *sock = (BG96SOCKET*)handle;
JMF 0:082731ede69f 497 nsapi_error_t ret =NSAPI_ERROR_DEVICE_ERROR;
JMF 0:082731ede69f 498 RXEVENT *rxsock;
JMF 0:082731ede69f 499 TXEVENT *txsock;
JMF 0:082731ede69f 500 int i = sock->id;
JMF 0:082731ede69f 501
JMF 0:082731ede69f 502 debugOutput(DBGMSG_DRV,"ENTER socket_close(); Socket=%d", i);
JMF 0:082731ede69f 503
JMF 0:082731ede69f 504 if(i >= 0) {
JMF 0:082731ede69f 505 txrx_mutex.lock();
JMF 0:082731ede69f 506 txsock = &g_socTx[i];
JMF 0:082731ede69f 507 rxsock = &g_socRx[i];
JMF 0:082731ede69f 508
JMF 0:082731ede69f 509 txsock->m_tx_state = TX_IDLE;
JMF 0:082731ede69f 510 rxsock->m_rx_state = READ_START;
JMF 0:082731ede69f 511
JMF 0:082731ede69f 512 dbgIO_lock;
JMF 0:082731ede69f 513 if( sock->connected )
JMF 0:082731ede69f 514 _BG96.close(sock->id);
JMF 0:082731ede69f 515 dbgIO_unlock;
JMF 0:082731ede69f 516
JMF 0:082731ede69f 517 sock->id = -1;
JMF 0:082731ede69f 518 sock->disTO = false;
JMF 0:082731ede69f 519 sock->proto = NSAPI_TCP;
JMF 0:082731ede69f 520 sock->connected= false;
JMF 0:082731ede69f 521 sock->_callback= NULL;
JMF 0:082731ede69f 522 sock->_data = NULL;
JMF 0:082731ede69f 523 ret = NSAPI_ERROR_OK;
JMF 0:082731ede69f 524 txrx_mutex.unlock();
JMF 0:082731ede69f 525 debugOutput(DBGMSG_DRV,"EXIT socket_close(), socket %d - success",i);
JMF 0:082731ede69f 526 }
JMF 0:082731ede69f 527 else
JMF 0:082731ede69f 528 debugOutput(DBGMSG_DRV,"EXIT socket_close() - fail");
JMF 0:082731ede69f 529 return ret;
JMF 0:082731ede69f 530 }
JMF 0:082731ede69f 531
JMF 0:082731ede69f 532 /**----------------------------------------------------------
JMF 0:082731ede69f 533 * @brief accept connections from remote sockets
JMF 0:082731ede69f 534 * @param handle: Pointer to handle of client socket (connecting)
JMF 0:082731ede69f 535 * proto: handle of server socket which will accept connections
JMF 0:082731ede69f 536 * @return nsapi_error_t
JMF 0:082731ede69f 537 */
JMF 0:082731ede69f 538 int BG96Interface::socket_accept(nsapi_socket_t server,nsapi_socket_t *handle, SocketAddress *address)
JMF 0:082731ede69f 539 {
JMF 0:082731ede69f 540 return NSAPI_ERROR_UNSUPPORTED;
JMF 0:082731ede69f 541 }
JMF 0:082731ede69f 542
JMF 0:082731ede69f 543 /**----------------------------------------------------------
JMF 0:082731ede69f 544 * @brief connect to a remote socket
JMF 0:082731ede69f 545 * @param handle: Pointer to socket handle
JMF 0:082731ede69f 546 * addr: Address to connect to
JMF 0:082731ede69f 547 * @return nsapi_error_t
JMF 0:082731ede69f 548 */
JMF 0:082731ede69f 549 int BG96Interface::socket_connect(void *handle, const SocketAddress &addr)
JMF 0:082731ede69f 550 {
JMF 0:082731ede69f 551 BG96SOCKET *sock = (BG96SOCKET *)handle;
JMF 0:082731ede69f 552 nsapi_error_t ret=NSAPI_ERROR_OK;
JMF 0:082731ede69f 553 const char proto = (sock->proto == NSAPI_UDP) ? 'u' : 't';
JMF 0:082731ede69f 554 bool k;
JMF 0:082731ede69f 555 int cnt;
JMF 0:082731ede69f 556
JMF 0:082731ede69f 557
JMF 0:082731ede69f 558 debugOutput(DBGMSG_DRV,"ENTER socket_connect(); Socket=%d; IP=%s; PORT=%d;",
JMF 0:082731ede69f 559 sock->id, addr.get_ip_address(), addr.get_port());
JMF 0:082731ede69f 560 dbgIO_lock;
JMF 0:082731ede69f 561 for( k=true, cnt=0; cnt<3 && k; cnt++ ) {
JMF 0:082731ede69f 562 k = !_BG96.open(proto, sock->id, addr.get_ip_address(), addr.get_port());
JMF 0:082731ede69f 563 if( k )
JMF 0:082731ede69f 564 _BG96.close(sock->id);
JMF 0:082731ede69f 565 }
JMF 0:082731ede69f 566 dbgIO_unlock;
JMF 0:082731ede69f 567
JMF 0:082731ede69f 568 if( cnt<3 ) {
JMF 0:082731ede69f 569 sock->addr = addr;
JMF 0:082731ede69f 570 sock->connected = true;
JMF 0:082731ede69f 571
JMF 0:082731ede69f 572 if( sock->_callback != NULL )
JMF 0:082731ede69f 573 sock->_callback(sock->_data);
JMF 0:082731ede69f 574 }
JMF 0:082731ede69f 575 else
JMF 0:082731ede69f 576 ret = NSAPI_ERROR_DEVICE_ERROR;
JMF 0:082731ede69f 577
JMF 0:082731ede69f 578 debugOutput(DBGMSG_DRV,"EXIT socket_connect(), Socket %d",sock->id);
JMF 0:082731ede69f 579 return ret;
JMF 0:082731ede69f 580 }
JMF 0:082731ede69f 581
JMF 0:082731ede69f 582 /**----------------------------------------------------------
JMF 0:082731ede69f 583 * @brief return the address of this object
JMF 0:082731ede69f 584 * @param none
JMF 0:082731ede69f 585 * @retval pointer to this class object
JMF 0:082731ede69f 586 */
JMF 0:082731ede69f 587 NetworkStack *BG96Interface::get_stack()
JMF 0:082731ede69f 588 {
JMF 0:082731ede69f 589 return this;
JMF 0:082731ede69f 590 }
JMF 0:082731ede69f 591
JMF 0:082731ede69f 592 /**----------------------------------------------------------
JMF 0:082731ede69f 593 * @brief return IP address after looking up the URL name
JMF 0:082731ede69f 594 * @param name = URL string
JMF 0:082731ede69f 595 * address = address to store IP in
JMF 0:082731ede69f 596 * version = not used
JMF 0:082731ede69f 597 * @return nsapi_error_t
JMF 0:082731ede69f 598 */
JMF 0:082731ede69f 599 nsapi_error_t BG96Interface::gethostbyname(const char* name, SocketAddress *address, nsapi_version_t version)
JMF 0:082731ede69f 600 {
JMF 0:082731ede69f 601 char ipstr[25];
JMF 0:082731ede69f 602 bool ok;
JMF 0:082731ede69f 603 nsapi_error_t ret=NSAPI_ERROR_OK;
JMF 0:082731ede69f 604
JMF 0:082731ede69f 605 debugOutput(DBGMSG_DRV,"ENTER gethostbyname(); IP=%s; PORT=%d; URL=%s;",
JMF 0:082731ede69f 606 address->get_ip_address(), address->get_port(), name);
JMF 0:082731ede69f 607
JMF 0:082731ede69f 608 dbgIO_lock;
JMF 0:082731ede69f 609 ok=_BG96.resolveUrl(name,ipstr);
JMF 0:082731ede69f 610 dbgIO_unlock;
JMF 0:082731ede69f 611
JMF 0:082731ede69f 612 if( !ok ) {
JMF 0:082731ede69f 613 ret = NSAPI_ERROR_DEVICE_ERROR;
JMF 0:082731ede69f 614 debugOutput(DBGMSG_DRV,"EXIT gethostbyname() -- failed to get DNS");
JMF 0:082731ede69f 615 }
JMF 0:082731ede69f 616 else{
JMF 0:082731ede69f 617 address->set_ip_address(ipstr);
JMF 0:082731ede69f 618 debugOutput(DBGMSG_DRV,"EXIT gethostbyname(); IP=%s; PORT=%d; URL=%s;",
JMF 0:082731ede69f 619 address->get_ip_address(), address->get_port(), name);
JMF 0:082731ede69f 620 }
JMF 0:082731ede69f 621 return ret;
JMF 0:082731ede69f 622 }
JMF 0:082731ede69f 623
JMF 0:082731ede69f 624 /**----------------------------------------------------------
JMF 0:082731ede69f 625 * @brief send data to a udp socket
JMF 0:082731ede69f 626 * @param handle: Pointer to handle
JMF 0:082731ede69f 627 * addr: address of udp socket
JMF 0:082731ede69f 628 * data: pointer to data
JMF 0:082731ede69f 629 * size: size of data
JMF 0:082731ede69f 630 * @retval no of bytes sent
JMF 0:082731ede69f 631 */
JMF 0:082731ede69f 632 int BG96Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
JMF 0:082731ede69f 633 {
JMF 0:082731ede69f 634 BG96SOCKET *sock = (BG96SOCKET *)handle;
JMF 0:082731ede69f 635 int err=NSAPI_ERROR_OK;
JMF 0:082731ede69f 636
JMF 0:082731ede69f 637 if (!sock->connected)
JMF 0:082731ede69f 638 err = socket_connect(sock, addr);
JMF 0:082731ede69f 639
JMF 0:082731ede69f 640 if( err != NSAPI_ERROR_OK )
JMF 0:082731ede69f 641 return err;
JMF 0:082731ede69f 642 else
JMF 0:082731ede69f 643 return socket_send(sock, data, size);
JMF 0:082731ede69f 644 }
JMF 0:082731ede69f 645
JMF 0:082731ede69f 646
JMF 0:082731ede69f 647 /**----------------------------------------------------------
JMF 0:082731ede69f 648 * @brief write to a socket
JMF 0:082731ede69f 649 * @param handle: Pointer to handle
JMF 0:082731ede69f 650 * data: pointer to data
JMF 0:082731ede69f 651 * size: size of data
JMF 0:082731ede69f 652 * @retval no of bytes sent
JMF 0:082731ede69f 653 */
JMF 0:082731ede69f 654 int BG96Interface::socket_send(void *handle, const void *data, unsigned size)
JMF 0:082731ede69f 655 {
JMF 0:082731ede69f 656 BG96SOCKET *sock = (BG96SOCKET *)handle;
JMF 0:082731ede69f 657 TXEVENT *txsock;
JMF 0:082731ede69f 658
JMF 0:082731ede69f 659 debugOutput(DBGMSG_DRV,"ENTER socket_send(),socket %d, send %d bytes",sock->id,size);
JMF 0:082731ede69f 660
JMF 0:082731ede69f 661 if( size < 1 || data == NULL ) // should never happen but have seen it
JMF 0:082731ede69f 662 return 0;
JMF 0:082731ede69f 663
JMF 0:082731ede69f 664 txrx_mutex.lock();
JMF 0:082731ede69f 665 txsock = &g_socTx[sock->id];
JMF 0:082731ede69f 666
JMF 0:082731ede69f 667 switch( txsock->m_tx_state ) {
JMF 0:082731ede69f 668 case TX_IDLE:
JMF 0:082731ede69f 669 txsock->m_tx_socketID = sock->id;
JMF 0:082731ede69f 670 txsock->m_tx_state = TX_STARTING;
JMF 0:082731ede69f 671 txsock->m_tx_dptr = (uint8_t*)data;
JMF 0:082731ede69f 672 txsock->m_tx_orig_size = size;
JMF 0:082731ede69f 673 txsock->m_tx_req_size = (uint32_t)size;
JMF 0:082731ede69f 674 txsock->m_tx_total_sent= 0;
JMF 0:082731ede69f 675 txsock->m_tx_callback = sock->_callback;
JMF 0:082731ede69f 676 txsock->m_tx_cb_data = sock->_data;
JMF 0:082731ede69f 677 debugDump_arry((const uint8_t*)data,size);
JMF 0:082731ede69f 678
JMF 0:082731ede69f 679 if( txsock->m_tx_req_size > BG96::BG96_BUFF_SIZE )
JMF 0:082731ede69f 680 txsock->m_tx_req_size= BG96::BG96_BUFF_SIZE;
JMF 0:082731ede69f 681
JMF 0:082731ede69f 682 if( tx_event(txsock) != EVENT_COMPLETE ) { //if we didn't sent all the data, schedule background send the rest
JMF 0:082731ede69f 683 debugOutput(DBGMSG_DRV,"Schedule TX event for socket %d",sock->id);
JMF 0:082731ede69f 684 txsock->m_tx_state = TX_ACTIVE;
JMF 0:082731ede69f 685 _eq_schedule();
JMF 0:082731ede69f 686 txrx_mutex.unlock();
JMF 0:082731ede69f 687 return NSAPI_ERROR_WOULD_BLOCK;
JMF 0:082731ede69f 688 }
JMF 0:082731ede69f 689 // fall through
JMF 0:082731ede69f 690
JMF 0:082731ede69f 691 if( txsock->m_tx_state == TX_DOCB ) {
JMF 0:082731ede69f 692 debugOutput(DBGMSG_DRV,"Call socket %d TX call-back",sock->id);
JMF 0:082731ede69f 693 txsock->m_tx_state = TX_COMPLETE;
JMF 0:082731ede69f 694 txsock->m_tx_callback( txsock->m_tx_cb_data );
JMF 0:082731ede69f 695 }
JMF 0:082731ede69f 696
JMF 0:082731ede69f 697 // fall through
JMF 0:082731ede69f 698
JMF 0:082731ede69f 699 case TX_COMPLETE:
JMF 0:082731ede69f 700 debugOutput(DBGMSG_DRV,"EXIT socket_send(), socket %d, sent %d bytes", txsock->m_tx_socketID,txsock->m_tx_total_sent);
JMF 0:082731ede69f 701 txsock->m_tx_state = TX_IDLE;
JMF 0:082731ede69f 702 txrx_mutex.unlock();
JMF 0:082731ede69f 703 return txsock->m_tx_total_sent;
JMF 0:082731ede69f 704
JMF 0:082731ede69f 705 case TX_ACTIVE:
JMF 0:082731ede69f 706 case TX_STARTING:
JMF 0:082731ede69f 707 debugOutput(DBGMSG_DRV,"EXIT socket_send(), TX_ACTIVE/TX_STARTING");
JMF 0:082731ede69f 708 txrx_mutex.unlock();
JMF 0:082731ede69f 709 return NSAPI_ERROR_WOULD_BLOCK;
JMF 0:082731ede69f 710
JMF 0:082731ede69f 711 case TX_DOCB:
JMF 0:082731ede69f 712 default:
JMF 0:082731ede69f 713 debugOutput(DBGMSG_DRV,"EXIT socket_send(), NSAPI_ERROR_DEVICE_ERROR");
JMF 0:082731ede69f 714 txrx_mutex.unlock();
JMF 0:082731ede69f 715 return NSAPI_ERROR_DEVICE_ERROR;
JMF 0:082731ede69f 716 }
JMF 0:082731ede69f 717 }
JMF 0:082731ede69f 718
JMF 0:082731ede69f 719 /**----------------------------------------------------------
JMF 0:082731ede69f 720 * @brief receive data on a udp socket
JMF 0:082731ede69f 721 * @param handle: Pointer to handle
JMF 0:082731ede69f 722 * addr: address of udp socket
JMF 0:082731ede69f 723 * data: pointer to data
JMF 0:082731ede69f 724 * size: size of data
JMF 0:082731ede69f 725 * @retval no of bytes read
JMF 0:082731ede69f 726 */
JMF 0:082731ede69f 727 int BG96Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
JMF 0:082731ede69f 728 {
JMF 0:082731ede69f 729 BG96SOCKET *sock = (BG96SOCKET *)handle;
JMF 0:082731ede69f 730
JMF 0:082731ede69f 731 if (!sock->connected)
JMF 0:082731ede69f 732 return NSAPI_ERROR_NO_CONNECTION;
JMF 0:082731ede69f 733 *addr = sock->addr;
JMF 0:082731ede69f 734 return socket_recv(sock, data, size);
JMF 0:082731ede69f 735 }
JMF 0:082731ede69f 736
JMF 0:082731ede69f 737 /**----------------------------------------------------------
JMF 0:082731ede69f 738 * @brief receive data on a socket
JMF 0:082731ede69f 739 * @param handle: Pointer to socket handle
JMF 0:082731ede69f 740 * data: pointer to data
JMF 0:082731ede69f 741 * size: size of data
JMF 0:082731ede69f 742 * @retval no of bytes read
JMF 0:082731ede69f 743 */
JMF 0:082731ede69f 744 int BG96Interface::socket_recv(void *handle, void *data, unsigned size)
JMF 0:082731ede69f 745 {
JMF 0:082731ede69f 746 BG96SOCKET *sock = (BG96SOCKET *)handle;
JMF 0:082731ede69f 747 RXEVENT *rxsock;
JMF 0:082731ede69f 748
JMF 0:082731ede69f 749 if( size < 1 || data == NULL ) // should never happen
JMF 0:082731ede69f 750 return 0;
JMF 0:082731ede69f 751
JMF 0:082731ede69f 752 txrx_mutex.lock();
JMF 0:082731ede69f 753 rxsock = &g_socRx[sock->id];
JMF 0:082731ede69f 754 debugOutput(DBGMSG_DRV,"ENTER socket_recv(), socket %d, request %d bytes",sock->id, size);
JMF 0:082731ede69f 755
JMF 0:082731ede69f 756 switch( rxsock->m_rx_state ) {
JMF 0:082731ede69f 757 case READ_START: //need to start a read sequence of events
JMF 0:082731ede69f 758 rxsock->m_rx_disTO = sock->disTO;
JMF 0:082731ede69f 759 rxsock->m_rx_socketID = sock->id;
JMF 0:082731ede69f 760 rxsock->m_rx_state = READ_INIT;
JMF 0:082731ede69f 761 rxsock->m_rx_dptr = (uint8_t*)data;
JMF 0:082731ede69f 762 rxsock->m_rx_req_size = (uint32_t)size;
JMF 0:082731ede69f 763 rxsock->m_rx_total_cnt = 0;
JMF 0:082731ede69f 764 rxsock->m_rx_timer = 0;
JMF 0:082731ede69f 765 rxsock->m_rx_return_cnt= 0;
JMF 0:082731ede69f 766
JMF 0:082731ede69f 767 if( rxsock->m_rx_req_size > BG96::BG96_BUFF_SIZE)
JMF 0:082731ede69f 768 rxsock->m_rx_req_size= BG96::BG96_BUFF_SIZE;
JMF 0:082731ede69f 769
JMF 0:082731ede69f 770 rxsock->m_rx_callback = sock->_callback;
JMF 0:082731ede69f 771 rxsock->m_rx_cb_data = sock->_data;
JMF 0:082731ede69f 772 // fall through
JMF 0:082731ede69f 773 if( rx_event(rxsock) != EVENT_COMPLETE ){
JMF 0:082731ede69f 774 rxsock->m_rx_state = READ_ACTIVE;
JMF 0:082731ede69f 775 _eq_schedule();
JMF 0:082731ede69f 776 debugOutput(DBGMSG_DRV,"EXIT socket_recv, scheduled read of socket %d.", sock->id);
JMF 0:082731ede69f 777 txrx_mutex.unlock();
JMF 0:082731ede69f 778 return NSAPI_ERROR_WOULD_BLOCK;
JMF 0:082731ede69f 779 }
JMF 0:082731ede69f 780
JMF 0:082731ede69f 781 //got data, fall thru and finish. no need to schedule the background task
JMF 0:082731ede69f 782 if( rxsock->m_rx_state == READ_DOCB ) {
JMF 0:082731ede69f 783 debugOutput(DBGMSG_DRV,"Call socket %d RX call-back",sock->id);
JMF 0:082731ede69f 784 rxsock->m_rx_state = DATA_AVAILABLE;
JMF 0:082731ede69f 785 rxsock->m_rx_callback( rxsock->m_rx_cb_data );
JMF 0:082731ede69f 786 }
JMF 0:082731ede69f 787
JMF 0:082731ede69f 788 // fall through
JMF 0:082731ede69f 789
JMF 0:082731ede69f 790 case DATA_AVAILABLE:
JMF 0:082731ede69f 791 debugOutput(DBGMSG_DRV,"EXIT socket_recv(),socket %d, return %d bytes",sock->id, rxsock->m_rx_return_cnt);
JMF 0:082731ede69f 792 debugDump_arry((const uint8_t*)data,rxsock->m_rx_return_cnt);
JMF 0:082731ede69f 793 rxsock->m_rx_state = READ_START;
JMF 0:082731ede69f 794 txrx_mutex.unlock();
JMF 0:082731ede69f 795 return rxsock->m_rx_return_cnt;
JMF 0:082731ede69f 796
JMF 0:082731ede69f 797 case READ_ACTIVE:
JMF 0:082731ede69f 798 case READ_INIT:
JMF 0:082731ede69f 799 debugOutput(DBGMSG_DRV,"EXIT socket_recv(), socket id %d, READ_ACTIVE/INIT", sock->id);
JMF 0:082731ede69f 800 txrx_mutex.unlock();
JMF 0:082731ede69f 801 return NSAPI_ERROR_WOULD_BLOCK;
JMF 0:082731ede69f 802
JMF 0:082731ede69f 803 case READ_DOCB:
JMF 0:082731ede69f 804 default:
JMF 0:082731ede69f 805 debugOutput(DBGMSG_DRV,"EXIT socket_recv(), NSAPI_ERROR_DEVICE_ERROR");
JMF 0:082731ede69f 806 txrx_mutex.unlock();
JMF 0:082731ede69f 807 return NSAPI_ERROR_DEVICE_ERROR;
JMF 0:082731ede69f 808 }
JMF 0:082731ede69f 809 }
JMF 0:082731ede69f 810
JMF 0:082731ede69f 811 /**----------------------------------------------------------
JMF 0:082731ede69f 812 * @brief check for and retrieve data user requested. Time out
JMF 0:082731ede69f 813 * after TO period unless socket has TO disabled.
JMF 0:082731ede69f 814 * @param pointer to an RXEVENT
JMF 0:082731ede69f 815 * @retval 1 if need to schedule another check, 0 if data received or Timed Out
JMF 0:082731ede69f 816 */
JMF 0:082731ede69f 817 int BG96Interface::rx_event(RXEVENT *ptr)
JMF 0:082731ede69f 818 {
JMF 0:082731ede69f 819 debugOutput(DBGMSG_EQ,"ENTER rx_event() for socket id %d, size=%d", ptr->m_rx_socketID, ptr->m_rx_req_size);
JMF 0:082731ede69f 820 dbgIO_lock;
JMF 0:082731ede69f 821 int cnt = _BG96.recv(ptr->m_rx_socketID, ptr->m_rx_dptr, ptr->m_rx_req_size);
JMF 0:082731ede69f 822 dbgIO_unlock;
JMF 0:082731ede69f 823
JMF 0:082731ede69f 824 if( cnt == NSAPI_ERROR_DEVICE_ERROR ) {
JMF 0:082731ede69f 825 debugOutput(DBGMSG_EQ,"EXIT rx_event(), error reading socket %d", ptr->m_rx_socketID);
JMF 0:082731ede69f 826 ptr->m_rx_timer=0;
JMF 0:082731ede69f 827 return EVENT_GETMORE;
JMF 0:082731ede69f 828 }
JMF 0:082731ede69f 829
JMF 0:082731ede69f 830 if( cnt>0 ) { //got data, return it to the caller
JMF 0:082731ede69f 831 debugOutput(DBGMSG_EQ,"EXIT rx_event(), socket %d received %d bytes", ptr->m_rx_socketID, cnt);
JMF 0:082731ede69f 832 ptr->m_rx_return_cnt += cnt;
JMF 0:082731ede69f 833 ptr->m_rx_state = DATA_AVAILABLE;
JMF 0:082731ede69f 834 if( ptr->m_rx_callback != NULL )
JMF 0:082731ede69f 835 ptr->m_rx_state = READ_DOCB;
JMF 0:082731ede69f 836 return EVENT_COMPLETE;
JMF 0:082731ede69f 837 }
JMF 0:082731ede69f 838
JMF 0:082731ede69f 839 if( ++ptr->m_rx_timer > (BG96_READ_TIMEOUTMS/EQ_FREQ) && !ptr->m_rx_disTO ) { //timed out waiting, return 0 to caller
JMF 0:082731ede69f 840 debugOutput(DBGMSG_EQ,"EXIT rx_event(), socket id %d, rx data TIME-OUT!",ptr->m_rx_socketID);
JMF 0:082731ede69f 841 ptr->m_rx_state = DATA_AVAILABLE;
JMF 0:082731ede69f 842 ptr->m_rx_return_cnt = 0;
JMF 0:082731ede69f 843 if( ptr->m_rx_callback != NULL )
JMF 0:082731ede69f 844 ptr->m_rx_state = READ_DOCB;
JMF 0:082731ede69f 845 return EVENT_COMPLETE;
JMF 0:082731ede69f 846 }
JMF 0:082731ede69f 847
JMF 0:082731ede69f 848 debugOutput(DBGMSG_EQ,"EXIT rx_event(), socket id %d, sechedule for more.",
JMF 0:082731ede69f 849 ptr->m_rx_socketID);
JMF 0:082731ede69f 850 return EVENT_GETMORE;
JMF 0:082731ede69f 851 }
JMF 0:082731ede69f 852
JMF 0:082731ede69f 853 /**----------------------------------------------------------
JMF 0:082731ede69f 854 * @brief send data, if more data than BG96 can handle at one
JMF 0:082731ede69f 855 * send as much as possible, and schedule another event
JMF 0:082731ede69f 856 * @param pointer to TXEVENT structure
JMF 0:082731ede69f 857 * @retval 1 if need to schedule another event, 0 if data sent
JMF 0:082731ede69f 858 */
JMF 0:082731ede69f 859 int BG96Interface::tx_event(TXEVENT *ptr)
JMF 0:082731ede69f 860 {
JMF 0:082731ede69f 861 debugOutput(DBGMSG_EQ,"ENTER tx_event(), socket id %d",ptr->m_tx_socketID);
JMF 0:082731ede69f 862
JMF 0:082731ede69f 863 dbgIO_lock;
JMF 0:082731ede69f 864 bool done =_BG96.send(ptr->m_tx_socketID, ptr->m_tx_dptr, ptr->m_tx_req_size);
JMF 0:082731ede69f 865 dbgIO_unlock;
JMF 0:082731ede69f 866
JMF 0:082731ede69f 867 if( done )
JMF 0:082731ede69f 868 ptr->m_tx_total_sent += ptr->m_tx_req_size;
JMF 0:082731ede69f 869 else{
JMF 0:082731ede69f 870 debugOutput(DBGMSG_EQ,"EXIT tx_event(), socket id %d, sent no data!",ptr->m_tx_socketID);
JMF 0:082731ede69f 871 return EVENT_GETMORE;
JMF 0:082731ede69f 872 }
JMF 0:082731ede69f 873
JMF 0:082731ede69f 874 if( ptr->m_tx_total_sent < ptr->m_tx_orig_size ) {
JMF 0:082731ede69f 875 ptr->m_tx_dptr += ptr->m_tx_req_size;
JMF 0:082731ede69f 876 ptr->m_tx_req_size = ptr->m_tx_orig_size-ptr->m_tx_total_sent;
JMF 0:082731ede69f 877
JMF 0:082731ede69f 878 if( ptr->m_tx_req_size > BG96::BG96_BUFF_SIZE)
JMF 0:082731ede69f 879 ptr->m_tx_req_size= BG96::BG96_BUFF_SIZE;
JMF 0:082731ede69f 880
JMF 0:082731ede69f 881 debugOutput(DBGMSG_EQ,"EXIT tx_event(), need to send %d more bytes.",ptr->m_tx_req_size);
JMF 0:082731ede69f 882 return EVENT_GETMORE;
JMF 0:082731ede69f 883 }
JMF 0:082731ede69f 884 debugOutput(DBGMSG_EQ,"EXIT tx_event, socket id %d, sent %d bytes",ptr->m_tx_socketID,ptr->m_tx_total_sent);
JMF 0:082731ede69f 885 ptr->m_tx_state = TX_COMPLETE;
JMF 0:082731ede69f 886 if( ptr->m_tx_callback != NULL )
JMF 0:082731ede69f 887 ptr->m_tx_state = TX_DOCB;
JMF 0:082731ede69f 888
JMF 0:082731ede69f 889 return EVENT_COMPLETE;
JMF 0:082731ede69f 890 }
JMF 0:082731ede69f 891
JMF 0:082731ede69f 892
JMF 0:082731ede69f 893 /**----------------------------------------------------------
JMF 0:082731ede69f 894 * @brief periodic event(EventQueu thread) to check for RX and TX data. If checking for RX data with TO disabled
JMF 0:082731ede69f 895 * slow down event checking after a while.
JMF 0:082731ede69f 896 * @param none
JMF 0:082731ede69f 897 * @retval none
JMF 0:082731ede69f 898 */
JMF 0:082731ede69f 899 void BG96Interface::g_eq_event(void)
JMF 0:082731ede69f 900 {
JMF 0:082731ede69f 901 int done = txrx_mutex.trylock();
JMF 0:082731ede69f 902 bool goSlow = false;
JMF 0:082731ede69f 903
JMF 0:082731ede69f 904 if( scheduled_events > 0 )
JMF 0:082731ede69f 905 scheduled_events--;
JMF 0:082731ede69f 906
JMF 0:082731ede69f 907 if( !done ) {
JMF 0:082731ede69f 908 _eq_schedule();
JMF 0:082731ede69f 909 return;
JMF 0:082731ede69f 910 }
JMF 0:082731ede69f 911
JMF 0:082731ede69f 912 done = EVENT_COMPLETE;
JMF 0:082731ede69f 913 for( unsigned int i=0; i<BG96_SOCKET_COUNT; i++ ) {
JMF 0:082731ede69f 914 if( g_socRx[i].m_rx_state == READ_ACTIVE || g_socRx[i].m_rx_disTO) {
JMF 0:082731ede69f 915 done |= rx_event(&g_socRx[i]);
JMF 0:082731ede69f 916 goSlow |= ( g_socRx[i].m_rx_timer > ((BG96_READ_TIMEOUTMS/EQ_FREQ)*(EQ_FREQ_SLOW/EQ_FREQ)) );
JMF 0:082731ede69f 917
JMF 0:082731ede69f 918 if( goSlow )
JMF 0:082731ede69f 919 g_socRx[i].m_rx_timer = (BG96_READ_TIMEOUTMS/EQ_FREQ)*(EQ_FREQ_SLOW/EQ_FREQ);
JMF 0:082731ede69f 920 }
JMF 0:082731ede69f 921
JMF 0:082731ede69f 922 if( g_socTx[i].m_tx_state == TX_ACTIVE ) {
JMF 0:082731ede69f 923 goSlow = false;
JMF 0:082731ede69f 924 done |= tx_event(&g_socTx[i]);
JMF 0:082731ede69f 925 }
JMF 0:082731ede69f 926 }
JMF 0:082731ede69f 927
JMF 0:082731ede69f 928 for( unsigned int i=0; i<BG96_SOCKET_COUNT; i++ ) {
JMF 0:082731ede69f 929 if( g_socRx[i].m_rx_state == READ_DOCB ) {
JMF 0:082731ede69f 930 debugOutput(DBGMSG_EQ,"Call socket %d RX call-back",i);
JMF 0:082731ede69f 931 g_socRx[i].m_rx_state = DATA_AVAILABLE;
JMF 0:082731ede69f 932 g_socRx[i].m_rx_callback( g_socRx[i].m_rx_cb_data );
JMF 0:082731ede69f 933 }
JMF 0:082731ede69f 934
JMF 0:082731ede69f 935 if( g_socTx[i].m_tx_state == TX_DOCB ) {
JMF 0:082731ede69f 936 debugOutput(DBGMSG_EQ,"Call socket %d TX call-back",i);
JMF 0:082731ede69f 937 g_socTx[i].m_tx_state = TX_COMPLETE;
JMF 0:082731ede69f 938 g_socTx[i].m_tx_callback( g_socTx[i].m_tx_cb_data );
JMF 0:082731ede69f 939 }
JMF 0:082731ede69f 940 }
JMF 0:082731ede69f 941
JMF 0:082731ede69f 942 if( done != EVENT_COMPLETE )
JMF 0:082731ede69f 943 _eq_schedule();
JMF 0:082731ede69f 944
JMF 0:082731ede69f 945 debugOutput(DBGMSG_EQ, "EXIT eq_event, queue=%d\n", scheduled_events);
JMF 0:082731ede69f 946 txrx_mutex.unlock();
JMF 0:082731ede69f 947 }
JMF 0:082731ede69f 948
JMF 0:082731ede69f 949
JMF 0:082731ede69f 950 void BG96Interface::_eq_schedule(void)
JMF 0:082731ede69f 951 {
JMF 0:082731ede69f 952 if( scheduled_events < BG96_SOCKET_COUNT ) {
JMF 0:082731ede69f 953 scheduled_events++;
JMF 0:082731ede69f 954 _bg96_queue.call_in(EQ_FREQ,mbed::Callback<void()>((BG96Interface*)this,&BG96Interface::g_eq_event));
JMF 0:082731ede69f 955 }
JMF 0:082731ede69f 956 }
JMF 0:082731ede69f 957