Jim Flynn / Mbed OS wifi_Example

Dependencies:   X_NUCLEO_IKS01A2 mbed-http

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SpwfSAInterface.cpp Source File

SpwfSAInterface.cpp

Go to the documentation of this file.
00001 /* mbed Microcontroller Library
00002  * Copyright (c) 20015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 /**
00018   ******************************************************************************
00019   * @file    SpwfSAInterface.cpp
00020   * @author  STMicroelectronics
00021   * @brief   Implementation of the NetworkStack for the SPWF Device
00022   ******************************************************************************
00023   * @copy
00024   *
00025   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00026   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00027   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00028   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00029   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00030   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00031   *
00032   * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
00033   ******************************************************************************
00034   */
00035 
00036 #include "SpwfSAInterface.h"
00037 #include "mbed_debug.h"
00038 #include "BlockExecuter.h"
00039 
00040 #if MBED_CONF_RTOS_PRESENT
00041 #define SYNC_HANDLER ScopedMutexLock sync_handler(_spwf_mutex)  // assuming a recursive mutex
00042 #else
00043 #define SYNC_HANDLER
00044 #endif
00045 
00046 
00047 SpwfSAInterface::SpwfSAInterface(PinName tx, PinName rx,
00048                                  PinName rts, PinName cts, bool debug,
00049                                  PinName wakeup, PinName reset)
00050 : _spwf(tx, rx, rts, cts, *this, debug, wakeup, reset),
00051   _dbg_on(debug)
00052 {
00053     inner_constructor();
00054     reset_credentials();
00055 }
00056 
00057 nsapi_error_t SpwfSAInterface::init(void)
00058 {
00059     _spwf.setTimeout(SPWF_INIT_TIMEOUT);
00060 
00061     if(_spwf.startup(0)) {
00062         return NSAPI_ERROR_OK;
00063     }
00064     else return NSAPI_ERROR_DEVICE_ERROR;
00065 }
00066 
00067 nsapi_error_t SpwfSAInterface::connect(void)
00068 {
00069     int mode;
00070     char *pass_phrase = ap_pass;
00071     SYNC_HANDLER;
00072 
00073     // check for valid SSID
00074     if(ap_ssid[0] == '\0') {
00075         return NSAPI_ERROR_PARAMETER;
00076     }
00077 
00078     switch(ap_sec)
00079     {
00080         case NSAPI_SECURITY_NONE:
00081             mode = 0;
00082             pass_phrase = NULL;
00083             break;
00084         case NSAPI_SECURITY_WEP:
00085             mode = 1;
00086             break;
00087         case NSAPI_SECURITY_WPA:
00088         case NSAPI_SECURITY_WPA2:
00089             mode = 2;
00090             break;
00091         default:
00092             mode = 2;
00093             break;
00094     }
00095 
00096     // First: disconnect
00097     if(_connected_to_network) {
00098         if(!disconnect()) {
00099             return NSAPI_ERROR_DEVICE_ERROR;
00100         }
00101     }
00102 
00103     //initialize the device before connecting
00104     if(!_isInitialized)
00105     {
00106         if(init() != NSAPI_ERROR_OK) return NSAPI_ERROR_DEVICE_ERROR;
00107         _isInitialized=true;
00108     }
00109 
00110     // Then: (re-)connect
00111     _spwf.setTimeout(SPWF_CONNECT_TIMEOUT);
00112 
00113     if (!_spwf.connect(ap_ssid, pass_phrase, mode)) {
00114         return NSAPI_ERROR_AUTH_FAILURE;
00115     }
00116 
00117     if (!_spwf.getIPAddress()) {
00118         return NSAPI_ERROR_DHCP_FAILURE;
00119     }
00120 
00121     _connected_to_network = true;
00122     return NSAPI_ERROR_OK;
00123 }
00124 
00125 nsapi_error_t SpwfSAInterface::connect(const char *ssid, const char *pass, nsapi_security_t security,
00126                                        uint8_t channel)
00127 {
00128     nsapi_error_t ret;
00129     SYNC_HANDLER;
00130 
00131     if (channel != 0) {
00132         return NSAPI_ERROR_UNSUPPORTED;
00133     }
00134 
00135     ret = set_credentials(ssid, pass, security);
00136     if(ret != NSAPI_ERROR_OK) return ret;
00137 
00138     return connect();
00139 }
00140 
00141 nsapi_error_t SpwfSAInterface::disconnect(void)
00142 {
00143     SYNC_HANDLER;
00144 
00145     _spwf.setTimeout(SPWF_DISCONNECT_TIMEOUT);
00146 
00147     if (!_spwf.disconnect()) {
00148         return NSAPI_ERROR_DEVICE_ERROR;
00149     }
00150 
00151     return NSAPI_ERROR_OK;
00152 }
00153 
00154 const char *SpwfSAInterface::get_ip_address(void)
00155 {
00156     SYNC_HANDLER;
00157 
00158     _spwf.setTimeout(SPWF_MISC_TIMEOUT);
00159     return _spwf.getIPAddress();
00160 }
00161 
00162 const char *SpwfSAInterface::get_mac_address(void)
00163 {
00164     SYNC_HANDLER;
00165 
00166     _spwf.setTimeout(SPWF_MISC_TIMEOUT);
00167     return _spwf.getMACAddress();
00168 }
00169 
00170 const char *SpwfSAInterface::get_gateway(void)
00171 {
00172     SYNC_HANDLER;
00173 
00174     if(!_connected_to_network) return NULL;
00175 
00176     _spwf.setTimeout(SPWF_MISC_TIMEOUT);
00177     return _spwf.getGateway();
00178 }
00179 
00180 const char *SpwfSAInterface::get_netmask(void)
00181 {
00182     SYNC_HANDLER;
00183 
00184     if(!_connected_to_network) return NULL;
00185 
00186     _spwf.setTimeout(SPWF_MISC_TIMEOUT);
00187     return _spwf.getNetmask();
00188 }
00189 
00190 nsapi_error_t SpwfSAInterface::socket_open(void **handle, nsapi_protocol_t proto)
00191 {
00192     int internal_id;
00193     SYNC_HANDLER;
00194 
00195     for (internal_id = 0; internal_id < SPWFSA_SOCKET_COUNT; internal_id++) {
00196         if(_ids[internal_id].internal_id == SPWFSA_SOCKET_COUNT) break;
00197     }
00198 
00199     if(internal_id == SPWFSA_SOCKET_COUNT) {
00200         debug_if(_dbg_on, "NO Socket ID Error\r\n");
00201         return NSAPI_ERROR_NO_SOCKET;
00202     }
00203 
00204     spwf_socket_t *socket = &_ids[internal_id];
00205     socket->internal_id = internal_id;
00206     socket->spwf_id = SPWFSA_SOCKET_COUNT;
00207     socket->server_gone = false;
00208     socket->no_more_data = false;
00209     socket->proto = proto;
00210     socket->addr = SocketAddress();
00211 
00212     *handle = socket;
00213     return NSAPI_ERROR_OK;
00214 }
00215 
00216 nsapi_error_t SpwfSAInterface::socket_connect(void *handle, const SocketAddress &addr)
00217 {
00218     spwf_socket_t *socket = (spwf_socket_t*)handle;
00219     SYNC_HANDLER;
00220 
00221     MBED_ASSERT(((unsigned int)socket->internal_id) < ((unsigned int)SPWFSA_SOCKET_COUNT));
00222 
00223     if(_socket_has_connected(socket->internal_id)) {
00224         return NSAPI_ERROR_IS_CONNECTED;
00225     }
00226 
00227     _spwf.setTimeout(SPWF_OPEN_TIMEOUT);
00228 
00229     const char *proto = (socket->proto == NSAPI_UDP) ? "u" : "t"; //"s" for secure socket?
00230 
00231     if(addr.get_ip_version() != NSAPI_IPv4) { // IPv6 not supported (yet)
00232         return NSAPI_ERROR_UNSUPPORTED;
00233     }
00234 
00235     {
00236         BlockExecuter netsock_wa_obj(Callback<void()>(&_spwf, &SPWFSAxx::_unblock_event_callback),
00237                                      Callback<void()>(&_spwf, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
00238 
00239         /* block asynchronous indications */
00240         if(!_spwf._winds_off()) {
00241             return NSAPI_ERROR_DEVICE_ERROR;
00242         }
00243 
00244         {
00245             BlockExecuter bh_handler(Callback<void()>(&_spwf, &SPWFSAxx::_execute_bottom_halves));
00246             {
00247                 BlockExecuter winds_enabler(Callback<void()>(&_spwf, &SPWFSAxx::_winds_on));
00248 
00249                 if(!_spwf.open(proto, &socket->spwf_id, addr.get_ip_address(), addr.get_port())) {
00250                     MBED_ASSERT(_spwf._call_event_callback_blocked == 1);
00251 
00252                     return NSAPI_ERROR_DEVICE_ERROR;
00253                 }
00254 
00255                 /* check for the module to report a valid id */
00256                 MBED_ASSERT(((unsigned int)socket->spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT));
00257 
00258                 _internal_ids[socket->spwf_id] = socket->internal_id;
00259                 socket->addr = addr;
00260 
00261                 MBED_ASSERT(_spwf._call_event_callback_blocked == 1);
00262 
00263                 return NSAPI_ERROR_OK;
00264             }
00265         }
00266     }
00267 }
00268 
00269 nsapi_error_t SpwfSAInterface::socket_bind(void *handle, const SocketAddress &address)
00270 {
00271     return NSAPI_ERROR_UNSUPPORTED;
00272 }
00273 
00274 nsapi_error_t SpwfSAInterface::socket_listen(void *handle, int backlog)
00275 {
00276     return NSAPI_ERROR_UNSUPPORTED;
00277 }
00278 
00279 nsapi_error_t SpwfSAInterface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address)
00280 {
00281     return NSAPI_ERROR_UNSUPPORTED;
00282 }
00283 
00284 nsapi_error_t SpwfSAInterface::socket_close(void *handle)
00285 {
00286     spwf_socket_t *socket = (spwf_socket_t*)handle;
00287     int internal_id = socket->internal_id;
00288     SYNC_HANDLER;
00289 
00290     if(!_socket_is_open(internal_id)) return NSAPI_ERROR_NO_SOCKET;
00291 
00292     if(_socket_has_connected(socket)) {
00293         _spwf.setTimeout(SPWF_CLOSE_TIMEOUT);
00294         if (!_spwf.close(socket->spwf_id)) {
00295             return NSAPI_ERROR_DEVICE_ERROR;
00296         }
00297         _internal_ids[socket->spwf_id] = SPWFSA_SOCKET_COUNT;
00298     }
00299 
00300     _ids[internal_id].internal_id = SPWFSA_SOCKET_COUNT;
00301     _ids[internal_id].spwf_id = SPWFSA_SOCKET_COUNT;
00302 
00303     return NSAPI_ERROR_OK;
00304 }
00305 
00306 nsapi_size_or_error_t SpwfSAInterface::socket_send(void *handle, const void *data, unsigned size)
00307 {
00308     spwf_socket_t *socket = (spwf_socket_t*)handle;
00309     SYNC_HANDLER;
00310 
00311     CHECK_NOT_CONNECTED_ERR();
00312 
00313     _spwf.setTimeout(SPWF_SEND_TIMEOUT);
00314     return _spwf.send(socket->spwf_id, data, size, socket->internal_id);
00315 }
00316 
00317 nsapi_size_or_error_t SpwfSAInterface::socket_recv(void *handle, void *data, unsigned size)
00318 {
00319     SYNC_HANDLER;
00320 
00321     return _socket_recv(handle, data, size, false);
00322 }
00323 
00324 nsapi_size_or_error_t SpwfSAInterface::_socket_recv(void *handle, void *data, unsigned size, bool datagram)
00325 {
00326     spwf_socket_t *socket = (spwf_socket_t*)handle;
00327 
00328     CHECK_NOT_CONNECTED_ERR();
00329 
00330     if(!_socket_has_connected(socket)) {
00331         return NSAPI_ERROR_WOULD_BLOCK;
00332     } else if(socket->no_more_data) {
00333         return 0;
00334     }
00335 
00336     _spwf.setTimeout(SPWF_RECV_TIMEOUT);
00337 
00338     int32_t recv = _spwf.recv(socket->spwf_id, (char*)data, (uint32_t)size, datagram);
00339 
00340     MBED_ASSERT(!_spwf._is_event_callback_blocked());
00341     MBED_ASSERT((recv != 0) || (size == 0));
00342 
00343     if (recv < 0) {
00344         if(!_socket_is_still_connected(socket)) {
00345             socket->no_more_data = true;
00346             return 0;
00347         }
00348 
00349         return NSAPI_ERROR_WOULD_BLOCK;
00350     }
00351 
00352     return recv;
00353 }
00354 
00355 nsapi_size_or_error_t SpwfSAInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
00356 {
00357     spwf_socket_t *socket = (spwf_socket_t*)handle;
00358     SYNC_HANDLER;
00359 
00360     CHECK_NOT_CONNECTED_ERR();
00361 
00362     if ((_socket_has_connected(socket)) && (socket->addr != addr)) {
00363         _spwf.setTimeout(SPWF_CLOSE_TIMEOUT);
00364         if (!_spwf.close(socket->spwf_id)) {
00365             return NSAPI_ERROR_DEVICE_ERROR;
00366         }
00367         _internal_ids[socket->spwf_id] = SPWFSA_SOCKET_COUNT;
00368         socket->spwf_id = SPWFSA_SOCKET_COUNT;
00369     }
00370 
00371     _spwf.setTimeout(SPWF_CONN_SND_TIMEOUT);
00372     if (!_socket_has_connected(socket)) {
00373         nsapi_error_t err = socket_connect(socket, addr);
00374         if (err < 0) {
00375             return err;
00376         }
00377     }
00378 
00379     return socket_send(socket, data, size);
00380 }
00381 
00382 nsapi_size_or_error_t SpwfSAInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
00383 {
00384     spwf_socket_t *socket = (spwf_socket_t*)handle;
00385     nsapi_error_t ret;
00386     SYNC_HANDLER;
00387 
00388     ret = _socket_recv(socket, data, size, true);
00389     if (ret >= 0 && addr) {
00390         *addr = socket->addr;
00391     }
00392 
00393     return ret;
00394 }
00395 
00396 void SpwfSAInterface::socket_attach(void *handle, void (*callback)(void *), void *data)
00397 {
00398     spwf_socket_t *socket = (spwf_socket_t*)handle;
00399     SYNC_HANDLER;
00400 
00401     if(!_socket_is_open(socket)) return; // might happen e.g. after module hard fault or voluntary disconnection
00402 
00403     _cbs[socket->internal_id].callback = callback;
00404     _cbs[socket->internal_id].data = data;
00405 }
00406 
00407 void SpwfSAInterface::event(void) {
00408     for (int internal_id = 0; internal_id < SPWFSA_SOCKET_COUNT; internal_id++) {
00409         if (_cbs[internal_id].callback && (_ids[internal_id].internal_id != SPWFSA_SOCKET_COUNT)) {
00410             _cbs[internal_id].callback(_cbs[internal_id].data);
00411         }
00412     }
00413 }
00414 
00415 nsapi_error_t SpwfSAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
00416 {
00417     SYNC_HANDLER;
00418 
00419     if((ssid == NULL) || (strlen(ssid) == 0)) {
00420         return NSAPI_ERROR_PARAMETER;
00421     }
00422 
00423     if((pass != NULL) && (strlen(pass) > 0)) {
00424         if(strlen(pass) < sizeof(ap_pass)) {
00425             if(security == NSAPI_SECURITY_NONE) {
00426                 return NSAPI_ERROR_PARAMETER;
00427             }
00428         } else {
00429             return NSAPI_ERROR_PARAMETER;
00430         }
00431     } else if(security != NSAPI_SECURITY_NONE) {
00432         return NSAPI_ERROR_PARAMETER;
00433     }
00434 
00435     reset_credentials();
00436 
00437     ap_sec = security;
00438     strncpy(ap_ssid, ssid, sizeof(ap_ssid) - 1);
00439     strncpy(ap_pass, pass, sizeof(ap_pass) - 1);
00440 
00441     return NSAPI_ERROR_OK;
00442 }
00443 
00444 nsapi_error_t SpwfSAInterface::set_channel(uint8_t channel)
00445 {
00446     return NSAPI_ERROR_UNSUPPORTED;
00447 }
00448 
00449 int8_t SpwfSAInterface::get_rssi(void)
00450 {
00451     SYNC_HANDLER;
00452 
00453     if(!_connected_to_network) return 0;
00454 
00455     _spwf.setTimeout(SPWF_MISC_TIMEOUT);
00456     return _spwf.getRssi();
00457 }
00458 
00459 nsapi_size_or_error_t SpwfSAInterface::scan(WiFiAccessPoint *res, unsigned count)
00460 {
00461     SYNC_HANDLER;
00462 
00463     nsapi_size_or_error_t ret;
00464 
00465     //initialize the device before scanning
00466     if(!_isInitialized)
00467     {
00468         if(init() != NSAPI_ERROR_OK) return NSAPI_ERROR_DEVICE_ERROR;
00469     }
00470 
00471     _spwf.setTimeout(SPWF_SCAN_TIMEOUT);
00472 
00473     {
00474         BlockExecuter netsock_wa_obj(Callback<void()>(&_spwf, &SPWFSAxx::_unblock_event_callback),
00475                                      Callback<void()>(&_spwf, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
00476 
00477         /* block asynchronous indications */
00478         if(!_spwf._winds_off()) {
00479             MBED_ASSERT(_spwf._call_event_callback_blocked == 1);
00480 
00481             return NSAPI_ERROR_DEVICE_ERROR;
00482         }
00483 
00484         ret = _spwf.scan(res, count);
00485 
00486         /* unblock asynchronous indications */
00487         _spwf._winds_on();
00488     }
00489 
00490     MBED_ASSERT(!_spwf._is_event_callback_blocked());
00491 
00492     //de-initialize the device after scanning
00493     if(!_isInitialized)
00494     {
00495         nsapi_error_t err = disconnect();
00496         if(err != NSAPI_ERROR_OK) return err;
00497     }
00498 
00499     return ret;
00500 }