wifi test
Dependencies: X_NUCLEO_IKS01A2 mbed-http
easy-connect/wifi-x-nucleo-idw01m1/SpwfSAInterface.cpp
- Committer:
- JMF
- Date:
- 2018-09-05
- Revision:
- 0:24d3eb812fd4
File content as of revision 0:24d3eb812fd4:
/* mbed Microcontroller Library
* Copyright (c) 20015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
******************************************************************************
* @file SpwfSAInterface.cpp
* @author STMicroelectronics
* @brief Implementation of the NetworkStack for the SPWF Device
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2>
******************************************************************************
*/
#include "SpwfSAInterface.h"
#include "mbed_debug.h"
#include "BlockExecuter.h"
#if MBED_CONF_RTOS_PRESENT
#define SYNC_HANDLER ScopedMutexLock sync_handler(_spwf_mutex) // assuming a recursive mutex
#else
#define SYNC_HANDLER
#endif
SpwfSAInterface::SpwfSAInterface(PinName tx, PinName rx,
PinName rts, PinName cts, bool debug,
PinName wakeup, PinName reset)
: _spwf(tx, rx, rts, cts, *this, debug, wakeup, reset),
_dbg_on(debug)
{
inner_constructor();
reset_credentials();
}
nsapi_error_t SpwfSAInterface::init(void)
{
_spwf.setTimeout(SPWF_INIT_TIMEOUT);
if(_spwf.startup(0)) {
return NSAPI_ERROR_OK;
}
else return NSAPI_ERROR_DEVICE_ERROR;
}
nsapi_error_t SpwfSAInterface::connect(void)
{
int mode;
char *pass_phrase = ap_pass;
SYNC_HANDLER;
// check for valid SSID
if(ap_ssid[0] == '\0') {
return NSAPI_ERROR_PARAMETER;
}
switch(ap_sec)
{
case NSAPI_SECURITY_NONE:
mode = 0;
pass_phrase = NULL;
break;
case NSAPI_SECURITY_WEP:
mode = 1;
break;
case NSAPI_SECURITY_WPA:
case NSAPI_SECURITY_WPA2:
mode = 2;
break;
default:
mode = 2;
break;
}
// First: disconnect
if(_connected_to_network) {
if(!disconnect()) {
return NSAPI_ERROR_DEVICE_ERROR;
}
}
//initialize the device before connecting
if(!_isInitialized)
{
if(init() != NSAPI_ERROR_OK) return NSAPI_ERROR_DEVICE_ERROR;
_isInitialized=true;
}
// Then: (re-)connect
_spwf.setTimeout(SPWF_CONNECT_TIMEOUT);
if (!_spwf.connect(ap_ssid, pass_phrase, mode)) {
return NSAPI_ERROR_AUTH_FAILURE;
}
if (!_spwf.getIPAddress()) {
return NSAPI_ERROR_DHCP_FAILURE;
}
_connected_to_network = true;
return NSAPI_ERROR_OK;
}
nsapi_error_t SpwfSAInterface::connect(const char *ssid, const char *pass, nsapi_security_t security,
uint8_t channel)
{
nsapi_error_t ret;
SYNC_HANDLER;
if (channel != 0) {
return NSAPI_ERROR_UNSUPPORTED;
}
ret = set_credentials(ssid, pass, security);
if(ret != NSAPI_ERROR_OK) return ret;
return connect();
}
nsapi_error_t SpwfSAInterface::disconnect(void)
{
SYNC_HANDLER;
_spwf.setTimeout(SPWF_DISCONNECT_TIMEOUT);
if (!_spwf.disconnect()) {
return NSAPI_ERROR_DEVICE_ERROR;
}
return NSAPI_ERROR_OK;
}
const char *SpwfSAInterface::get_ip_address(void)
{
SYNC_HANDLER;
_spwf.setTimeout(SPWF_MISC_TIMEOUT);
return _spwf.getIPAddress();
}
const char *SpwfSAInterface::get_mac_address(void)
{
SYNC_HANDLER;
_spwf.setTimeout(SPWF_MISC_TIMEOUT);
return _spwf.getMACAddress();
}
const char *SpwfSAInterface::get_gateway(void)
{
SYNC_HANDLER;
if(!_connected_to_network) return NULL;
_spwf.setTimeout(SPWF_MISC_TIMEOUT);
return _spwf.getGateway();
}
const char *SpwfSAInterface::get_netmask(void)
{
SYNC_HANDLER;
if(!_connected_to_network) return NULL;
_spwf.setTimeout(SPWF_MISC_TIMEOUT);
return _spwf.getNetmask();
}
nsapi_error_t SpwfSAInterface::socket_open(void **handle, nsapi_protocol_t proto)
{
int internal_id;
SYNC_HANDLER;
for (internal_id = 0; internal_id < SPWFSA_SOCKET_COUNT; internal_id++) {
if(_ids[internal_id].internal_id == SPWFSA_SOCKET_COUNT) break;
}
if(internal_id == SPWFSA_SOCKET_COUNT) {
debug_if(_dbg_on, "NO Socket ID Error\r\n");
return NSAPI_ERROR_NO_SOCKET;
}
spwf_socket_t *socket = &_ids[internal_id];
socket->internal_id = internal_id;
socket->spwf_id = SPWFSA_SOCKET_COUNT;
socket->server_gone = false;
socket->no_more_data = false;
socket->proto = proto;
socket->addr = SocketAddress();
*handle = socket;
return NSAPI_ERROR_OK;
}
nsapi_error_t SpwfSAInterface::socket_connect(void *handle, const SocketAddress &addr)
{
spwf_socket_t *socket = (spwf_socket_t*)handle;
SYNC_HANDLER;
MBED_ASSERT(((unsigned int)socket->internal_id) < ((unsigned int)SPWFSA_SOCKET_COUNT));
if(_socket_has_connected(socket->internal_id)) {
return NSAPI_ERROR_IS_CONNECTED;
}
_spwf.setTimeout(SPWF_OPEN_TIMEOUT);
const char *proto = (socket->proto == NSAPI_UDP) ? "u" : "t"; //"s" for secure socket?
if(addr.get_ip_version() != NSAPI_IPv4) { // IPv6 not supported (yet)
return NSAPI_ERROR_UNSUPPORTED;
}
{
BlockExecuter netsock_wa_obj(Callback<void()>(&_spwf, &SPWFSAxx::_unblock_event_callback),
Callback<void()>(&_spwf, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
/* block asynchronous indications */
if(!_spwf._winds_off()) {
return NSAPI_ERROR_DEVICE_ERROR;
}
{
BlockExecuter bh_handler(Callback<void()>(&_spwf, &SPWFSAxx::_execute_bottom_halves));
{
BlockExecuter winds_enabler(Callback<void()>(&_spwf, &SPWFSAxx::_winds_on));
if(!_spwf.open(proto, &socket->spwf_id, addr.get_ip_address(), addr.get_port())) {
MBED_ASSERT(_spwf._call_event_callback_blocked == 1);
return NSAPI_ERROR_DEVICE_ERROR;
}
/* check for the module to report a valid id */
MBED_ASSERT(((unsigned int)socket->spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT));
_internal_ids[socket->spwf_id] = socket->internal_id;
socket->addr = addr;
MBED_ASSERT(_spwf._call_event_callback_blocked == 1);
return NSAPI_ERROR_OK;
}
}
}
}
nsapi_error_t SpwfSAInterface::socket_bind(void *handle, const SocketAddress &address)
{
return NSAPI_ERROR_UNSUPPORTED;
}
nsapi_error_t SpwfSAInterface::socket_listen(void *handle, int backlog)
{
return NSAPI_ERROR_UNSUPPORTED;
}
nsapi_error_t SpwfSAInterface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address)
{
return NSAPI_ERROR_UNSUPPORTED;
}
nsapi_error_t SpwfSAInterface::socket_close(void *handle)
{
spwf_socket_t *socket = (spwf_socket_t*)handle;
int internal_id = socket->internal_id;
SYNC_HANDLER;
if(!_socket_is_open(internal_id)) return NSAPI_ERROR_NO_SOCKET;
if(_socket_has_connected(socket)) {
_spwf.setTimeout(SPWF_CLOSE_TIMEOUT);
if (!_spwf.close(socket->spwf_id)) {
return NSAPI_ERROR_DEVICE_ERROR;
}
_internal_ids[socket->spwf_id] = SPWFSA_SOCKET_COUNT;
}
_ids[internal_id].internal_id = SPWFSA_SOCKET_COUNT;
_ids[internal_id].spwf_id = SPWFSA_SOCKET_COUNT;
return NSAPI_ERROR_OK;
}
nsapi_size_or_error_t SpwfSAInterface::socket_send(void *handle, const void *data, unsigned size)
{
spwf_socket_t *socket = (spwf_socket_t*)handle;
SYNC_HANDLER;
CHECK_NOT_CONNECTED_ERR();
_spwf.setTimeout(SPWF_SEND_TIMEOUT);
return _spwf.send(socket->spwf_id, data, size, socket->internal_id);
}
nsapi_size_or_error_t SpwfSAInterface::socket_recv(void *handle, void *data, unsigned size)
{
SYNC_HANDLER;
return _socket_recv(handle, data, size, false);
}
nsapi_size_or_error_t SpwfSAInterface::_socket_recv(void *handle, void *data, unsigned size, bool datagram)
{
spwf_socket_t *socket = (spwf_socket_t*)handle;
CHECK_NOT_CONNECTED_ERR();
if(!_socket_has_connected(socket)) {
return NSAPI_ERROR_WOULD_BLOCK;
} else if(socket->no_more_data) {
return 0;
}
_spwf.setTimeout(SPWF_RECV_TIMEOUT);
int32_t recv = _spwf.recv(socket->spwf_id, (char*)data, (uint32_t)size, datagram);
MBED_ASSERT(!_spwf._is_event_callback_blocked());
MBED_ASSERT((recv != 0) || (size == 0));
if (recv < 0) {
if(!_socket_is_still_connected(socket)) {
socket->no_more_data = true;
return 0;
}
return NSAPI_ERROR_WOULD_BLOCK;
}
return recv;
}
nsapi_size_or_error_t SpwfSAInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
{
spwf_socket_t *socket = (spwf_socket_t*)handle;
SYNC_HANDLER;
CHECK_NOT_CONNECTED_ERR();
if ((_socket_has_connected(socket)) && (socket->addr != addr)) {
_spwf.setTimeout(SPWF_CLOSE_TIMEOUT);
if (!_spwf.close(socket->spwf_id)) {
return NSAPI_ERROR_DEVICE_ERROR;
}
_internal_ids[socket->spwf_id] = SPWFSA_SOCKET_COUNT;
socket->spwf_id = SPWFSA_SOCKET_COUNT;
}
_spwf.setTimeout(SPWF_CONN_SND_TIMEOUT);
if (!_socket_has_connected(socket)) {
nsapi_error_t err = socket_connect(socket, addr);
if (err < 0) {
return err;
}
}
return socket_send(socket, data, size);
}
nsapi_size_or_error_t SpwfSAInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
{
spwf_socket_t *socket = (spwf_socket_t*)handle;
nsapi_error_t ret;
SYNC_HANDLER;
ret = _socket_recv(socket, data, size, true);
if (ret >= 0 && addr) {
*addr = socket->addr;
}
return ret;
}
void SpwfSAInterface::socket_attach(void *handle, void (*callback)(void *), void *data)
{
spwf_socket_t *socket = (spwf_socket_t*)handle;
SYNC_HANDLER;
if(!_socket_is_open(socket)) return; // might happen e.g. after module hard fault or voluntary disconnection
_cbs[socket->internal_id].callback = callback;
_cbs[socket->internal_id].data = data;
}
void SpwfSAInterface::event(void) {
for (int internal_id = 0; internal_id < SPWFSA_SOCKET_COUNT; internal_id++) {
if (_cbs[internal_id].callback && (_ids[internal_id].internal_id != SPWFSA_SOCKET_COUNT)) {
_cbs[internal_id].callback(_cbs[internal_id].data);
}
}
}
nsapi_error_t SpwfSAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
{
SYNC_HANDLER;
if((ssid == NULL) || (strlen(ssid) == 0)) {
return NSAPI_ERROR_PARAMETER;
}
if((pass != NULL) && (strlen(pass) > 0)) {
if(strlen(pass) < sizeof(ap_pass)) {
if(security == NSAPI_SECURITY_NONE) {
return NSAPI_ERROR_PARAMETER;
}
} else {
return NSAPI_ERROR_PARAMETER;
}
} else if(security != NSAPI_SECURITY_NONE) {
return NSAPI_ERROR_PARAMETER;
}
reset_credentials();
ap_sec = security;
strncpy(ap_ssid, ssid, sizeof(ap_ssid) - 1);
strncpy(ap_pass, pass, sizeof(ap_pass) - 1);
return NSAPI_ERROR_OK;
}
nsapi_error_t SpwfSAInterface::set_channel(uint8_t channel)
{
return NSAPI_ERROR_UNSUPPORTED;
}
int8_t SpwfSAInterface::get_rssi(void)
{
SYNC_HANDLER;
if(!_connected_to_network) return 0;
_spwf.setTimeout(SPWF_MISC_TIMEOUT);
return _spwf.getRssi();
}
nsapi_size_or_error_t SpwfSAInterface::scan(WiFiAccessPoint *res, unsigned count)
{
SYNC_HANDLER;
nsapi_size_or_error_t ret;
//initialize the device before scanning
if(!_isInitialized)
{
if(init() != NSAPI_ERROR_OK) return NSAPI_ERROR_DEVICE_ERROR;
}
_spwf.setTimeout(SPWF_SCAN_TIMEOUT);
{
BlockExecuter netsock_wa_obj(Callback<void()>(&_spwf, &SPWFSAxx::_unblock_event_callback),
Callback<void()>(&_spwf, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
/* block asynchronous indications */
if(!_spwf._winds_off()) {
MBED_ASSERT(_spwf._call_event_callback_blocked == 1);
return NSAPI_ERROR_DEVICE_ERROR;
}
ret = _spwf.scan(res, count);
/* unblock asynchronous indications */
_spwf._winds_on();
}
MBED_ASSERT(!_spwf._is_event_callback_blocked());
//de-initialize the device after scanning
if(!_isInitialized)
{
nsapi_error_t err = disconnect();
if(err != NSAPI_ERROR_OK) return err;
}
return ret;
}