blob: 3b448f4d176d231a344d85e242f885cc5db07233 (
plain) (
tree)
|
|
/* SLIP send/recv code, from RFC 1055 */
#include <stdio.h> /* 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
}
|