leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WizFi310Interface.cpp Source File

WizFi310Interface.cpp

00001 /* WizFi310 implementation of NetworkInterfaceAPI
00002  * Copyright (c) 2015 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    WizFi310Interface.h
00020   * @author  Gateway Team
00021   * @brief   Implementation file of the NetworkStack for the WizFi310 WiFi Device
00022   ******************************************************************************
00023   * @attention
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, WIZnet 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 2017 WIZnet Co.,Ltd.</center></h2>
00033   ******************************************************************************
00034   */
00035 
00036 #include <string.h>
00037 #include "WizFi310Interface.h"
00038 #include "mbed_trace.h"
00039 
00040 #define TRACE_GROUP "WZ__"
00041 
00042 using namespace mbed;
00043 // Various timeouts for different WizFi310 operations
00044 #ifndef WIZFI310_CONNECT_TIMEOUT
00045 #define WIZFI310_CONNECT_TIMEOUT 15000
00046 #endif
00047 #ifndef WIZFI310_SEND_TIMEOUT
00048 #define WIZFI310_SEND_TIMEOUT    500
00049 #endif
00050 #ifndef WIZFI310_RECV_TIMEOUT
00051 #define WIZFI310_RECV_TIMEOUT    0
00052 #endif
00053 #ifndef WIZFI310_MISC_TIMEOUT
00054 #define WIZFI310_MISC_TIMEOUT    500
00055 #endif
00056 #ifndef WIZFI310_OPEN_TIMEOUT
00057 #define WIZFI310_OPEN_TIMEOUT   10000
00058 #endif
00059 #ifndef WIZFI310_CLOSE_TIMEOUT
00060 #define WIZFI310_CLOSE_TIMEOUT   500
00061 #endif
00062 
00063 #ifndef WIZFI310_MAX_CONNECT_COUNT
00064 #define WIZFI310_MAX_CONNECT    2
00065 #endif
00066 
00067 #ifndef WIZFI310_DELAY_MS
00068 #define WIZFI310_DELAY_MS       300
00069 #endif
00070 
00071 // =================================================================================================
00072 // helper functions
00073 static const char *sec2str(nsapi_security_t sec)
00074 {
00075     switch (sec) {
00076         case NSAPI_SECURITY_NONE:
00077             return "OPEN";
00078         case NSAPI_SECURITY_WEP:
00079             return "WEP";
00080         case NSAPI_SECURITY_WPA:
00081             return "WPA";
00082         case NSAPI_SECURITY_WPA2:
00083             return "WPA2";
00084         case NSAPI_SECURITY_WPA_WPA2:
00085             return "WPAWPA2";
00086         default:
00087             return "";
00088     }
00089 }
00090 
00091 // =================================================================================================
00092 // WizFi310Interface implementation
00093 WizFi310Interface::WizFi310Interface(PinName tx, PinName rx, PinName rts, PinName cts, PinName rst) :
00094     m_wizfi310(tx, rx, rts, cts, rst),
00095     m_mutex("WizFi310Interface")
00096 {
00097     memset(ap_ssid, 0, sizeof(ap_ssid));
00098     memset(ap_pass, 0, sizeof(ap_pass));
00099     ap_sec = NSAPI_SECURITY_NONE;
00100     m_wizfi310.attach(Callback<void(nsapi_connection_status_t)>(this, &WizFi310Interface::link_status_change));
00101 }
00102 
00103 void WizFi310Interface::link_status_change(nsapi_connection_status_t status)
00104 {
00105     if (m_on_status_change) {
00106         m_on_status_change(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, status);
00107     }
00108     m_semphr.release();
00109 }
00110 
00111 // =================================================================================================
00112 // WiFi network api
00113 
00114 nsapi_error_t WizFi310Interface::connect(
00115     const char *ssid,
00116     const char *pass,
00117     nsapi_security_t security,
00118     uint8_t channel)
00119 {
00120     m_mutex.lock();
00121     nsapi_error_t res = set_channel(channel);
00122     if (res == NSAPI_ERROR_OK) {
00123         res = set_credentials(ssid, pass, security);
00124     }
00125     if (res == NSAPI_ERROR_OK) {
00126         res = connect();
00127     }
00128     m_mutex.unlock();
00129     return  res;
00130 }
00131 
00132 nsapi_error_t WizFi310Interface::connect()
00133 {
00134     if (strlen(ap_ssid) == 0) {
00135         return NSAPI_ERROR_PARAMETER;
00136     }
00137     if ((ap_sec != NSAPI_SECURITY_NONE) && ((strlen(ap_pass) == 0) || (strlen(ap_pass) >= 64))) {
00138         return NSAPI_ERROR_PARAMETER;
00139     }
00140     if (m_wizfi310.status() == NSAPI_STATUS_GLOBAL_UP) {
00141         return NSAPI_ERROR_IS_CONNECTED;
00142     } else if (m_wizfi310.status() == NSAPI_STATUS_CONNECTING) {
00143         return NSAPI_ERROR_WOULD_BLOCK;
00144     }
00145 
00146     nsapi_error_t res = NSAPI_ERROR_OK;
00147 
00148     m_mutex.lock();
00149     if (!m_wizfi310.dhcp(true)) {
00150         res = NSAPI_ERROR_DHCP_FAILURE;
00151     } else {
00152         if (ap_sec == NSAPI_SECURITY_NONE && (strlen(ap_pass) > 0)) {
00153             ap_sec = NSAPI_SECURITY_UNKNOWN;
00154         }
00155 
00156         m_semphr.wait(0);
00157         while ((res = m_wizfi310.connect(ap_ssid, ap_pass, sec2str(ap_sec))) == NSAPI_ERROR_WOULD_BLOCK) {
00158             wait_ms(10);
00159         }
00160         if (res == NSAPI_ERROR_IN_PROGRESS) {
00161             do {
00162                 // wait for connect
00163                 m_semphr.wait();
00164             } while (m_wizfi310.status() == NSAPI_STATUS_CONNECTING);
00165             res = (m_wizfi310.status() == NSAPI_STATUS_DISCONNECTED) ? NSAPI_ERROR_NO_CONNECTION : NSAPI_ERROR_OK;
00166         }
00167     }
00168     m_mutex.unlock();
00169 
00170     return res;
00171 }
00172 
00173 nsapi_error_t WizFi310Interface::set_channel(uint8_t chan)
00174 {
00175     if (chan != 0) {
00176         return NSAPI_ERROR_UNSUPPORTED;
00177     }
00178     return NSAPI_ERROR_OK;
00179 }
00180 
00181 int WizFi310Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
00182 {
00183     if ((ssid == NULL) || (strlen(ssid) == 0)) {
00184         return NSAPI_ERROR_PARAMETER;
00185     }
00186     if ((security != NSAPI_SECURITY_NONE) && ((pass == NULL) || (strlen(pass) == 0) || (strlen(pass) >= 64))) {
00187         return NSAPI_ERROR_PARAMETER;
00188     }
00189 
00190     m_mutex.lock();
00191     memset(ap_ssid, 0, sizeof(ap_ssid));
00192     strncpy(ap_ssid, ssid, sizeof(ap_ssid));
00193 
00194     memset(ap_pass, 0, sizeof(ap_pass));
00195     if (pass != NULL) {
00196         strncpy(ap_pass, pass, sizeof(ap_pass));
00197     }
00198 
00199     ap_sec = security;
00200     m_mutex.unlock();
00201 
00202     return NSAPI_ERROR_OK;
00203 }
00204 
00205 int WizFi310Interface::disconnect()
00206 {
00207     nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION;
00208 
00209     m_mutex.lock();
00210     if (m_wizfi310.status() != NSAPI_STATUS_DISCONNECTED) {
00211         m_semphr.wait(0);
00212         while ((err = m_wizfi310.disconnect()) == NSAPI_ERROR_WOULD_BLOCK) {
00213             wait_ms(10);
00214         }
00215         if (err == NSAPI_ERROR_IN_PROGRESS) {
00216             while (m_wizfi310.status() != NSAPI_STATUS_DISCONNECTED) {
00217                 m_semphr.wait();
00218                 err = NSAPI_ERROR_OK;
00219             }
00220         }
00221     }
00222     m_mutex.unlock();
00223     return err;
00224 }
00225 
00226 nsapi_connection_status_t WizFi310Interface::get_connection_status() const
00227 {
00228     return m_wizfi310.status();
00229 }
00230 
00231 const char *WizFi310Interface::get_ip_address()
00232 {
00233     return m_wizfi310.get_ip_address();
00234 }
00235 
00236 int8_t WizFi310Interface::get_rssi()
00237 {
00238     return 0;
00239 }
00240 
00241 void WizFi310Interface::attach(Callback<void(nsapi_event_t, intptr_t)> status_cb)
00242 {
00243     m_mutex.lock();
00244     m_on_status_change = status_cb;
00245     m_mutex.unlock();
00246 }
00247 
00248 nsapi_size_or_error_t WizFi310Interface::scan(WiFiAccessPoint *res, nsapi_size_t count)
00249 {
00250     m_mutex.lock();
00251     m_scan_ctx.res = res;
00252     m_scan_ctx.count = count;
00253     m_scan_ctx.idx = 0;
00254 
00255     m_semphr.wait(0);
00256     nsapi_error_t err = m_wizfi310.scan (Callback<void(nsapi_wifi_ap_t *)>(this, &WizFi310Interface::scan_ap));
00257     if (err == NSAPI_ERROR_IN_PROGRESS) {
00258         m_semphr.wait();
00259     }
00260 
00261     uint32_t total = m_scan_ctx.idx;
00262     if ((count != 0) && (count < total)) {
00263         total = count;
00264     }
00265     m_mutex.unlock();
00266     return total;
00267 }
00268 
00269 void WizFi310Interface::scan_ap(nsapi_wifi_ap_t *ap)
00270 {
00271     if (ap == NULL) {
00272         m_semphr.release();
00273         return;
00274     }
00275     if (m_scan_ctx.idx < m_scan_ctx.count) {
00276         m_scan_ctx.res[m_scan_ctx.idx] = WiFiAccessPoint(*ap);
00277     }
00278     m_scan_ctx.idx += 1;
00279 }
00280 
00281 // =================================================================================================
00282 // Socket API
00283 nsapi_error_t WizFi310Interface::socket_open(void **handle, nsapi_protocol_t proto)
00284 {
00285     tr_debug("socket_open(%p, %d)", handle, proto);
00286     if (handle == NULL) {
00287         tr_debug("socket_open()=%d,--", NSAPI_ERROR_PARAMETER);
00288         return NSAPI_ERROR_PARAMETER;
00289     }
00290 
00291     // Look for an unused socket
00292     m_mutex.lock();
00293     // limit the number of active socket to WIZFI310_SOCKET_COUNT
00294     if (m_socket_count == WIZFI310_SOCKET_COUNT) {
00295         m_mutex.unlock();
00296         tr_debug("socket_open()=%d,--", NSAPI_ERROR_NO_SOCKET);
00297         return NSAPI_ERROR_NO_SOCKET;
00298     }
00299 
00300     struct wizfi310_socket *socket = new (std::nothrow) struct wizfi310_socket(m_wizfi310, proto);
00301     if (!socket) {
00302         m_mutex.unlock();
00303         tr_debug("socket_open()=%d,--", NSAPI_ERROR_NO_MEMORY);
00304         return NSAPI_ERROR_NO_MEMORY;
00305     }
00306     m_socket_count += 1;
00307     m_mutex.unlock();
00308 
00309     *handle = socket;
00310     tr_debug("socket_open()=0,%p", socket);
00311 
00312     return 0;
00313 }
00314 
00315 int WizFi310Interface::socket_bind(void *handle, const SocketAddress &address)
00316 {
00317     return NSAPI_ERROR_UNSUPPORTED;
00318 }
00319 
00320 int WizFi310Interface::socket_listen(void *handle, int backlog)
00321 {
00322     return NSAPI_ERROR_UNSUPPORTED;
00323 }
00324 
00325 int WizFi310Interface::socket_connect(void *handle, const SocketAddress &addr)
00326 {
00327     struct wizfi310_socket *socket = (struct wizfi310_socket *)handle;
00328     if (addr.get_ip_version() != NSAPI_IPv4) {
00329         return NSAPI_ERROR_UNSUPPORTED;
00330     }
00331 
00332     tr_debug("socket_connect(%p, %s:%u)", handle, addr.get_ip_address(), addr.get_port());
00333     socket->op_mtx.lock();
00334     nsapi_error_t res = NSAPI_ERROR_DEVICE_ERROR;
00335     if (socket->id >= 0) {
00336         if (socket->connected) {
00337             res = NSAPI_ERROR_IS_CONNECTED;
00338         } else {
00339             res = NSAPI_ERROR_ALREADY;
00340         }
00341     } else {
00342         socket->addr = addr;
00343         const char *proto = (socket->proto == NSAPI_UDP) ? "UCN" : "TCN";
00344         int id = NSAPI_ERROR_WOULD_BLOCK;
00345         while (id == NSAPI_ERROR_WOULD_BLOCK) {
00346             id = m_wizfi310.open(proto, addr.get_ip_address(), addr.get_port(), socket_event, socket);
00347             if (id == NSAPI_ERROR_WOULD_BLOCK) {
00348                 wait_ms(1000);
00349             } else if (id < 0) {
00350                 res = id;
00351             } else {
00352                 socket->id = id;
00353                 res = NSAPI_ERROR_IN_PROGRESS;
00354             }
00355         }
00356     }
00357     socket->op_mtx.unlock();
00358     tr_debug("socket_connect(%p,...)=(%d)%d", handle, socket->id, res);
00359     return res;
00360 }
00361 
00362 int WizFi310Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
00363 {
00364     return NSAPI_ERROR_UNSUPPORTED;
00365 }
00366 
00367 int WizFi310Interface::socket_send(void *handle, const void *data, unsigned size)
00368 {
00369     tr_debug("socket_send(%p, %p, %u)", handle, data, size);
00370     if (size == 0) {
00371         return 0;
00372     }
00373     struct wizfi310_socket *socket = (struct wizfi310_socket *)handle;
00374     socket->op_mtx.lock();
00375     if (!socket->connected) {
00376         socket->op_mtx.unlock();
00377         return NSAPI_ERROR_NO_CONNECTION;
00378     }
00379     nsapi_error_t res;
00380     do {
00381         socket->semphr.wait(0);
00382         res = m_wizfi310.send(socket->id, data, size);
00383         if (res == NSAPI_ERROR_WOULD_BLOCK) {
00384             wait_ms(10);
00385         }
00386     } while (res == NSAPI_ERROR_WOULD_BLOCK);
00387     if (res == NSAPI_ERROR_IN_PROGRESS) {
00388         socket->semphr.wait();
00389         res = size;
00390     }
00391     socket->op_mtx.unlock();
00392     tr_debug("socket_send(%p, %p, %u)=%d", handle, data, size, res);
00393     return res;
00394 }
00395 
00396 int WizFi310Interface::socket_recv(void *handle, void *data, unsigned size)
00397 {
00398     tr_debug("socket_recv(%p, %p, %u)", handle, data, size);
00399     struct wizfi310_socket *s = (struct wizfi310_socket *)handle;
00400     int32_t read = NSAPI_ERROR_WOULD_BLOCK;
00401     Packet *p = NULL;
00402 
00403     s->state_mtx.lock();
00404     if (s->first != NULL) {
00405         p = s->first;
00406 
00407         uint32_t plen = p->len();
00408         read = p->consume((char *)data, size);
00409         tr_debug("%d: f: %p l: %p; read: %lu/%lu", __LINE__, s->first, s->last, read, plen);
00410         (void)plen;
00411         if (p->len() == 0) {
00412             s->first = p->next();
00413             if (s->first == NULL) {
00414                 s->last = NULL;
00415             } else {
00416                 p->set_next(NULL); // detach head from the rest
00417             }
00418             delete p;
00419 
00420             // TODO: we need a way to signal the driver that we made some space for further reception
00421         }
00422         tr_debug("%d: f: %p l: %p", __LINE__, s->first, s->last);
00423     } else if (!s->connected) {
00424         read = 0;
00425     }
00426     s->state_mtx.unlock();
00427     tr_debug("socket_recv(%p, %p, %u)=%ld", s, data, size, read);
00428     return read;
00429 }
00430 
00431 int WizFi310Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
00432 {
00433     if (addr.get_ip_version() != NSAPI_IPv4) {
00434         return NSAPI_ERROR_PARAMETER;
00435     }
00436     nsapi_error_t res;
00437 
00438     tr_debug("socket_sendto(%p, %s:%hu, %p, %u)", handle, addr.get_ip_address(), (uint16_t)addr.get_port(), data, size);
00439     struct wizfi310_socket *socket = (struct wizfi310_socket *)handle;
00440     socket->op_mtx.lock();
00441     if (socket->connected && socket->addr != addr) {
00442         socket->close();
00443     }
00444     res = socket_connect(socket, addr);
00445     if ((res == NSAPI_ERROR_IN_PROGRESS) || (res == NSAPI_ERROR_ALREADY) || (res == NSAPI_ERROR_IS_CONNECTED)) {
00446         if (!socket->connected) {
00447             socket->semphr.wait();
00448         }
00449         if (!socket->connected) {
00450             res = NSAPI_ERROR_NO_CONNECTION;
00451         } else {
00452             res = socket_send(socket, data, size);
00453         }
00454     }
00455     socket->op_mtx.unlock();
00456     return res;
00457 }
00458 int WizFi310Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
00459 {
00460     tr_debug("socket_recvfrom(%p, %p, %u)", handle, data, size);
00461     struct wizfi310_socket *socket = (struct wizfi310_socket *)handle;
00462     int ret = socket_recv(socket, data, size);
00463     if (ret >= 0 && addr) {
00464         *addr = socket->addr;
00465     }
00466 
00467     return ret;
00468 }
00469 
00470 nsapi_error_t WizFi310Interface::socket_close(void *handle)
00471 {
00472     struct wizfi310_socket *socket = (struct wizfi310_socket *)handle;
00473     tr_debug("socket_close(%p)", handle);
00474 
00475     m_mutex.lock();
00476     socket->close();
00477     m_socket_count -= 1;
00478     m_mutex.unlock();
00479     delete socket;
00480 
00481     return NSAPI_ERROR_OK;
00482 }
00483 void WizFi310Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
00484 {
00485     tr_debug("socket_attach(%p, %p, %p)", handle, callback, data);
00486     struct wizfi310_socket *socket = (struct wizfi310_socket *)handle;
00487     socket->state_mtx.lock();
00488     socket->cbk = callback;
00489     socket->data = data;
00490     socket->state_mtx.unlock();
00491 }
00492 
00493 void WizFi310Interface::socket_event(void *ctx, WizFi310::socket_event_t type, WizFi310::socket_event_data_t &data)
00494 {
00495     struct wizfi310_socket *s = (struct wizfi310_socket *)ctx;
00496     tr_debug("socket_event(%p, %s)", ctx, WizFi310::event2str(type));
00497     s->state_mtx.lock();
00498     switch (type) {
00499         case WizFi310::EventConnected: {
00500             s->connected = true;
00501             s->semphr.release();
00502             break;
00503         }
00504         case WizFi310::EventDataReceived: {
00505             tr_debug("%d: Data received: %p (f:%p l:%p)", __LINE__, data.data_received.packet, s->first, s->last);
00506             if (s->last == NULL) {
00507                 s->last = data.data_received.packet;
00508                 s->first = s->last;
00509             } else {
00510                 s->last->set_next(data.data_received.packet);
00511                 s->last = data.data_received.packet;
00512             }
00513             tr_debug("%d: f: %p l: %p", __LINE__, s->first, s->last);
00514             break;
00515         }
00516         case WizFi310::EventDataSent: {
00517             s->semphr.release();
00518             break;
00519         }
00520         case WizFi310::EventDisconnected: {
00521             s->connected = false;
00522             s->id = -1;
00523             // TODO: on recv transfer the packet owner ship to this layer as we may be disconnected before those data are actually read.
00524             // This would also remove the need of the WizFi310::recv method.
00525             s->semphr.release();
00526             break;
00527         }
00528         default: {
00529             // tr_error("Unknown event %d", type);
00530             break;
00531         }
00532     }
00533     if (s->cbk) {
00534         s->cbk(s->data);
00535     }
00536     s->state_mtx.unlock();
00537 }
00538 
00539 void WizFi310Interface::wizfi310_socket::close()
00540 {
00541     // no lock required here as no other thread shall access this object as it is freed.
00542     state_mtx.lock();
00543     int id = this->id;
00544     this->id = -1;
00545     state_mtx.unlock();
00546     if (id >= 0) {
00547         wifi.close(id);
00548     }
00549 }
00550 
00551 WizFi310Interface::wizfi310_socket::~wizfi310_socket()
00552 {
00553     close();
00554     if (first != NULL) {
00555         delete first;
00556     }
00557 }
00558 
00559 #ifdef MBED_CONF_WIZFI310_PROVIDE_DEFAULT
00560 
00561 WiFiInterface *WiFiInterface::get_default_instance()
00562 {
00563     static WizFi310Interface wizfi;
00564     return &wizfi;
00565 }
00566 
00567 #endif