]> Joshua Wise's Git repositories - netwatch.git/blob - lwip/src/netif/slipif.c
more rfb work
[netwatch.git] / lwip / src / 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 }
This page took 0.041395 seconds and 4 git commands to generate.