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.
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 */ 00039 00040 /* 00041 * This is an arch independent SLIP netif. The specific serial hooks must be 00042 * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send 00043 */ 00044 00045 #include "netif/slipif.h" 00046 #include "lwip/opt.h" 00047 00048 #if LWIP_HAVE_SLIPIF 00049 00050 #include "lwip/def.h" 00051 #include "lwip/pbuf.h" 00052 #include "lwip/sys.h" 00053 #include "lwip/stats.h" 00054 #include "lwip/snmp.h" 00055 #include "lwip/sio.h" 00056 00057 #define SLIP_BLOCK 1 00058 #define SLIP_DONTBLOCK 0 00059 00060 #define SLIP_END 0300 /* 0xC0 */ 00061 #define SLIP_ESC 0333 /* 0xDB */ 00062 #define SLIP_ESC_END 0334 /* 0xDC */ 00063 #define SLIP_ESC_ESC 0335 /* 0xDD */ 00064 00065 #define SLIP_MAX_SIZE 1500 00066 00067 enum slipif_recv_state { 00068 SLIP_RECV_NORMAL, 00069 SLIP_RECV_ESCAPE, 00070 }; 00071 00072 struct slipif_priv { 00073 sio_fd_t sd; 00074 /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ 00075 struct pbuf *p, *q; 00076 enum slipif_recv_state state; 00077 u16_t i, recved; 00078 }; 00079 00080 /** 00081 * Send a pbuf doing the necessary SLIP encapsulation 00082 * 00083 * Uses the serial layer's sio_send() 00084 * 00085 * @param netif the lwip network interface structure for this slipif 00086 * @param p the pbuf chaing packet to send 00087 * @param ipaddr the ip address to send the packet to (not used for slipif) 00088 * @return always returns ERR_OK since the serial layer does not provide return values 00089 */ 00090 err_t 00091 slipif_output(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr) 00092 { 00093 struct slipif_priv *priv; 00094 struct pbuf *q; 00095 u16_t i; 00096 u8_t c; 00097 00098 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00099 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00100 LWIP_ASSERT("p != NULL", (p != NULL)); 00101 00102 LWIP_UNUSED_ARG(ipaddr); 00103 00104 priv = netif->state; 00105 00106 /* Send pbuf out on the serial I/O device. */ 00107 sio_send(SLIP_END, priv->sd); 00108 00109 for (q = p; q != NULL; q = q->next) { 00110 for (i = 0; i < q->len; i++) { 00111 c = ((u8_t *)q->payload)[i]; 00112 switch (c) { 00113 case SLIP_END: 00114 sio_send(SLIP_ESC, priv->sd); 00115 sio_send(SLIP_ESC_END, priv->sd); 00116 break; 00117 case SLIP_ESC: 00118 sio_send(SLIP_ESC, priv->sd); 00119 sio_send(SLIP_ESC_ESC, priv->sd); 00120 break; 00121 default: 00122 sio_send(c, priv->sd); 00123 break; 00124 } 00125 } 00126 } 00127 sio_send(SLIP_END, priv->sd); 00128 return ERR_OK; 00129 } 00130 00131 /** 00132 * Static function for easy use of blockig or non-blocking 00133 * sio_read 00134 * 00135 * @param fd serial device handle 00136 * @param data pointer to data buffer for receiving 00137 * @param len maximum length (in bytes) of data to receive 00138 * @param block if 1, call sio_read; if 0, call sio_tryread 00139 * @return return value of sio_read of sio_tryread 00140 */ 00141 static u32_t 00142 slip_sio_read(sio_fd_t fd, u8_t* data, u32_t len, u8_t block) 00143 { 00144 if (block) { 00145 return sio_read(fd, data, len); 00146 } else { 00147 return sio_tryread(fd, data, len); 00148 } 00149 } 00150 00151 /** 00152 * Handle the incoming SLIP stream character by character 00153 * 00154 * Poll the serial layer by calling sio_read() or sio_tryread(). 00155 * 00156 * @param netif the lwip network interface structure for this slipif 00157 * @param block if 1, block until data is received; if 0, return when all data 00158 * from the buffer is received (multiple calls to this function will 00159 * return a complete packet, NULL is returned before - used for polling) 00160 * @return The IP packet when SLIP_END is received 00161 */ 00162 static struct pbuf * 00163 slipif_input(struct netif *netif, u8_t block) 00164 { 00165 struct slipif_priv *priv; 00166 u8_t c; 00167 struct pbuf *t; 00168 00169 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00170 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00171 00172 priv = netif->state; 00173 00174 while (slip_sio_read(priv->sd, &c, 1, block) > 0) { 00175 switch (priv->state) { 00176 case SLIP_RECV_NORMAL: 00177 switch (c) { 00178 case SLIP_END: 00179 if (priv->recved > 0) { 00180 /* Received whole packet. */ 00181 /* Trim the pbuf to the size of the received packet. */ 00182 pbuf_realloc(priv->q, priv->recved); 00183 00184 LINK_STATS_INC(link.recv); 00185 00186 LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n")); 00187 t = priv->q; 00188 priv->p = priv->q = NULL; 00189 priv->i = priv->recved = 0; 00190 return t; 00191 } 00192 continue; 00193 case SLIP_ESC: 00194 priv->state = SLIP_RECV_ESCAPE; 00195 continue; 00196 } 00197 break; 00198 case SLIP_RECV_ESCAPE: 00199 switch (c) { 00200 case SLIP_ESC_END: 00201 c = SLIP_END; 00202 break; 00203 case SLIP_ESC_ESC: 00204 c = SLIP_ESC; 00205 break; 00206 } 00207 priv->state = SLIP_RECV_NORMAL; 00208 /* FALLTHROUGH */ 00209 } 00210 00211 /* byte received, packet not yet completely received */ 00212 if (priv->p == NULL) { 00213 /* allocate a new pbuf */ 00214 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); 00215 priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL); 00216 00217 if (priv->p == NULL) { 00218 LINK_STATS_INC(link.drop); 00219 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); 00220 /* don't process any further since we got no pbuf to receive to */ 00221 break; 00222 } 00223 00224 if (priv->q != NULL) { 00225 /* 'chain' the pbuf to the existing chain */ 00226 pbuf_cat(priv->q, priv->p); 00227 } else { 00228 /* p is the first pbuf in the chain */ 00229 priv->q = priv->p; 00230 } 00231 } 00232 00233 /* this automatically drops bytes if > SLIP_MAX_SIZE */ 00234 if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { 00235 ((u8_t *)priv->p->payload)[priv->i] = c; 00236 priv->recved++; 00237 priv->i++; 00238 if (priv->i >= priv->p->len) { 00239 /* on to the next pbuf */ 00240 priv->i = 0; 00241 if (priv->p->next != NULL && priv->p->next->len > 0) { 00242 /* p is a chain, on to the next in the chain */ 00243 priv->p = priv->p->next; 00244 } else { 00245 /* p is a single pbuf, set it to NULL so next time a new 00246 * pbuf is allocated */ 00247 priv->p = NULL; 00248 } 00249 } 00250 } 00251 } 00252 00253 return NULL; 00254 } 00255 00256 #if !NO_SYS 00257 /** 00258 * The SLIP input thread. 00259 * 00260 * Feed the IP layer with incoming packets 00261 * 00262 * @param nf the lwip network interface structure for this slipif 00263 */ 00264 static void 00265 slipif_loop_thread(void *nf) 00266 { 00267 struct pbuf *p; 00268 struct netif *netif = (struct netif *)nf; 00269 00270 while (1) { 00271 p = slipif_input(netif, SLIP_BLOCK); 00272 if (p != NULL) { 00273 if (netif->input(p, netif) != ERR_OK) { 00274 pbuf_free(p); 00275 p = NULL; 00276 } 00277 } 00278 } 00279 } 00280 #endif /* !NO_SYS */ 00281 00282 /** 00283 * SLIP netif initialization 00284 * 00285 * Call the arch specific sio_open and remember 00286 * the opened device in the state field of the netif. 00287 * 00288 * @param netif the lwip network interface structure for this slipif 00289 * @return ERR_OK if serial line could be opened, 00290 * ERR_MEM if no memory could be allocated, 00291 * ERR_IF is serial line couldn't be opened 00292 * 00293 * @note netif->num must contain the number of the serial port to open 00294 * (0 by default) 00295 */ 00296 err_t 00297 slipif_init(struct netif *netif) 00298 { 00299 struct slipif_priv *priv; 00300 00301 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); 00302 00303 /* Allocate private data */ 00304 priv = mem_malloc(sizeof(struct slipif_priv)); 00305 if (!priv) { 00306 return ERR_MEM; 00307 } 00308 00309 netif->name[0] = 's'; 00310 netif->name[1] = 'l'; 00311 netif->output = slipif_output; 00312 netif->mtu = SLIP_MAX_SIZE; 00313 netif->flags |= NETIF_FLAG_POINTTOPOINT; 00314 00315 /* Try to open the serial port (netif->num contains the port number). */ 00316 priv->sd = sio_open(netif->num); 00317 if (!priv->sd) { 00318 /* Opening the serial port failed. */ 00319 mem_free(priv); 00320 return ERR_IF; 00321 } 00322 00323 /* Initialize private data */ 00324 priv->p = NULL; 00325 priv->q = NULL; 00326 priv->state = SLIP_RECV_NORMAL; 00327 priv->i = 0; 00328 priv->recved = 0; 00329 00330 netif->state = priv; 00331 00332 /* initialize the snmp variables and counters inside the struct netif 00333 * ifSpeed: no assumption can be made without knowing more about the 00334 * serial line! 00335 */ 00336 NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0); 00337 00338 /* Create a thread to poll the serial line. */ 00339 sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, 00340 SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); 00341 return ERR_OK; 00342 } 00343 00344 /** 00345 * Polls the serial device and feeds the IP layer with incoming packets. 00346 * 00347 * @param netif The lwip network interface structure for this slipif 00348 */ 00349 void 00350 slipif_poll(struct netif *netif) 00351 { 00352 struct pbuf *p; 00353 struct slipif_priv *priv; 00354 00355 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00356 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00357 00358 priv = netif->state; 00359 00360 while ((p = slipif_input(netif, SLIP_DONTBLOCK)) != NULL) { 00361 if (netif->input(p, netif) != ERR_OK) { 00362 pbuf_free(p); 00363 } 00364 } 00365 } 00366 00367 #endif /* LWIP_HAVE_SLIPIF */
Generated on Tue Jul 12 2022 17:34:53 by
