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