lwip-1.4.1 (partial)
Embed:
(wiki syntax)
Show/hide line numbers
slipif.c
Go to the documentation of this file.
00001 /** 00002 * @file 00003 * SLIP Interface 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions 00013 * are met: 00014 * 1. Redistributions of source code must retain the above copyright 00015 * notice, this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright 00017 * notice, this list of conditions and the following disclaimer in the 00018 * documentation and/or other materials provided with the distribution. 00019 * 3. Neither the name of the Institute nor the names of its contributors 00020 * may be used to endorse or promote products derived from this software 00021 * without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00027 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00028 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00029 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00032 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00033 * SUCH DAMAGE. 00034 * 00035 * This file is built upon the file: src/arch/rtxc/netif/sioslip.c 00036 * 00037 * Author: Magnus Ivarsson <magnus.ivarsson(at)volvo.com> 00038 * Simon Goldschmidt 00039 * 00040 * Usage: This netif can be used in three ways: 00041 * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() 00042 * until data is received. 00043 * 2) In your main loop, call slipif_poll() to check for new RX bytes, 00044 * completed packets are fed into netif->input(). 00045 * 3) Call slipif_received_byte[s]() from your serial RX ISR and 00046 * slipif_process_rxqueue() from your main loop. ISR level decodes 00047 * packets and puts completed packets on a queue which is fed into 00048 * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for 00049 * pbuf_alloc to work on ISR level!). 00050 * 00051 */ 00052 00053 /* 00054 * This is an arch independent SLIP netif. The specific serial hooks must be 00055 * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send 00056 */ 00057 00058 #include "netif/slipif.h" 00059 #include "lwip/opt.h" 00060 00061 #if LWIP_HAVE_SLIPIF 00062 00063 #include "lwip/def.h" 00064 #include "lwip/pbuf.h" 00065 #include "lwip/stats.h" 00066 #include "lwip/snmp.h" 00067 #include "lwip/sio.h" 00068 #include "lwip/sys.h" 00069 00070 #define SLIP_END 0xC0 /* 0300: start and end of every packet */ 00071 #define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ 00072 #define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ 00073 #define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ 00074 00075 /** Maximum packet size that is received by this netif */ 00076 #ifndef SLIP_MAX_SIZE 00077 #define SLIP_MAX_SIZE 1500 00078 #endif 00079 00080 /** Define this to the interface speed for SNMP 00081 * (sio_fd is the sio_fd_t returned by sio_open). 00082 * The default value of zero means 'unknown'. 00083 */ 00084 #ifndef SLIP_SIO_SPEED 00085 #define SLIP_SIO_SPEED(sio_fd) 0 00086 #endif 00087 00088 enum slipif_recv_state { 00089 SLIP_RECV_NORMAL, 00090 SLIP_RECV_ESCAPE, 00091 }; 00092 00093 struct slipif_priv { 00094 sio_fd_t sd; 00095 /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ 00096 struct pbuf *p, *q; 00097 u8_t state; 00098 u16_t i, recved; 00099 #if SLIP_RX_FROM_ISR 00100 struct pbuf *rxpackets; 00101 #endif 00102 }; 00103 00104 /** 00105 * Send a pbuf doing the necessary SLIP encapsulation 00106 * 00107 * Uses the serial layer's sio_send() 00108 * 00109 * @param netif the lwip network interface structure for this slipif 00110 * @param p the pbuf chaing packet to send 00111 * @param ipaddr the ip address to send the packet to (not used for slipif) 00112 * @return always returns ERR_OK since the serial layer does not provide return values 00113 */ 00114 err_t 00115 slipif_output(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr) 00116 { 00117 struct slipif_priv *priv; 00118 struct pbuf *q; 00119 u16_t i; 00120 u8_t c; 00121 00122 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00123 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00124 LWIP_ASSERT("p != NULL", (p != NULL)); 00125 00126 LWIP_UNUSED_ARG(ipaddr); 00127 00128 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); 00129 priv = netif->state; 00130 00131 /* Send pbuf out on the serial I/O device. */ 00132 /* Start with packet delimiter. */ 00133 sio_send(SLIP_END, priv->sd); 00134 00135 for (q = p; q != NULL; q = q->next) { 00136 for (i = 0; i < q->len; i++) { 00137 c = ((u8_t *)q->payload)[i]; 00138 switch (c) { 00139 case SLIP_END: 00140 /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ 00141 sio_send(SLIP_ESC, priv->sd); 00142 sio_send(SLIP_ESC_END, priv->sd); 00143 break; 00144 case SLIP_ESC: 00145 /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ 00146 sio_send(SLIP_ESC, priv->sd); 00147 sio_send(SLIP_ESC_ESC, priv->sd); 00148 break; 00149 default: 00150 /* normal byte - no need for escaping */ 00151 sio_send(c, priv->sd); 00152 break; 00153 } 00154 } 00155 } 00156 /* End with packet delimiter. */ 00157 sio_send(SLIP_END, priv->sd); 00158 return ERR_OK; 00159 } 00160 00161 /** 00162 * Handle the incoming SLIP stream character by character 00163 * 00164 * @param netif the lwip network interface structure for this slipif 00165 * @param c received character (multiple calls to this function will 00166 * return a complete packet, NULL is returned before - used for polling) 00167 * @return The IP packet when SLIP_END is received 00168 */ 00169 static struct pbuf* 00170 slipif_rxbyte(struct netif *netif, u8_t c) 00171 { 00172 struct slipif_priv *priv; 00173 struct pbuf *t; 00174 00175 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00176 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00177 00178 priv = netif->state; 00179 00180 switch (priv->state) { 00181 case SLIP_RECV_NORMAL: 00182 switch (c) { 00183 case SLIP_END: 00184 if (priv->recved > 0) { 00185 /* Received whole packet. */ 00186 /* Trim the pbuf to the size of the received packet. */ 00187 pbuf_realloc(priv->q, priv->recved); 00188 00189 LINK_STATS_INC(link.recv); 00190 00191 LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); 00192 t = priv->q; 00193 priv->p = priv->q = NULL; 00194 priv->i = priv->recved = 0; 00195 return t; 00196 } 00197 return NULL; 00198 case SLIP_ESC: 00199 priv->state = SLIP_RECV_ESCAPE; 00200 return NULL; 00201 } /* end switch (c) */ 00202 break; 00203 case SLIP_RECV_ESCAPE: 00204 /* un-escape END or ESC bytes, leave other bytes 00205 (although that would be a protocol error) */ 00206 switch (c) { 00207 case SLIP_ESC_END: 00208 c = SLIP_END; 00209 break; 00210 case SLIP_ESC_ESC: 00211 c = SLIP_ESC; 00212 break; 00213 } 00214 priv->state = SLIP_RECV_NORMAL; 00215 break; 00216 } /* end switch (priv->state) */ 00217 00218 /* byte received, packet not yet completely received */ 00219 if (priv->p == NULL) { 00220 /* allocate a new pbuf */ 00221 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); 00222 priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL); 00223 00224 if (priv->p == NULL) { 00225 LINK_STATS_INC(link.drop); 00226 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); 00227 /* don't process any further since we got no pbuf to receive to */ 00228 return NULL; 00229 } 00230 00231 if (priv->q != NULL) { 00232 /* 'chain' the pbuf to the existing chain */ 00233 pbuf_cat(priv->q, priv->p); 00234 } else { 00235 /* p is the first pbuf in the chain */ 00236 priv->q = priv->p; 00237 } 00238 } 00239 00240 /* this automatically drops bytes if > SLIP_MAX_SIZE */ 00241 if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { 00242 ((u8_t *)priv->p->payload)[priv->i] = c; 00243 priv->recved++; 00244 priv->i++; 00245 if (priv->i >= priv->p->len) { 00246 /* on to the next pbuf */ 00247 priv->i = 0; 00248 if (priv->p->next != NULL && priv->p->next->len > 0) { 00249 /* p is a chain, on to the next in the chain */ 00250 priv->p = priv->p->next; 00251 } else { 00252 /* p is a single pbuf, set it to NULL so next time a new 00253 * pbuf is allocated */ 00254 priv->p = NULL; 00255 } 00256 } 00257 } 00258 return NULL; 00259 } 00260 00261 /** Like slipif_rxbyte, but passes completed packets to netif->input 00262 * 00263 * @param netif The lwip network interface structure for this slipif 00264 * @param data received character 00265 */ 00266 static void 00267 slipif_rxbyte_input(struct netif *netif, u8_t c) 00268 { 00269 struct pbuf *p; 00270 p = slipif_rxbyte(netif, c); 00271 if (p != NULL) { 00272 if (netif->input(p, netif) != ERR_OK) { 00273 pbuf_free(p); 00274 } 00275 } 00276 } 00277 00278 #if SLIP_USE_RX_THREAD 00279 /** 00280 * The SLIP input thread. 00281 * 00282 * Feed the IP layer with incoming packets 00283 * 00284 * @param nf the lwip network interface structure for this slipif 00285 */ 00286 static void 00287 slipif_loop_thread(void *nf) 00288 { 00289 u8_t c; 00290 struct netif *netif = (struct netif *)nf; 00291 struct slipif_priv *priv = (struct slipif_priv *)netif->state; 00292 00293 while (1) { 00294 if (sio_read(priv->sd, &c, 1) > 0) { 00295 slipif_rxbyte_input(netif, c); 00296 } 00297 } 00298 } 00299 #endif /* SLIP_USE_RX_THREAD */ 00300 00301 /** 00302 * SLIP netif initialization 00303 * 00304 * Call the arch specific sio_open and remember 00305 * the opened device in the state field of the netif. 00306 * 00307 * @param netif the lwip network interface structure for this slipif 00308 * @return ERR_OK if serial line could be opened, 00309 * ERR_MEM if no memory could be allocated, 00310 * ERR_IF is serial line couldn't be opened 00311 * 00312 * @note netif->num must contain the number of the serial port to open 00313 * (0 by default). If netif->state is != NULL, it is interpreted as an 00314 * u8_t pointer pointing to the serial port number instead of netif->num. 00315 * 00316 */ 00317 err_t 00318 slipif_init(struct netif *netif) 00319 { 00320 struct slipif_priv *priv; 00321 u8_t sio_num; 00322 00323 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); 00324 00325 /* Allocate private data */ 00326 priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); 00327 if (!priv) { 00328 return ERR_MEM; 00329 } 00330 00331 netif->name[0] = 's'; 00332 netif->name[1] = 'l'; 00333 netif->output = slipif_output; 00334 netif->mtu = SLIP_MAX_SIZE; 00335 netif->flags |= NETIF_FLAG_POINTTOPOINT; 00336 00337 /* netif->state or netif->num contain the port number */ 00338 if (netif->state != NULL) { 00339 sio_num = *(u8_t*)netif->state; 00340 } else { 00341 sio_num = netif->num; 00342 } 00343 /* Try to open the serial port. */ 00344 priv->sd = sio_open(sio_num); 00345 if (!priv->sd) { 00346 /* Opening the serial port failed. */ 00347 mem_free(priv); 00348 return ERR_IF; 00349 } 00350 00351 /* Initialize private data */ 00352 priv->p = NULL; 00353 priv->q = NULL; 00354 priv->state = SLIP_RECV_NORMAL; 00355 priv->i = 0; 00356 priv->recved = 0; 00357 #if SLIP_RX_FROM_ISR 00358 priv->rxpackets = NULL; 00359 #endif 00360 00361 netif->state = priv; 00362 00363 /* initialize the snmp variables and counters inside the struct netif */ 00364 NETIF_INIT_SNMP(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); 00365 00366 #if SLIP_USE_RX_THREAD 00367 /* Create a thread to poll the serial line. */ 00368 sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, 00369 SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); 00370 #endif /* SLIP_USE_RX_THREAD */ 00371 return ERR_OK; 00372 } 00373 00374 /** 00375 * Polls the serial device and feeds the IP layer with incoming packets. 00376 * 00377 * @param netif The lwip network interface structure for this slipif 00378 */ 00379 void 00380 slipif_poll(struct netif *netif) 00381 { 00382 u8_t c; 00383 struct slipif_priv *priv; 00384 00385 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00386 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00387 00388 priv = (struct slipif_priv *)netif->state; 00389 00390 while (sio_tryread(priv->sd, &c, 1) > 0) { 00391 slipif_rxbyte_input(netif, c); 00392 } 00393 } 00394 00395 #if SLIP_RX_FROM_ISR 00396 /** 00397 * Feeds the IP layer with incoming packets that were receive 00398 * 00399 * @param netif The lwip network interface structure for this slipif 00400 */ 00401 void 00402 slipif_process_rxqueue(struct netif *netif) 00403 { 00404 struct slipif_priv *priv; 00405 SYS_ARCH_DECL_PROTECT(old_level); 00406 00407 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00408 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00409 00410 priv = (struct slipif_priv *)netif->state; 00411 00412 SYS_ARCH_PROTECT(old_level); 00413 while (priv->rxpackets != NULL) { 00414 struct pbuf *p = priv->rxpackets; 00415 #if SLIP_RX_QUEUE 00416 /* dequeue packet */ 00417 struct pbuf *q = p; 00418 while ((q->len != q->tot_len) && (q->next != NULL)) { 00419 q = q->next; 00420 } 00421 priv->rxpackets = q->next; 00422 q->next = NULL; 00423 #else /* SLIP_RX_QUEUE */ 00424 priv->rxpackets = NULL; 00425 #endif /* SLIP_RX_QUEUE */ 00426 SYS_ARCH_UNPROTECT(old_level); 00427 if (netif->input(p, netif) != ERR_OK) { 00428 pbuf_free(p); 00429 } 00430 SYS_ARCH_PROTECT(old_level); 00431 } 00432 } 00433 00434 /** Like slipif_rxbyte, but queues completed packets. 00435 * 00436 * @param netif The lwip network interface structure for this slipif 00437 * @param data Received serial byte 00438 */ 00439 static void 00440 slipif_rxbyte_enqueue(struct netif *netif, u8_t data) 00441 { 00442 struct pbuf *p; 00443 struct slipif_priv *priv = (struct slipif_priv *)netif->state; 00444 SYS_ARCH_DECL_PROTECT(old_level); 00445 00446 p = slipif_rxbyte(netif, data); 00447 if (p != NULL) { 00448 SYS_ARCH_PROTECT(old_level); 00449 if (priv->rxpackets != NULL) { 00450 #if SLIP_RX_QUEUE 00451 /* queue multiple pbufs */ 00452 struct pbuf *q = p; 00453 while(q->next != NULL) { 00454 q = q->next; 00455 } 00456 q->next = p; 00457 } else { 00458 #else /* SLIP_RX_QUEUE */ 00459 pbuf_free(priv->rxpackets); 00460 } 00461 { 00462 #endif /* SLIP_RX_QUEUE */ 00463 priv->rxpackets = p; 00464 } 00465 SYS_ARCH_UNPROTECT(old_level); 00466 } 00467 } 00468 00469 /** 00470 * Process a received byte, completed packets are put on a queue that is 00471 * fed into IP through slipif_process_rxqueue(). 00472 * 00473 * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. 00474 * 00475 * @param netif The lwip network interface structure for this slipif 00476 * @param data received character 00477 */ 00478 void 00479 slipif_received_byte(struct netif *netif, u8_t data) 00480 { 00481 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00482 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00483 slipif_rxbyte_enqueue(netif, data); 00484 } 00485 00486 /** 00487 * Process multiple received byte, completed packets are put on a queue that is 00488 * fed into IP through slipif_process_rxqueue(). 00489 * 00490 * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. 00491 * 00492 * @param netif The lwip network interface structure for this slipif 00493 * @param data received character 00494 * @param len Number of received characters 00495 */ 00496 void 00497 slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) 00498 { 00499 u8_t i; 00500 u8_t *rxdata = data; 00501 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00502 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00503 00504 for (i = 0; i < len; i++, rxdata++) { 00505 slipif_rxbyte_enqueue(netif, *rxdata); 00506 } 00507 } 00508 #endif /* SLIP_RX_FROM_ISR */ 00509 00510 #endif /* LWIP_HAVE_SLIPIF */
Generated on Wed Jul 13 2022 09:48:38 by 1.7.2