Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / lwip / netif / slipif.c
1 /**
2  * @file
3  * SLIP Interface
4  *
5  */
6
7 /*
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9  * All rights reserved. 
10  *
11  * Redistribution and use in source and binary forms, with or without 
12  * modification, are permitted provided that the following conditions 
13  * are met: 
14  * 1. Redistributions of source code must retain the above copyright 
15  *    notice, this list of conditions and the following disclaimer. 
16  * 2. Redistributions in binary form must reproduce the above copyright 
17  *    notice, this list of conditions and the following disclaimer in the 
18  *    documentation and/or other materials provided with the distribution. 
19  * 3. Neither the name of the Institute nor the names of its contributors 
20  *    may be used to endorse or promote products derived from this software 
21  *    without specific prior written permission. 
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
33  * SUCH DAMAGE. 
34  *
35  * This file is built upon the file: src/arch/rtxc/netif/sioslip.c
36  *
37  * Author: Magnus Ivarsson <magnus.ivarsson(at)volvo.com> 
38  */
39
40 /* 
41  * This is an arch independent SLIP netif. The specific serial hooks must be
42  * provided by another file. They are sio_open, sio_recv and sio_send
43  */
44
45 #include "netif/slipif.h"
46 #include "lwip/opt.h"
47 #include "lwip/def.h"
48 #include "lwip/pbuf.h"
49 #include "lwip/sys.h"
50 #include "lwip/stats.h"
51 #include "lwip/snmp.h"
52 #include "lwip/sio.h"
53
54 #define SLIP_END     0300 /* 0xC0 */
55 #define SLIP_ESC     0333 /* 0xDB */
56 #define SLIP_ESC_END 0334 /* 0xDC */
57 #define SLIP_ESC_ESC 0335 /* 0xDD */
58
59 #define MAX_SIZE     1500
60
61 /**
62  * Send a pbuf doing the necessary SLIP encapsulation
63  *
64  * Uses the serial layer's sio_send()
65  *
66  * @param netif the lwip network interface structure for this slipif
67  * @param p the pbuf chaing packet to send
68  * @param ipaddr the ip address to send the packet to (not used for slipif)
69  * @return always returns ERR_OK since the serial layer does not provide return values
70  */
71 err_t
72 slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
73 {
74   struct pbuf *q;
75   u16_t i;
76   u8_t c;
77
78   LWIP_ASSERT("netif != NULL", (netif != NULL));
79   LWIP_ASSERT("netif->state != NULL", (netif->state != NULL));
80   LWIP_ASSERT("p != NULL", (p != NULL));
81
82   LWIP_UNUSED_ARG(ipaddr);
83
84   /* Send pbuf out on the serial I/O device. */
85   sio_send(SLIP_END, netif->state);
86
87   for (q = p; q != NULL; q = q->next) {
88     for (i = 0; i < q->len; i++) {
89       c = ((u8_t *)q->payload)[i];
90       switch (c) {
91       case SLIP_END:
92         sio_send(SLIP_ESC, netif->state);
93         sio_send(SLIP_ESC_END, netif->state);
94         break;
95       case SLIP_ESC:
96         sio_send(SLIP_ESC, netif->state);
97         sio_send(SLIP_ESC_ESC, netif->state);
98         break;
99       default:
100         sio_send(c, netif->state);
101         break;
102       }
103     }
104   }
105   sio_send(SLIP_END, netif->state);
106   return ERR_OK;
107 }
108
109 /**
110  * Handle the incoming SLIP stream character by character
111  *
112  * Poll the serial layer by calling sio_recv()
113  *
114  * @param netif the lwip network interface structure for this slipif
115  * @return The IP packet when SLIP_END is received 
116  */
117 static struct pbuf *
118 slipif_input(struct netif *netif)
119 {
120   u8_t c;
121   /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */
122   struct pbuf *p, *q;
123   u16_t recved;
124   u16_t i;
125
126   LWIP_ASSERT("netif != NULL", (netif != NULL));
127   LWIP_ASSERT("netif->state != NULL", (netif->state != NULL));
128
129   q = p = NULL;
130   recved = i = 0;
131   c = 0;
132
133   while (1) {
134     c = sio_recv(netif->state);
135     switch (c) {
136     case SLIP_END:
137       if (recved > 0) {
138         /* Received whole packet. */
139         /* Trim the pbuf to the size of the received packet. */
140         pbuf_realloc(q, recved);
141         
142         LINK_STATS_INC(link.recv);
143         
144         LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
145         return q;
146       }
147       break;
148
149     case SLIP_ESC:
150       c = sio_recv(netif->state);
151       switch (c) {
152       case SLIP_ESC_END:
153         c = SLIP_END;
154         break;
155       case SLIP_ESC_ESC:
156         c = SLIP_ESC;
157         break;
158       }
159       /* FALLTHROUGH */
160
161     default:
162       /* byte received, packet not yet completely received */
163       if (p == NULL) {
164         /* allocate a new pbuf */
165         LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
166         p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
167
168         if (p == NULL) {
169           LINK_STATS_INC(link.drop);
170           LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
171           /* don't process any further since we got no pbuf to receive to */
172           break;
173         }
174
175         if (q != NULL) {
176           /* 'chain' the pbuf to the existing chain */
177           pbuf_cat(q, p);
178         } else {
179           /* p is the first pbuf in the chain */
180           q = p;
181         }
182       }
183
184       /* this automatically drops bytes if > MAX_SIZE */
185       if ((p != NULL) && (recved <= MAX_SIZE)) {
186         ((u8_t *)p->payload)[i] = c;
187         recved++;
188         i++;
189         if (i >= p->len) {
190           /* on to the next pbuf */
191           i = 0;
192           if (p->next != NULL && p->next->len > 0) {
193             /* p is a chain, on to the next in the chain */
194             p = p->next;
195           } else {
196             /* p is a single pbuf, set it to NULL so next time a new
197              * pbuf is allocated */
198             p = NULL;
199           }
200         }
201       }
202       break;
203     }
204   }
205   return NULL;
206 }
207
208 #if !NO_SYS
209 /**
210  * The SLIP input thread.
211  *
212  * Feed the IP layer with incoming packets
213  *
214  * @param nf the lwip network interface structure for this slipif
215  */
216 static void
217 slipif_loop(void *nf)
218 {
219   struct pbuf *p;
220   struct netif *netif = (struct netif *)nf;
221
222   while (1) {
223     p = slipif_input(netif);
224     if (p != NULL) {
225       if (netif->input(p, netif) != ERR_OK) {
226         pbuf_free(p);
227         p = NULL;
228       }
229     }
230   }
231 }
232 #endif /* !NO_SYS */
233
234 /**
235  * SLIP netif initialization
236  *
237  * Call the arch specific sio_open and remember
238  * the opened device in the state field of the netif.
239  *
240  * @param netif the lwip network interface structure for this slipif
241  * @return ERR_OK if serial line could be opened,
242  *         ERR_IF is serial line couldn't be opened
243  *
244  * @note netif->num must contain the number of the serial port to open
245  *       (0 by default)
246  */
247 err_t
248 slipif_init(struct netif *netif)
249 {
250
251   LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num));
252
253   netif->name[0] = 's';
254   netif->name[1] = 'l';
255   netif->output = slipif_output;
256   netif->mtu = MAX_SIZE;
257   netif->flags = NETIF_FLAG_POINTTOPOINT;
258
259   /* Try to open the serial port (netif->num contains the port number). */
260   netif->state = sio_open(netif->num);
261   if (!netif->state) {
262     /* Opening the serial port failed. */
263     return ERR_IF;
264   }
265
266   /* initialize the snmp variables and counters inside the struct netif
267    * ifSpeed: no assumption can be made without knowing more about the
268    * serial line!
269    */
270   NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0);
271
272   /* Create a thread to poll the serial line. */
273   sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop, netif, SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO);
274   return ERR_OK;
275 }