Farnell-Element14 Bologna IOT Team / wifi-ism43362

Dependents:   DISCO_L475VG_IOT01-Sensors-BSP

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 2017
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 // ao activate  / de-activate debug
00022 #define ism_debug false
00023 
00024 // Various timeouts for different ISM43362 operations
00025 #define ISM43362_CONNECT_TIMEOUT 15000 /* milliseconds */
00026 #define ISM43362_SEND_TIMEOUT    1000   /* milliseconds */
00027 #define ISM43362_RECV_TIMEOUT    100   /* milliseconds */
00028 #define ISM43362_MISC_TIMEOUT    100   /* milliseconds */
00029 
00030 // Tested firmware versions
00031 // Example of versions string returned by the module:
00032 // "ISM43362-M3G-L44-SPI,C3.5.2.3.BETA9,v3.5.2,v1.4.0.rc1,v8.2.1,120000000,Inventek eS-WiFi"
00033 // "ISM43362-M3G-L44-SPI,C3.5.2.2,v3.5.2,v1.4.0.rc1,v8.2.1,120000000,Inventek eS-WiFi"
00034 // Only the first version is checked !
00035 const char supported_fw_versions[2][15] = {"C3.5.2.3.BETA9", "C3.5.2.2"};
00036 
00037 #define MIN(a,b) (((a)<(b))?(a):(b))
00038 
00039 // ISM43362Interface implementation
00040 ISM43362Interface::ISM43362Interface(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, PinName datareadypin, PinName wakeup, bool debug)
00041     : _ism(mosi, miso, sclk, nss, reset, datareadypin, wakeup, debug)
00042 {
00043     memset(_ids, 0, sizeof(_ids));
00044     memset(_socket_obj, 0, sizeof(_socket_obj));
00045     memset(_cbs, 0, sizeof(_cbs));
00046     thread_read_socket.start(callback(this, &ISM43362Interface::socket_check_read));
00047 }
00048 
00049 int ISM43362Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
00050                                         uint8_t channel)
00051 {
00052     if (channel != 0) {
00053         return NSAPI_ERROR_UNSUPPORTED;
00054     }
00055 
00056     set_credentials(ssid, pass, security);
00057     return connect();
00058 }
00059 
00060 int ISM43362Interface::connect()
00061 {
00062     _mutex.lock();
00063     const char* read_version;
00064 
00065     _ism.setTimeout(ISM43362_MISC_TIMEOUT);
00066 
00067     // Check all supported firmware versions
00068     read_version = _ism.get_firmware_version();
00069 
00070     if (!read_version) {
00071         debug_if(ism_debug, "ISM43362: ERROR cannot read firmware version\r\n");
00072         return NSAPI_ERROR_DEVICE_ERROR;
00073     }
00074     debug_if(ism_debug, "ISM43362: read_version = [%s]\r\n", read_version);
00075 
00076     if ((strcmp(read_version, supported_fw_versions[0]) == 0) || (strcmp(read_version, supported_fw_versions[1]) == 0)) {
00077         debug_if(ism_debug, "ISM43362: firmware version is OK\r\n");
00078     } else {
00079         debug_if(ism_debug, "ISM43362: WARNING this firmware version has not been tested !\r\n");
00080     }
00081 
00082     if (!_ism.dhcp(true)) {
00083         return NSAPI_ERROR_DHCP_FAILURE;
00084     }
00085 
00086     _ism.setTimeout(ISM43362_CONNECT_TIMEOUT);
00087 
00088     if (!_ism.connect(ap_ssid, ap_pass)) {
00089         return NSAPI_ERROR_NO_CONNECTION;
00090     }
00091 
00092     _ism.setTimeout(ISM43362_MISC_TIMEOUT);
00093     if (!_ism.getIPAddress()) {
00094         return NSAPI_ERROR_DHCP_FAILURE;
00095     }
00096 
00097     _ism.setTimeout(ISM43362_MISC_TIMEOUT);
00098     _mutex.unlock();
00099 
00100     return NSAPI_ERROR_OK;
00101 }
00102 
00103 nsapi_error_t ISM43362Interface::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version)
00104 {
00105     _mutex.lock();
00106     if (address->set_ip_address(name)) {
00107         if (version != NSAPI_UNSPEC && address->get_ip_version() != version) {
00108             return NSAPI_ERROR_DNS_FAILURE;
00109         }
00110 
00111         return NSAPI_ERROR_OK;
00112     }
00113 
00114     char *ipbuff = new char[NSAPI_IP_SIZE];
00115     int ret = 0;
00116     _ism.setTimeout(ISM43362_CONNECT_TIMEOUT);
00117     if(!_ism.dns_lookup(name, ipbuff)) {
00118         ret = NSAPI_ERROR_DEVICE_ERROR;
00119     } else {
00120         address->set_ip_address(ipbuff);
00121     }
00122     _mutex.unlock();
00123 
00124     delete[] ipbuff;
00125 
00126     return ret;
00127 }
00128 
00129 int ISM43362Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
00130 {
00131     _mutex.lock();
00132 
00133     memset(ap_ssid, 0, sizeof(ap_ssid));
00134     strncpy(ap_ssid, ssid, sizeof(ap_ssid));
00135 
00136     memset(ap_pass, 0, sizeof(ap_pass));
00137     strncpy(ap_pass, pass, sizeof(ap_pass));
00138 
00139     ap_sec = security;
00140     _mutex.unlock();
00141 
00142     return 0;
00143 }
00144 
00145 int ISM43362Interface::set_channel(uint8_t channel)
00146 {
00147     return NSAPI_ERROR_UNSUPPORTED;
00148 }
00149 
00150 int ISM43362Interface::disconnect()
00151 {
00152     _mutex.lock();
00153 
00154     _ism.setTimeout(ISM43362_MISC_TIMEOUT);
00155 
00156     if (!_ism.disconnect()) {
00157         return NSAPI_ERROR_DEVICE_ERROR;
00158     }
00159 
00160     _mutex.unlock();
00161 
00162     return NSAPI_ERROR_OK;
00163 }
00164 
00165 const char *ISM43362Interface::get_ip_address()
00166 {
00167     _mutex.lock();
00168     const char *ret = _ism.getIPAddress();
00169     _mutex.unlock();
00170     return ret;
00171 }
00172 
00173 const char *ISM43362Interface::get_mac_address()
00174 {
00175     _mutex.lock();
00176     const char *ret = _ism.getMACAddress();
00177     _mutex.unlock();
00178     return ret;
00179 }
00180 
00181 const char *ISM43362Interface::get_gateway()
00182 {
00183     _mutex.lock();
00184     const char *ret = _ism.getGateway();
00185     _mutex.unlock();
00186     return ret;
00187 }
00188 
00189 const char *ISM43362Interface::get_netmask()
00190 {
00191     _mutex.lock();
00192     const char *ret = _ism.getNetmask();
00193     _mutex.unlock();
00194     return ret;
00195 }
00196 
00197 int8_t ISM43362Interface::get_rssi()
00198 {
00199     _mutex.lock();
00200     int8_t ret = _ism.getRSSI();
00201     _mutex.unlock();
00202     return ret;
00203 }
00204 
00205 int ISM43362Interface::scan(WiFiAccessPoint *res, unsigned count)
00206 {
00207     _mutex.lock();
00208     _ism.setTimeout(ISM43362_CONNECT_TIMEOUT);
00209     int ret = _ism.scan(res, count);
00210     _mutex.unlock();
00211     return ret;
00212 }
00213 
00214 struct ISM43362_socket {
00215     int id;
00216     nsapi_protocol_t proto;
00217     volatile bool connected;
00218     SocketAddress addr;
00219     char read_data[1400];
00220     volatile uint32_t read_data_size;
00221 };
00222 
00223 int ISM43362Interface::socket_open(void **handle, nsapi_protocol_t proto)
00224 {
00225     // Look for an unused socket
00226     int id = -1;
00227     for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
00228         if (!_ids[i]) {
00229             id = i;
00230             _ids[i] = true;
00231             break;
00232         }
00233     }
00234 
00235     if (id == -1) {
00236         return NSAPI_ERROR_NO_SOCKET;
00237     }
00238     _mutex.lock();
00239     struct ISM43362_socket *socket = new struct ISM43362_socket;
00240     if (!socket) {
00241         return NSAPI_ERROR_NO_SOCKET;
00242     }
00243     socket->id = id;
00244     debug_if(ism_debug, "socket_open, id=%d", socket->id);
00245     memset(socket->read_data, 0, sizeof(socket->read_data));
00246     socket->addr = 0;
00247     socket->read_data_size = 0;
00248     socket->proto = proto;
00249     socket->connected = false;
00250     *handle = socket;
00251     _mutex.unlock();
00252 
00253     return 0;
00254 }
00255 
00256 int ISM43362Interface::socket_close(void *handle)
00257 {
00258     _mutex.lock();
00259     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00260     debug_if(ism_debug, "socket_close, id=%d", socket->id);
00261     int err = 0;
00262     _ism.setTimeout(ISM43362_MISC_TIMEOUT);
00263  
00264     if (!_ism.close(socket->id)) {
00265         err = NSAPI_ERROR_DEVICE_ERROR;
00266     }
00267 
00268     socket->connected = false;
00269     _ids[socket->id] = false;
00270     _socket_obj[socket->id] = 0;
00271     _mutex.unlock();
00272     delete socket;
00273     return err;
00274 }
00275 
00276 int ISM43362Interface::socket_bind(void *handle, const SocketAddress &address)
00277 {
00278     return NSAPI_ERROR_UNSUPPORTED;
00279 }
00280 
00281 int ISM43362Interface::socket_listen(void *handle, int backlog)
00282 {
00283     return NSAPI_ERROR_UNSUPPORTED;
00284 }
00285 
00286 int ISM43362Interface::socket_connect(void *handle, const SocketAddress &addr)
00287 {
00288     _mutex.lock();
00289     int ret = socket_connect_nolock(handle, addr);
00290     _mutex.unlock();
00291     return ret;
00292 }
00293 
00294 int ISM43362Interface::socket_connect_nolock(void *handle, const SocketAddress &addr)
00295 {
00296     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00297     _ism.setTimeout(ISM43362_CONNECT_TIMEOUT);
00298     const char *proto = (socket->proto == NSAPI_UDP) ? "1" : "0";
00299     if (!_ism.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) {
00300         return NSAPI_ERROR_DEVICE_ERROR;
00301     }
00302     _ids[socket->id]  = true;
00303     _socket_obj[socket->id] = (uint32_t)socket;
00304     socket->connected = true;
00305     return 0;
00306 
00307 }
00308 
00309 
00310 
00311 void ISM43362Interface::socket_check_read()
00312 {
00313     while (1) {
00314         for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
00315             _mutex.lock();
00316             if (_socket_obj[i] != 0) {
00317                 struct ISM43362_socket *socket = (struct ISM43362_socket *)_socket_obj[i];
00318                 /* Check if there is something to read for this socket. But if it */
00319                 /* has already been read : don't read again */
00320                 if ((socket->connected) && (socket->read_data_size == 0) && _cbs[socket->id].callback) {
00321                     _ism.setTimeout(1);
00322                     /* if no callback is set, no need to read ?*/
00323                     int read_amount = _ism.check_recv_status(socket->id, socket->read_data);
00324                     if (read_amount > 0) {
00325                         socket->read_data_size = read_amount;
00326                     } else if (read_amount < 0) {
00327                         /* Mark donw connection has been lost or closed */
00328                         socket->connected = false;
00329                     }
00330                     if (read_amount != 0) {
00331                         /* There is something to read in this socket*/
00332                         if (_cbs[socket->id].callback) {
00333                             _cbs[socket->id].callback(_cbs[socket->id].data);
00334                        }
00335                     }
00336                 }
00337             }
00338             _mutex.unlock();
00339         }
00340         wait_ms(50);
00341     }
00342 }
00343 
00344 int ISM43362Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
00345 {
00346     return NSAPI_ERROR_UNSUPPORTED;
00347 }
00348 
00349 int ISM43362Interface::socket_send(void *handle, const void *data, unsigned size)
00350 {
00351     _mutex.lock();
00352     int ret = socket_send_nolock(handle, data, size);
00353     _mutex.unlock();
00354     return ret;
00355 }
00356 
00357 /*  CAREFULL LOCK must be taken before callling this function */
00358 int ISM43362Interface::socket_send_nolock(void *handle, const void *data, unsigned size)
00359 {
00360     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00361     _ism.setTimeout(ISM43362_SEND_TIMEOUT);
00362 
00363     if (size > ES_WIFI_MAX_TX_PACKET_SIZE) {
00364         size = ES_WIFI_MAX_TX_PACKET_SIZE;
00365     }
00366 
00367     if (!_ism.send(socket->id, data, size)) {
00368         debug_if(ism_debug, "socket_send ERROR\r\n");
00369         return NSAPI_ERROR_DEVICE_ERROR; // or WOULD_BLOCK ?
00370     }
00371 
00372     return size;
00373 }
00374 
00375 int ISM43362Interface::socket_recv(void *handle, void *data, unsigned size)
00376 {
00377     _mutex.lock();
00378     unsigned recv = 0;
00379     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00380     char *ptr = (char *)data;
00381 
00382     debug_if(ism_debug, "[socket_recv] req=%d\r\n", size);
00383 
00384     if (!socket->connected) {
00385         _mutex.unlock();
00386         return NSAPI_ERROR_CONNECTION_LOST;
00387     }
00388 
00389     _ism.setTimeout(ISM43362_RECV_TIMEOUT);
00390 
00391     if (socket->read_data_size == 0) {
00392         /* if no callback is set, no need to read ?*/
00393         int read_amount = _ism.check_recv_status(socket->id, socket->read_data);
00394         if (read_amount > 0) {
00395             socket->read_data_size = read_amount;
00396         } else if (read_amount < 0) {
00397             socket->connected = false;
00398             _mutex.unlock();
00399             return NSAPI_ERROR_CONNECTION_LOST;
00400         }
00401     }
00402 
00403     if (socket->read_data_size != 0) {
00404         debug_if(ism_debug, "read_data_size=%d\r\n", socket->read_data_size);
00405         uint32_t i=0;
00406         while ((i < socket->read_data_size) && (i < size)) {
00407             *ptr++ = socket->read_data[i];
00408             i++;
00409         }
00410 
00411         debug_if(ism_debug, "Copied i bytes=%d, vs %d requestd\r\n", i, size);
00412         recv += i;
00413 
00414         if (i >= socket->read_data_size) {
00415             /* All the storeed data has been read, reset buffer */
00416             memset(socket->read_data, 0, sizeof(socket->read_data));
00417             socket->read_data_size = 0;
00418             debug_if(ism_debug, "Socket_recv buffer reset\r\n");
00419         } else {
00420             /*  In case there is remaining data in buffer, update socket content
00421              *  For now by shift copy of all data (not very efficient to be
00422              *  revised */
00423             while (i < socket->read_data_size) {
00424                 socket->read_data[i - size] = socket->read_data[i];
00425                 i++;
00426             }
00427 
00428             socket->read_data_size -= size;
00429         }
00430     } else {
00431         debug_if(ism_debug, "Nothing in buffer\r\n");
00432     }
00433 
00434     debug_if(ism_debug, "[socket_recv]read_datasize=%d, recv=%d\r\n", socket->read_data_size, recv);
00435     _mutex.unlock();
00436 
00437     if (recv > 0) {
00438         return recv;
00439     } else {
00440         debug_if(ism_debug, "sock_recv returns WOULD BLOCK\r\n");
00441         return NSAPI_ERROR_WOULD_BLOCK;
00442     }
00443 }
00444 
00445 int ISM43362Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
00446 {
00447     _mutex.lock();
00448     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00449 
00450     if (socket->connected && socket->addr != addr) {
00451         _ism.setTimeout(ISM43362_MISC_TIMEOUT);
00452         if (!_ism.close(socket->id)) {
00453             debug_if(ism_debug, "socket_send ERROR\r\n");
00454             _mutex.unlock();
00455             return NSAPI_ERROR_DEVICE_ERROR;
00456         }
00457         socket->connected = false;
00458         _ids[socket->id] = false;
00459         _socket_obj[socket->id] = 0;
00460     }
00461 
00462     if (!socket->connected) {
00463         int err = socket_connect_nolock(socket, addr);
00464         if (err < 0) {
00465             _mutex.unlock();
00466             return err;
00467         }
00468         socket->addr = addr;
00469     }
00470 
00471     int ret = socket_send_nolock(socket, data, size);
00472 
00473     _mutex.unlock();
00474 
00475     return ret;
00476 }
00477 
00478 int ISM43362Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
00479 {
00480     int ret = socket_recv(handle, data, size);
00481     _mutex.lock();
00482     if ((ret >= 0) && addr) {
00483         struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00484         *addr = socket->addr;
00485     }
00486     _mutex.unlock();
00487     return ret;
00488 }
00489 
00490 void ISM43362Interface::socket_attach(void *handle, void (*cb)(void *), void *data)
00491 {
00492     _mutex.lock();
00493     struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
00494     _cbs[socket->id].callback = cb;
00495     _cbs[socket->id].data = data;
00496     _mutex.unlock();
00497 }
00498 
00499 void ISM43362Interface::event() {
00500     for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
00501         if (_cbs[i].callback) {
00502             _cbs[i].callback(_cbs[i].data);
00503         }
00504     }
00505 }