1 #define TTY_BUFSIZE 1024 /* size of one serial buffer */
7 } tty_speeds[] = { /* table of usable baud rates */
8 { "50", B50 }, { "75", B75 },
9 { "110", B110 }, { "300", B300 },
10 { "600", B600 }, { "1200", B1200 },
11 { "2400", B2400 }, { "4800", B4800 },
26 { "115200", B115200 },
30 static struct termios tty_saved, /* saved TTY device state */
31 tty_current; /* current TTY device state */
32 static char *in_buff, /* line input/output buffers */
36 static int in_size, /* buffer sizes and counters */
40 tty_sdisc, /* saved TTY line discipline */
41 tty_ldisc, /* current TTY line discipline */
42 tty_fd = -1; /* TTY file descriptor */
45 /* Find a serial speed code in the table. */
47 tty_find_speed(char *speed)
52 while (tty_speeds[i].speed != NULL) {
53 if (!strcmp(tty_speeds[i].speed, speed)) return(tty_speeds[i].code);
60 /* Set the number of stop bits. */
62 tty_set_stopbits(struct termios *tty, char *stopbits)
66 tty->c_cflag &= ~CSTOPB;
70 tty->c_cflag |= CSTOPB;
76 if (opt_v) printf("STOPBITS = %c\n", *stopbits);
81 /* Set the number of data bits. */
83 tty_set_databits(struct termios *tty, char *databits)
85 tty->c_cflag &= ~CSIZE;
106 if (opt_v) printf("DATABITS = %c\n", *databits);
111 /* Set the type of parity encoding. */
113 tty_set_parity(struct termios *tty, char *parity)
115 switch(toupper(*parity)) {
117 tty->c_cflag &= ~(PARENB | PARODD);
121 tty->c_cflag &= ~(PARENB | PARODD);
122 tty->c_cflag |= (PARENB | PARODD);
126 tty->c_cflag &= ~(PARENB | PARODD);
127 tty->c_cflag |= (PARENB);
133 if (opt_v) printf("PARITY = %c\n", *parity);
138 /* Set the line speed of a terminal line. */
140 tty_set_speed(struct termios *tty, char *speed)
144 if ((code = tty_find_speed(speed)) < 0) return(code);
145 tty->c_cflag &= ~CBAUD;
146 tty->c_cflag |= code;
151 /* Put a terminal line in a transparent state. */
153 tty_set_raw(struct termios *tty)
158 for(i = 0; i < NCCS; i++)
159 tty->c_cc[i] = '\0'; /* no spec chr */
161 tty->c_cc[VTIME] = 0;
162 tty->c_iflag = (IGNBRK | IGNPAR); /* input flags */
163 tty->c_oflag = (0); /* output flags */
164 tty->c_lflag = (0); /* local flags */
165 speed = (tty->c_cflag & CBAUD); /* save current speed */
166 tty->c_cflag = (CRTSCTS | HUPCL | CREAD); /* UART flags */
168 tty->c_cflag |= CLOCAL; /* not good! */
170 tty->c_cflag |= speed; /* restore speed */
175 /* Fetch the state of a terminal. */
177 tty_get_state(struct termios *tty)
179 if (ioctl(tty_fd, TCGETS, tty) < 0) {
180 fprintf(stderr, "dip: tty_get_state: %s\n", strerror(errno));
187 /* Set the state of a terminal. */
189 tty_set_state(struct termios *tty)
191 if (ioctl(tty_fd, TCSETS, tty) < 0) {
192 fprintf(stderr, "dip: tty_set_state: %s\n", strerror(errno));
199 /* Get the line discipline of a terminal line. */
201 tty_get_disc(int *disc)
203 if (ioctl(tty_fd, TIOCGETD, disc) < 0) {
204 fprintf(stderr, "dip: tty_get_disc: %s\n", strerror(errno));
211 /* Set the line discipline of a terminal line. */
213 tty_set_disc(int disc)
215 if (disc == -1) disc = tty_sdisc;
217 if (ioctl(tty_fd, TIOCSETD, &disc) < 0) {
218 fprintf(stderr, "dip: tty_set_disc(%d): %s\n", disc, strerror(errno));
225 /* Get the encapsulation type of a terminal line. */
227 tty_get_encap(int *encap)
229 if (ioctl(tty_fd, SIOCGIFENCAP, encap) < 0) {
230 fprintf(stderr, "dip: tty_get_encap: %s\n", strerror(errno));
237 /* Set the encapsulation type of a terminal line. */
239 tty_set_encap(int encap)
241 if (ioctl(tty_fd, SIOCSIFENCAP, &encap) < 0) {
242 fprintf(stderr, "dip: tty_set_encap(%d): %s\n", encap, strerror(errno));
249 /* Fetch the name of the network interface attached to this terminal. */
251 tty_get_name(char *name)
253 if (ioctl(tty_fd, SIOCGIFNAME, name) < 0) {
254 fprintf(stderr, "dip: tty_get_name: %s\n", strerror(errno));
261 /* Read one character (byte) from the TTY link. */
268 s = read(tty_fd, in_buff, in_size);
269 if (s < 0) return(-1);
275 if (opt_v == 1) printf("dip: tty_getc: I/O error.\n");
287 /* Write one character (byte) to the TTY link. */
293 if ((out_cnt == out_size) || (c == -1)) {
294 s = write(tty_fd, out_buff, out_cnt);
297 if (s < 0) return(-1);
310 /* Output a string of characters to the TTY link. */
314 while(*s != '\0') tty_putc((int) *s++);
315 tty_putc(-1); /* flush */
319 /* Return the TTY link's file descriptor. */
327 /* Set the number of databits a terminal line. */
329 tty_databits(char *bits)
331 if (tty_set_databits(&tty_current, bits) < 0) return(-1);
332 return(tty_set_state(&tty_current));
336 /* Set the number of stopbits of a terminal line. */
338 tty_stopbits(char *bits)
340 if (tty_set_stopbits(&tty_current, bits) < 0) return(-1);
341 return(tty_set_state(&tty_current));
345 /* Set the type of parity of a terminal line. */
347 tty_parity(char *type)
349 if (tty_set_parity(&tty_current, type) < 0) return(-1);
350 return(tty_set_state(&tty_current));
354 /* Set the line speed of a terminal line. */
356 tty_speed(char *speed)
358 if (tty_set_speed(&tty_current, speed) < 0) return(-1);
359 return(tty_set_state(&tty_current));
363 /* Hangup the line. */
370 (void) tty_set_speed(&tty, "0");
371 if (tty_set_state(&tty) < 0) {
372 fprintf(stderr, "dip: tty_hangup(DROP): %s\n", strerror(errno));
378 if (tty_set_state(&tty_current) < 0) {
379 fprintf(stderr, "dip: tty_hangup(RAISE): %s\n", strerror(errno));
386 /* Close down a terminal line. */
391 (void) tty_set_disc(tty_sdisc);
396 /* Open and initialize a terminal line. */
404 /* Try opening the TTY device. */
406 if ((sp = strrchr(name, '/')) != (char *)NULL) *sp++ = '\0';
408 sprintf(path, "/dev/%s", sp);
409 if ((fd = open(path, O_RDWR)) < 0) {
410 fprintf(stderr, "dip: tty_open(%s, RW): %s\n",
411 path, strerror(errno));
415 if (opt_v) printf("TTY = %s (%d) ", path, fd);
418 /* Size and allocate the I/O buffers. */
419 in_size = TTY_BUFSIZE;
421 in_buff = (char *) malloc(in_size);
422 out_buff = (char *) malloc(out_size);
423 if (in_buff == (char *)NULL || out_buff == (char *)NULL) {
424 fprintf(stderr, "dip: tty_open: cannot allocate(%d, %d) buffers (%d)\n",
425 in_size, out_size, errno);
432 out_size -= 4; /* safety */
433 if (opt_v) printf("IBUF=%d OBUF=%d\n", in_size, out_size);
435 /* Fetch the current state of the terminal. */
436 if (tty_get_state(&tty_saved) < 0) {
437 fprintf(stderr, "dip: tty_open: cannot get current state!\n");
440 tty_current = tty_saved;
442 /* Fetch the current line discipline of this terminal. */
443 if (tty_get_disc(&tty_sdisc) < 0) {
444 fprintf(stderr, "dip: tty_open: cannot get current line disc!\n");
447 tty_ldisc = tty_sdisc;
449 /* Put this terminal line in a 8-bit transparent mode. */
450 if (tty_set_raw(&tty_current) < 0) {
451 fprintf(stderr, "dip: tty_open: cannot set RAW mode!\n");
455 /* If we are running in MASTER mode, set the default speed. */
456 if ((name != NULL) && (tty_set_speed(&tty_current, "9600") != 0)) {
457 fprintf(stderr, "dip: tty_open: cannot set 9600 bps!\n");
461 /* Set up a completely 8-bit clean line. */
462 if (tty_set_databits(&tty_current, "8") ||
463 tty_set_stopbits(&tty_current, "1") ||
464 tty_set_parity(&tty_current, "N")) {
465 fprintf(stderr, "dip: tty_open: cannot set 8N1 mode!\n");
468 return(tty_set_state(&tty_current));