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

« Back to documentation index

Show/hide line numbers ISM43362Interface.cpp Source File

ISM43362Interface.cpp

00001 /* ISM43362 implementation of NetworkInterfaceAPI
00002  * Copyright (c) STMicroelectronics 2018
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 #include <string.h>
00018 #include "ISM43362Interface.h"
00019 #include "mbed_debug.h"
00020 
00021                                             // Product ID,FW Revision,API Revision,Stack Revision,RTOS Revision,CPU Clock,Product Name
00022 #define LATEST_FW_VERSION_NUMBER "C3.5.2.5" // ISM43362-M3G-L44-SPI,C3.5.2.5.STM,v3.5.2,v1.4.0.rc1,v8.2.1,120000000,Inventek eS-WiFi
00023 
00024 // activate / de-activate debug
00025 #define ism_interface_debug 0
00026 
00027 #define MIN(a,b) (((a)<(b))?(a):(b))
00028 
00029 // ISM43362Interface implementation
00030 ISM43362Interface::ISM43362Interface(bool debug)
00031     : _ism(MBED_CONF_ISM43362_WIFI_MOSI, MBED_CONF_ISM43362_WIFI_MISO, MBED_CONF_ISM43362_WIFI_SCLK, MBED_CONF_ISM43362_WIFI_NSS, MBED_CONF_ISM43362_WIFI_RESET, MBED_CONF_ISM43362_WIFI_DATAREADY, MBED_CONF_ISM43362_WIFI_WAKEUP, debug),
00032       _conn_stat(NSAPI_STATUS_DISCONNECTED),
00033       _conn_stat_cb(NULL)
00034 {
00035     _ism_debug = ism_interface_debug || debug;
00036     memset(_ids, 0, sizeof(_ids));
00037     memset(_socket_obj, 0, sizeof(_socket_obj));
00038     _ism.attach(this, &ISM43362Interface::update_conn_state_cb);
00039     memset(_cbs, 0, sizeof(_cbs));
00040     memset(ap_ssid, 0, sizeof(ap_ssid));
00041     memset(ap_pass, 0, sizeof(ap_pass));
00042     ap_sec = ISM_SECURITY_UNKNOWN;
00043 
00044     thread_read_socket.start(callback(this, &ISM43362Interface::socket_check_read));
00045 
00046     _mutex.lock();
00047 
00048     // Check all supported firmware versions
00049     _FwVersion = _ism.get_firmware_version();
00050 
00051     if (!_FwVersion) {
00052         error("ISM43362Interface: ERROR cannot read firmware version\r\n");
00053     }
00054 
00055     debug_if(_ism_debug, "ISM43362Interface: read_version = %lu\r\n", _FwVersion);
00056     /* FW Revision should be with format "CX.X.X.X" with X as a single digit */
00057     if ( (_FwVersion < 1000) || (_FwVersion > 9999) ) {
00058         debug_if(_ism_debug, "ISM43362Interface: read_version issue\r\n");
00059     }
00060 
00061 #if TARGET_DISCO_L475VG_IOT01A
00062     if (_FwVersion < ParseNumber(LATEST_FW_VERSION_NUMBER, NULL)) {
00063         debug_if(_ism_debug, "ISM43362Interface: please update FW\r\n");
00064     }
00065 #endif
00066 
00067     _connect_status = NSAPI_ERROR_NO_CONNECTION;
00068     _mutex.unlock();
00069 }
00070 
00071 nsapi_error_t ISM43362Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
00072                                uint8_t channel)
00073 {
00074     if (channel != 0) {
00075         return NSAPI_ERROR_UNSUPPORTED;
00076     }
00077 
00078     nsapi_error_t credentials_status = set_credentials(ssid, pass, security);
00079     if (credentials_status) {
00080         return credentials_status;
00081     }
00082 
00083     return connect();
00084 }
00085 
00086 nsapi_error_t ISM43362Interface::connect()
00087 {
00088     if (strlen(ap_ssid) == 0) {
00089         return NSAPI_ERROR_NO_SSID;
00090     }
00091 
00092     _mutex.lock();
00093 
00094     if (!_ism.dhcp(true)) {
00095         _mutex.unlock();
00096         return NSAPI_ERROR_DHCP_FAILURE;
00097     }
00098 
00099     _connect_status = _ism.connect(ap_ssid, ap_pass, ap_sec);
00100     debug_if(_ism_debug, "ISM43362Interface: connect_status %d\n", _connect_status);
00101 
00102     if (_connect_status != NSAPI_ERROR_OK) {
00103         _mutex.unlock();
00104         return _connect_status;
00105     }
00106 
00107     if (!_ism.getIPAddress()) {
00108         _connect_status = NSAPI_ERROR_DHCP_FAILURE;
00109         _mutex.unlock();
00110         return NSAPI_ERROR_DHCP_FAILURE;
00111     }
00112 
00113     _mutex.unlock();
00114 
00115     return NSAPI_ERROR_OK;
00116 }
00117 
00118 nsapi_error_t ISM43362Interface::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version)
00119 {
00120     if (strlen(name) == 0) {
00121         return NSAPI_ERROR_NO_SOCKET;
00122     }
00123 
00124     _mutex.lock();
00125     if (address->set_ip_address(name)) {
00126         if (version != NSAPI_UNSPEC && address->get_ip_version() != version) {
00127             _mutex.unlock();
00128             return NSAPI_ERROR_DNS_FAILURE;
00129         }
00130 
00131         _mutex.unlock();
00132         return NSAPI_ERROR_OK;
00133     }
00134 
00135     char *ipbuff = new char[NSAPI_IP_SIZE];
00136     int ret = 0;
00137     if (!_ism.dns_lookup(name, ipbuff)) {
00138         ret = NSAPI_ERROR_DNS_FAILURE;
00139     } else {
00140         address->set_ip_address(ipbuff);
00141     }
00142     _mutex.unlock();
00143 
00144     delete[] ipbuff;
00145 
00146     return ret;
00147 }
00148 
00149 int ISM43362Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
00150 {
00151     if ((ssid == NULL) || (strlen(ssid) == 0) || (strlen(ssid) > 32)) {
00152         return NSAPI_ERROR_PARAMETER;
00153     }
00154 
00155     if (security != NSAPI_SECURITY_NONE) {
00156         if ((pass == NULL) || (strcmp(pass, "") == 0)) {
00157             return NSAPI_ERROR_PARAMETER;
00158         }
00159     }
00160 
00161     if (strlen(pass) > 63) {
00162         return NSAPI_ERROR_PARAMETER;
00163     }
00164 
00165     _mutex.lock();
00166     memset(ap_ssid, 0, sizeof(ap_ssid));
00167     strncpy(ap_ssid, ssid, sizeof(ap_ssid));
00168 
00169     memset(ap_pass, 0, sizeof(ap_pass));
00170     strncpy(ap_pass, pass, sizeof(ap_pass));
00171 
00172     switch (security) {
00173         case NSAPI_SECURITY_NONE:
00174             ap_sec = ISM_SECURITY_NONE;
00175             break;
00176         case NSAPI_SECURITY_WEP:
00177             ap_sec = ISM_SECURITY_WEP;
00178             break;
00179         case NSAPI_SECURITY_WPA:
00180             ap_sec = ISM_SECURITY_WPA;
00181             break;
00182         case NSAPI_SECURITY_WPA2:
00183             ap_sec = ISM_SECURITY_WPA2;
00184             break;
00185         case NSAPI_SECURITY_WPA_WPA2:
00186             ap_sec = ISM_SECURITY_WPA_WPA2;
00187             break;
00188         default:
00189             ap_sec = ISM_SECURITY_UNKNOWN;
00190             break;
00191     }
00192     _mutex.unlock();
00193 
00194     return NSAPI_ERROR_OK;
00195 }
00196 
00197 int ISM43362Interface::set_channel(uint8_t channel)
00198 {
00199     return NSAPI_ERROR_UNSUPPORTED;
00200 }
00201 
00202 nsapi_error_t ISM43362Interface::disconnect()
00203 {
00204     _mutex.lock();
00205 
00206     if (_connect_status != NSAPI_ERROR_OK) {
00207         _mutex.unlock();
00208         return NSAPI_ERROR_NO_CONNECTION;
00209     }
00210 
00211     if (!_ism.disconnect()) {
00212         _mutex.unlock();
00213         return NSAPI_ERROR_DEVICE_ERROR;
00214     }
00215 
00216     _connect_status = NSAPI_ERROR_NO_CONNECTION;
00217     _mutex.unlock();
00218     return NSAPI_ERROR_OK;
00219 }
00220 
00221 const char *ISM43362Interface::get_ip_address()
00222 {
00223     _mutex.lock();
00224     const char *ret = _ism.getIPAddress();
00225     _mutex.unlock();
00226     return ret;
00227 }
00228 
00229 const char *ISM43362Interface::get_mac_address()
00230 {
00231     _mutex.lock();
00232     const char *ret = _ism.getMACAddress();
00233     _mutex.unlock();
00234     return ret;
00235 }
00236 
00237 const char *ISM43362Interface::get_gateway()
00238 {
00239     _mutex.lock();
00240     const char *ret = _ism.getGateway();
00241     _mutex.unlock();
00242     return ret;
00243 }
00244 
00245 const char *ISM43362Interface::get_netmask()
00246 {
00247     _mutex.lock();
00248     const char *ret = _ism.getNetmask();
00249     _mutex.unlock();
00250     return ret;
00251 }
00252 
00253 int8_t ISM43362Interface::get_rssi()
00254 {
00255     _mutex.lock();
00256     int8_t ret = _ism.getRSSI();
00257     _mutex.unlock();
00258     return ret;
00259 }
00260 
00261 int ISM43362Interface::scan(WiFiAccessPoint *res, unsigned count)
00262 {
00263     _mutex.lock();
00264     int ret = _ism.scan(res, count);
00265     _mutex.unlock();
00266     return ret;
00267 }
00268 
00269 struct ISM43362_socket {
00270     int id;
00271     nsapi_protocol_t proto;
00272     volatile bool connected;
00273     SocketAddress addr;
00274     char read_data[1400];
00275     volatile uint32_t read_data_size;
00276 };
00277 
00278 int ISM43362Interface::socket_open(void **handle, nsapi_protocol_t proto)
00279 {
00280     // Look for an unused socket
00281     int id = -1;
00282     for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
00283         if (!_ids[i]) {
00284             id = i;
00285             _ids[i] = true;
00286             break;
00287         }
00288     }
00289 
00290     if (id == -1) {
00291         return NSAPI_ERROR_NO_SOCKET;
00292     }
00293     _mutex.lock();
00294     struct ISM43362_socket *socket = new struct ISM43362_socket;
00295     if (!socket) {
00296         _mutex.unlock();
00297         return NSAPI_ERROR_NO_SOCKET;
00298     }
00299     socket->id = id;
00300     debug_if(_ism_debug, "ISM43362Interface: socket_open, id=%d\n", socket->id);
00301     memset(socket->read_data, 0, sizeof(socket->read_data));
00302     socket->addr = 0;
00303     socket->read_data_size = 0;
00304     socket->proto = proto;
00305     socket->connected = false;
00306     *handle = socket;
00307     _mutex.unlock();
00308 
00309     return 0;
00310 }
00311 
00312 int ISM43362Interface::socket_close(void *handle)
00313 {
00314     _mutex.lock();
00315     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00316     debug_if(_ism_debug, "ISM43362Interface: socket_close, id=%d\n", socket->id);
00317     int err = 0;
00318 
00319     if (!_ism.close(socket->id)) {
00320         err = NSAPI_ERROR_DEVICE_ERROR;
00321     }
00322 
00323     socket->connected = false;
00324     _ids[socket->id] = false;
00325     _socket_obj[socket->id] = 0;
00326     _mutex.unlock();
00327     delete socket;
00328     return err;
00329 }
00330 
00331 int ISM43362Interface::socket_bind(void *handle, const SocketAddress &address)
00332 {
00333     return NSAPI_ERROR_UNSUPPORTED;
00334 }
00335 
00336 int ISM43362Interface::socket_listen(void *handle, int backlog)
00337 {
00338     return NSAPI_ERROR_UNSUPPORTED;
00339 }
00340 
00341 int ISM43362Interface::socket_connect(void *handle, const SocketAddress &addr)
00342 {
00343     _mutex.lock();
00344     int ret = socket_connect_nolock(handle, addr);
00345     _mutex.unlock();
00346     return ret;
00347 }
00348 
00349 int ISM43362Interface::socket_connect_nolock(void *handle, const SocketAddress &addr)
00350 {
00351     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00352     const char *proto = (socket->proto == NSAPI_UDP) ? "1" : "0";
00353     if (!_ism.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) {
00354         return NSAPI_ERROR_DEVICE_ERROR;
00355     }
00356     _ids[socket->id]  = true;
00357     _socket_obj[socket->id] = (uint32_t)socket;
00358     socket->connected = true;
00359     return 0;
00360 
00361 }
00362 
00363 
00364 
00365 void ISM43362Interface::socket_check_read()
00366 {
00367     while (1) {
00368         for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
00369             _mutex.lock();
00370             if (_socket_obj[i] != 0) {
00371                 struct ISM43362_socket *socket = (struct ISM43362_socket *)_socket_obj[i];
00372                 /* Check if there is something to read for this socket. But if it */
00373                 /* has already been read : don't read again */
00374                 if ((socket->connected) && (socket->read_data_size == 0) && _cbs[socket->id].callback) {
00375                     /* if no callback is set, no need to read ?*/
00376                     int read_amount = _ism.check_recv_status(socket->id, socket->read_data);
00377                     // debug_if(_ism_debug, "ISM43362Interface socket_check_read: i %d read_amount %d \r\n", i, read_amount);
00378                     if (read_amount > 0) {
00379                         socket->read_data_size = read_amount;
00380                     } else if (read_amount < 0) {
00381                         /* Mark donw connection has been lost or closed */
00382                         debug_if(_ism_debug, "ISM43362Interface socket_check_read: i %d closed\r\n", i);
00383                         socket->connected = false;
00384                     }
00385                     if (read_amount != 0) {
00386                         /* There is something to read in this socket*/
00387                         if (_cbs[socket->id].callback) {
00388                             _cbs[socket->id].callback(_cbs[socket->id].data);
00389                         }
00390                     }
00391                 }
00392             }
00393             _mutex.unlock();
00394         }
00395         wait_ms(50);
00396     }
00397 }
00398 
00399 int ISM43362Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
00400 {
00401     return NSAPI_ERROR_UNSUPPORTED;
00402 }
00403 
00404 int ISM43362Interface::socket_send(void *handle, const void *data, unsigned size)
00405 {
00406     _mutex.lock();
00407     int ret = socket_send_nolock(handle, data, size);
00408     _mutex.unlock();
00409     return ret;
00410 }
00411 
00412 /*  CAREFULL LOCK must be taken before callling this function */
00413 int ISM43362Interface::socket_send_nolock(void *handle, const void *data, unsigned size)
00414 {
00415     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00416 
00417     if (size > ES_WIFI_MAX_TX_PACKET_SIZE) {
00418         size = ES_WIFI_MAX_TX_PACKET_SIZE;
00419     }
00420 
00421     if (!_ism.send(socket->id, data, size)) {
00422         debug_if(_ism_debug, "ISM43362Interface: socket_send ERROR\r\n");
00423         return NSAPI_ERROR_DEVICE_ERROR; // or WOULD_BLOCK ?
00424     }
00425 
00426     return size;
00427 }
00428 
00429 int ISM43362Interface::socket_recv(void *handle, void *data, unsigned size)
00430 {
00431     _mutex.lock();
00432     unsigned recv = 0;
00433     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00434     char *ptr = (char *)data;
00435 
00436     // debug_if(_ism_debug, "ISM43362Interface socket_recv: req=%d read_data_size=%d connected %d\r\n", size, socket->read_data_size, socket->connected);
00437 
00438     if (!socket->connected) {
00439         _mutex.unlock();
00440         return 0;
00441     }
00442 
00443     if (socket->read_data_size == 0) {
00444         /* if no callback is set, no need to read ?*/
00445         int read_amount = _ism.check_recv_status(socket->id, socket->read_data);
00446         if (read_amount > 0) {
00447             socket->read_data_size = read_amount;
00448         } else if (read_amount < 0) {
00449             socket->connected = false;
00450             debug_if(_ism_debug, "ISM43362Interface socket_recv: socket closed\r\n");
00451             _mutex.unlock();
00452             return 0;
00453         }
00454     }
00455 
00456     if (socket->read_data_size != 0) {
00457         // debug_if(_ism_debug, "ISM43362Interface socket_recv: read_data_size=%d\r\n", socket->read_data_size);
00458         uint32_t i = 0;
00459         while ((i < socket->read_data_size) && (i < size)) {
00460             *ptr++ = socket->read_data[i];
00461             i++;
00462         }
00463 
00464         recv += i;
00465 
00466         if (i >= socket->read_data_size) {
00467             /* All the storeed data has been read, reset buffer */
00468             memset(socket->read_data, 0, sizeof(socket->read_data));
00469             socket->read_data_size = 0;
00470             // debug_if(_ism_debug, "ISM43362Interface: Socket_recv buffer reset\r\n");
00471         } else {
00472             /*  In case there is remaining data in buffer, update socket content
00473              *  For now by shift copy of all data (not very efficient to be
00474              *  revised */
00475             while (i < socket->read_data_size) {
00476                 socket->read_data[i - size] = socket->read_data[i];
00477                 i++;
00478             }
00479 
00480             socket->read_data_size -= size;
00481         }
00482     }
00483     // else {
00484     //     debug_if(_ism_debug, "ISM43362Interface socket_recv: Nothing in buffer\r\n");
00485     // }
00486 
00487     _mutex.unlock();
00488 
00489     if (recv > 0) {
00490         debug_if(_ism_debug, "ISM43362Interface socket_recv: recv=%d\r\n", recv);
00491         return recv;
00492     } else {
00493         debug_if(_ism_debug, "ISM43362Interface socket_recv: returns WOULD BLOCK\r\n");
00494         return NSAPI_ERROR_WOULD_BLOCK;
00495     }
00496 }
00497 
00498 int ISM43362Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
00499 {
00500     _mutex.lock();
00501     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00502 
00503     if (socket->connected && socket->addr != addr) {
00504         if (!_ism.close(socket->id)) {
00505             debug_if(_ism_debug, "ISM43362Interface: socket_sendto ERROR\r\n");
00506             _mutex.unlock();
00507             return NSAPI_ERROR_DEVICE_ERROR;
00508         }
00509         socket->connected = false;
00510         _ids[socket->id] = false;
00511         _socket_obj[socket->id] = 0;
00512     }
00513 
00514     if (!socket->connected) {
00515         int err = socket_connect_nolock(socket, addr);
00516         if (err < 0) {
00517             _mutex.unlock();
00518             return err;
00519         }
00520         socket->addr = addr;
00521     }
00522 
00523     int ret = socket_send_nolock(socket, data, size);
00524 
00525     _mutex.unlock();
00526 
00527     return ret;
00528 }
00529 
00530 int ISM43362Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
00531 {
00532     int ret = socket_recv(handle, data, size);
00533     _mutex.lock();
00534     if ((ret >= 0) && addr) {
00535         struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00536         *addr = socket->addr;
00537     }
00538     _mutex.unlock();
00539     return ret;
00540 }
00541 
00542 void ISM43362Interface::socket_attach(void *handle, void (*cb)(void *), void *data)
00543 {
00544     _mutex.lock();
00545     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00546     _cbs[socket->id].callback = cb;
00547     _cbs[socket->id].data = data;
00548     _mutex.unlock();
00549 }
00550 
00551 void ISM43362Interface::event()
00552 {
00553     for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
00554         if (_cbs[i].callback) {
00555             _cbs[i].callback(_cbs[i].data);
00556         }
00557     }
00558 }
00559 
00560 void ISM43362Interface::attach(Callback<void(nsapi_event_t, intptr_t)> status_cb)
00561 {
00562     debug_if(_ism_debug, "ISM43362Interface: attach\n");
00563     _conn_stat_cb = status_cb;
00564 }
00565 
00566 nsapi_connection_status_t ISM43362Interface::get_connection_status() const
00567 {
00568     debug_if(_ism_debug, "ISM43362Interface: get_connection_status %d\n", _conn_stat);
00569     return _conn_stat;
00570 }
00571 
00572 
00573 void ISM43362Interface::update_conn_state_cb()
00574 {
00575     nsapi_connection_status_t prev_stat = _conn_stat;
00576     _conn_stat = _ism.connection_status();
00577     debug_if(_ism_debug, "ISM43362Interface: update_conn_state_cb %d -> %d\n", prev_stat, _conn_stat);
00578 
00579     if (prev_stat == _conn_stat) {
00580         return;
00581     }
00582 
00583     // Inform upper layers
00584     if (_conn_stat_cb) {
00585         _conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat);
00586     }
00587 }
00588 
00589 
00590 #if MBED_CONF_ISM43362_PROVIDE_DEFAULT
00591 
00592 WiFiInterface *WiFiInterface::get_default_instance() {
00593     static ISM43362Interface ism;
00594     return &ism;
00595 }
00596 
00597 #endif