Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / os-support / shared / posix_tty.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright 1993-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the XFree86 Project shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from the
25 * XFree86 Project.
26 */
27/*
28 *
29 * Copyright (c) 1997 Metro Link Incorporated
30 *
31 * Permission is hereby granted, free of charge, to any person obtaining a
32 * copy of this software and associated documentation files (the "Software"),
33 * to deal in the Software without restriction, including without limitation
34 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35 * and/or sell copies of the Software, and to permit persons to whom the
36 * Software is furnished to do so, subject to the following conditions:
37 *
38 * The above copyright notice and this permission notice shall be included in
39 * all copies or substantial portions of the Software.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
45 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
46 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
47 * SOFTWARE.
48 *
49 * Except as contained in this notice, the name of the Metro Link shall not be
50 * used in advertising or otherwise to promote the sale, use or other dealings
51 * in this Software without prior written authorization from Metro Link.
52 *
53 */
54
55#ifdef HAVE_XORG_CONFIG_H
56#include <xorg-config.h>
57#endif
58
59#include <X11/X.h>
60#include "xf86.h"
61#include "xf86Priv.h"
62#include "xf86_OSlib.h"
63
64static int
65GetBaud(int baudrate)
66{
67#ifdef B300
68 if (baudrate == 300)
69 return B300;
70#endif
71#ifdef B1200
72 if (baudrate == 1200)
73 return B1200;
74#endif
75#ifdef B2400
76 if (baudrate == 2400)
77 return B2400;
78#endif
79#ifdef B4800
80 if (baudrate == 4800)
81 return B4800;
82#endif
83#ifdef B9600
84 if (baudrate == 9600)
85 return B9600;
86#endif
87#ifdef B19200
88 if (baudrate == 19200)
89 return B19200;
90#endif
91#ifdef B38400
92 if (baudrate == 38400)
93 return B38400;
94#endif
95#ifdef B57600
96 if (baudrate == 57600)
97 return B57600;
98#endif
99#ifdef B115200
100 if (baudrate == 115200)
101 return B115200;
102#endif
103#ifdef B230400
104 if (baudrate == 230400)
105 return B230400;
106#endif
107#ifdef B460800
108 if (baudrate == 460800)
109 return B460800;
110#endif
111 return 0;
112}
113
114int
115xf86OpenSerial(XF86OptionPtr options)
116{
117 struct termios t;
118 int fd, i;
119 char *dev;
120
121 dev = xf86SetStrOption(options, "Device", NULL);
122 if (!dev) {
123 xf86Msg(X_ERROR, "xf86OpenSerial: No Device specified.\n");
124 return -1;
125 }
126
127 SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK));
128 if (fd == -1) {
129 xf86Msg(X_ERROR,
130 "xf86OpenSerial: Cannot open device %s\n\t%s.\n",
131 dev, strerror(errno));
132 free(dev);
133 return -1;
134 }
135
136 if (!isatty(fd)) {
137 /* Allow non-tty devices to be opened. */
138 free(dev);
139 return fd;
140 }
141
142 /* set up default port parameters */
143 SYSCALL(tcgetattr(fd, &t));
144 t.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
145 | IGNCR | ICRNL | IXON);
146 t.c_oflag &= ~OPOST;
147 t.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
148 t.c_cflag &= ~(CSIZE | PARENB);
149 t.c_cflag |= CS8 | CLOCAL;
150
151 cfsetispeed(&t, B9600);
152 cfsetospeed(&t, B9600);
153 t.c_cc[VMIN] = 1;
154 t.c_cc[VTIME] = 0;
155
156 SYSCALL(tcsetattr(fd, TCSANOW, &t));
157
158 if (xf86SetSerial(fd, options) == -1) {
159 SYSCALL(close(fd));
160 free(dev);
161 return -1;
162 }
163
164 SYSCALL(i = fcntl(fd, F_GETFL, 0));
165 if (i == -1) {
166 SYSCALL(close(fd));
167 free(dev);
168 return -1;
169 }
170 i &= ~O_NONBLOCK;
171 SYSCALL(i = fcntl(fd, F_SETFL, i));
172 if (i == -1) {
173 SYSCALL(close(fd));
174 free(dev);
175 return -1;
176 }
177 free(dev);
178 return fd;
179}
180
181int
182xf86SetSerial(int fd, XF86OptionPtr options)
183{
184 struct termios t;
185 int val;
186 const char *s;
187 int baud, r;
188
189 if (fd < 0)
190 return -1;
191
192 /* Don't try to set parameters for non-tty devices. */
193 if (!isatty(fd))
194 return 0;
195
196 SYSCALL(tcgetattr(fd, &t));
197
198 if ((val = xf86SetIntOption(options, "BaudRate", 0))) {
199 if ((baud = GetBaud(val))) {
200 cfsetispeed(&t, baud);
201 cfsetospeed(&t, baud);
202 }
203 else {
204 xf86Msg(X_ERROR, "Invalid Option BaudRate value: %d\n", val);
205 return -1;
206 }
207 }
208
209 if ((val = xf86SetIntOption(options, "StopBits", 0))) {
210 switch (val) {
211 case 1:
212 t.c_cflag &= ~(CSTOPB);
213 break;
214 case 2:
215 t.c_cflag |= CSTOPB;
216 break;
217 default:
218 xf86Msg(X_ERROR, "Invalid Option StopBits value: %d\n", val);
219 return -1;
220 break;
221 }
222 }
223
224 if ((val = xf86SetIntOption(options, "DataBits", 0))) {
225 switch (val) {
226 case 5:
227 t.c_cflag &= ~(CSIZE);
228 t.c_cflag |= CS5;
229 break;
230 case 6:
231 t.c_cflag &= ~(CSIZE);
232 t.c_cflag |= CS6;
233 break;
234 case 7:
235 t.c_cflag &= ~(CSIZE);
236 t.c_cflag |= CS7;
237 break;
238 case 8:
239 t.c_cflag &= ~(CSIZE);
240 t.c_cflag |= CS8;
241 break;
242 default:
243 xf86Msg(X_ERROR, "Invalid Option DataBits value: %d\n", val);
244 return -1;
245 break;
246 }
247 }
248
249 if ((s = xf86SetStrOption(options, "Parity", NULL))) {
250 if (xf86NameCmp(s, "Odd") == 0) {
251 t.c_cflag |= PARENB | PARODD;
252 }
253 else if (xf86NameCmp(s, "Even") == 0) {
254 t.c_cflag |= PARENB;
255 t.c_cflag &= ~(PARODD);
256 }
257 else if (xf86NameCmp(s, "None") == 0) {
258 t.c_cflag &= ~(PARENB);
259 }
260 else {
261 xf86Msg(X_ERROR, "Invalid Option Parity value: %s\n", s);
262 return -1;
263 }
264 }
265
266 if ((val = xf86SetIntOption(options, "Vmin", -1)) != -1) {
267 t.c_cc[VMIN] = val;
268 }
269 if ((val = xf86SetIntOption(options, "Vtime", -1)) != -1) {
270 t.c_cc[VTIME] = val;
271 }
272
273 if ((s = xf86SetStrOption(options, "FlowControl", NULL))) {
274 xf86MarkOptionUsedByName(options, "FlowControl");
275 if (xf86NameCmp(s, "Xoff") == 0) {
276 t.c_iflag |= IXOFF;
277 }
278 else if (xf86NameCmp(s, "Xon") == 0) {
279 t.c_iflag |= IXON;
280 }
281 else if (xf86NameCmp(s, "XonXoff") == 0) {
282 t.c_iflag |= IXON | IXOFF;
283 }
284 else if (xf86NameCmp(s, "None") == 0) {
285 t.c_iflag &= ~(IXON | IXOFF);
286 }
287 else {
288 xf86Msg(X_ERROR, "Invalid Option FlowControl value: %s\n", s);
289 return -1;
290 }
291 }
292
293 if ((xf86SetBoolOption(options, "ClearDTR", FALSE))) {
294#ifdef CLEARDTR_SUPPORT
295#if defined(TIOCMBIC)
296 val = TIOCM_DTR;
297 SYSCALL(ioctl(fd, TIOCMBIC, &val));
298#else
299 SYSCALL(ioctl(fd, TIOCCDTR, NULL));
300#endif
301#else
302 xf86Msg(X_WARNING, "Option ClearDTR not supported on this OS\n");
303 return -1;
304#endif
305 xf86MarkOptionUsedByName(options, "ClearDTR");
306 }
307
308 if ((xf86SetBoolOption(options, "ClearRTS", FALSE))) {
309 xf86Msg(X_WARNING, "Option ClearRTS not supported on this OS\n");
310 return -1;
311 xf86MarkOptionUsedByName(options, "ClearRTS");
312 }
313
314 SYSCALL(r = tcsetattr(fd, TCSANOW, &t));
315 return r;
316}
317
318int
319xf86SetSerialSpeed(int fd, int speed)
320{
321 struct termios t;
322 int baud, r;
323
324 if (fd < 0)
325 return -1;
326
327 /* Don't try to set parameters for non-tty devices. */
328 if (!isatty(fd))
329 return 0;
330
331 SYSCALL(tcgetattr(fd, &t));
332
333 if ((baud = GetBaud(speed))) {
334 cfsetispeed(&t, baud);
335 cfsetospeed(&t, baud);
336 }
337 else {
338 xf86Msg(X_ERROR, "Invalid Option BaudRate value: %d\n", speed);
339 return -1;
340 }
341
342 SYSCALL(r = tcsetattr(fd, TCSANOW, &t));
343 return r;
344}
345
346int
347xf86ReadSerial(int fd, void *buf, int count)
348{
349 int r;
350 int i;
351
352 SYSCALL(r = read(fd, buf, count));
353 DebugF("ReadingSerial: 0x%x", (unsigned char) *(((unsigned char *) buf)));
354 for (i = 1; i < r; i++)
355 DebugF(", 0x%x", (unsigned char) *(((unsigned char *) buf) + i));
356 DebugF("\n");
357 return r;
358}
359
360int
361xf86WriteSerial(int fd, const void *buf, int count)
362{
363 int r;
364 int i;
365
366 DebugF("WritingSerial: 0x%x", (unsigned char) *(((unsigned char *) buf)));
367 for (i = 1; i < count; i++)
368 DebugF(", 0x%x", (unsigned char) *(((unsigned char *) buf) + i));
369 DebugF("\n");
370 SYSCALL(r = write(fd, buf, count));
371 return r;
372}
373
374int
375xf86CloseSerial(int fd)
376{
377 int r;
378
379 SYSCALL(r = close(fd));
380 return r;
381}
382
383int
384xf86WaitForInput(int fd, int timeout)
385{
386 fd_set readfds;
387 struct timeval to;
388 int r;
389
390 FD_ZERO(&readfds);
391
392 if (fd >= 0) {
393 FD_SET(fd, &readfds);
394 }
395
396 to.tv_sec = timeout / 1000000;
397 to.tv_usec = timeout % 1000000;
398
399 if (fd >= 0) {
400 SYSCALL(r = select(FD_SETSIZE, &readfds, NULL, NULL, &to));
401 }
402 else {
403 SYSCALL(r = select(FD_SETSIZE, NULL, NULL, NULL, &to));
404 }
405 xf86ErrorFVerb(9, "select returned %d\n", r);
406 return r;
407}
408
409int
410xf86SerialSendBreak(int fd, int duration)
411{
412 int r;
413
414 SYSCALL(r = tcsendbreak(fd, duration));
415 return r;
416
417}
418
419int
420xf86FlushInput(int fd)
421{
422 fd_set fds;
423 struct timeval timeout;
424 /* this needs to be big enough to flush an evdev event. */
425 char c[256];
426
427 DebugF("FlushingSerial\n");
428 if (tcflush(fd, TCIFLUSH) == 0)
429 return 0;
430
431 timeout.tv_sec = 0;
432 timeout.tv_usec = 0;
433 FD_ZERO(&fds);
434 FD_SET(fd, &fds);
435 while (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) > 0) {
436 if (read(fd, &c, sizeof(c)) < 1)
437 return 0;
438 FD_ZERO(&fds);
439 FD_SET(fd, &fds);
440 }
441 return 0;
442}
443
444static struct states {
445 int xf;
446 int os;
447} modemStates[] = {
448#ifdef TIOCM_LE
449 {
450 XF86_M_LE, TIOCM_LE},
451#endif
452#ifdef TIOCM_DTR
453 {
454 XF86_M_DTR, TIOCM_DTR},
455#endif
456#ifdef TIOCM_RTS
457 {
458 XF86_M_RTS, TIOCM_RTS},
459#endif
460#ifdef TIOCM_ST
461 {
462 XF86_M_ST, TIOCM_ST},
463#endif
464#ifdef TIOCM_SR
465 {
466 XF86_M_SR, TIOCM_SR},
467#endif
468#ifdef TIOCM_CTS
469 {
470 XF86_M_CTS, TIOCM_CTS},
471#endif
472#ifdef TIOCM_CAR
473 {
474 XF86_M_CAR, TIOCM_CAR},
475#elif defined(TIOCM_CD)
476 {
477 XF86_M_CAR, TIOCM_CD},
478#endif
479#ifdef TIOCM_RNG
480 {
481 XF86_M_RNG, TIOCM_RNG},
482#elif defined(TIOCM_RI)
483 {
484 XF86_M_CAR, TIOCM_RI},
485#endif
486#ifdef TIOCM_DSR
487 {
488 XF86_M_DSR, TIOCM_DSR},
489#endif
490};
491
492static int numStates = sizeof(modemStates) / sizeof(modemStates[0]);
493
494static int
495xf2osState(int state)
496{
497 int i;
498 int ret = 0;
499
500 for (i = 0; i < numStates; i++)
501 if (state & modemStates[i].xf)
502 ret |= modemStates[i].os;
503 return ret;
504}
505
506static int
507os2xfState(int state)
508{
509 int i;
510 int ret = 0;
511
512 for (i = 0; i < numStates; i++)
513 if (state & modemStates[i].os)
514 ret |= modemStates[i].xf;
515 return ret;
516}
517
518static int
519getOsStateMask(void)
520{
521 int i;
522 int ret = 0;
523
524 for (i = 0; i < numStates; i++)
525 ret |= modemStates[i].os;
526 return ret;
527}
528
529static int osStateMask = 0;
530
531int
532xf86SetSerialModemState(int fd, int state)
533{
534 int ret;
535 int s;
536
537 if (fd < 0)
538 return -1;
539
540 /* Don't try to set parameters for non-tty devices. */
541 if (!isatty(fd))
542 return 0;
543
544#ifndef TIOCMGET
545 return -1;
546#else
547 if (!osStateMask)
548 osStateMask = getOsStateMask();
549
550 state = xf2osState(state);
551 SYSCALL((ret = ioctl(fd, TIOCMGET, &s)));
552 if (ret < 0)
553 return -1;
554 s &= ~osStateMask;
555 s |= state;
556 SYSCALL((ret = ioctl(fd, TIOCMSET, &s)));
557 if (ret < 0)
558 return -1;
559 else
560 return 0;
561#endif
562}
563
564int
565xf86GetSerialModemState(int fd)
566{
567 int ret;
568 int s;
569
570 if (fd < 0)
571 return -1;
572
573 /* Don't try to set parameters for non-tty devices. */
574 if (!isatty(fd))
575 return 0;
576
577#ifndef TIOCMGET
578 return -1;
579#else
580 SYSCALL((ret = ioctl(fd, TIOCMGET, &s)));
581 if (ret < 0)
582 return -1;
583 return os2xfState(s);
584#endif
585}
586
587int
588xf86SerialModemSetBits(int fd, int bits)
589{
590 int ret;
591 int s;
592
593 if (fd < 0)
594 return -1;
595
596 /* Don't try to set parameters for non-tty devices. */
597 if (!isatty(fd))
598 return 0;
599
600#ifndef TIOCMGET
601 return -1;
602#else
603 s = xf2osState(bits);
604 SYSCALL((ret = ioctl(fd, TIOCMBIS, &s)));
605 return ret;
606#endif
607}
608
609int
610xf86SerialModemClearBits(int fd, int bits)
611{
612 int ret;
613 int s;
614
615 if (fd < 0)
616 return -1;
617
618 /* Don't try to set parameters for non-tty devices. */
619 if (!isatty(fd))
620 return 0;
621
622#ifndef TIOCMGET
623 return -1;
624#else
625 s = xf2osState(bits);
626 SYSCALL((ret = ioctl(fd, TIOCMBIC, &s)));
627 return ret;
628#endif
629}