A version of LWIP, provided for backwards compatibility.

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

Committer:
root@mbed.org
Date:
Tue May 08 15:32:10 2012 +0100
Revision:
0:5e1631496985
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
root@mbed.org 0:5e1631496985 1 /**
root@mbed.org 0:5e1631496985 2 * @file
root@mbed.org 0:5e1631496985 3 * Ethernet Interface Skeleton
root@mbed.org 0:5e1631496985 4 *
root@mbed.org 0:5e1631496985 5 */
root@mbed.org 0:5e1631496985 6
root@mbed.org 0:5e1631496985 7 /*
root@mbed.org 0:5e1631496985 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
root@mbed.org 0:5e1631496985 9 * All rights reserved.
root@mbed.org 0:5e1631496985 10 *
root@mbed.org 0:5e1631496985 11 * Redistribution and use in source and binary forms, with or without modification,
root@mbed.org 0:5e1631496985 12 * are permitted provided that the following conditions are met:
root@mbed.org 0:5e1631496985 13 *
root@mbed.org 0:5e1631496985 14 * 1. Redistributions of source code must retain the above copyright notice,
root@mbed.org 0:5e1631496985 15 * this list of conditions and the following disclaimer.
root@mbed.org 0:5e1631496985 16 * 2. Redistributions in binary form must reproduce the above copyright notice,
root@mbed.org 0:5e1631496985 17 * this list of conditions and the following disclaimer in the documentation
root@mbed.org 0:5e1631496985 18 * and/or other materials provided with the distribution.
root@mbed.org 0:5e1631496985 19 * 3. The name of the author may not be used to endorse or promote products
root@mbed.org 0:5e1631496985 20 * derived from this software without specific prior written permission.
root@mbed.org 0:5e1631496985 21 *
root@mbed.org 0:5e1631496985 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
root@mbed.org 0:5e1631496985 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
root@mbed.org 0:5e1631496985 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
root@mbed.org 0:5e1631496985 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
root@mbed.org 0:5e1631496985 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
root@mbed.org 0:5e1631496985 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
root@mbed.org 0:5e1631496985 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
root@mbed.org 0:5e1631496985 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
root@mbed.org 0:5e1631496985 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
root@mbed.org 0:5e1631496985 31 * OF SUCH DAMAGE.
root@mbed.org 0:5e1631496985 32 *
root@mbed.org 0:5e1631496985 33 * This file is part of the lwIP TCP/IP stack.
root@mbed.org 0:5e1631496985 34 *
root@mbed.org 0:5e1631496985 35 * Author: Adam Dunkels <adam@sics.se>
root@mbed.org 0:5e1631496985 36 *
root@mbed.org 0:5e1631496985 37 */
root@mbed.org 0:5e1631496985 38
root@mbed.org 0:5e1631496985 39 /*
root@mbed.org 0:5e1631496985 40 * This file is a skeleton for developing Ethernet network interface
root@mbed.org 0:5e1631496985 41 * drivers for lwIP. Add code to the low_level functions and do a
root@mbed.org 0:5e1631496985 42 * search-and-replace for the word "ethernetif" to replace it with
root@mbed.org 0:5e1631496985 43 * something that better describes your network interface.
root@mbed.org 0:5e1631496985 44 */
root@mbed.org 0:5e1631496985 45
root@mbed.org 0:5e1631496985 46 #include "lwip/opt.h"
root@mbed.org 0:5e1631496985 47
root@mbed.org 0:5e1631496985 48 #if 0 /* don't build, this is only a skeleton, see previous comment */
root@mbed.org 0:5e1631496985 49
root@mbed.org 0:5e1631496985 50 #include "lwip/def.h"
root@mbed.org 0:5e1631496985 51 #include "lwip/mem.h"
root@mbed.org 0:5e1631496985 52 #include "lwip/pbuf.h"
root@mbed.org 0:5e1631496985 53 #include "lwip/sys.h"
root@mbed.org 0:5e1631496985 54 #include <lwip/stats.h>
root@mbed.org 0:5e1631496985 55 #include <lwip/snmp.h>
root@mbed.org 0:5e1631496985 56 #include "netif/etharp.h"
root@mbed.org 0:5e1631496985 57 #include "netif/ppp_oe.h"
root@mbed.org 0:5e1631496985 58
root@mbed.org 0:5e1631496985 59 /* Define those to better describe your network interface. */
root@mbed.org 0:5e1631496985 60 #define IFNAME0 'e'
root@mbed.org 0:5e1631496985 61 #define IFNAME1 'n'
root@mbed.org 0:5e1631496985 62
root@mbed.org 0:5e1631496985 63 /**
root@mbed.org 0:5e1631496985 64 * Helper struct to hold private data used to operate your ethernet interface.
root@mbed.org 0:5e1631496985 65 * Keeping the ethernet address of the MAC in this struct is not necessary
root@mbed.org 0:5e1631496985 66 * as it is already kept in the struct netif.
root@mbed.org 0:5e1631496985 67 * But this is only an example, anyway...
root@mbed.org 0:5e1631496985 68 */
root@mbed.org 0:5e1631496985 69 struct ethernetif {
root@mbed.org 0:5e1631496985 70 struct eth_addr *ethaddr;
root@mbed.org 0:5e1631496985 71 /* Add whatever per-interface state that is needed here. */
root@mbed.org 0:5e1631496985 72 };
root@mbed.org 0:5e1631496985 73
root@mbed.org 0:5e1631496985 74 /* Forward declarations. */
root@mbed.org 0:5e1631496985 75 static void ethernetif_input(struct netif *netif);
root@mbed.org 0:5e1631496985 76
root@mbed.org 0:5e1631496985 77 /**
root@mbed.org 0:5e1631496985 78 * In this function, the hardware should be initialized.
root@mbed.org 0:5e1631496985 79 * Called from ethernetif_init().
root@mbed.org 0:5e1631496985 80 *
root@mbed.org 0:5e1631496985 81 * @param netif the already initialized lwip network interface structure
root@mbed.org 0:5e1631496985 82 * for this ethernetif
root@mbed.org 0:5e1631496985 83 */
root@mbed.org 0:5e1631496985 84 static void
root@mbed.org 0:5e1631496985 85 low_level_init(struct netif *netif)
root@mbed.org 0:5e1631496985 86 {
root@mbed.org 0:5e1631496985 87 struct ethernetif *ethernetif = netif->state;
root@mbed.org 0:5e1631496985 88
root@mbed.org 0:5e1631496985 89 /* set MAC hardware address length */
root@mbed.org 0:5e1631496985 90 netif->hwaddr_len = ETHARP_HWADDR_LEN;
root@mbed.org 0:5e1631496985 91
root@mbed.org 0:5e1631496985 92 /* set MAC hardware address */
root@mbed.org 0:5e1631496985 93 netif->hwaddr[0] = ;
root@mbed.org 0:5e1631496985 94 ...
root@mbed.org 0:5e1631496985 95 netif->hwaddr[5] = ;
root@mbed.org 0:5e1631496985 96
root@mbed.org 0:5e1631496985 97 /* maximum transfer unit */
root@mbed.org 0:5e1631496985 98 netif->mtu = 1500;
root@mbed.org 0:5e1631496985 99
root@mbed.org 0:5e1631496985 100 /* device capabilities */
root@mbed.org 0:5e1631496985 101 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
root@mbed.org 0:5e1631496985 102 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
root@mbed.org 0:5e1631496985 103
root@mbed.org 0:5e1631496985 104 /* Do whatever else is needed to initialize interface. */
root@mbed.org 0:5e1631496985 105 }
root@mbed.org 0:5e1631496985 106
root@mbed.org 0:5e1631496985 107 /**
root@mbed.org 0:5e1631496985 108 * This function should do the actual transmission of the packet. The packet is
root@mbed.org 0:5e1631496985 109 * contained in the pbuf that is passed to the function. This pbuf
root@mbed.org 0:5e1631496985 110 * might be chained.
root@mbed.org 0:5e1631496985 111 *
root@mbed.org 0:5e1631496985 112 * @param netif the lwip network interface structure for this ethernetif
root@mbed.org 0:5e1631496985 113 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
root@mbed.org 0:5e1631496985 114 * @return ERR_OK if the packet could be sent
root@mbed.org 0:5e1631496985 115 * an err_t value if the packet couldn't be sent
root@mbed.org 0:5e1631496985 116 *
root@mbed.org 0:5e1631496985 117 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
root@mbed.org 0:5e1631496985 118 * strange results. You might consider waiting for space in the DMA queue
root@mbed.org 0:5e1631496985 119 * to become availale since the stack doesn't retry to send a packet
root@mbed.org 0:5e1631496985 120 * dropped because of memory failure (except for the TCP timers).
root@mbed.org 0:5e1631496985 121 */
root@mbed.org 0:5e1631496985 122
root@mbed.org 0:5e1631496985 123 static err_t
root@mbed.org 0:5e1631496985 124 low_level_output(struct netif *netif, struct pbuf *p)
root@mbed.org 0:5e1631496985 125 {
root@mbed.org 0:5e1631496985 126 struct ethernetif *ethernetif = netif->state;
root@mbed.org 0:5e1631496985 127 struct pbuf *q;
root@mbed.org 0:5e1631496985 128
root@mbed.org 0:5e1631496985 129 initiate transfer();
root@mbed.org 0:5e1631496985 130
root@mbed.org 0:5e1631496985 131 #if ETH_PAD_SIZE
root@mbed.org 0:5e1631496985 132 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
root@mbed.org 0:5e1631496985 133 #endif
root@mbed.org 0:5e1631496985 134
root@mbed.org 0:5e1631496985 135 for(q = p; q != NULL; q = q->next) {
root@mbed.org 0:5e1631496985 136 /* Send the data from the pbuf to the interface, one pbuf at a
root@mbed.org 0:5e1631496985 137 time. The size of the data in each pbuf is kept in the ->len
root@mbed.org 0:5e1631496985 138 variable. */
root@mbed.org 0:5e1631496985 139 send data from(q->payload, q->len);
root@mbed.org 0:5e1631496985 140 }
root@mbed.org 0:5e1631496985 141
root@mbed.org 0:5e1631496985 142 signal that packet should be sent();
root@mbed.org 0:5e1631496985 143
root@mbed.org 0:5e1631496985 144 #if ETH_PAD_SIZE
root@mbed.org 0:5e1631496985 145 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
root@mbed.org 0:5e1631496985 146 #endif
root@mbed.org 0:5e1631496985 147
root@mbed.org 0:5e1631496985 148 LINK_STATS_INC(link.xmit);
root@mbed.org 0:5e1631496985 149
root@mbed.org 0:5e1631496985 150 return ERR_OK;
root@mbed.org 0:5e1631496985 151 }
root@mbed.org 0:5e1631496985 152
root@mbed.org 0:5e1631496985 153 /**
root@mbed.org 0:5e1631496985 154 * Should allocate a pbuf and transfer the bytes of the incoming
root@mbed.org 0:5e1631496985 155 * packet from the interface into the pbuf.
root@mbed.org 0:5e1631496985 156 *
root@mbed.org 0:5e1631496985 157 * @param netif the lwip network interface structure for this ethernetif
root@mbed.org 0:5e1631496985 158 * @return a pbuf filled with the received packet (including MAC header)
root@mbed.org 0:5e1631496985 159 * NULL on memory error
root@mbed.org 0:5e1631496985 160 */
root@mbed.org 0:5e1631496985 161 static struct pbuf *
root@mbed.org 0:5e1631496985 162 low_level_input(struct netif *netif)
root@mbed.org 0:5e1631496985 163 {
root@mbed.org 0:5e1631496985 164 struct ethernetif *ethernetif = netif->state;
root@mbed.org 0:5e1631496985 165 struct pbuf *p, *q;
root@mbed.org 0:5e1631496985 166 u16_t len;
root@mbed.org 0:5e1631496985 167
root@mbed.org 0:5e1631496985 168 /* Obtain the size of the packet and put it into the "len"
root@mbed.org 0:5e1631496985 169 variable. */
root@mbed.org 0:5e1631496985 170 len = ;
root@mbed.org 0:5e1631496985 171
root@mbed.org 0:5e1631496985 172 #if ETH_PAD_SIZE
root@mbed.org 0:5e1631496985 173 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
root@mbed.org 0:5e1631496985 174 #endif
root@mbed.org 0:5e1631496985 175
root@mbed.org 0:5e1631496985 176 /* We allocate a pbuf chain of pbufs from the pool. */
root@mbed.org 0:5e1631496985 177 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
root@mbed.org 0:5e1631496985 178
root@mbed.org 0:5e1631496985 179 if (p != NULL) {
root@mbed.org 0:5e1631496985 180
root@mbed.org 0:5e1631496985 181 #if ETH_PAD_SIZE
root@mbed.org 0:5e1631496985 182 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
root@mbed.org 0:5e1631496985 183 #endif
root@mbed.org 0:5e1631496985 184
root@mbed.org 0:5e1631496985 185 /* We iterate over the pbuf chain until we have read the entire
root@mbed.org 0:5e1631496985 186 * packet into the pbuf. */
root@mbed.org 0:5e1631496985 187 for(q = p; q != NULL; q = q->next) {
root@mbed.org 0:5e1631496985 188 /* Read enough bytes to fill this pbuf in the chain. The
root@mbed.org 0:5e1631496985 189 * available data in the pbuf is given by the q->len
root@mbed.org 0:5e1631496985 190 * variable.
root@mbed.org 0:5e1631496985 191 * This does not necessarily have to be a memcpy, you can also preallocate
root@mbed.org 0:5e1631496985 192 * pbufs for a DMA-enabled MAC and after receiving truncate it to the
root@mbed.org 0:5e1631496985 193 * actually received size. In this case, ensure the tot_len member of the
root@mbed.org 0:5e1631496985 194 * pbuf is the sum of the chained pbuf len members.
root@mbed.org 0:5e1631496985 195 */
root@mbed.org 0:5e1631496985 196 read data into(q->payload, q->len);
root@mbed.org 0:5e1631496985 197 }
root@mbed.org 0:5e1631496985 198 acknowledge that packet has been read();
root@mbed.org 0:5e1631496985 199
root@mbed.org 0:5e1631496985 200 #if ETH_PAD_SIZE
root@mbed.org 0:5e1631496985 201 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
root@mbed.org 0:5e1631496985 202 #endif
root@mbed.org 0:5e1631496985 203
root@mbed.org 0:5e1631496985 204 LINK_STATS_INC(link.recv);
root@mbed.org 0:5e1631496985 205 } else {
root@mbed.org 0:5e1631496985 206 drop packet();
root@mbed.org 0:5e1631496985 207 LINK_STATS_INC(link.memerr);
root@mbed.org 0:5e1631496985 208 LINK_STATS_INC(link.drop);
root@mbed.org 0:5e1631496985 209 }
root@mbed.org 0:5e1631496985 210
root@mbed.org 0:5e1631496985 211 return p;
root@mbed.org 0:5e1631496985 212 }
root@mbed.org 0:5e1631496985 213
root@mbed.org 0:5e1631496985 214 /**
root@mbed.org 0:5e1631496985 215 * This function should be called when a packet is ready to be read
root@mbed.org 0:5e1631496985 216 * from the interface. It uses the function low_level_input() that
root@mbed.org 0:5e1631496985 217 * should handle the actual reception of bytes from the network
root@mbed.org 0:5e1631496985 218 * interface. Then the type of the received packet is determined and
root@mbed.org 0:5e1631496985 219 * the appropriate input function is called.
root@mbed.org 0:5e1631496985 220 *
root@mbed.org 0:5e1631496985 221 * @param netif the lwip network interface structure for this ethernetif
root@mbed.org 0:5e1631496985 222 */
root@mbed.org 0:5e1631496985 223 static void
root@mbed.org 0:5e1631496985 224 ethernetif_input(struct netif *netif)
root@mbed.org 0:5e1631496985 225 {
root@mbed.org 0:5e1631496985 226 struct ethernetif *ethernetif;
root@mbed.org 0:5e1631496985 227 struct eth_hdr *ethhdr;
root@mbed.org 0:5e1631496985 228 struct pbuf *p;
root@mbed.org 0:5e1631496985 229
root@mbed.org 0:5e1631496985 230 ethernetif = netif->state;
root@mbed.org 0:5e1631496985 231
root@mbed.org 0:5e1631496985 232 /* move received packet into a new pbuf */
root@mbed.org 0:5e1631496985 233 p = low_level_input(netif);
root@mbed.org 0:5e1631496985 234 /* no packet could be read, silently ignore this */
root@mbed.org 0:5e1631496985 235 if (p == NULL) return;
root@mbed.org 0:5e1631496985 236 /* points to packet payload, which starts with an Ethernet header */
root@mbed.org 0:5e1631496985 237 ethhdr = p->payload;
root@mbed.org 0:5e1631496985 238
root@mbed.org 0:5e1631496985 239 switch (htons(ethhdr->type)) {
root@mbed.org 0:5e1631496985 240 /* IP or ARP packet? */
root@mbed.org 0:5e1631496985 241 case ETHTYPE_IP:
root@mbed.org 0:5e1631496985 242 case ETHTYPE_ARP:
root@mbed.org 0:5e1631496985 243 #if PPPOE_SUPPORT
root@mbed.org 0:5e1631496985 244 /* PPPoE packet? */
root@mbed.org 0:5e1631496985 245 case ETHTYPE_PPPOEDISC:
root@mbed.org 0:5e1631496985 246 case ETHTYPE_PPPOE:
root@mbed.org 0:5e1631496985 247 #endif /* PPPOE_SUPPORT */
root@mbed.org 0:5e1631496985 248 /* full packet send to tcpip_thread to process */
root@mbed.org 0:5e1631496985 249 if (netif->input(p, netif)!=ERR_OK)
root@mbed.org 0:5e1631496985 250 { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
root@mbed.org 0:5e1631496985 251 pbuf_free(p);
root@mbed.org 0:5e1631496985 252 p = NULL;
root@mbed.org 0:5e1631496985 253 }
root@mbed.org 0:5e1631496985 254 break;
root@mbed.org 0:5e1631496985 255
root@mbed.org 0:5e1631496985 256 default:
root@mbed.org 0:5e1631496985 257 pbuf_free(p);
root@mbed.org 0:5e1631496985 258 p = NULL;
root@mbed.org 0:5e1631496985 259 break;
root@mbed.org 0:5e1631496985 260 }
root@mbed.org 0:5e1631496985 261 }
root@mbed.org 0:5e1631496985 262
root@mbed.org 0:5e1631496985 263 /**
root@mbed.org 0:5e1631496985 264 * Should be called at the beginning of the program to set up the
root@mbed.org 0:5e1631496985 265 * network interface. It calls the function low_level_init() to do the
root@mbed.org 0:5e1631496985 266 * actual setup of the hardware.
root@mbed.org 0:5e1631496985 267 *
root@mbed.org 0:5e1631496985 268 * This function should be passed as a parameter to netif_add().
root@mbed.org 0:5e1631496985 269 *
root@mbed.org 0:5e1631496985 270 * @param netif the lwip network interface structure for this ethernetif
root@mbed.org 0:5e1631496985 271 * @return ERR_OK if the loopif is initialized
root@mbed.org 0:5e1631496985 272 * ERR_MEM if private data couldn't be allocated
root@mbed.org 0:5e1631496985 273 * any other err_t on error
root@mbed.org 0:5e1631496985 274 */
root@mbed.org 0:5e1631496985 275 err_t
root@mbed.org 0:5e1631496985 276 ethernetif_init(struct netif *netif)
root@mbed.org 0:5e1631496985 277 {
root@mbed.org 0:5e1631496985 278 struct ethernetif *ethernetif;
root@mbed.org 0:5e1631496985 279
root@mbed.org 0:5e1631496985 280 LWIP_ASSERT("netif != NULL", (netif != NULL));
root@mbed.org 0:5e1631496985 281
root@mbed.org 0:5e1631496985 282 ethernetif = mem_malloc(sizeof(struct ethernetif));
root@mbed.org 0:5e1631496985 283 if (ethernetif == NULL) {
root@mbed.org 0:5e1631496985 284 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
root@mbed.org 0:5e1631496985 285 return ERR_MEM;
root@mbed.org 0:5e1631496985 286 }
root@mbed.org 0:5e1631496985 287
root@mbed.org 0:5e1631496985 288 #if LWIP_NETIF_HOSTNAME
root@mbed.org 0:5e1631496985 289 /* Initialize interface hostname */
root@mbed.org 0:5e1631496985 290 netif->hostname = "lwip";
root@mbed.org 0:5e1631496985 291 #endif /* LWIP_NETIF_HOSTNAME */
root@mbed.org 0:5e1631496985 292
root@mbed.org 0:5e1631496985 293 /*
root@mbed.org 0:5e1631496985 294 * Initialize the snmp variables and counters inside the struct netif.
root@mbed.org 0:5e1631496985 295 * The last argument should be replaced with your link speed, in units
root@mbed.org 0:5e1631496985 296 * of bits per second.
root@mbed.org 0:5e1631496985 297 */
root@mbed.org 0:5e1631496985 298 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
root@mbed.org 0:5e1631496985 299
root@mbed.org 0:5e1631496985 300 netif->state = ethernetif;
root@mbed.org 0:5e1631496985 301 netif->name[0] = IFNAME0;
root@mbed.org 0:5e1631496985 302 netif->name[1] = IFNAME1;
root@mbed.org 0:5e1631496985 303 /* We directly use etharp_output() here to save a function call.
root@mbed.org 0:5e1631496985 304 * You can instead declare your own function an call etharp_output()
root@mbed.org 0:5e1631496985 305 * from it if you have to do some checks before sending (e.g. if link
root@mbed.org 0:5e1631496985 306 * is available...) */
root@mbed.org 0:5e1631496985 307 netif->output = etharp_output;
root@mbed.org 0:5e1631496985 308 netif->linkoutput = low_level_output;
root@mbed.org 0:5e1631496985 309
root@mbed.org 0:5e1631496985 310 ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
root@mbed.org 0:5e1631496985 311
root@mbed.org 0:5e1631496985 312 /* initialize the hardware */
root@mbed.org 0:5e1631496985 313 low_level_init(netif);
root@mbed.org 0:5e1631496985 314
root@mbed.org 0:5e1631496985 315 return ERR_OK;
root@mbed.org 0:5e1631496985 316 }
root@mbed.org 0:5e1631496985 317
root@mbed.org 0:5e1631496985 318 #endif /* 0 */