Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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>© 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
Generated on Mon Aug 29 2022 19:53:42 by
