/* SLIP send/recv code, from RFC 1055 */ #include /* perror */ #include "slip_internal.h" /* SLIP special character codes */ #define END 0300 /* indicates end of packet */ #define ESC 0333 /* indicates byte stuffing */ #define ESC_END 0334 /* ESC ESC_END means END data byte */ #define ESC_ESC 0335 /* ESC ESC_ESC means ESC data byte */ /* SLIP_SEND: sends a packet of length "len", starting at * location "p". */ int hal_slip_send(const uint8_t * const ptr, const size_t len) { int i; uint8_t *p = (uint8_t *)ptr; #define check_send_char(c) if (hal_slip_send_char(c) == -1) return perror("write"), -1; /* send an initial END character to flush out any data that may * have accumulated in the receiver due to line noise */ check_send_char(END); /* for each byte in the packet, send the appropriate character * sequence */ for (i = 0; i < len; ++i) { switch (*p) { /* if it's the same code as an END character, we send a * special two character code so as not to make the * receiver think we sent an END */ case END: check_send_char(ESC); check_send_char(ESC_END); break; /* if it's the same code as an ESC character, * we send a special two character code so as not * to make the receiver think we sent an ESC */ case ESC: check_send_char(ESC); check_send_char(ESC_ESC); break; /* otherwise, we just send the character */ default: check_send_char(*p); } p++; } /* tell the receiver that we're done sending the packet */ check_send_char(END); return 0; #undef check_send_char } /* SLIP_RECV: receives a packet into the buffer located at "p". * If more than len bytes are received, the packet will * be truncated. * Returns the number of bytes stored in the buffer. */ int hal_slip_recv(uint8_t * const p, const size_t len) { uint8_t c; size_t received = 0; #define check_recv_char(c) if (hal_slip_recv_char(&c) == -1) return perror("read"), -1; /* sit in a loop reading bytes until we put together * a whole packet. * Make sure not to copy them into the packet if we * run out of room. */ while (1) { /* get a character to process */ check_recv_char(c); /* handle bytestuffing if necessary */ switch (c) { /* if it's an END character then we're done with * the packet */ case END: /* a minor optimization: if there is no * data in the packet, ignore it. This is * meant to avoid bothering IP with all * the empty packets generated by the * duplicate END characters which are in * turn sent to try to detect line noise. */ if (received) return received; else break; /* if it's the same code as an ESC character, wait * and get another character and then figure out * what to store in the packet based on that. */ case ESC: check_recv_char(c); /* if "c" is not one of these two, then we * have a protocol violation. The best bet * seems to be to leave the byte alone and * just stuff it into the packet */ switch(c) { case ESC_END: c = END; break; case ESC_ESC: c = ESC; break; } /* here we fall into the default handler and let * it store the character for us */ default: if (received < len) p[received++] = c; } } #undef check_recv_char }