NetworkSocketAPI / BSDInterface

Dependents:   BSDInterfaceTests HelloBSDInterface

Files at this revision

API Documentation at this revision

Comitter:
geky
Date:
Sun Feb 28 02:00:46 2016 +0000
Child:
1:29c61c1420c8
Commit message:
Created stubs for BSDInterface

Changed in this revision

BSDInterface.cpp Show annotated file Show diff for this revision Revisions of this file
BSDInterface.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BSDInterface.cpp	Sun Feb 28 02:00:46 2016 +0000
@@ -0,0 +1,248 @@
+/* LWIP implementation of NetworkInterfaceAPI
+ * Copyright (c) 2015 ARM Limited
+ *
+ * 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 "LWIPInterface.h"
+
+#include "mbed.h"
+#include "lwip/inet.h"
+#include "lwip/netif.h"
+#include "lwip/dhcp.h"
+#include "lwip/tcpip.h"
+#include "lwip/sockets.h"
+#include "lwip/netdb.h"
+#include "netif/etharp.h"
+#include "eth_arch.h"
+
+
+#define LWIP_TIMEOUT 15000
+
+
+/* TCP/IP and Network Interface Initialisation */
+static LWIPInterface *iface = 0;
+static struct netif netif;
+
+static char mac_addr[NS_MAC_SIZE] = "\0";
+
+static Semaphore tcpip_inited(0);
+static Semaphore netif_linked(0);
+static Semaphore netif_up(0);
+
+static void tcpip_init_done(void *) {
+    tcpip_inited.release();
+}
+
+static void netif_link_callback(struct netif *netif) {
+    if (netif_is_link_up(netif)) {
+        netif_linked.release();
+    }
+}
+
+static void netif_status_callback(struct netif *netif) {
+    if (netif_is_up(netif)) {
+        iface->setIPAddress  (inet_ntoa(netif->ip_addr));
+        iface->setNetworkMask(inet_ntoa(netif->netmask));
+        iface->setGateway    (inet_ntoa(netif->gw));
+        netif_up.release();
+    }
+}
+
+static void init_netif(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw) {
+    tcpip_init(tcpip_init_done, NULL);
+    tcpip_inited.wait();
+    
+    memset((void*) &netif, 0, sizeof(netif));
+    netif_add(&netif, ipaddr, netmask, gw, NULL, eth_arch_enetif_init, tcpip_input);
+    netif_set_default(&netif);
+    
+    netif_set_link_callback  (&netif, netif_link_callback);
+    netif_set_status_callback(&netif, netif_status_callback);
+}
+
+static void set_mac_address(void) {
+#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
+    snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", MBED_MAC_ADDR_0, MBED_MAC_ADDR_1, MBED_MAC_ADDR_2,
+             MBED_MAC_ADDR_3, MBED_MAC_ADDR_4, MBED_MAC_ADDR_5);
+#else
+    char mac[6];
+    mbed_mac_address(mac);
+    snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+#endif
+}
+
+
+// LWIPInterface implementation
+int32_t LWIPInterface::connect()
+{
+    // Only one instance of LWIP is currently supported
+    if (iface) {
+        return NS_ERROR_DEVICE_ERROR;
+    }
+
+    iface = this;
+
+    // Set up network
+    set_mac_address();
+
+    if (getDHCP()) {
+        init_netif(0, 0, 0);
+    } else {
+        ip_addr_t ip_n, mask_n, gateway_n;
+        inet_aton(getIPAddress(), &ip_n);
+        inet_aton(getNetworkMask(), &mask_n);
+        inet_aton(getGateway(), &gateway_n);
+        init_netif(&ip_n, &mask_n, &gateway_n);
+    }
+
+    // Connect to network
+    eth_arch_enable_interrupts();
+
+    if (getDHCP()) {
+        dhcp_start(&netif);
+        
+        // Wait for an IP Address
+        // -1: error, 0: timeout
+        if (netif_up.wait(LWIP_TIMEOUT) < 0) {
+            return NS_ERROR_TIMEOUT;
+        }
+    } else {
+        netif_set_up(&netif);
+        
+        // Wait for the link up
+        if (netif_linked.wait(LWIP_TIMEOUT) < 0) {
+            return NS_ERROR_TIMEOUT;
+        }
+    }
+
+    return 0;
+}
+
+int32_t LWIPInterface::disconnect()
+{
+    if (getDHCP()) {
+        dhcp_release(&netif);
+        dhcp_stop(&netif);
+    } else {
+        netif_set_down(&netif);
+    }
+    
+    eth_arch_disable_interrupts();
+    
+    return 0;
+}
+
+const char *LWIPInterface::getMACAddress() 
+{
+    return mac_addr;
+}
+
+
+/** LWIPSocket class
+ *  Implementation of the TCP SocketInterface for LWIP
+ */
+class LWIPSocket : public SocketInterface
+{
+public:
+    LWIPSocket(int fd) : fd(fd) {}
+
+    // Implementation of SocketInterface
+    virtual int32_t open(const char *ip, uint16_t port);
+    virtual int32_t close();
+
+    virtual int32_t send(const void *data, uint32_t size);
+    virtual int32_t recv(void *data, uint32_t size);
+
+    int fd;
+};
+
+
+SocketInterface *LWIPInterface::createSocket(socket_protocol_t proto)
+{
+    int type = (proto == SOCK_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+    int fd = lwip_socket(AF_INET, type, 0);
+
+    if (fd < 0) {
+        return 0;
+    }
+
+    return new LWIPSocket(fd);
+}
+
+void LWIPInterface::destroySocket(SocketInterface *siface)
+{
+    LWIPSocket *socket = (LWIPSocket *)siface;
+    lwip_close(socket->fd);
+
+    delete socket;
+}
+
+
+// TCP SocketInterface implementation
+int32_t LWIPSocket::open(const char *ip, uint16_t port)
+{
+    struct sockaddr_in host;
+    memset(&host, 0, sizeof host);
+    inet_aton(ip, &host.sin_addr);
+    host.sin_family = AF_INET;
+    host.sin_port = htons(port);
+
+    if (lwip_connect(fd, (const struct sockaddr *)&host, sizeof host) < 0) {
+        return NS_ERROR_NO_CONNECTION;
+    }
+
+    return 0;
+}
+
+int32_t LWIPSocket::close()
+{
+    return 0;
+}
+
+int32_t LWIPSocket::send(const void *voiddata, uint32_t size)
+{
+    uint8_t *data = (uint8_t *)voiddata;
+    uint32_t writtenLen = 0;
+
+    while (writtenLen < size) {
+        int ret = lwip_send(fd, data + writtenLen, size - writtenLen, 0);
+
+        if (ret > 0) {
+            writtenLen += ret;
+        } else if (ret == 0) {
+            return NS_ERROR_NO_CONNECTION;
+        } else {
+            return NS_ERROR_DEVICE_ERROR;
+        }
+    }
+
+    return 0;
+}
+
+int32_t LWIPSocket::recv(void *data, uint32_t size)
+{
+    int ret = lwip_recv(fd, data, size, MSG_DONTWAIT);
+
+    if (ret > 0) {
+        return ret;
+    } else if (ret == 0) {
+        return NS_ERROR_NO_CONNECTION;
+    } else if (ret == -1) {
+        return 0;
+    } else {
+        return NS_ERROR_DEVICE_ERROR;
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BSDInterface.h	Sun Feb 28 02:00:46 2016 +0000
@@ -0,0 +1,43 @@
+/* LWIP implementation of NetworkInterfaceAPI
+ * Copyright (c) 2015 ARM Limited
+ *
+ * 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.
+ */
+
+#ifndef LWIP_INTERFACE_H
+#define LWIP_INTERFACE_H
+
+#include "EthernetInterface.h"
+#include "rtos.h"
+#include "lwip/netif.h"
+
+
+/** LWIPInterface class
+ *  Implementation of the NetworkInterface for LWIP
+ */
+class LWIPInterface : public EthernetInterface
+{
+public:
+    // Implementation of EthernetInterface
+    virtual int32_t connect();
+    virtual int32_t disconnect();
+
+    // Implementation of NetworkInterface
+    virtual const char *getMACAddress();
+
+    virtual SocketInterface *createSocket(socket_protocol_t proto);
+    virtual void destroySocket(SocketInterface *socket);
+};
+
+
+#endif