xref: /linux/arch/um/drivers/slip_common.h (revision 6fdcba32711044c35c0e1b094cbd8f3f0b4472c9)
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 
16 static 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 
47 static 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 
84 struct 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 
92 static 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 
101 extern int slip_proto_read(int fd, void *buf, int len,
102 			   struct slip_proto *slip);
103 extern int slip_proto_write(int fd, void *buf, int len,
104 			    struct slip_proto *slip);
105 
106 #endif
107