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