8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
35 * This file is built upon the file: src/arch/rtxc/netif/sioslip.c
37 * Author: Magnus Ivarsson <magnus.ivarsson(at)volvo.com>
43 * @defgroup slipif SLIP netif
46 * This is an arch independent SLIP netif. The specific serial hooks must be
47 * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send
49 * Usage: This netif can be used in three ways:\n
50 * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read()
51 * until data is received.\n
52 * 2) In your main loop, call slipif_poll() to check for new RX bytes,
53 * completed packets are fed into netif->input().\n
54 * 3) Call slipif_received_byte[s]() from your serial RX ISR and
55 * slipif_process_rxqueue() from your main loop. ISR level decodes
56 * packets and puts completed packets on a queue which is fed into
57 * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for
58 * pbuf_alloc to work on ISR level!).
62 #include "netif/slipif.h"
66 #include "lwip/pbuf.h"
67 #include "lwip/stats.h"
68 #include "lwip/snmp.h"
72 #define SLIP_END 0xC0 /* 0300: start and end of every packet */
73 #define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */
74 #define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */
75 #define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */
77 /** Maximum packet size that is received by this netif */
79 #define SLIP_MAX_SIZE 1500
82 /** Define this to the interface speed for SNMP
83 * (sio_fd is the sio_fd_t returned by sio_open).
84 * The default value of zero means 'unknown'.
86 #ifndef SLIP_SIO_SPEED
87 #define SLIP_SIO_SPEED(sio_fd) 0
90 enum slipif_recv_state
{
97 /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */
102 struct pbuf
*rxpackets
;
107 * Send a pbuf doing the necessary SLIP encapsulation
109 * Uses the serial layer's sio_send()
111 * @param netif the lwip network interface structure for this slipif
112 * @param p the pbuf chain packet to send
113 * @return always returns ERR_OK since the serial layer does not provide return values
116 slipif_output(struct netif
*netif
, struct pbuf
*p
)
118 struct slipif_priv
*priv
;
123 LWIP_ASSERT("netif != NULL", (netif
!= NULL
));
124 LWIP_ASSERT("netif->state != NULL", (netif
->state
!= NULL
));
125 LWIP_ASSERT("p != NULL", (p
!= NULL
));
127 LWIP_DEBUGF(SLIP_DEBUG
, ("slipif_output: sending %"U16_F
" bytes\n", p
->tot_len
));
128 priv
= (struct slipif_priv
*)netif
->state
;
130 /* Send pbuf out on the serial I/O device. */
131 /* Start with packet delimiter. */
132 sio_send(SLIP_END
, priv
->sd
);
134 for (q
= p
; q
!= NULL
; q
= q
->next
) {
135 for (i
= 0; i
< q
->len
; i
++) {
136 c
= ((u8_t
*)q
->payload
)[i
];
139 /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */
140 sio_send(SLIP_ESC
, priv
->sd
);
141 sio_send(SLIP_ESC_END
, priv
->sd
);
144 /* need to escape this byte (0xDB -> 0xDB, 0xDD) */
145 sio_send(SLIP_ESC
, priv
->sd
);
146 sio_send(SLIP_ESC_ESC
, priv
->sd
);
149 /* normal byte - no need for escaping */
150 sio_send(c
, priv
->sd
);
155 /* End with packet delimiter. */
156 sio_send(SLIP_END
, priv
->sd
);
162 * Send a pbuf doing the necessary SLIP encapsulation
164 * Uses the serial layer's sio_send()
166 * @param netif the lwip network interface structure for this slipif
167 * @param p the pbuf chain packet to send
168 * @param ipaddr the ip address to send the packet to (not used for slipif)
169 * @return always returns ERR_OK since the serial layer does not provide return values
172 slipif_output_v4(struct netif
*netif
, struct pbuf
*p
, const ip4_addr_t
*ipaddr
)
174 LWIP_UNUSED_ARG(ipaddr
);
175 return slipif_output(netif
, p
);
177 #endif /* LWIP_IPV4 */
181 * Send a pbuf doing the necessary SLIP encapsulation
183 * Uses the serial layer's sio_send()
185 * @param netif the lwip network interface structure for this slipif
186 * @param p the pbuf chain packet to send
187 * @param ipaddr the ip address to send the packet to (not used for slipif)
188 * @return always returns ERR_OK since the serial layer does not provide return values
191 slipif_output_v6(struct netif
*netif
, struct pbuf
*p
, const ip6_addr_t
*ipaddr
)
193 LWIP_UNUSED_ARG(ipaddr
);
194 return slipif_output(netif
, p
);
196 #endif /* LWIP_IPV6 */
199 * Handle the incoming SLIP stream character by character
201 * @param netif the lwip network interface structure for this slipif
202 * @param c received character (multiple calls to this function will
203 * return a complete packet, NULL is returned before - used for polling)
204 * @return The IP packet when SLIP_END is received
207 slipif_rxbyte(struct netif
*netif
, u8_t c
)
209 struct slipif_priv
*priv
;
212 LWIP_ASSERT("netif != NULL", (netif
!= NULL
));
213 LWIP_ASSERT("netif->state != NULL", (netif
->state
!= NULL
));
215 priv
= (struct slipif_priv
*)netif
->state
;
217 switch (priv
->state
) {
218 case SLIP_RECV_NORMAL
:
221 if (priv
->recved
> 0) {
222 /* Received whole packet. */
223 /* Trim the pbuf to the size of the received packet. */
224 pbuf_realloc(priv
->q
, priv
->recved
);
226 LINK_STATS_INC(link
.recv
);
228 LWIP_DEBUGF(SLIP_DEBUG
, ("slipif: Got packet (%"U16_F
" bytes)\n", priv
->recved
));
230 priv
->p
= priv
->q
= NULL
;
231 priv
->i
= priv
->recved
= 0;
236 priv
->state
= SLIP_RECV_ESCAPE
;
240 } /* end switch (c) */
242 case SLIP_RECV_ESCAPE
:
243 /* un-escape END or ESC bytes, leave other bytes
244 (although that would be a protocol error) */
255 priv
->state
= SLIP_RECV_NORMAL
;
259 } /* end switch (priv->state) */
261 /* byte received, packet not yet completely received */
262 if (priv
->p
== NULL
) {
263 /* allocate a new pbuf */
264 LWIP_DEBUGF(SLIP_DEBUG
, ("slipif_input: alloc\n"));
265 priv
->p
= pbuf_alloc(PBUF_LINK
, (PBUF_POOL_BUFSIZE
- PBUF_LINK_HLEN
- PBUF_LINK_ENCAPSULATION_HLEN
), PBUF_POOL
);
267 if (priv
->p
== NULL
) {
268 LINK_STATS_INC(link
.drop
);
269 LWIP_DEBUGF(SLIP_DEBUG
, ("slipif_input: no new pbuf! (DROP)\n"));
270 /* don't process any further since we got no pbuf to receive to */
274 if (priv
->q
!= NULL
) {
275 /* 'chain' the pbuf to the existing chain */
276 pbuf_cat(priv
->q
, priv
->p
);
278 /* p is the first pbuf in the chain */
283 /* this automatically drops bytes if > SLIP_MAX_SIZE */
284 if ((priv
->p
!= NULL
) && (priv
->recved
<= SLIP_MAX_SIZE
)) {
285 ((u8_t
*)priv
->p
->payload
)[priv
->i
] = c
;
288 if (priv
->i
>= priv
->p
->len
) {
289 /* on to the next pbuf */
291 if (priv
->p
->next
!= NULL
&& priv
->p
->next
->len
> 0) {
292 /* p is a chain, on to the next in the chain */
293 priv
->p
= priv
->p
->next
;
295 /* p is a single pbuf, set it to NULL so next time a new
296 * pbuf is allocated */
304 /** Like slipif_rxbyte, but passes completed packets to netif->input
306 * @param netif The lwip network interface structure for this slipif
307 * @param c received character
310 slipif_rxbyte_input(struct netif
*netif
, u8_t c
)
313 p
= slipif_rxbyte(netif
, c
);
315 if (netif
->input(p
, netif
) != ERR_OK
) {
321 #if SLIP_USE_RX_THREAD
323 * The SLIP input thread.
325 * Feed the IP layer with incoming packets
327 * @param nf the lwip network interface structure for this slipif
330 slipif_loop_thread(void *nf
)
333 struct netif
*netif
= (struct netif
*)nf
;
334 struct slipif_priv
*priv
= (struct slipif_priv
*)netif
->state
;
337 if (sio_read(priv
->sd
, &c
, 1) > 0) {
338 slipif_rxbyte_input(netif
, c
);
342 #endif /* SLIP_USE_RX_THREAD */
345 * SLIP netif initialization
347 * Call the arch specific sio_open and remember
348 * the opened device in the state field of the netif.
350 * @param netif the lwip network interface structure for this slipif
351 * @return ERR_OK if serial line could be opened,
352 * ERR_MEM if no memory could be allocated,
353 * ERR_IF is serial line couldn't be opened
355 * @note If netif->state is interpreted as an u8_t serial port number.
359 slipif_init(struct netif
*netif
)
361 struct slipif_priv
*priv
;
364 /* netif->state contains serial port number */
365 sio_num
= LWIP_PTR_NUMERIC_CAST(u8_t
, netif
->state
);
367 LWIP_DEBUGF(SLIP_DEBUG
, ("slipif_init: netif->num=%"U16_F
"\n", (u16_t
)sio_num
));
369 /* Allocate private data */
370 priv
= (struct slipif_priv
*)mem_malloc(sizeof(struct slipif_priv
));
375 netif
->name
[0] = 's';
376 netif
->name
[1] = 'l';
378 netif
->output
= slipif_output_v4
;
379 #endif /* LWIP_IPV4 */
381 netif
->output_ip6
= slipif_output_v6
;
382 #endif /* LWIP_IPV6 */
383 netif
->mtu
= SLIP_MAX_SIZE
;
385 /* Try to open the serial port. */
386 priv
->sd
= sio_open(sio_num
);
388 /* Opening the serial port failed. */
393 /* Initialize private data */
396 priv
->state
= SLIP_RECV_NORMAL
;
400 priv
->rxpackets
= NULL
;
405 /* initialize the snmp variables and counters inside the struct netif */
406 MIB2_INIT_NETIF(netif
, snmp_ifType_slip
, SLIP_SIO_SPEED(priv
->sd
));
408 #if SLIP_USE_RX_THREAD
409 /* Create a thread to poll the serial line. */
410 sys_thread_new(SLIPIF_THREAD_NAME
, slipif_loop_thread
, netif
,
411 SLIPIF_THREAD_STACKSIZE
, SLIPIF_THREAD_PRIO
);
412 #endif /* SLIP_USE_RX_THREAD */
417 * Polls the serial device and feeds the IP layer with incoming packets.
419 * @param netif The lwip network interface structure for this slipif
422 slipif_poll(struct netif
*netif
)
425 struct slipif_priv
*priv
;
427 LWIP_ASSERT("netif != NULL", (netif
!= NULL
));
428 LWIP_ASSERT("netif->state != NULL", (netif
->state
!= NULL
));
430 priv
= (struct slipif_priv
*)netif
->state
;
432 while (sio_tryread(priv
->sd
, &c
, 1) > 0) {
433 slipif_rxbyte_input(netif
, c
);
439 * Feeds the IP layer with incoming packets that were receive
441 * @param netif The lwip network interface structure for this slipif
444 slipif_process_rxqueue(struct netif
*netif
)
446 struct slipif_priv
*priv
;
447 SYS_ARCH_DECL_PROTECT(old_level
);
449 LWIP_ASSERT("netif != NULL", (netif
!= NULL
));
450 LWIP_ASSERT("netif->state != NULL", (netif
->state
!= NULL
));
452 priv
= (struct slipif_priv
*)netif
->state
;
454 SYS_ARCH_PROTECT(old_level
);
455 while (priv
->rxpackets
!= NULL
) {
456 struct pbuf
*p
= priv
->rxpackets
;
460 while ((q
->len
!= q
->tot_len
) && (q
->next
!= NULL
)) {
463 priv
->rxpackets
= q
->next
;
465 #else /* SLIP_RX_QUEUE */
466 priv
->rxpackets
= NULL
;
467 #endif /* SLIP_RX_QUEUE */
468 SYS_ARCH_UNPROTECT(old_level
);
469 if (netif
->input(p
, netif
) != ERR_OK
) {
472 SYS_ARCH_PROTECT(old_level
);
476 /** Like slipif_rxbyte, but queues completed packets.
478 * @param netif The lwip network interface structure for this slipif
479 * @param data Received serial byte
482 slipif_rxbyte_enqueue(struct netif
*netif
, u8_t data
)
485 struct slipif_priv
*priv
= (struct slipif_priv
*)netif
->state
;
486 SYS_ARCH_DECL_PROTECT(old_level
);
488 p
= slipif_rxbyte(netif
, data
);
490 SYS_ARCH_PROTECT(old_level
);
491 if (priv
->rxpackets
!= NULL
) {
493 /* queue multiple pbufs */
495 while (q
->next
!= NULL
) {
500 #else /* SLIP_RX_QUEUE */
501 pbuf_free(priv
->rxpackets
);
504 #endif /* SLIP_RX_QUEUE */
507 SYS_ARCH_UNPROTECT(old_level
);
512 * Process a received byte, completed packets are put on a queue that is
513 * fed into IP through slipif_process_rxqueue().
515 * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled.
517 * @param netif The lwip network interface structure for this slipif
518 * @param data received character
521 slipif_received_byte(struct netif
*netif
, u8_t data
)
523 LWIP_ASSERT("netif != NULL", (netif
!= NULL
));
524 LWIP_ASSERT("netif->state != NULL", (netif
->state
!= NULL
));
525 slipif_rxbyte_enqueue(netif
, data
);
529 * Process multiple received byte, completed packets are put on a queue that is
530 * fed into IP through slipif_process_rxqueue().
532 * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled.
534 * @param netif The lwip network interface structure for this slipif
535 * @param data received character
536 * @param len Number of received characters
539 slipif_received_bytes(struct netif
*netif
, u8_t
*data
, u8_t len
)
543 LWIP_ASSERT("netif != NULL", (netif
!= NULL
));
544 LWIP_ASSERT("netif->state != NULL", (netif
->state
!= NULL
));
546 for (i
= 0; i
< len
; i
++, rxdata
++) {
547 slipif_rxbyte_enqueue(netif
, *rxdata
);
550 #endif /* SLIP_RX_FROM_ISR */