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