32 |
*/ |
*/ |
33 |
|
|
34 |
/* |
/* |
35 |
* This is an arch independent SLIP netif. The specific serial hooks must be provided |
* This is an arch independent SLIP netif. The specific serial hooks must be |
36 |
* by another file.They are sio_open, sio_recv and sio_send |
* provided by another file. They are sio_open, sio_recv and sio_send |
37 |
*/ |
*/ |
38 |
|
|
39 |
#include "netif/slipif.h" |
#include "netif/slipif.h" |
40 |
#include "lwip/opt.h" |
#include "lwip/opt.h" |
55 |
* Send a pbuf doing the necessary SLIP encapsulation |
* Send a pbuf doing the necessary SLIP encapsulation |
56 |
* |
* |
57 |
* Uses the serial layer's sio_send() |
* Uses the serial layer's sio_send() |
58 |
*/ |
*/ |
59 |
err_t |
err_t |
60 |
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) |
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) |
61 |
{ |
{ |
66 |
/* Send pbuf out on the serial I/O device. */ |
/* Send pbuf out on the serial I/O device. */ |
67 |
sio_send(SLIP_END, netif->state); |
sio_send(SLIP_END, netif->state); |
68 |
|
|
69 |
for(q = p; q != NULL; q = q->next) { |
for (q = p; q != NULL; q = q->next) { |
70 |
for(i = 0; i < q->len; i++) { |
for (i = 0; i < q->len; i++) { |
71 |
c = ((u8_t *)q->payload)[i]; |
c = ((u8_t *)q->payload)[i]; |
72 |
switch (c) { |
switch (c) { |
73 |
case SLIP_END: |
case SLIP_END: |
74 |
sio_send(SLIP_ESC, netif->state); |
sio_send(SLIP_ESC, netif->state); |
75 |
sio_send(SLIP_ESC_END, netif->state); |
sio_send(SLIP_ESC_END, netif->state); |
76 |
break; |
break; |
77 |
case SLIP_ESC: |
case SLIP_ESC: |
78 |
sio_send(SLIP_ESC, netif->state); |
sio_send(SLIP_ESC, netif->state); |
79 |
sio_send(SLIP_ESC_ESC, netif->state); |
sio_send(SLIP_ESC_ESC, netif->state); |
80 |
break; |
break; |
81 |
default: |
default: |
82 |
sio_send(c, netif->state); |
sio_send(c, netif->state); |
83 |
break; |
break; |
84 |
} |
} |
85 |
} |
} |
86 |
} |
} |
94 |
* Poll the serial layer by calling sio_recv() |
* Poll the serial layer by calling sio_recv() |
95 |
* |
* |
96 |
* @return The IP packet when SLIP_END is received |
* @return The IP packet when SLIP_END is received |
97 |
*/ |
*/ |
98 |
static struct pbuf * |
static struct pbuf * |
99 |
slipif_input( struct netif * netif ) |
slipif_input(struct netif *netif) |
100 |
{ |
{ |
101 |
u8_t c; |
u8_t c; |
102 |
struct pbuf *p, *q; |
struct pbuf *p, *q; |
112 |
switch (c) { |
switch (c) { |
113 |
case SLIP_END: |
case SLIP_END: |
114 |
if (recved > 0) { |
if (recved > 0) { |
115 |
/* Received whole packet. */ |
/* Received whole packet. */ |
116 |
pbuf_realloc(q, recved); |
pbuf_realloc(q, recved); |
117 |
|
|
118 |
LINK_STATS_INC(link.recv); |
LINK_STATS_INC(link.recv); |
119 |
|
|
120 |
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n")); |
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n")); |
121 |
return q; |
return q; |
122 |
} |
} |
123 |
break; |
break; |
124 |
|
|
126 |
c = sio_recv(netif->state); |
c = sio_recv(netif->state); |
127 |
switch (c) { |
switch (c) { |
128 |
case SLIP_ESC_END: |
case SLIP_ESC_END: |
129 |
c = SLIP_END; |
c = SLIP_END; |
130 |
break; |
break; |
131 |
case SLIP_ESC_ESC: |
case SLIP_ESC_ESC: |
132 |
c = SLIP_ESC; |
c = SLIP_ESC; |
133 |
break; |
break; |
134 |
} |
} |
135 |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
136 |
|
|
137 |
default: |
default: |
138 |
if (p == NULL) { |
if (p == NULL) { |
139 |
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); |
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); |
140 |
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL); |
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL); |
141 |
|
|
142 |
if (p == NULL) { |
if (p == NULL) { |
143 |
LINK_STATS_INC(link.drop); |
LINK_STATS_INC(link.drop); |
144 |
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); |
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); |
145 |
} |
} |
146 |
|
|
147 |
if (q != NULL) { |
if (q != NULL) { |
148 |
pbuf_cat(q, p); |
pbuf_cat(q, p); |
149 |
} else { |
} else { |
150 |
q = p; |
q = p; |
151 |
} |
} |
152 |
} |
} |
153 |
if (p != NULL && recved < MAX_SIZE) { |
if (p != NULL && recved < MAX_SIZE) { |
154 |
((u8_t *)p->payload)[i] = c; |
((u8_t *)p->payload)[i] = c; |
155 |
recved++; |
recved++; |
156 |
i++; |
i++; |
157 |
if (i >= p->len) { |
if (i >= p->len) { |
158 |
i = 0; |
i = 0; |
159 |
p = NULL; |
if (p->next != NULL && p->next->len > 0) |
160 |
} |
p = p->next; |
161 |
|
else |
162 |
|
p = NULL; |
163 |
|
} |
164 |
} |
} |
165 |
break; |
break; |
166 |
} |
} |
167 |
|
|
168 |
} |
} |
169 |
return NULL; |
return NULL; |
170 |
} |
} |
173 |
* The SLIP input thread |
* The SLIP input thread |
174 |
* |
* |
175 |
* Feed the IP layer with incoming packets |
* Feed the IP layer with incoming packets |
176 |
*/ |
*/ |
177 |
static void |
static void |
178 |
slipif_loop(void *nf) |
slipif_loop(void *nf) |
179 |
{ |
{ |
191 |
* |
* |
192 |
* Call the arch specific sio_open and remember |
* Call the arch specific sio_open and remember |
193 |
* the opened device in the state field of the netif. |
* the opened device in the state field of the netif. |
194 |
*/ |
*/ |
195 |
err_t |
err_t |
196 |
slipif_init(struct netif *netif) |
slipif_init(struct netif *netif) |
197 |
{ |
{ |
198 |
|
|
199 |
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%x\n", (int)netif->num)); |
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%x\n", (int)netif->num)); |
200 |
|
|
201 |
netif->name[0] = 's'; |
netif->name[0] = 's'; |
202 |
netif->name[1] = 'l'; |
netif->name[1] = 'l'; |
203 |
netif->output = slipif_output; |
netif->output = slipif_output; |
204 |
netif->mtu = 1500; |
netif->mtu = 1500; |
205 |
netif->flags = NETIF_FLAG_POINTTOPOINT; |
netif->flags = NETIF_FLAG_POINTTOPOINT; |
206 |
|
|
207 |
netif->state = sio_open(netif->num); |
netif->state = sio_open(netif->num); |
208 |
if (!netif->state) |
if (!netif->state) |
209 |
return ERR_IF; |
return ERR_IF; |
210 |
|
|
211 |
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO); |
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO); |
212 |
return ERR_OK; |
return ERR_OK; |