1 /*
2 * sysdep1.c system dependant routines.
3 *
4 * m_dtrtoggle - dropt dtr and raise it again
5 * m_break - send BREAK signal
6 * m_getdcd - get modem dcd status
7 * m_setdcd - set modem dcd status
8 * m_savestate - save modem state
9 * m_restorestate - restore saved modem state
10 * m_nohang - tell driver not to hang up at DTR drop
11 * m_hupcl - set hangup on close on/off
12 * m_setparms - set speed, parity, bits and stopbits
13 * m_readchk - see if there is input waiting.
14 * m_wait - wait for child to finish. Sysdep. too.
15 *
16 * If it's possible, Posix termios are preferred.
17 *
18 * This file is part of the minicom communications package,
19 * Copyright 1991-1995 Miquel van Smoorenburg.
20 *
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version
24 * 2 of the License, or (at your option) any later version.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 *
30 * jl 23.06.97 adjustable DTR downtime
31 */
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include "sysdep.h"
37 #include "minicom.h"
38
39 /* Set hardware flow control. */
m_sethwf(int fd,int on)40 void m_sethwf(int fd, int on)
41 {
42 #ifdef POSIX_TERMIOS
43 struct termios tty;
44 #endif
45
46 #ifdef USE_SOCKET
47 if (portfd_is_socket)
48 return;
49 #endif
50
51 #ifdef POSIX_TERMIOS
52 tcgetattr(fd, &tty);
53 if (on)
54 tty.c_cflag |= CRTSCTS;
55 else
56 tty.c_cflag &= ~CRTSCTS;
57 tcsetattr(fd, TCSANOW, &tty);
58 #endif
59 }
60
61 /* Set RTS line. Sometimes dropped. Linux specific? */
m_setrts(int fd)62 static void m_setrts(int fd)
63 {
64 #ifdef USE_SOCKET
65 if (portfd_is_socket)
66 return;
67 #endif
68 #if defined(TIOCM_RTS) && defined(TIOCMGET)
69 {
70 int mcs=0;
71
72 ioctl(fd, TIOCMGET, &mcs);
73 mcs |= TIOCM_RTS;
74 ioctl(fd, TIOCMSET, &mcs);
75 }
76 #endif
77 }
78
79 /*
80 * Drop DTR line and raise it again.
81 */
m_dtrtoggle(int fd,int sec)82 void m_dtrtoggle(int fd, int sec)
83 {
84 #ifdef USE_SOCKET
85 if (portfd_is_socket)
86 return;
87 #endif
88 {
89 #ifdef TIOCSDTR
90 /* Use the ioctls meant for this type of thing. */
91 ioctl(fd, TIOCCDTR, 0);
92 if (sec>0) {
93 sleep(sec);
94 ioctl(fd, TIOCSDTR, 0);
95 }
96
97 #else /* TIOCSDTR */
98 # if defined (POSIX_TERMIOS)
99
100 /* Posix - set baudrate to 0 and back */
101 struct termios tty, old;
102
103 tcgetattr(fd, &tty);
104 tcgetattr(fd, &old);
105 cfsetospeed(&tty, B0);
106 cfsetispeed(&tty, B0);
107 tcsetattr(fd, TCSANOW, &tty);
108 if (sec > 0) {
109 sleep(sec);
110 tcsetattr(fd, TCSANOW, &old);
111 }
112
113 # else /* POSIX */
114 # ifdef _V7
115
116 /* Just drop speed to 0 and back to normal again */
117 struct sgttyb sg, ng;
118
119 ioctl(fd, TIOCGETP, &sg);
120 ioctl(fd, TIOCGETP, &ng);
121
122 ng.sg_ispeed = ng.sg_ospeed = 0;
123 ioctl(fd, TIOCSETP, &ng);
124 if (sec > 0) {
125 sleep(sec);
126 ioctl(fd, TIOCSETP, &sg);
127 }
128
129 # endif /* _V7 */
130 # endif /* POSIX */
131 #endif /* TIOCSDTR */
132 }
133 }
134
135 /*
136 * Send a break
137 */
m_break(int fd)138 void m_break(int fd)
139 {
140 #ifdef USE_SOCKET
141 if (portfd_is_socket)
142 return;
143 #endif
144 #ifdef POSIX_TERMIOS
145 tcsendbreak(fd, 0);
146 #else
147 # ifdef _V7
148 # ifndef TIOCSBRK
149 {
150 struct sgttyb sg, ng;
151
152 ioctl(fd, TIOCGETP, &sg);
153 ioctl(fd, TIOCGETP, &ng);
154 ng.sg_ispeed = ng.sg_ospeed = B110;
155 ng.sg_flags = BITS8 | RAW;
156 ioctl(fd, TIOCSETP, &ng);
157 write(fd, "\0\0\0\0\0\0\0\0\0\0", 10);
158 ioctl(fd, TIOCSETP, &sg);
159 }
160 # else
161 ioctl(fd, TIOCSBRK, 0);
162 sleep(1);
163 ioctl(fd, TIOCCBRK, 0);
164 # endif
165 # endif
166 #endif
167 }
168
169 /*
170 * Get the dcd status
171 */
m_getdcd(int fd)172 int m_getdcd(int fd)
173 {
174 #ifdef USE_SOCKET
175 if (portfd_is_socket) {
176 if (portfd_is_connected)
177 return 1;
178 /* we are not connected so this may be a good point to try to connect */
179 term_socket_connect();
180 return portfd_is_connected;
181 }
182 #endif
183 #ifdef TIOCMODGET
184 {
185 int mcs = 0;
186
187 if (ioctl(fd, TIOCMODGET, &mcs) < 0)
188 return -1;
189 return mcs & TIOCM_CAR ? 1 : 0;
190 }
191 #else
192 (void)fd;
193 return 0; /* Impossible!! (eg. Coherent) */
194 #endif
195 }
196
197 /* Variables to save states in */
198 #ifdef POSIX_TERMIOS
199 static struct termios savetty;
200 static int m_word;
201 #else
202 # if defined (_BSD43) || defined (_V7)
203 static struct sgttyb sg;
204 static struct tchars tch;
205 static int lsw;
206 static int m_word;
207 # endif
208 #endif
209
210 /*
211 * Save the state of a port
212 */
m_savestate(int fd)213 void m_savestate(int fd)
214 {
215 #ifdef USE_SOCKET
216 if (portfd_is_socket)
217 return;
218 #endif
219 #ifdef POSIX_TERMIOS
220 tcgetattr(fd, &savetty);
221 #else
222 # if defined(_BSD43) || defined(_V7)
223 ioctl(fd, TIOCGETP, &sg);
224 ioctl(fd, TIOCGETC, &tch);
225 # endif
226 # ifdef _BSD43
227 ioctl(fd, TIOCLGET, &lsw);
228 # endif
229 #endif
230 #ifdef TIOCMGET
231 ioctl(fd, TIOCMGET, &m_word);
232 #endif
233 }
234
235 /*
236 * Restore the state of a port
237 */
m_restorestate(int fd)238 void m_restorestate(int fd)
239 {
240 #ifdef USE_SOCKET
241 if (portfd_is_socket)
242 return;
243 #endif
244 #ifdef POSIX_TERMIOS
245 tcsetattr(fd, TCSANOW, &savetty);
246 #else
247 # if defined(_BSD43) || defined(_V7)
248 ioctl(fd, TIOCSETP, &sg);
249 ioctl(fd, TIOCSETC, &tch);
250 # endif
251 # ifdef _BSD43
252 ioctl(fd, TIOCLSET, &lsw);
253 # endif
254 #endif
255 #ifdef TIOCMSET
256 ioctl(fd, TIOCMSET, &m_word);
257 #endif
258 }
259
260 /*
261 * Set the line status so that it will not kill our process
262 * if the line hangs up.
263 */
264 /*ARGSUSED*/
m_nohang(int fd)265 void m_nohang(int fd)
266 {
267 #ifdef USE_SOCKET
268 if (portfd_is_socket)
269 return;
270 #endif
271 {
272 #ifdef POSIX_TERMIOS
273 struct termios sgg;
274
275 tcgetattr(fd, &sgg);
276 sgg.c_cflag |= CLOCAL;
277 tcsetattr(fd, TCSANOW, &sgg);
278 #else
279 # if defined (_BSD43) && defined(LNOHANG)
280 int lsw;
281
282 ioctl(fd, TIOCLGET, &lsw);
283 lsw |= LNOHANG;
284 ioctl(fd, TIOCLSET, &lsw);
285 # endif
286 #endif
287 }
288 }
289
290 /*
291 * Set hangup on close on/off.
292 */
m_hupcl(int fd,int on)293 void m_hupcl(int fd, int on)
294 {
295 #ifdef USE_SOCKET
296 if (portfd_is_socket)
297 return;
298 #endif
299 /* Eh, I don't know how to do this under BSD (yet..) */
300 #ifdef POSIX_TERMIOS
301 {
302 struct termios sgg;
303
304 tcgetattr(fd, &sgg);
305 if (on)
306 sgg.c_cflag |= HUPCL;
307 else
308 sgg.c_cflag &= ~HUPCL;
309 tcsetattr(fd, TCSANOW, &sgg);
310 }
311 #endif
312 }
313
314 /*
315 * See if there is input waiting.
316 * returns: 0=nothing, >0=something, -1=can't.
317 */
m_readchk(int fd)318 int m_readchk(int fd)
319 {
320 #ifdef FIONREAD
321 long i = -1;
322
323 ioctl(fd, FIONREAD, &i);
324 return (int)i;
325 #else
326 # if defined(F_GETFL) && defined(O_NDELAY)
327 int i, old;
328 char c;
329
330 old = fcntl(fd, F_GETFL, 0);
331 fcntl(fd, F_SETFL, old | O_NDELAY);
332 i = read(fd, &c, 1);
333 fcntl(fd, F_SETFL, old);
334
335 return i;
336 # else
337 return -1;
338 # endif
339 #endif
340 }
341
342 /*
343 * Get maximum speed.
344 * Returns maximum speed in baud
345 */
m_getmaxspd(void)346 unsigned m_getmaxspd(void)
347 {
348 #if defined(B4000000)
349 return 4000000;
350 #elif defined(B3500000)
351 return 3500000;
352 #elif defined(B3000000)
353 return 3000000;
354 #elif defined(B2500000)
355 return 2500000;
356 #elif defined(B2000000)
357 return 2000000;
358 #elif defined(B1500000)
359 return 1500000;
360 #elif defined(B1152000)
361 return 1152000;
362 #elif defined(B1000000)
363 return 1000000;
364 #elif defined(B921600)
365 return 921600;
366 #elif defined(B576000)
367 return 576000;
368 #elif defined(B500000)
369 return 500000;
370 #elif defined(B460800)
371 return 460800;
372 #elif defined(B230400)
373 return 230400;
374 #elif defined(B115200)
375 return 115200;
376 #elif defined(B57600)
377 return 57600;
378 #elif defined(B38400)
379 return 38400;
380 #elif defined(EXTB)
381 return 38400;
382 #elif defined(B19200)
383 return 19200;
384 #elif defined(EXTA)
385 return 19200;
386 #else
387 return 9600;
388 #endif
389 }
390
391 /*
392 * Set baudrate, parity and number of bits.
393 */
m_setparms(int fd,char * baudr,char * par,char * bits,char * stopb,int hwf,int swf)394 void m_setparms(int fd, char *baudr, char *par, char *bits, char *stopb,
395 int hwf, int swf)
396 {
397 int spd = -1;
398 int newbaud;
399 int bit = bits[0];
400
401 #ifdef POSIX_TERMIOS
402 struct termios tty;
403 #else /* POSIX_TERMIOS */
404 struct sgttyb tty;
405 #endif /* POSIX_TERMIOS */
406
407 #ifdef USE_SOCKET
408 if (portfd_is_socket)
409 return;
410 #endif
411
412 #ifdef POSIX_TERMIOS
413 tcgetattr(fd, &tty);
414 #else /* POSIX_TERMIOS */
415 ioctl(fd, TIOCGETP, &tty);
416 #endif /* POSIX_TERMIOS */
417
418
419 /* We generate mark and space parity ourself. */
420 if (bit == '7' && (par[0] == 'M' || par[0] == 'S'))
421 bit = '8';
422
423 /* Check if 'baudr' is really a number */
424 if ((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0')
425 newbaud = -1;
426
427 switch (newbaud) {
428 case 0:
429 #ifdef B0
430 spd = B0;
431 #else
432 spd = 0;
433 #endif
434 break;
435 case 3: spd = B300; break;
436 case 6: spd = B600; break;
437 case 12: spd = B1200; break;
438 case 24: spd = B2400; break;
439 case 48: spd = B4800; break;
440 case 96: spd = B9600; break;
441 #ifdef B19200
442 case 192: spd = B19200; break;
443 #else /* B19200 */
444 # ifdef EXTA
445 case 192: spd = EXTA; break;
446 # else /* EXTA */
447 case 192: spd = B9600; break;
448 # endif /* EXTA */
449 #endif /* B19200 */
450 #ifdef B38400
451 case 384: spd = B38400; break;
452 #else /* B38400 */
453 # ifdef EXTB
454 case 384: spd = EXTB; break;
455 # else /* EXTB */
456 case 384: spd = B9600; break;
457 # endif /* EXTB */
458 #endif /* B38400 */
459 #ifdef B57600
460 case 576: spd = B57600; break;
461 #endif
462 #ifdef B115200
463 case 1152: spd = B115200; break;
464 #endif
465 #ifdef B230400
466 case 2304: spd = B230400; break;
467 #endif
468 #ifdef B460800
469 case 4608: spd = B460800; break;
470 #endif
471 #ifdef B500000
472 case 5000: spd = B500000; break;
473 #endif
474 #ifdef B576000
475 case 5760: spd = B576000; break;
476 #endif
477 #ifdef B921600
478 case 9216: spd = B921600; break;
479 #endif
480 #ifdef B1000000
481 case 10000: spd = B1000000; break;
482 #endif
483 #ifdef B1152000
484 case 11520: spd = B1152000; break;
485 #endif
486 #ifdef B1500000
487 case 15000: spd = B1500000; break;
488 #endif
489 #ifdef B2000000
490 case 20000: spd = B2000000; break;
491 #endif
492 #ifdef B2500000
493 case 25000: spd = B2500000; break;
494 #endif
495 #ifdef B3000000
496 case 30000: spd = B3000000; break;
497 #endif
498 #ifdef B3500000
499 case 35000: spd = B3500000; break;
500 #endif
501 #ifdef B4000000
502 case 40000: spd = B4000000; break;
503 #endif
504 }
505
506 #if defined (_BSD43) && !defined(POSIX_TERMIOS)
507 if (spd != -1)
508 tty.sg_ispeed = tty.sg_ospeed = spd;
509 /* Number of bits is ignored */
510
511 tty.sg_flags = RAW | TANDEM;
512 if (par[0] == 'E')
513 tty.sg_flags |= EVENP;
514 else if (par[0] == 'O')
515 tty.sg_flags |= ODDP;
516 else
517 tty.sg_flags |= PASS8 | ANYP;
518
519 ioctl(fd, TIOCSETP, &tty);
520
521 # ifdef TIOCSDTR
522 /* FIXME: huh? - MvS */
523 ioctl(fd, TIOCSDTR, 0);
524 # endif
525 #endif /* _BSD43 && !POSIX_TERMIOS */
526
527 #if defined (_V7) && !defined(POSIX_TERMIOS)
528 if (spd != -1)
529 tty.sg_ispeed = tty.sg_ospeed = spd;
530 tty.sg_flags = RAW;
531 if (par[0] == 'E')
532 tty.sg_flags |= EVENP;
533 else if (par[0] == 'O')
534 tty.sg_flags |= ODDP;
535
536 ioctl(fd, TIOCSETP, &tty);
537 #endif /* _V7 && !POSIX */
538
539 #ifdef POSIX_TERMIOS
540
541 if (spd != -1) {
542 cfsetospeed(&tty, (speed_t)spd);
543 cfsetispeed(&tty, (speed_t)spd);
544 }
545
546 switch (bit) {
547 case '5':
548 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5;
549 break;
550 case '6':
551 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6;
552 break;
553 case '7':
554 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7;
555 break;
556 case '8':
557 default:
558 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
559 break;
560 }
561 /* Set into raw, no echo mode */
562 tty.c_iflag = IGNBRK;
563 tty.c_lflag = 0;
564 tty.c_oflag = 0;
565 tty.c_cflag |= CLOCAL | CREAD;
566 #ifdef _DCDFLOW
567 tty.c_cflag &= ~CRTSCTS;
568 #endif
569 tty.c_cc[VMIN] = 1;
570 tty.c_cc[VTIME] = 5;
571
572 if (swf)
573 tty.c_iflag |= IXON | IXOFF;
574 else
575 tty.c_iflag &= ~(IXON|IXOFF|IXANY);
576
577 tty.c_cflag &= ~(PARENB | PARODD);
578 if (par[0] == 'E')
579 tty.c_cflag |= PARENB;
580 else if (par[0] == 'O')
581 tty.c_cflag |= (PARENB | PARODD);
582
583 if (stopb[0] == '2')
584 tty.c_cflag |= CSTOPB;
585 else
586 tty.c_cflag &= ~CSTOPB;
587
588 tcsetattr(fd, TCSANOW, &tty);
589
590 m_setrts(fd);
591 #endif /* POSIX_TERMIOS */
592
593 #ifndef _DCDFLOW
594 m_sethwf(fd, hwf);
595 #endif
596 }
597
598 /*
599 * Wait for child and return pid + status
600 */
m_wait(int * stt)601 int m_wait(int *stt)
602 {
603 #if defined (_BSD43) && !defined(POSIX_TERMIOS)
604 int pid;
605 union wait st1;
606
607 pid = wait((void *)&st1);
608 *stt = (unsigned)st1.w_retcode + 256 * (unsigned)st1.w_termsig;
609 return pid;
610 #else
611 int pid;
612 int st1;
613
614 pid = wait(&st1);
615 *stt = (unsigned)WEXITSTATUS(st1) + 256 * (unsigned)WTERMSIG(st1);
616 return pid;
617 #endif
618 }
619