162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __UM_SLIP_COMMON_H
362306a36Sopenharmony_ci#define __UM_SLIP_COMMON_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#define BUF_SIZE 1500
662306a36Sopenharmony_ci /* two bytes each for a (pathological) max packet of escaped chars +  *
762306a36Sopenharmony_ci  * terminating END char + initial END char                            */
862306a36Sopenharmony_ci#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/* SLIP protocol characters. */
1162306a36Sopenharmony_ci#define SLIP_END             0300	/* indicates end of frame	*/
1262306a36Sopenharmony_ci#define SLIP_ESC             0333	/* indicates byte stuffing	*/
1362306a36Sopenharmony_ci#define SLIP_ESC_END         0334	/* ESC ESC_END means END 'data'	*/
1462306a36Sopenharmony_ci#define SLIP_ESC_ESC         0335	/* ESC ESC_ESC means ESC 'data'	*/
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistatic inline int slip_unesc(unsigned char c, unsigned char *buf, int *pos,
1762306a36Sopenharmony_ci                             int *esc)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	int ret;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	switch(c){
2262306a36Sopenharmony_ci	case SLIP_END:
2362306a36Sopenharmony_ci		*esc = 0;
2462306a36Sopenharmony_ci		ret=*pos;
2562306a36Sopenharmony_ci		*pos=0;
2662306a36Sopenharmony_ci		return(ret);
2762306a36Sopenharmony_ci	case SLIP_ESC:
2862306a36Sopenharmony_ci		*esc = 1;
2962306a36Sopenharmony_ci		return(0);
3062306a36Sopenharmony_ci	case SLIP_ESC_ESC:
3162306a36Sopenharmony_ci		if(*esc){
3262306a36Sopenharmony_ci			*esc = 0;
3362306a36Sopenharmony_ci			c = SLIP_ESC;
3462306a36Sopenharmony_ci		}
3562306a36Sopenharmony_ci		break;
3662306a36Sopenharmony_ci	case SLIP_ESC_END:
3762306a36Sopenharmony_ci		if(*esc){
3862306a36Sopenharmony_ci			*esc = 0;
3962306a36Sopenharmony_ci			c = SLIP_END;
4062306a36Sopenharmony_ci		}
4162306a36Sopenharmony_ci		break;
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci	buf[(*pos)++] = c;
4462306a36Sopenharmony_ci	return(0);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic inline int slip_esc(unsigned char *s, unsigned char *d, int len)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	unsigned char *ptr = d;
5062306a36Sopenharmony_ci	unsigned char c;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/*
5362306a36Sopenharmony_ci	 * Send an initial END character to flush out any
5462306a36Sopenharmony_ci	 * data that may have accumulated in the receiver
5562306a36Sopenharmony_ci	 * due to line noise.
5662306a36Sopenharmony_ci	 */
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	*ptr++ = SLIP_END;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	/*
6162306a36Sopenharmony_ci	 * For each byte in the packet, send the appropriate
6262306a36Sopenharmony_ci	 * character sequence, according to the SLIP protocol.
6362306a36Sopenharmony_ci	 */
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	while (len-- > 0) {
6662306a36Sopenharmony_ci		switch(c = *s++) {
6762306a36Sopenharmony_ci		case SLIP_END:
6862306a36Sopenharmony_ci			*ptr++ = SLIP_ESC;
6962306a36Sopenharmony_ci			*ptr++ = SLIP_ESC_END;
7062306a36Sopenharmony_ci			break;
7162306a36Sopenharmony_ci		case SLIP_ESC:
7262306a36Sopenharmony_ci			*ptr++ = SLIP_ESC;
7362306a36Sopenharmony_ci			*ptr++ = SLIP_ESC_ESC;
7462306a36Sopenharmony_ci			break;
7562306a36Sopenharmony_ci		default:
7662306a36Sopenharmony_ci			*ptr++ = c;
7762306a36Sopenharmony_ci			break;
7862306a36Sopenharmony_ci		}
7962306a36Sopenharmony_ci	}
8062306a36Sopenharmony_ci	*ptr++ = SLIP_END;
8162306a36Sopenharmony_ci	return (ptr - d);
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistruct slip_proto {
8562306a36Sopenharmony_ci	unsigned char ibuf[ENC_BUF_SIZE];
8662306a36Sopenharmony_ci	unsigned char obuf[ENC_BUF_SIZE];
8762306a36Sopenharmony_ci	int more; /* more data: do not read fd until ibuf has been drained */
8862306a36Sopenharmony_ci	int pos;
8962306a36Sopenharmony_ci	int esc;
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic inline void slip_proto_init(struct slip_proto * slip)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	memset(slip->ibuf, 0, sizeof(slip->ibuf));
9562306a36Sopenharmony_ci	memset(slip->obuf, 0, sizeof(slip->obuf));
9662306a36Sopenharmony_ci	slip->more = 0;
9762306a36Sopenharmony_ci	slip->pos = 0;
9862306a36Sopenharmony_ci	slip->esc = 0;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciextern int slip_proto_read(int fd, void *buf, int len,
10262306a36Sopenharmony_ci			   struct slip_proto *slip);
10362306a36Sopenharmony_ciextern int slip_proto_write(int fd, void *buf, int len,
10462306a36Sopenharmony_ci			    struct slip_proto *slip);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci#endif
107