Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of F7_Ethernet by
slipif.c
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 02:45:41 by
1.7.2
