Example self-announcing webserver which controls a servo through a smallHTML userinterface.

Dependencies:   mbed

Committer:
dirkx
Date:
Sat Aug 14 15:56:01 2010 +0000
Revision:
0:a259777c45a3

        

Who changed what in which revision?

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