1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __UM_SLIP_COMMON_H
3#define __UM_SLIP_COMMON_H
4
5#define BUF_SIZE 1500
6 /* two bytes each for a (pathological) max packet of escaped chars +  *
7  * terminating END char + initial END char                            */
8#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
9
10/* SLIP protocol characters. */
11#define SLIP_END             0300	/* indicates end of frame	*/
12#define SLIP_ESC             0333	/* indicates byte stuffing	*/
13#define SLIP_ESC_END         0334	/* ESC ESC_END means END 'data'	*/
14#define SLIP_ESC_ESC         0335	/* ESC ESC_ESC means ESC 'data'	*/
15
16static inline int slip_unesc(unsigned char c, unsigned char *buf, int *pos,
17                             int *esc)
18{
19	int ret;
20
21	switch(c){
22	case SLIP_END:
23		*esc = 0;
24		ret=*pos;
25		*pos=0;
26		return(ret);
27	case SLIP_ESC:
28		*esc = 1;
29		return(0);
30	case SLIP_ESC_ESC:
31		if(*esc){
32			*esc = 0;
33			c = SLIP_ESC;
34		}
35		break;
36	case SLIP_ESC_END:
37		if(*esc){
38			*esc = 0;
39			c = SLIP_END;
40		}
41		break;
42	}
43	buf[(*pos)++] = c;
44	return(0);
45}
46
47static inline int slip_esc(unsigned char *s, unsigned char *d, int len)
48{
49	unsigned char *ptr = d;
50	unsigned char c;
51
52	/*
53	 * Send an initial END character to flush out any
54	 * data that may have accumulated in the receiver
55	 * due to line noise.
56	 */
57
58	*ptr++ = SLIP_END;
59
60	/*
61	 * For each byte in the packet, send the appropriate
62	 * character sequence, according to the SLIP protocol.
63	 */
64
65	while (len-- > 0) {
66		switch(c = *s++) {
67		case SLIP_END:
68			*ptr++ = SLIP_ESC;
69			*ptr++ = SLIP_ESC_END;
70			break;
71		case SLIP_ESC:
72			*ptr++ = SLIP_ESC;
73			*ptr++ = SLIP_ESC_ESC;
74			break;
75		default:
76			*ptr++ = c;
77			break;
78		}
79	}
80	*ptr++ = SLIP_END;
81	return (ptr - d);
82}
83
84struct slip_proto {
85	unsigned char ibuf[ENC_BUF_SIZE];
86	unsigned char obuf[ENC_BUF_SIZE];
87	int more; /* more data: do not read fd until ibuf has been drained */
88	int pos;
89	int esc;
90};
91
92static inline void slip_proto_init(struct slip_proto * slip)
93{
94	memset(slip->ibuf, 0, sizeof(slip->ibuf));
95	memset(slip->obuf, 0, sizeof(slip->obuf));
96	slip->more = 0;
97	slip->pos = 0;
98	slip->esc = 0;
99}
100
101extern int slip_proto_read(int fd, void *buf, int len,
102			   struct slip_proto *slip);
103extern int slip_proto_write(int fd, void *buf, int len,
104			    struct slip_proto *slip);
105
106#endif
107