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