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 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 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 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