fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 385 lines 6.7 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/devices/slip.c * 7 * Created: 2004-12-15 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2004-2009 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <config.h> 24 25#include <stdio.h> 26#include <stdlib.h> 27 28#ifdef PCE_ENABLE_TUN 29#include <lib/tun.h> 30#endif 31 32#include "slip.h" 33 34 35/* #define SLIP_DEBUG 1 */ 36 37/* receive packet buffer */ 38#define SLIP_PACKET_BUFFER 8 39 40 41void slip_init (slip_t *slip) 42{ 43 slip->out_cnt = 0; 44 slip->out_esc = 0; 45 46 slip->inp_hd = NULL; 47 slip->inp_tl = NULL; 48 slip->inp_cnt = 0; 49 50 slip->tun_fd = -1; 51 52 slip->checking = 0; 53 54 slip->get_uint8 = NULL; 55 slip->get_uint8_ext = NULL; 56 57 slip->set_uint8 = NULL; 58 slip->set_uint8_ext = NULL; 59} 60 61void slip_free (slip_t *slip) 62{ 63#ifdef PCE_ENABLE_TUN 64 if (slip->tun_fd >= 0) { 65 tun_close (slip->tun_fd); 66 } 67#endif 68} 69 70slip_t *slip_new (void) 71{ 72 slip_t *slip; 73 74 slip = malloc (sizeof (slip_t)); 75 if (slip == NULL) { 76 return (NULL); 77 } 78 79 slip_init (slip); 80 81 return (slip); 82} 83 84void slip_del (slip_t *slip) 85{ 86 if (slip != NULL) { 87 slip_free (slip); 88 free (slip); 89 } 90} 91 92void slip_set_set_uint8_fct (slip_t *slip, void *ext, void *fct) 93{ 94 slip->set_uint8 = fct; 95 slip->set_uint8_ext = ext; 96} 97 98void slip_set_get_uint8_fct (slip_t *slip, void *ext, void *fct) 99{ 100 slip->get_uint8 = fct; 101 slip->get_uint8_ext = ext; 102} 103 104int slip_set_tun (slip_t *slip, const char *name) 105{ 106#ifdef PCE_ENABLE_TUN 107 if (slip->tun_fd >= 0) { 108 tun_close (slip->tun_fd); 109 } 110 111 slip->tun_fd = tun_open (name); 112 if (slip->tun_fd < 0) { 113 return (1); 114 } 115 116 return (0); 117#else 118 return (1); 119#endif 120} 121 122 123static 124int slip_get_uint8 (slip_t *slip, unsigned char *val) 125{ 126 if (slip->get_uint8 != NULL) { 127 return (slip->get_uint8 (slip->get_uint8_ext, val)); 128 } 129 130 return (1); 131} 132 133static 134int slip_set_uint8 (slip_t *slip, unsigned char val) 135{ 136 if (slip->set_uint8 != NULL) { 137 return (slip->set_uint8 (slip->set_uint8_ext, val)); 138 } 139 140 return (1); 141} 142 143 144static 145slip_buf_t *slip_buf_alloc (slip_t *slip) 146{ 147 slip_buf_t *buf; 148 149 buf = malloc (sizeof (slip_buf_t)); 150 if (buf == NULL) { 151 return (0); 152 } 153 154 buf->next = NULL; 155 buf->i = 0; 156 buf->n = 0; 157 158 return (buf); 159} 160 161static 162void slip_buf_free (slip_t *slip, slip_buf_t *buf) 163{ 164 free (buf); 165} 166 167static 168void slip_send_packet (slip_t *slip) 169{ 170#ifdef PCE_ENABLE_TUN 171 if (slip->tun_fd >= 0) { 172#ifdef SLIP_DEBUG 173 fprintf (stderr, "slip: send tun S=%u\n", slip->out_cnt); 174 fflush (stderr); 175#endif 176 177 if (tun_set_packet (slip->tun_fd, slip->out, slip->out_cnt)) { 178 fprintf (stderr, "slip: packet drop\n"); 179 } 180 } 181#endif 182} 183 184static 185int slip_receive_packet (slip_t *slip) 186{ 187#ifdef PCE_ENABLE_TUN 188 unsigned i, j, n; 189 unsigned char tmp[PCE_SLIP_BUF_MAX]; 190 slip_buf_t *buf; 191 192 if (tun_check_packet (slip->tun_fd) == 0) { 193 return (1); 194 } 195 196 n = PCE_SLIP_BUF_MAX; 197 198 if (tun_get_packet (slip->tun_fd, tmp, &n)) { 199 return (1); 200 } 201 202 buf = slip_buf_alloc (slip); 203 if (buf == NULL) { 204 return (1); 205 } 206 207 j = 0; 208 buf->buf[j++] = 192; 209 210 for (i = 0; i < n; i++) { 211 if (tmp[i] == 192) { 212 if (j < PCE_SLIP_BUF_MAX) { 213 buf->buf[j++] = 219; 214 } 215 if (j < PCE_SLIP_BUF_MAX) { 216 buf->buf[j++] = 220; 217 } 218 } 219 else if (tmp[i] == 219) { 220 if (j < PCE_SLIP_BUF_MAX) { 221 buf->buf[j++] = 219; 222 } 223 if (j < PCE_SLIP_BUF_MAX) { 224 buf->buf[j++] = 221; 225 } 226 } 227 else { 228 if (j < PCE_SLIP_BUF_MAX) { 229 buf->buf[j++] = tmp[i]; 230 } 231 } 232 } 233 234 if (j < PCE_SLIP_BUF_MAX) { 235 buf->buf[j++] = 192; 236 } 237 238#ifdef SLIP_DEBUG 239 fprintf (stderr, "slip: recv tun S=%u+%u Q=%u\n", 240 n, j - n, slip->inp_cnt + 1 241 ); 242#endif 243 244 buf->n = j; 245 246 if (slip->inp_hd == NULL) { 247 slip->inp_hd = buf; 248 } 249 else { 250 slip->inp_tl->next = buf; 251 } 252 253 slip->inp_tl = buf; 254 slip->inp_cnt += 1; 255 256 return (0); 257#else 258 return (1); 259#endif 260} 261 262static 263void slip_set_out (slip_t *slip, unsigned char c) 264{ 265 if (c == 192) { 266 if (slip->out_cnt > 0) { 267 slip_send_packet (slip); 268 } 269 270 slip->out_cnt = 0; 271 slip->out_esc = 0; 272 273 return; 274 } 275 276 if (slip->out_esc) { 277 slip->out_esc = 0; 278 279 if (c == 220) { 280 c = 192; 281 } 282 else if (c == 221) { 283 c = 219; 284 } 285 else { 286 fprintf (stderr, "slip: unknown escape (%02X)\n", 287 (unsigned) c 288 ); 289 return; 290 } 291 } 292 else { 293 if (c == 219) { 294 slip->out_esc = 1; 295 return; 296 } 297 } 298 299 if (slip->out_cnt >= PCE_SLIP_BUF_MAX) { 300 fprintf (stderr, "slip: send buffer overrun\n"); 301 return; 302 } 303 304 slip->out[slip->out_cnt++] = c; 305} 306 307void slip_uart_check_out (slip_t *slip, unsigned char val) 308{ 309 unsigned char c; 310 311 if (slip->checking) { 312 return; 313 } 314 315 slip->checking = 1; 316 317 while (1) { 318 if (slip_get_uint8 (slip, &c)) { 319 break; 320 } 321 322 slip_set_out (slip, c); 323 } 324 325 slip->checking = 0; 326} 327 328void slip_uart_check_inp (slip_t *slip, unsigned char val) 329{ 330 if (slip->checking) { 331 return; 332 } 333 334 slip->checking = 1; 335 336 while (slip->inp_hd != NULL) { 337 slip_buf_t *buf; 338 339 buf = slip->inp_hd; 340 341 while (buf->i < buf->n) { 342 if (slip_set_uint8 (slip, buf->buf[buf->i])) { 343 break; 344 } 345 346 buf->i += 1; 347 } 348 349 if (buf->i < buf->n) { 350 break; 351 } 352 353#ifdef SLIP_DEBUG 354 fprintf (stderr, "slip: recv uart S=%u Q=%u\n", 355 buf->n, slip->inp_cnt - 1 356 ); 357#endif 358 359 if (buf->next == NULL) { 360 slip->inp_hd = NULL; 361 slip->inp_tl = NULL; 362 } 363 else { 364 slip->inp_hd = buf->next; 365 } 366 367 slip_buf_free (slip, buf); 368 369 slip->inp_cnt -= 1; 370 } 371 372 while (slip->inp_cnt < SLIP_PACKET_BUFFER) { 373 if (slip_receive_packet (slip)) { 374 break; 375 } 376 } 377 378 slip->checking = 0; 379} 380 381void slip_clock (slip_t *slip, unsigned n) 382{ 383 slip_uart_check_inp (slip, 1); 384 slip_uart_check_out (slip, 1); 385}