xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/os-support/shared/posix_tty.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 <xserver_poll.h>
61 #include "xf86.h"
62 #include "xf86Priv.h"
63 #include "xf86_OSlib.h"
64 
65 static int
GetBaud(int baudrate)66 GetBaud(int baudrate)
67 {
68 #ifdef B300
69     if (baudrate == 300)
70         return B300;
71 #endif
72 #ifdef B1200
73     if (baudrate == 1200)
74         return B1200;
75 #endif
76 #ifdef B2400
77     if (baudrate == 2400)
78         return B2400;
79 #endif
80 #ifdef B4800
81     if (baudrate == 4800)
82         return B4800;
83 #endif
84 #ifdef B9600
85     if (baudrate == 9600)
86         return B9600;
87 #endif
88 #ifdef B19200
89     if (baudrate == 19200)
90         return B19200;
91 #endif
92 #ifdef B38400
93     if (baudrate == 38400)
94         return B38400;
95 #endif
96 #ifdef B57600
97     if (baudrate == 57600)
98         return B57600;
99 #endif
100 #ifdef B115200
101     if (baudrate == 115200)
102         return B115200;
103 #endif
104 #ifdef B230400
105     if (baudrate == 230400)
106         return B230400;
107 #endif
108 #ifdef B460800
109     if (baudrate == 460800)
110         return B460800;
111 #endif
112     return 0;
113 }
114 
115 int
xf86OpenSerial(XF86OptionPtr options)116 xf86OpenSerial(XF86OptionPtr options)
117 {
118     struct termios t;
119     int fd, i;
120     char *dev;
121 
122     dev = xf86SetStrOption(options, "Device", NULL);
123     if (!dev) {
124         xf86Msg(X_ERROR, "xf86OpenSerial: No Device specified.\n");
125         return -1;
126     }
127 
128     fd = xf86CheckIntOption(options, "fd", -1);
129 
130     if (fd == -1)
131         SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK));
132 
133     if (fd == -1) {
134         xf86Msg(X_ERROR,
135                 "xf86OpenSerial: Cannot open device %s\n\t%s.\n",
136                 dev, strerror(errno));
137         free(dev);
138         return -1;
139     }
140 
141     if (!isatty(fd)) {
142         /* Allow non-tty devices to be opened. */
143         free(dev);
144         return fd;
145     }
146 
147     /* set up default port parameters */
148     SYSCALL(tcgetattr(fd, &t));
149     t.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
150                    | IGNCR | ICRNL | IXON);
151     t.c_oflag &= ~OPOST;
152     t.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
153     t.c_cflag &= ~(CSIZE | PARENB);
154     t.c_cflag |= CS8 | CLOCAL;
155 
156     cfsetispeed(&t, B9600);
157     cfsetospeed(&t, B9600);
158     t.c_cc[VMIN] = 1;
159     t.c_cc[VTIME] = 0;
160 
161     SYSCALL(tcsetattr(fd, TCSANOW, &t));
162 
163     if (xf86SetSerial(fd, options) == -1) {
164         SYSCALL(close(fd));
165         free(dev);
166         return -1;
167     }
168 
169     SYSCALL(i = fcntl(fd, F_GETFL, 0));
170     if (i == -1) {
171         SYSCALL(close(fd));
172         free(dev);
173         return -1;
174     }
175     i &= ~O_NONBLOCK;
176     SYSCALL(i = fcntl(fd, F_SETFL, i));
177     if (i == -1) {
178         SYSCALL(close(fd));
179         free(dev);
180         return -1;
181     }
182     free(dev);
183     return fd;
184 }
185 
186 int
xf86SetSerial(int fd,XF86OptionPtr options)187 xf86SetSerial(int fd, XF86OptionPtr options)
188 {
189     struct termios t;
190     int val;
191     char *s;
192     int baud, r;
193 
194     if (fd < 0)
195         return -1;
196 
197     /* Don't try to set parameters for non-tty devices. */
198     if (!isatty(fd))
199         return 0;
200 
201     SYSCALL(tcgetattr(fd, &t));
202 
203     if ((val = xf86SetIntOption(options, "BaudRate", 0))) {
204         if ((baud = GetBaud(val))) {
205             cfsetispeed(&t, baud);
206             cfsetospeed(&t, baud);
207         }
208         else {
209             xf86Msg(X_ERROR, "Invalid Option BaudRate value: %d\n", val);
210             return -1;
211         }
212     }
213 
214     if ((val = xf86SetIntOption(options, "StopBits", 0))) {
215         switch (val) {
216         case 1:
217             t.c_cflag &= ~(CSTOPB);
218             break;
219         case 2:
220             t.c_cflag |= CSTOPB;
221             break;
222         default:
223             xf86Msg(X_ERROR, "Invalid Option StopBits value: %d\n", val);
224             return -1;
225             break;
226         }
227     }
228 
229     if ((val = xf86SetIntOption(options, "DataBits", 0))) {
230         switch (val) {
231         case 5:
232             t.c_cflag &= ~(CSIZE);
233             t.c_cflag |= CS5;
234             break;
235         case 6:
236             t.c_cflag &= ~(CSIZE);
237             t.c_cflag |= CS6;
238             break;
239         case 7:
240             t.c_cflag &= ~(CSIZE);
241             t.c_cflag |= CS7;
242             break;
243         case 8:
244             t.c_cflag &= ~(CSIZE);
245             t.c_cflag |= CS8;
246             break;
247         default:
248             xf86Msg(X_ERROR, "Invalid Option DataBits value: %d\n", val);
249             return -1;
250             break;
251         }
252     }
253 
254     if ((s = xf86SetStrOption(options, "Parity", NULL))) {
255         if (xf86NameCmp(s, "Odd") == 0) {
256             t.c_cflag |= PARENB | PARODD;
257         }
258         else if (xf86NameCmp(s, "Even") == 0) {
259             t.c_cflag |= PARENB;
260             t.c_cflag &= ~(PARODD);
261         }
262         else if (xf86NameCmp(s, "None") == 0) {
263             t.c_cflag &= ~(PARENB);
264         }
265         else {
266             xf86Msg(X_ERROR, "Invalid Option Parity value: %s\n", s);
267             free(s);
268             return -1;
269         }
270         free(s);
271     }
272 
273     if ((val = xf86SetIntOption(options, "Vmin", -1)) != -1) {
274         t.c_cc[VMIN] = val;
275     }
276     if ((val = xf86SetIntOption(options, "Vtime", -1)) != -1) {
277         t.c_cc[VTIME] = val;
278     }
279 
280     if ((s = xf86SetStrOption(options, "FlowControl", NULL))) {
281         xf86MarkOptionUsedByName(options, "FlowControl");
282         if (xf86NameCmp(s, "Xoff") == 0) {
283             t.c_iflag |= IXOFF;
284         }
285         else if (xf86NameCmp(s, "Xon") == 0) {
286             t.c_iflag |= IXON;
287         }
288         else if (xf86NameCmp(s, "XonXoff") == 0) {
289             t.c_iflag |= IXON | IXOFF;
290         }
291         else if (xf86NameCmp(s, "None") == 0) {
292             t.c_iflag &= ~(IXON | IXOFF);
293         }
294         else {
295             xf86Msg(X_ERROR, "Invalid Option FlowControl value: %s\n", s);
296             free(s);
297             return -1;
298         }
299         free(s);
300     }
301 
302     if ((xf86SetBoolOption(options, "ClearDTR", FALSE))) {
303 #ifdef CLEARDTR_SUPPORT
304 #if defined(TIOCMBIC)
305         val = TIOCM_DTR;
306         SYSCALL(ioctl(fd, TIOCMBIC, &val));
307 #else
308         SYSCALL(ioctl(fd, TIOCCDTR, NULL));
309 #endif
310 #else
311         xf86Msg(X_WARNING, "Option ClearDTR not supported on this OS\n");
312         return -1;
313 #endif
314         xf86MarkOptionUsedByName(options, "ClearDTR");
315     }
316 
317     if ((xf86SetBoolOption(options, "ClearRTS", FALSE))) {
318         xf86Msg(X_WARNING, "Option ClearRTS not supported on this OS\n");
319         return -1;
320         xf86MarkOptionUsedByName(options, "ClearRTS");
321     }
322 
323     SYSCALL(r = tcsetattr(fd, TCSANOW, &t));
324     return r;
325 }
326 
327 int
xf86SetSerialSpeed(int fd,int speed)328 xf86SetSerialSpeed(int fd, int speed)
329 {
330     struct termios t;
331     int baud, r;
332 
333     if (fd < 0)
334         return -1;
335 
336     /* Don't try to set parameters for non-tty devices. */
337     if (!isatty(fd))
338         return 0;
339 
340     SYSCALL(tcgetattr(fd, &t));
341 
342     if ((baud = GetBaud(speed))) {
343         cfsetispeed(&t, baud);
344         cfsetospeed(&t, baud);
345     }
346     else {
347         xf86Msg(X_ERROR, "Invalid Option BaudRate value: %d\n", speed);
348         return -1;
349     }
350 
351     SYSCALL(r = tcsetattr(fd, TCSANOW, &t));
352     return r;
353 }
354 
355 int
xf86ReadSerial(int fd,void * buf,int count)356 xf86ReadSerial(int fd, void *buf, int count)
357 {
358     int r;
359     int i;
360 
361     SYSCALL(r = read(fd, buf, count));
362     DebugF("ReadingSerial: 0x%x", (unsigned char) *(((unsigned char *) buf)));
363     for (i = 1; i < r; i++)
364         DebugF(", 0x%x", (unsigned char) *(((unsigned char *) buf) + i));
365     DebugF("\n");
366     return r;
367 }
368 
369 int
xf86WriteSerial(int fd,const void * buf,int count)370 xf86WriteSerial(int fd, const void *buf, int count)
371 {
372     int r;
373     int i;
374 
375     DebugF("WritingSerial: 0x%x", (unsigned char) *(((unsigned char *) buf)));
376     for (i = 1; i < count; i++)
377         DebugF(", 0x%x", (unsigned char) *(((unsigned char *) buf) + i));
378     DebugF("\n");
379     SYSCALL(r = write(fd, buf, count));
380     return r;
381 }
382 
383 int
xf86CloseSerial(int fd)384 xf86CloseSerial(int fd)
385 {
386     int r;
387 
388     SYSCALL(r = close(fd));
389     return r;
390 }
391 
392 int
xf86WaitForInput(int fd,int timeout)393 xf86WaitForInput(int fd, int timeout)
394 {
395     int r;
396     struct pollfd poll_fd;
397 
398     poll_fd.fd = fd;
399     poll_fd.events = POLLIN;
400 
401     /* convert microseconds to milliseconds */
402     timeout = (timeout + 999) / 1000;
403 
404     if (fd >= 0) {
405         SYSCALL(r = xserver_poll(&poll_fd, 1, timeout));
406     }
407     else {
408         SYSCALL(r = xserver_poll(&poll_fd, 0, timeout));
409     }
410     xf86ErrorFVerb(9, "poll returned %d\n", r);
411     return r;
412 }
413 
414 int
xf86SerialSendBreak(int fd,int duration)415 xf86SerialSendBreak(int fd, int duration)
416 {
417     int r;
418 
419     SYSCALL(r = tcsendbreak(fd, duration));
420     return r;
421 
422 }
423 
424 int
xf86FlushInput(int fd)425 xf86FlushInput(int fd)
426 {
427     struct pollfd poll_fd;
428     /* this needs to be big enough to flush an evdev event. */
429     char c[256];
430 
431     DebugF("FlushingSerial\n");
432     if (tcflush(fd, TCIFLUSH) == 0)
433         return 0;
434 
435     poll_fd.fd = fd;
436     poll_fd.events = POLLIN;
437     while (xserver_poll(&poll_fd, 1, 0) > 0) {
438         if (read(fd, &c, sizeof(c)) < 1)
439             return 0;
440     }
441     return 0;
442 }
443 
444 static 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 
492 static int numStates = ARRAY_SIZE(modemStates);
493 
494 static int
xf2osState(int state)495 xf2osState(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 
506 static int
os2xfState(int state)507 os2xfState(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 
518 static int
getOsStateMask(void)519 getOsStateMask(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 
529 static int osStateMask = 0;
530 
531 int
xf86SetSerialModemState(int fd,int state)532 xf86SetSerialModemState(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 
564 int
xf86GetSerialModemState(int fd)565 xf86GetSerialModemState(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 
587 int
xf86SerialModemSetBits(int fd,int bits)588 xf86SerialModemSetBits(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 
609 int
xf86SerialModemClearBits(int fd,int bits)610 xf86SerialModemClearBits(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 }
630