Murata Type YD Wi-Fi driver
Dependents: easy-connect-type-yd
Diff: TypeYDInterface.cpp
- 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); + } +} +