Murata Type YD Wi-Fi driver

Dependents:   easy-connect-type-yd

Revision:
0:35a2186cf186
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TypeYDInterface.cpp	Wed Jul 12 10:49:10 2017 +0000
@@ -0,0 +1,650 @@
+/* Murata Type-YD implementation of NetworkInterfaceAPI
+ * Copyright (c) 2017 Murat Manufacturing CO., LTD.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include "TypeYDInterface.h"
+#include "SNICInterface/Socket/SNIC_Socket.h"
+#include "SNICInterface/Socket/Endpoint.h"
+#include "SNICInterface/Socket/SNIC_UDPSocket.h"
+#include "SNICInterface/Socket/TCPSocketConnection.h"
+#include "SNICInterface/Socket/TCPSocketServer.h"
+
+#include "mbed.h"
+#include "mbed-trace/mbed_trace.h"
+#define TRACE_GROUP "SNIC"
+
+//#define USE_DYNAMIC_CAST
+
+// socket structure
+struct managed_socket {
+    nsapi_protocol_t proto;
+    bool connected;
+    SnicSocket *snic_socket;
+    void (*callback)(void *);
+    void *data;
+};
+
+
+// TypeYDInterface implementation
+TypeYDInterface::TypeYDInterface(PinName tx, PinName rx, PinName cts, PinName rts, PinName reset, PinName alarm, int baud)
+    : _snic(tx, rx, cts, rts, reset, alarm, baud)
+{
+}
+
+int TypeYDInterface::init()
+{
+    int ret = _snic.init();
+    if (ret == 0) {
+        tagWIFI_STATUS_T status;
+        _snic.getWifiStatus(&status);
+        memcpy(mac_address, status.mac_address, sizeof(mac_address));
+        sprintf(str_macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
+                mac_address[0], mac_address[1], mac_address[2],
+                mac_address[3], mac_address[4], mac_address[5]); 
+
+        ret = _snic.wifi_softap_off();
+        if (ret != 0) {
+            tr_error("wifi off error");
+        }
+    }
+    return ret;
+}
+
+int TypeYDInterface::getFWVersion(unsigned char *version, int length)
+{
+    int ret = _snic.getFWVersion(version, &length);
+    return ret;
+}
+
+int TypeYDInterface::connect()
+{
+    int ret;
+    
+    if( _snic.disconnect() != 0 ) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    int ssid_length = strlen(ap_ssid);
+    int pass_length = strlen(ap_pass);
+
+    if (_snic.connect(ap_ssid, ssid_length, ap_esec, ap_pass, pass_length) != 0) {
+        ret = NSAPI_ERROR_NO_CONNECTION;
+    }
+    else if (_snic.setIPConfig(true) != 0) {
+        ret = NSAPI_ERROR_DHCP_FAILURE;
+    }
+    else {
+        ret = NSAPI_ERROR_OK;
+    }
+
+    return ret;
+}
+
+
+int TypeYDInterface::connect(const char *ssid, const char *pass, nsapi_security_t security,
+                                        uint8_t channel)
+{
+    int ret;
+
+    if (channel != 0) {
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    set_credentials(ssid, pass, security);
+    int ssid_length = strlen(ap_ssid);
+    int pass_length = strlen(ap_pass);
+#if 0
+    int repeat = 0;
+    bool bFound = false;
+    do {
+        tr_info("scan...%d\n", repeat);
+        WiFiAccessPoint res[10];
+        ret = scan(res,10);
+        if (ret < 0) {
+            tr_info("scan fail %d\n",ret);
+        }
+        else {
+            tr_info("scan result = %d\n", ret);
+            for (int i = 0; i < ret; i++) {
+                tr_info("ssid        :%s\n", res[i].get_ssid());
+                tr_info("channel     :%d\n", res[i].get_channel());
+                if (strcmp(ap_ssid, res[i].get_ssid()) == 0) {
+                    bFound = true;
+                    tr_info("-------- BSS ---------\n");
+                    tr_info("ssid        :%s\n", res[i].get_ssid());
+                    tr_info("channel     :%d\n", res[i].get_channel());
+                    tr_info("rssi        :%d\n", res[i].get_rssi());
+                    tr_info("security    :%d\n", res[i].get_security());
+                    const uint8_t *bssid = res[i].get_bssid();
+                    tr_info("bssid       :%02x-%02x-%02x-%02x-%02x-%02x\n",
+                           bssid[0],bssid[1],bssid[2],
+                           bssid[3],bssid[4],bssid[5]);
+                    break;
+                }
+            }
+        } 
+    }while((bFound == false) && (repeat++ < 10));
+#endif
+    do {
+        wait(0.5);
+        if( _snic.disconnect() != 0 ) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        wait(0.5);
+
+        /*
+        ret = _snic.getWifiStatus(&status);
+        if (ret == 0) {
+            printf("status:%02x\n", status.status);
+            printf("mac   :%02x-%02x-%02x-%02x-%02x-%02x\n",
+                   status.mac_address[0],status.mac_address[1],status.mac_address[2],
+                   status.mac_address[3],status.mac_address[4],status.mac_address[5]);
+        }*/
+        tr_info("TryConnect\r\n");
+
+        if (_snic.connect(ap_ssid, ssid_length, ap_esec, ap_pass, pass_length) != 0) {
+            ret = NSAPI_ERROR_NO_CONNECTION;
+        }
+        else if (_snic.setIPConfig(true) != 0) {
+            ret = NSAPI_ERROR_DHCP_FAILURE;
+        }
+        else {
+            ret = NSAPI_ERROR_OK;
+        }
+    } while (ret != NSAPI_ERROR_OK);
+    
+    return ret;
+}
+
+
+int TypeYDInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
+{
+    ap_esec = e_SEC_WPA2_MIXED;
+    switch(security) {
+    case    NSAPI_SECURITY_NONE:      /*!< open access point */
+        ap_esec = e_SEC_OPEN;
+        break;
+    case    NSAPI_SECURITY_WEP:       /*!< phrase conforms to WEP */
+        ap_esec = e_SEC_WEP;
+        break;
+    case    NSAPI_SECURITY_WPA:       /*!< phrase conforms to WPA */
+        ap_esec = e_SEC_WPA_TKIP;
+        break;
+    case    NSAPI_SECURITY_WPA2:      /*!< phrase conforms to WPA2 */
+        ap_esec = e_SEC_WPA2_MIXED;
+        break;
+    case    NSAPI_SECURITY_WPA_WPA2:  /*!< phrase conforms to WPA/WPA2 */
+        ap_esec = e_SEC_WPA2_MIXED;
+        break;
+    default:
+        break;
+    }
+
+    strncpy(ap_ssid, ssid, sizeof(ap_ssid));
+    ap_ssid[sizeof(ap_ssid)-1] = 0;
+
+    strncpy(ap_pass, pass, sizeof(ap_pass));
+    ap_pass[sizeof(ap_pass)-1] = 0;
+
+    return 0;
+}
+
+int TypeYDInterface::set_channel(uint8_t channel)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int TypeYDInterface::disconnect()
+{
+    if (!_snic.disconnect()) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+const char *TypeYDInterface::get_ip_address()
+{
+    return _snic.getIPAddress();
+}
+
+const char *TypeYDInterface::get_mac_address()
+{
+
+    return (const char*)str_macaddr;
+}
+
+const char *TypeYDInterface::get_gateway()
+{
+    return _snic.getGatewayAddress();
+}
+
+const char *TypeYDInterface::get_netmask()
+{
+    return _snic.getSubnetAddress();
+}
+
+int8_t TypeYDInterface::get_rssi()
+{
+    signed char rssi;
+    _snic.getRssi(&rssi);
+
+    return (int8_t)rssi;
+}
+
+static volatile int _scan_wait = 0;
+static WiFiAccessPoint *_scan_results = 0; 
+static int _scan_count;
+static int _scan_limit;
+static void scan_results_callback(tagSCAN_RESULT_T *scan_result)
+{
+    nsapi_wifi_ap_t ap;
+
+    if (_scan_count < _scan_limit) {
+        memcpy(ap.ssid, scan_result->ssid, 33);
+        memcpy(ap.bssid, scan_result->bssid, 6);
+        switch(scan_result->security) {
+        case    e_SEC_OPEN:
+            ap.security = NSAPI_SECURITY_NONE;
+            break;
+        case    e_SEC_WEP:
+            ap.security = NSAPI_SECURITY_WEP;
+            break;
+        case    e_SEC_WPA_TKIP:
+            ap.security = NSAPI_SECURITY_WPA;
+            break;
+        case    e_SEC_WPA2_AES:
+            ap.security = NSAPI_SECURITY_WPA2;
+            break;
+        case    e_SEC_WPA2_MIXED:
+            ap.security = NSAPI_SECURITY_WPA_WPA2;
+            break;
+        case    e_SEC_WPA_AES:
+            ap.security = NSAPI_SECURITY_WPA;
+            break;
+        default:
+            ap.security = NSAPI_SECURITY_UNKNOWN;
+            break;
+        }
+        ap.rssi    = scan_result->rssi;
+        ap.channel = scan_result->channel;
+        _scan_results[_scan_count++] = WiFiAccessPoint(ap);
+    }
+    
+    if (scan_result->is_complete == 0) _scan_wait = 1;
+}
+
+int TypeYDInterface::scan(WiFiAccessPoint *res, unsigned count)
+{
+    _scan_results = res;
+    _scan_limit = count;
+    _scan_count = 0;
+    int ret = _snic.scan(NULL, NULL, scan_results_callback);
+    if (ret == 0) {
+        _scan_wait = 0;
+        while(_scan_wait == 0) {
+            wait(1);
+        }
+    }
+
+    return _scan_count;
+}
+
+nsapi_error_t TypeYDInterface::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version)
+{
+    int ret;
+    unsigned char ipaddr[4];
+
+    ret = _snic.resolveName(name, ipaddr);
+    if (ret != 0) {
+        tr_error("DNS failure\n");
+        return NSAPI_ERROR_DNS_FAILURE;
+    }
+
+    tr_info("DNS res:%u.%u.%u.%u\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+
+    address->set_ip_bytes(ipaddr, NSAPI_IPv4);
+    
+    return NSAPI_ERROR_OK;
+}
+
+int TypeYDInterface::socket_open(void **handle, nsapi_protocol_t proto)
+{
+    tr_info("socket_open"); 
+ 
+    struct managed_socket *socket = new struct managed_socket;
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    
+    socket->proto = proto;
+    socket->connected = false;
+    socket->snic_socket = NULL;
+    socket->callback = NULL;
+    socket->data = NULL;
+    *handle = socket;
+
+    return 0;
+}
+
+int TypeYDInterface::socket_close(void *handle)
+{
+    struct managed_socket *socket = (struct managed_socket *)handle;
+
+    tr_info("socket_close"); 
+
+    int err = 0;
+    if (socket->snic_socket != NULL) {
+        err = socket->snic_socket->close();
+        delete socket->snic_socket;
+    }
+ 
+    delete socket;
+    return err;
+}
+
+int TypeYDInterface::socket_bind(void *handle, const SocketAddress &address)
+{
+    int ret;
+    uint16_t port;
+
+    struct managed_socket *socket = (struct managed_socket *)handle;
+
+    port = address.get_port();
+    if (port == 0) {
+#if defined(ST)
+        srand(HAL_GetTick());
+#else
+        srand(0);
+#endif
+        port = (rand() % 10240) + 20000;
+    }
+    
+    tr_info("socket_bind IP:%s:%u\n", address.get_ip_address(), port);
+
+    if (socket->proto == NSAPI_UDP) {
+        SnicUDPSocket *udp = new SnicUDPSocket();
+        socket->snic_socket = udp;
+        if (socket->snic_socket == NULL) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        socket->snic_socket->socket_attach(socket->callback, socket->data);
+        ret = udp->bind(port);
+        if (ret != 0) {
+            tr_info("bind err %d\n", ret);
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        socket->connected = true;
+    }
+    else {
+        TCPSocketConnection *tcp = new TCPSocketConnection();
+        socket->snic_socket = tcp;
+        if (socket->snic_socket == NULL) {
+            tr_error("tcp bind err\n");
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        socket->snic_socket->socket_attach(socket->callback, socket->data);
+        ret = tcp->bind(port);
+        if (ret != 0) {
+            tr_error("tcp bind err %d\n", ret);
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        socket->connected = false;
+    }
+
+    return ret;
+}
+
+int TypeYDInterface::socket_listen(void *handle, int backlog)
+{
+    int ret;
+    struct managed_socket *socket = (struct managed_socket *)handle;
+
+    if (socket->proto == NSAPI_UDP) {
+        tr_info("unsupport:socket_listen\n");
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+    else {
+        TCPSocketServer* tcp;
+        #ifdef USE_DYNAMIC_CAST
+        tcp = dynamic_cast<TCPSocketServer*>(socket->snic_socket);
+        if (tcp == NULL){
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        #else
+        tcp = (TCPSocketServer*)(socket->snic_socket);
+        #endif
+        ret = tcp->listen(backlog);
+        if (ret != 0) {
+            tr_error("tcp listen err %d\n",ret);
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+    }
+    return 0;
+}
+
+int TypeYDInterface::socket_connect(void *handle, const SocketAddress &addr)
+{
+    struct managed_socket *socket = (struct managed_socket *)handle;
+    
+    //tr_info("socket_connect(%d)\n",socket->proto);
+
+    if (socket->proto == NSAPI_UDP) {
+        tr_error("un sup:socket_connect");
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+    else {
+        TCPSocketConnection *tcp;
+        if (socket->snic_socket == NULL) {
+            tcp = new TCPSocketConnection();
+            socket->snic_socket = tcp;
+            if (socket->snic_socket == NULL) {
+                tr_error("tcp connect err\n");
+                return NSAPI_ERROR_DEVICE_ERROR;
+            }
+            socket->snic_socket->socket_attach(socket->callback, socket->data);
+        }
+        else {
+            #ifdef USE_DYNAMIC_CAST
+            tcp = dynamic_cast<TCPSocketConnection*>(socket->snic_socket);
+            if (tcp == NULL){
+                return NSAPI_ERROR_DEVICE_ERROR;
+            }
+            #else
+            tcp = (TCPSocketConnection*)(socket->snic_socket);
+            #endif
+        }
+
+        tr_info("socket_connect IP:%s:%u\n", addr.get_ip_address(), addr.get_port());
+        if (tcp->connect(addr.get_ip_address(), addr.get_port()) != 0) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+    }
+
+    //tr_info("socket_connect success\n");
+    socket->connected = true;
+    return 0;
+}
+    
+int TypeYDInterface::socket_accept(void *handle, void **client_socket, SocketAddress *addr)
+{
+    int ret;
+    struct managed_socket *server = (struct managed_socket *)handle;
+    
+    if (server->proto == NSAPI_UDP) {
+        tr_info("unsupport:accept");
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+    else {
+        TCPSocketServer *tcp;
+        #ifdef USE_DYNAMIC_CAST
+        tcp = dynamic_cast<TCPSocketServer*>(server->snic_socket);
+        if (tcp == NULL){
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        #else
+        tcp = (TCPSocketServer*)(server->snic_socket);
+        #endif
+        socket_open(client_socket, NSAPI_TCP);
+        struct managed_socket *client = (struct managed_socket *)*client_socket;
+        TCPSocketConnection *conn = new TCPSocketConnection();
+        client->snic_socket = conn;
+        if (client->snic_socket == NULL) {
+            tr_error("tcp accept err\n");
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        ret = tcp->accept(*conn, addr);
+        if (ret != 0) {
+            tr_error("tcp listen err %d",ret);
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+    }
+    return 0;
+}
+
+int TypeYDInterface::socket_send(void *handle, const void *data, unsigned size)
+{
+    struct managed_socket *socket = (struct managed_socket *)handle;
+
+    //tr_info("socket_send");
+
+    if (socket->proto != NSAPI_TCP) {
+        tr_error("un sup:socket_send");
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    #ifdef USE_DYNAMIC_CAST
+    TCPSocketConnection *tcp = dynamic_cast<TCPSocketConnection*>(socket->snic_socket);
+    if ((tcp == NULL) || ) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+    #else
+    TCPSocketConnection *tcp = (TCPSocketConnection*)(socket->snic_socket);
+    #endif
+    if (tcp->send((char*)data, size) < 0) {
+        tr_error("socket_send");
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    return size;
+}
+
+int TypeYDInterface::socket_recv(void *handle, void *data, unsigned size)
+{
+    struct managed_socket *socket = (struct managed_socket *)handle;
+
+    //tr_info("socket_recv");
+
+    if (socket->proto != NSAPI_TCP) {
+        tr_error("not sup:socket_recv");
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    int recv;
+    #ifdef USE_DYNAMIC_CAST
+    TCPSocketConnection *tcp = dynamic_cast<TCPSocketConnection*>(socket->snic_socket);
+    if (tcp == NULL){
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+    #else
+    TCPSocketConnection *tcp = (TCPSocketConnection*)(socket->snic_socket);
+    #endif
+    if ((recv = tcp->receive((char*)data, size)) < 0) {
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    return recv;
+}
+
+int TypeYDInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
+{
+    struct managed_socket *socket = (struct managed_socket *)handle;
+    int ret;
+
+    //tr_info("socket_sendto");
+
+    if (!socket->connected) {
+        int err = socket_connect(socket, addr);
+        if (err < 0) {
+            return err;
+        }
+    }
+
+    if (socket->proto == NSAPI_UDP) {
+        Endpoint remote;
+        remote.set_address(addr.get_ip_address(), addr.get_port());
+        #ifdef USE_DYNAMIC_CAST
+        SnicUDPSocket *udp = dynamic_cast<SnicUDPSocket*>(socket->snic_socket);
+        if (udp == NULL) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        #else
+        SnicUDPSocket *udp = (SnicUDPSocket*)(socket->snic_socket);
+        #endif
+        ret = udp->sendTo(remote, (char*)data, size);
+    }
+    else {
+        tr_error("TCP sendto\n");
+        return -1;
+    }
+
+    return ret;
+}
+
+int TypeYDInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
+{
+    struct managed_socket *socket = (struct managed_socket *)handle;
+    int recv;
+
+    //tr_info("socket_recvfrom");
+        
+    if (socket->proto == NSAPI_UDP) {
+        Endpoint remote;
+        #ifdef USE_DYNAMIC_CAST
+        SnicUDPSocket *udp = dynamic_cast<SnicUDPSocket*>(socket->snic_socket);
+        if (udp == NULL) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        #else
+        SnicUDPSocket *udp = (SnicUDPSocket*)(socket->snic_socket);
+        #endif
+        recv = udp->receiveFrom(remote, (char*)data, size);
+        if (recv > 0) {
+            addr->set_ip_address(remote.get_address());
+            addr->set_port(remote.get_port());
+        }
+    }
+    else {
+        tr_error("TCP recvfrom\n");
+        return -1;
+    }
+
+    return recv;
+}
+
+
+void TypeYDInterface::socket_attach(void *handle, void (*callback)(void *), void *data)
+{
+    struct managed_socket *socket = (struct managed_socket *)handle;    
+
+    //tr_info("socket_attach");
+    socket->callback = callback;
+    socket->data = data;
+    if (socket->snic_socket != NULL) {
+        socket->snic_socket->socket_attach(callback, data);
+    }
+}
+