Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

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