NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
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 11:52:58 by 1.7.2