-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathslip.c
131 lines (116 loc) · 3.95 KB
/
slip.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* slip.c of arm_emulator
* Copyright (C) 2019-2020 hxdyxd <hxdyxd@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <slip.h>
#include <sys/time.h>
#include <sys/select.h>
/* Blockable */
static inline void send_char(struct __kfifo *fifo, int ch, uint8_t *is_run)
{
while(__kfifo_in(fifo, &ch, 1) == 0 && *is_run) {
struct timeval timeout = {
.tv_sec = 0,
.tv_usec = 20,
};
select(0, NULL, NULL, NULL, &timeout);
}
}
#define FIFO_OUT_CHAR_PEEK(f,c,l) __kfifo_out_peek_one(f,c,l)
/* 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 */
void slip_send_packet(struct __kfifo *fifo, uint8_t *buf, int len, uint8_t *is_run)
{
/* send an initial END character to flush out any data that may
* have accumulated in the receiver due to line noise
*/
send_char(fifo, END, is_run);
/* for each byte in the packet, send the appropriate character
* sequence
*/
while(len--) {
switch(*buf) {
/* 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:
send_char(fifo, ESC, is_run);
send_char(fifo, ESC_END, is_run);
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:
send_char(fifo, ESC, is_run);
send_char(fifo, ESC_ESC, is_run);
break;
/* otherwise, we just send the character
*/
default:
send_char(fifo, *buf, is_run);
}
buf++;
}
/* tell the receiver that we're done sending the packet */
send_char(fifo, END, is_run);
}
int slip_recv_poll(struct __kfifo *fifo, uint8_t *buf, int len)
{
uint8_t ch;
int fifo_out = 0;
int received = 0;
while(FIFO_OUT_CHAR_PEEK(fifo, &ch, fifo_out+1) == fifo_out+1) {
fifo_out++;
switch(ch) {
case END:
if(received) {
fifo->out += fifo_out;
return received;
} else {
break;
}
case ESC:
if(FIFO_OUT_CHAR_PEEK(fifo, &ch, fifo_out+1) == fifo_out+1) {
fifo_out++;
switch(ch) {
case ESC_END:
ch = END;
break;
case ESC_ESC:
ch = ESC;
break;
}
} else {
return 0;
}
default:
if(received < len) {
buf[received++] = ch;
} else {
//long packet
fifo->out += fifo_out;
return received;
}
}
}
return 0;
}
/*****************************END OF FILE***************************/