1*c2c66affSColin Finck /* -*- c-basic-offset: 8 -*-
2*c2c66affSColin Finck rdesktop: A Remote Desktop Protocol client.
3*c2c66affSColin Finck
4*c2c66affSColin Finck Copyright (C) Matthew Chapman 1999-2005
5*c2c66affSColin Finck
6*c2c66affSColin Finck This program is free software; you can redistribute it and/or modify
7*c2c66affSColin Finck it under the terms of the GNU General Public License as published by
8*c2c66affSColin Finck the Free Software Foundation; either version 2 of the License, or
9*c2c66affSColin Finck (at your option) any later version.
10*c2c66affSColin Finck
11*c2c66affSColin Finck This program is distributed in the hope that it will be useful,
12*c2c66affSColin Finck but WITHOUT ANY WARRANTY; without even the implied warranty of
13*c2c66affSColin Finck MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*c2c66affSColin Finck GNU General Public License for more details.
15*c2c66affSColin Finck
16*c2c66affSColin Finck You should have received a copy of the GNU General Public License along
17*c2c66affSColin Finck with this program; if not, write to the Free Software Foundation, Inc.,
18*c2c66affSColin Finck 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*c2c66affSColin Finck */
20*c2c66affSColin Finck #include <unistd.h>
21*c2c66affSColin Finck #include <fcntl.h>
22*c2c66affSColin Finck #include <termios.h>
23*c2c66affSColin Finck #include <strings.h>
24*c2c66affSColin Finck #include <sys/ioctl.h>
25*c2c66affSColin Finck
26*c2c66affSColin Finck #ifdef HAVE_SYS_MODEM_H
27*c2c66affSColin Finck #include <sys/modem.h>
28*c2c66affSColin Finck #endif
29*c2c66affSColin Finck #ifdef HAVE_SYS_FILIO_H
30*c2c66affSColin Finck #include <sys/filio.h>
31*c2c66affSColin Finck #endif
32*c2c66affSColin Finck #ifdef HAVE_SYS_STRTIO_H
33*c2c66affSColin Finck #include <sys/strtio.h>
34*c2c66affSColin Finck #endif
35*c2c66affSColin Finck
36*c2c66affSColin Finck #include "rdesktop.h"
37*c2c66affSColin Finck
38*c2c66affSColin Finck #ifdef WITH_DEBUG_SERIAL
39*c2c66affSColin Finck #define DEBUG_SERIAL(args) printf args;
40*c2c66affSColin Finck #else
41*c2c66affSColin Finck #define DEBUG_SERIAL(args)
42*c2c66affSColin Finck #endif
43*c2c66affSColin Finck
44*c2c66affSColin Finck #define FILE_DEVICE_SERIAL_PORT 0x1b
45*c2c66affSColin Finck
46*c2c66affSColin Finck #define SERIAL_SET_BAUD_RATE 1
47*c2c66affSColin Finck #define SERIAL_SET_QUEUE_SIZE 2
48*c2c66affSColin Finck #define SERIAL_SET_LINE_CONTROL 3
49*c2c66affSColin Finck #define SERIAL_SET_BREAK_ON 4
50*c2c66affSColin Finck #define SERIAL_SET_BREAK_OFF 5
51*c2c66affSColin Finck #define SERIAL_IMMEDIATE_CHAR 6
52*c2c66affSColin Finck #define SERIAL_SET_TIMEOUTS 7
53*c2c66affSColin Finck #define SERIAL_GET_TIMEOUTS 8
54*c2c66affSColin Finck #define SERIAL_SET_DTR 9
55*c2c66affSColin Finck #define SERIAL_CLR_DTR 10
56*c2c66affSColin Finck #define SERIAL_RESET_DEVICE 11
57*c2c66affSColin Finck #define SERIAL_SET_RTS 12
58*c2c66affSColin Finck #define SERIAL_CLR_RTS 13
59*c2c66affSColin Finck #define SERIAL_SET_XOFF 14
60*c2c66affSColin Finck #define SERIAL_SET_XON 15
61*c2c66affSColin Finck #define SERIAL_GET_WAIT_MASK 16
62*c2c66affSColin Finck #define SERIAL_SET_WAIT_MASK 17
63*c2c66affSColin Finck #define SERIAL_WAIT_ON_MASK 18
64*c2c66affSColin Finck #define SERIAL_PURGE 19
65*c2c66affSColin Finck #define SERIAL_GET_BAUD_RATE 20
66*c2c66affSColin Finck #define SERIAL_GET_LINE_CONTROL 21
67*c2c66affSColin Finck #define SERIAL_GET_CHARS 22
68*c2c66affSColin Finck #define SERIAL_SET_CHARS 23
69*c2c66affSColin Finck #define SERIAL_GET_HANDFLOW 24
70*c2c66affSColin Finck #define SERIAL_SET_HANDFLOW 25
71*c2c66affSColin Finck #define SERIAL_GET_MODEMSTATUS 26
72*c2c66affSColin Finck #define SERIAL_GET_COMMSTATUS 27
73*c2c66affSColin Finck #define SERIAL_XOFF_COUNTER 28
74*c2c66affSColin Finck #define SERIAL_GET_PROPERTIES 29
75*c2c66affSColin Finck #define SERIAL_GET_DTRRTS 30
76*c2c66affSColin Finck #define SERIAL_LSRMST_INSERT 31
77*c2c66affSColin Finck #define SERIAL_CONFIG_SIZE 32
78*c2c66affSColin Finck #define SERIAL_GET_COMMCONFIG 33
79*c2c66affSColin Finck #define SERIAL_SET_COMMCONFIG 34
80*c2c66affSColin Finck #define SERIAL_GET_STATS 35
81*c2c66affSColin Finck #define SERIAL_CLEAR_STATS 36
82*c2c66affSColin Finck #define SERIAL_GET_MODEM_CONTROL 37
83*c2c66affSColin Finck #define SERIAL_SET_MODEM_CONTROL 38
84*c2c66affSColin Finck #define SERIAL_SET_FIFO_CONTROL 39
85*c2c66affSColin Finck
86*c2c66affSColin Finck #define STOP_BITS_1 0
87*c2c66affSColin Finck #define STOP_BITS_2 2
88*c2c66affSColin Finck
89*c2c66affSColin Finck #define NO_PARITY 0
90*c2c66affSColin Finck #define ODD_PARITY 1
91*c2c66affSColin Finck #define EVEN_PARITY 2
92*c2c66affSColin Finck
93*c2c66affSColin Finck #define SERIAL_PURGE_TXABORT 0x00000001
94*c2c66affSColin Finck #define SERIAL_PURGE_RXABORT 0x00000002
95*c2c66affSColin Finck #define SERIAL_PURGE_TXCLEAR 0x00000004
96*c2c66affSColin Finck #define SERIAL_PURGE_RXCLEAR 0x00000008
97*c2c66affSColin Finck
98*c2c66affSColin Finck /* SERIAL_WAIT_ON_MASK */
99*c2c66affSColin Finck #define SERIAL_EV_RXCHAR 0x0001 /* Any Character received */
100*c2c66affSColin Finck #define SERIAL_EV_RXFLAG 0x0002 /* Received certain character */
101*c2c66affSColin Finck #define SERIAL_EV_TXEMPTY 0x0004 /* Transmitt Queue Empty */
102*c2c66affSColin Finck #define SERIAL_EV_CTS 0x0008 /* CTS changed state */
103*c2c66affSColin Finck #define SERIAL_EV_DSR 0x0010 /* DSR changed state */
104*c2c66affSColin Finck #define SERIAL_EV_RLSD 0x0020 /* RLSD changed state */
105*c2c66affSColin Finck #define SERIAL_EV_BREAK 0x0040 /* BREAK received */
106*c2c66affSColin Finck #define SERIAL_EV_ERR 0x0080 /* Line status error occurred */
107*c2c66affSColin Finck #define SERIAL_EV_RING 0x0100 /* Ring signal detected */
108*c2c66affSColin Finck #define SERIAL_EV_PERR 0x0200 /* Printer error occured */
109*c2c66affSColin Finck #define SERIAL_EV_RX80FULL 0x0400 /* Receive buffer is 80 percent full */
110*c2c66affSColin Finck #define SERIAL_EV_EVENT1 0x0800 /* Provider specific event 1 */
111*c2c66affSColin Finck #define SERIAL_EV_EVENT2 0x1000 /* Provider specific event 2 */
112*c2c66affSColin Finck
113*c2c66affSColin Finck /* Modem Status */
114*c2c66affSColin Finck #define SERIAL_MS_DTR 0x01
115*c2c66affSColin Finck #define SERIAL_MS_RTS 0x02
116*c2c66affSColin Finck #define SERIAL_MS_CTS 0x10
117*c2c66affSColin Finck #define SERIAL_MS_DSR 0x20
118*c2c66affSColin Finck #define SERIAL_MS_RNG 0x40
119*c2c66affSColin Finck #define SERIAL_MS_CAR 0x80
120*c2c66affSColin Finck
121*c2c66affSColin Finck /* Handflow */
122*c2c66affSColin Finck #define SERIAL_DTR_CONTROL 0x01
123*c2c66affSColin Finck #define SERIAL_CTS_HANDSHAKE 0x08
124*c2c66affSColin Finck #define SERIAL_ERROR_ABORT 0x80000000
125*c2c66affSColin Finck
126*c2c66affSColin Finck #define SERIAL_XON_HANDSHAKE 0x01
127*c2c66affSColin Finck #define SERIAL_XOFF_HANDSHAKE 0x02
128*c2c66affSColin Finck #define SERIAL_DSR_SENSITIVITY 0x40
129*c2c66affSColin Finck
130*c2c66affSColin Finck #define SERIAL_CHAR_EOF 0
131*c2c66affSColin Finck #define SERIAL_CHAR_ERROR 1
132*c2c66affSColin Finck #define SERIAL_CHAR_BREAK 2
133*c2c66affSColin Finck #define SERIAL_CHAR_EVENT 3
134*c2c66affSColin Finck #define SERIAL_CHAR_XON 4
135*c2c66affSColin Finck #define SERIAL_CHAR_XOFF 5
136*c2c66affSColin Finck
137*c2c66affSColin Finck #ifndef CRTSCTS
138*c2c66affSColin Finck #define CRTSCTS 0
139*c2c66affSColin Finck #endif
140*c2c66affSColin Finck
141*c2c66affSColin Finck /* FIONREAD should really do the same thing as TIOCINQ, where it is
142*c2c66affSColin Finck * not available */
143*c2c66affSColin Finck #if !defined(TIOCINQ) && defined(FIONREAD)
144*c2c66affSColin Finck #define TIOCINQ FIONREAD
145*c2c66affSColin Finck #endif
146*c2c66affSColin Finck #if !defined(TIOCOUTQ) && defined(FIONWRITE)
147*c2c66affSColin Finck #define TIOCOUTQ FIONWRITE
148*c2c66affSColin Finck #endif
149*c2c66affSColin Finck
150*c2c66affSColin Finck static SERIAL_DEVICE *
get_serial_info(RDPCLIENT * This,NTHANDLE handle)151*c2c66affSColin Finck get_serial_info(RDPCLIENT * This, NTHANDLE handle)
152*c2c66affSColin Finck {
153*c2c66affSColin Finck int index;
154*c2c66affSColin Finck
155*c2c66affSColin Finck for (index = 0; index < RDPDR_MAX_DEVICES; index++)
156*c2c66affSColin Finck {
157*c2c66affSColin Finck if (handle == This->rdpdr_device[index].handle)
158*c2c66affSColin Finck return (SERIAL_DEVICE *) This->rdpdr_device[index].pdevice_data;
159*c2c66affSColin Finck }
160*c2c66affSColin Finck return NULL;
161*c2c66affSColin Finck }
162*c2c66affSColin Finck
163*c2c66affSColin Finck static BOOL
get_termios(SERIAL_DEVICE * pser_inf,NTHANDLE serial_fd)164*c2c66affSColin Finck get_termios(SERIAL_DEVICE * pser_inf, NTHANDLE serial_fd)
165*c2c66affSColin Finck {
166*c2c66affSColin Finck speed_t speed;
167*c2c66affSColin Finck struct termios *ptermios;
168*c2c66affSColin Finck
169*c2c66affSColin Finck ptermios = pser_inf->ptermios;
170*c2c66affSColin Finck
171*c2c66affSColin Finck if (tcgetattr(serial_fd, ptermios) == -1)
172*c2c66affSColin Finck return False;
173*c2c66affSColin Finck
174*c2c66affSColin Finck speed = cfgetispeed(ptermios);
175*c2c66affSColin Finck switch (speed)
176*c2c66affSColin Finck {
177*c2c66affSColin Finck #ifdef B75
178*c2c66affSColin Finck case B75:
179*c2c66affSColin Finck pser_inf->baud_rate = 75;
180*c2c66affSColin Finck break;
181*c2c66affSColin Finck #endif
182*c2c66affSColin Finck #ifdef B110
183*c2c66affSColin Finck case B110:
184*c2c66affSColin Finck pser_inf->baud_rate = 110;
185*c2c66affSColin Finck break;
186*c2c66affSColin Finck #endif
187*c2c66affSColin Finck #ifdef B134
188*c2c66affSColin Finck case B134:
189*c2c66affSColin Finck pser_inf->baud_rate = 134;
190*c2c66affSColin Finck break;
191*c2c66affSColin Finck #endif
192*c2c66affSColin Finck #ifdef B150
193*c2c66affSColin Finck case B150:
194*c2c66affSColin Finck pser_inf->baud_rate = 150;
195*c2c66affSColin Finck break;
196*c2c66affSColin Finck #endif
197*c2c66affSColin Finck #ifdef B300
198*c2c66affSColin Finck case B300:
199*c2c66affSColin Finck pser_inf->baud_rate = 300;
200*c2c66affSColin Finck break;
201*c2c66affSColin Finck #endif
202*c2c66affSColin Finck #ifdef B600
203*c2c66affSColin Finck case B600:
204*c2c66affSColin Finck pser_inf->baud_rate = 600;
205*c2c66affSColin Finck break;
206*c2c66affSColin Finck #endif
207*c2c66affSColin Finck #ifdef B1200
208*c2c66affSColin Finck case B1200:
209*c2c66affSColin Finck pser_inf->baud_rate = 1200;
210*c2c66affSColin Finck break;
211*c2c66affSColin Finck #endif
212*c2c66affSColin Finck #ifdef B1800
213*c2c66affSColin Finck case B1800:
214*c2c66affSColin Finck pser_inf->baud_rate = 1800;
215*c2c66affSColin Finck break;
216*c2c66affSColin Finck #endif
217*c2c66affSColin Finck #ifdef B2400
218*c2c66affSColin Finck case B2400:
219*c2c66affSColin Finck pser_inf->baud_rate = 2400;
220*c2c66affSColin Finck break;
221*c2c66affSColin Finck #endif
222*c2c66affSColin Finck #ifdef B4800
223*c2c66affSColin Finck case B4800:
224*c2c66affSColin Finck pser_inf->baud_rate = 4800;
225*c2c66affSColin Finck break;
226*c2c66affSColin Finck #endif
227*c2c66affSColin Finck #ifdef B9600
228*c2c66affSColin Finck case B9600:
229*c2c66affSColin Finck pser_inf->baud_rate = 9600;
230*c2c66affSColin Finck break;
231*c2c66affSColin Finck #endif
232*c2c66affSColin Finck #ifdef B19200
233*c2c66affSColin Finck case B19200:
234*c2c66affSColin Finck pser_inf->baud_rate = 19200;
235*c2c66affSColin Finck break;
236*c2c66affSColin Finck #endif
237*c2c66affSColin Finck #ifdef B38400
238*c2c66affSColin Finck case B38400:
239*c2c66affSColin Finck pser_inf->baud_rate = 38400;
240*c2c66affSColin Finck break;
241*c2c66affSColin Finck #endif
242*c2c66affSColin Finck #ifdef B57600
243*c2c66affSColin Finck case B57600:
244*c2c66affSColin Finck pser_inf->baud_rate = 57600;
245*c2c66affSColin Finck break;
246*c2c66affSColin Finck #endif
247*c2c66affSColin Finck #ifdef B115200
248*c2c66affSColin Finck case B115200:
249*c2c66affSColin Finck pser_inf->baud_rate = 115200;
250*c2c66affSColin Finck break;
251*c2c66affSColin Finck #endif
252*c2c66affSColin Finck #ifdef B230400
253*c2c66affSColin Finck case B230400:
254*c2c66affSColin Finck pser_inf->baud_rate = 230400;
255*c2c66affSColin Finck break;
256*c2c66affSColin Finck #endif
257*c2c66affSColin Finck #ifdef B460800
258*c2c66affSColin Finck case B460800:
259*c2c66affSColin Finck pser_inf->baud_rate = 460800;
260*c2c66affSColin Finck break;
261*c2c66affSColin Finck #endif
262*c2c66affSColin Finck default:
263*c2c66affSColin Finck pser_inf->baud_rate = 9600;
264*c2c66affSColin Finck break;
265*c2c66affSColin Finck }
266*c2c66affSColin Finck
267*c2c66affSColin Finck speed = cfgetospeed(ptermios);
268*c2c66affSColin Finck pser_inf->dtr = (speed == B0) ? 0 : 1;
269*c2c66affSColin Finck
270*c2c66affSColin Finck pser_inf->stop_bits = (ptermios->c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;
271*c2c66affSColin Finck pser_inf->parity =
272*c2c66affSColin Finck (ptermios->
273*c2c66affSColin Finck c_cflag & PARENB) ? ((ptermios->
274*c2c66affSColin Finck c_cflag & PARODD) ? ODD_PARITY : EVEN_PARITY) : NO_PARITY;
275*c2c66affSColin Finck switch (ptermios->c_cflag & CSIZE)
276*c2c66affSColin Finck {
277*c2c66affSColin Finck case CS5:
278*c2c66affSColin Finck pser_inf->word_length = 5;
279*c2c66affSColin Finck break;
280*c2c66affSColin Finck case CS6:
281*c2c66affSColin Finck pser_inf->word_length = 6;
282*c2c66affSColin Finck break;
283*c2c66affSColin Finck case CS7:
284*c2c66affSColin Finck pser_inf->word_length = 7;
285*c2c66affSColin Finck break;
286*c2c66affSColin Finck default:
287*c2c66affSColin Finck pser_inf->word_length = 8;
288*c2c66affSColin Finck break;
289*c2c66affSColin Finck }
290*c2c66affSColin Finck
291*c2c66affSColin Finck if (ptermios->c_cflag & CRTSCTS)
292*c2c66affSColin Finck {
293*c2c66affSColin Finck pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_CTS_HANDSHAKE | SERIAL_ERROR_ABORT;
294*c2c66affSColin Finck }
295*c2c66affSColin Finck else
296*c2c66affSColin Finck {
297*c2c66affSColin Finck pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_ERROR_ABORT;
298*c2c66affSColin Finck }
299*c2c66affSColin Finck
300*c2c66affSColin Finck pser_inf->xonoff = SERIAL_DSR_SENSITIVITY;
301*c2c66affSColin Finck if (ptermios->c_iflag & IXON)
302*c2c66affSColin Finck pser_inf->xonoff |= SERIAL_XON_HANDSHAKE;
303*c2c66affSColin Finck
304*c2c66affSColin Finck if (ptermios->c_iflag & IXOFF)
305*c2c66affSColin Finck pser_inf->xonoff |= SERIAL_XOFF_HANDSHAKE;
306*c2c66affSColin Finck
307*c2c66affSColin Finck pser_inf->chars[SERIAL_CHAR_XON] = ptermios->c_cc[VSTART];
308*c2c66affSColin Finck pser_inf->chars[SERIAL_CHAR_XOFF] = ptermios->c_cc[VSTOP];
309*c2c66affSColin Finck pser_inf->chars[SERIAL_CHAR_EOF] = ptermios->c_cc[VEOF];
310*c2c66affSColin Finck pser_inf->chars[SERIAL_CHAR_BREAK] = ptermios->c_cc[VINTR];
311*c2c66affSColin Finck pser_inf->chars[SERIAL_CHAR_ERROR] = ptermios->c_cc[VKILL];
312*c2c66affSColin Finck
313*c2c66affSColin Finck return True;
314*c2c66affSColin Finck }
315*c2c66affSColin Finck
316*c2c66affSColin Finck static void
set_termios(SERIAL_DEVICE * pser_inf,NTHANDLE serial_fd)317*c2c66affSColin Finck set_termios(SERIAL_DEVICE * pser_inf, NTHANDLE serial_fd)
318*c2c66affSColin Finck {
319*c2c66affSColin Finck speed_t speed;
320*c2c66affSColin Finck
321*c2c66affSColin Finck struct termios *ptermios;
322*c2c66affSColin Finck
323*c2c66affSColin Finck ptermios = pser_inf->ptermios;
324*c2c66affSColin Finck
325*c2c66affSColin Finck
326*c2c66affSColin Finck switch (pser_inf->baud_rate)
327*c2c66affSColin Finck {
328*c2c66affSColin Finck #ifdef B75
329*c2c66affSColin Finck case 75:
330*c2c66affSColin Finck speed = B75;
331*c2c66affSColin Finck break;
332*c2c66affSColin Finck #endif
333*c2c66affSColin Finck #ifdef B110
334*c2c66affSColin Finck case 110:
335*c2c66affSColin Finck speed = B110;
336*c2c66affSColin Finck break;
337*c2c66affSColin Finck #endif
338*c2c66affSColin Finck #ifdef B134
339*c2c66affSColin Finck case 134:
340*c2c66affSColin Finck speed = B134;
341*c2c66affSColin Finck break;
342*c2c66affSColin Finck #endif
343*c2c66affSColin Finck #ifdef B150
344*c2c66affSColin Finck case 150:
345*c2c66affSColin Finck speed = B150;
346*c2c66affSColin Finck break;
347*c2c66affSColin Finck #endif
348*c2c66affSColin Finck #ifdef B300
349*c2c66affSColin Finck case 300:
350*c2c66affSColin Finck speed = B300;
351*c2c66affSColin Finck break;
352*c2c66affSColin Finck #endif
353*c2c66affSColin Finck #ifdef B600
354*c2c66affSColin Finck case 600:
355*c2c66affSColin Finck speed = B600;
356*c2c66affSColin Finck break;
357*c2c66affSColin Finck #endif
358*c2c66affSColin Finck #ifdef B1200
359*c2c66affSColin Finck case 1200:
360*c2c66affSColin Finck speed = B1200;
361*c2c66affSColin Finck break;
362*c2c66affSColin Finck #endif
363*c2c66affSColin Finck #ifdef B1800
364*c2c66affSColin Finck case 1800:
365*c2c66affSColin Finck speed = B1800;
366*c2c66affSColin Finck break;
367*c2c66affSColin Finck #endif
368*c2c66affSColin Finck #ifdef B2400
369*c2c66affSColin Finck case 2400:
370*c2c66affSColin Finck speed = B2400;
371*c2c66affSColin Finck break;
372*c2c66affSColin Finck #endif
373*c2c66affSColin Finck #ifdef B4800
374*c2c66affSColin Finck case 4800:
375*c2c66affSColin Finck speed = B4800;
376*c2c66affSColin Finck break;
377*c2c66affSColin Finck #endif
378*c2c66affSColin Finck #ifdef B9600
379*c2c66affSColin Finck case 9600:
380*c2c66affSColin Finck speed = B9600;
381*c2c66affSColin Finck break;
382*c2c66affSColin Finck #endif
383*c2c66affSColin Finck #ifdef B19200
384*c2c66affSColin Finck case 19200:
385*c2c66affSColin Finck speed = B19200;
386*c2c66affSColin Finck break;
387*c2c66affSColin Finck #endif
388*c2c66affSColin Finck #ifdef B38400
389*c2c66affSColin Finck case 38400:
390*c2c66affSColin Finck speed = B38400;
391*c2c66affSColin Finck break;
392*c2c66affSColin Finck #endif
393*c2c66affSColin Finck #ifdef B57600
394*c2c66affSColin Finck case 57600:
395*c2c66affSColin Finck speed = B57600;
396*c2c66affSColin Finck break;
397*c2c66affSColin Finck #endif
398*c2c66affSColin Finck #ifdef B115200
399*c2c66affSColin Finck case 115200:
400*c2c66affSColin Finck speed = B115200;
401*c2c66affSColin Finck break;
402*c2c66affSColin Finck #endif
403*c2c66affSColin Finck #ifdef B230400
404*c2c66affSColin Finck case 230400:
405*c2c66affSColin Finck speed = B115200;
406*c2c66affSColin Finck break;
407*c2c66affSColin Finck #endif
408*c2c66affSColin Finck #ifdef B460800
409*c2c66affSColin Finck case 460800:
410*c2c66affSColin Finck speed = B115200;
411*c2c66affSColin Finck break;
412*c2c66affSColin Finck #endif
413*c2c66affSColin Finck default:
414*c2c66affSColin Finck speed = B9600;
415*c2c66affSColin Finck break;
416*c2c66affSColin Finck }
417*c2c66affSColin Finck
418*c2c66affSColin Finck #ifdef CBAUD
419*c2c66affSColin Finck ptermios->c_cflag &= ~CBAUD;
420*c2c66affSColin Finck ptermios->c_cflag |= speed;
421*c2c66affSColin Finck #else
422*c2c66affSColin Finck /* on systems with separate ispeed and ospeed, we can remember the speed
423*c2c66affSColin Finck in ispeed while changing DTR with ospeed */
424*c2c66affSColin Finck cfsetispeed(pser_inf->ptermios, speed);
425*c2c66affSColin Finck cfsetospeed(pser_inf->ptermios, pser_inf->dtr ? speed : 0);
426*c2c66affSColin Finck #endif
427*c2c66affSColin Finck
428*c2c66affSColin Finck ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS);
429*c2c66affSColin Finck switch (pser_inf->stop_bits)
430*c2c66affSColin Finck {
431*c2c66affSColin Finck case STOP_BITS_2:
432*c2c66affSColin Finck ptermios->c_cflag |= CSTOPB;
433*c2c66affSColin Finck break;
434*c2c66affSColin Finck default:
435*c2c66affSColin Finck ptermios->c_cflag &= ~CSTOPB;
436*c2c66affSColin Finck break;
437*c2c66affSColin Finck }
438*c2c66affSColin Finck
439*c2c66affSColin Finck switch (pser_inf->parity)
440*c2c66affSColin Finck {
441*c2c66affSColin Finck case EVEN_PARITY:
442*c2c66affSColin Finck ptermios->c_cflag |= PARENB;
443*c2c66affSColin Finck break;
444*c2c66affSColin Finck case ODD_PARITY:
445*c2c66affSColin Finck ptermios->c_cflag |= PARENB | PARODD;
446*c2c66affSColin Finck break;
447*c2c66affSColin Finck case NO_PARITY:
448*c2c66affSColin Finck ptermios->c_cflag &= ~(PARENB | PARODD);
449*c2c66affSColin Finck break;
450*c2c66affSColin Finck }
451*c2c66affSColin Finck
452*c2c66affSColin Finck switch (pser_inf->word_length)
453*c2c66affSColin Finck {
454*c2c66affSColin Finck case 5:
455*c2c66affSColin Finck ptermios->c_cflag |= CS5;
456*c2c66affSColin Finck break;
457*c2c66affSColin Finck case 6:
458*c2c66affSColin Finck ptermios->c_cflag |= CS6;
459*c2c66affSColin Finck break;
460*c2c66affSColin Finck case 7:
461*c2c66affSColin Finck ptermios->c_cflag |= CS7;
462*c2c66affSColin Finck break;
463*c2c66affSColin Finck default:
464*c2c66affSColin Finck ptermios->c_cflag |= CS8;
465*c2c66affSColin Finck break;
466*c2c66affSColin Finck }
467*c2c66affSColin Finck
468*c2c66affSColin Finck #if 0
469*c2c66affSColin Finck if (pser_inf->rts)
470*c2c66affSColin Finck ptermios->c_cflag |= CRTSCTS;
471*c2c66affSColin Finck else
472*c2c66affSColin Finck ptermios->c_cflag &= ~CRTSCTS;
473*c2c66affSColin Finck #endif
474*c2c66affSColin Finck
475*c2c66affSColin Finck if (pser_inf->control & SERIAL_CTS_HANDSHAKE)
476*c2c66affSColin Finck {
477*c2c66affSColin Finck ptermios->c_cflag |= CRTSCTS;
478*c2c66affSColin Finck }
479*c2c66affSColin Finck else
480*c2c66affSColin Finck {
481*c2c66affSColin Finck ptermios->c_cflag &= ~CRTSCTS;
482*c2c66affSColin Finck }
483*c2c66affSColin Finck
484*c2c66affSColin Finck
485*c2c66affSColin Finck if (pser_inf->xonoff & SERIAL_XON_HANDSHAKE)
486*c2c66affSColin Finck {
487*c2c66affSColin Finck ptermios->c_iflag |= IXON | IMAXBEL;
488*c2c66affSColin Finck }
489*c2c66affSColin Finck if (pser_inf->xonoff & SERIAL_XOFF_HANDSHAKE)
490*c2c66affSColin Finck {
491*c2c66affSColin Finck ptermios->c_iflag |= IXOFF | IMAXBEL;
492*c2c66affSColin Finck }
493*c2c66affSColin Finck
494*c2c66affSColin Finck if ((pser_inf->xonoff & (SERIAL_XOFF_HANDSHAKE | SERIAL_XON_HANDSHAKE)) == 0)
495*c2c66affSColin Finck {
496*c2c66affSColin Finck ptermios->c_iflag &= ~IXON;
497*c2c66affSColin Finck ptermios->c_iflag &= ~IXOFF;
498*c2c66affSColin Finck }
499*c2c66affSColin Finck
500*c2c66affSColin Finck ptermios->c_cc[VSTART] = pser_inf->chars[SERIAL_CHAR_XON];
501*c2c66affSColin Finck ptermios->c_cc[VSTOP] = pser_inf->chars[SERIAL_CHAR_XOFF];
502*c2c66affSColin Finck ptermios->c_cc[VEOF] = pser_inf->chars[SERIAL_CHAR_EOF];
503*c2c66affSColin Finck ptermios->c_cc[VINTR] = pser_inf->chars[SERIAL_CHAR_BREAK];
504*c2c66affSColin Finck ptermios->c_cc[VKILL] = pser_inf->chars[SERIAL_CHAR_ERROR];
505*c2c66affSColin Finck
506*c2c66affSColin Finck tcsetattr(serial_fd, TCSANOW, ptermios);
507*c2c66affSColin Finck }
508*c2c66affSColin Finck
509*c2c66affSColin Finck /* Enumeration of devices from rdesktop.c */
510*c2c66affSColin Finck /* returns numer of units found and initialized. */
511*c2c66affSColin Finck /* optarg looks like ':com1=/dev/ttyS0' */
512*c2c66affSColin Finck /* when it arrives to this function. */
513*c2c66affSColin Finck /* :com1=/dev/ttyS0,com2=/dev/ttyS1 */
514*c2c66affSColin Finck int
serial_enum_devices(RDPCLIENT * This,uint32 * id,char * optarg)515*c2c66affSColin Finck serial_enum_devices(RDPCLIENT * This, uint32 * id, char *optarg)
516*c2c66affSColin Finck {
517*c2c66affSColin Finck SERIAL_DEVICE *pser_inf;
518*c2c66affSColin Finck
519*c2c66affSColin Finck char *pos = optarg;
520*c2c66affSColin Finck char *pos2;
521*c2c66affSColin Finck int count = 0;
522*c2c66affSColin Finck
523*c2c66affSColin Finck /* skip the first colon */
524*c2c66affSColin Finck optarg++;
525*c2c66affSColin Finck while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
526*c2c66affSColin Finck {
527*c2c66affSColin Finck /* Init data structures for device */
528*c2c66affSColin Finck pser_inf = (SERIAL_DEVICE *) xmalloc(sizeof(SERIAL_DEVICE));
529*c2c66affSColin Finck pser_inf->ptermios = (struct termios *) xmalloc(sizeof(struct termios));
530*c2c66affSColin Finck memset(pser_inf->ptermios, 0, sizeof(struct termios));
531*c2c66affSColin Finck pser_inf->pold_termios = (struct termios *) xmalloc(sizeof(struct termios));
532*c2c66affSColin Finck memset(pser_inf->pold_termios, 0, sizeof(struct termios));
533*c2c66affSColin Finck
534*c2c66affSColin Finck pos2 = next_arg(optarg, '=');
535*c2c66affSColin Finck strcpy(This->rdpdr_device[*id].name, optarg);
536*c2c66affSColin Finck
537*c2c66affSColin Finck toupper_str(This->rdpdr_device[*id].name);
538*c2c66affSColin Finck
539*c2c66affSColin Finck This->rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
540*c2c66affSColin Finck strcpy(This->rdpdr_device[*id].local_path, pos2);
541*c2c66affSColin Finck printf("SERIAL %s to %s\n", This->rdpdr_device[*id].name,
542*c2c66affSColin Finck This->rdpdr_device[*id].local_path);
543*c2c66affSColin Finck /* set device type */
544*c2c66affSColin Finck This->rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;
545*c2c66affSColin Finck This->rdpdr_device[*id].pdevice_data = (void *) pser_inf;
546*c2c66affSColin Finck count++;
547*c2c66affSColin Finck (*id)++;
548*c2c66affSColin Finck
549*c2c66affSColin Finck optarg = pos;
550*c2c66affSColin Finck }
551*c2c66affSColin Finck return count;
552*c2c66affSColin Finck }
553*c2c66affSColin Finck
554*c2c66affSColin Finck static NTSTATUS
serial_create(RDPCLIENT * This,uint32 device_id,uint32 access,uint32 share_mode,uint32 disposition,uint32 flags_and_attributes,char * filename,NTHANDLE * handle)555*c2c66affSColin Finck serial_create(RDPCLIENT * This, uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
556*c2c66affSColin Finck uint32 flags_and_attributes, char *filename, NTHANDLE * handle)
557*c2c66affSColin Finck {
558*c2c66affSColin Finck NTHANDLE serial_fd;
559*c2c66affSColin Finck SERIAL_DEVICE *pser_inf;
560*c2c66affSColin Finck struct termios *ptermios;
561*c2c66affSColin Finck
562*c2c66affSColin Finck pser_inf = (SERIAL_DEVICE *) This->rdpdr_device[device_id].pdevice_data;
563*c2c66affSColin Finck ptermios = pser_inf->ptermios;
564*c2c66affSColin Finck serial_fd = open(This->rdpdr_device[device_id].local_path, O_RDWR | O_NOCTTY | O_NONBLOCK);
565*c2c66affSColin Finck
566*c2c66affSColin Finck if (serial_fd == -1)
567*c2c66affSColin Finck {
568*c2c66affSColin Finck perror("open");
569*c2c66affSColin Finck return STATUS_ACCESS_DENIED;
570*c2c66affSColin Finck }
571*c2c66affSColin Finck
572*c2c66affSColin Finck if (!get_termios(pser_inf, serial_fd))
573*c2c66affSColin Finck {
574*c2c66affSColin Finck printf("INFO: SERIAL %s access denied\n", This->rdpdr_device[device_id].name);
575*c2c66affSColin Finck fflush(stdout);
576*c2c66affSColin Finck return STATUS_ACCESS_DENIED;
577*c2c66affSColin Finck }
578*c2c66affSColin Finck
579*c2c66affSColin Finck /* Store handle for later use */
580*c2c66affSColin Finck This->rdpdr_device[device_id].handle = serial_fd;
581*c2c66affSColin Finck
582*c2c66affSColin Finck /* some sane information */
583*c2c66affSColin Finck DEBUG_SERIAL(("INFO: SERIAL %s to %s\nINFO: speed %u baud, stop bits %u, parity %u, word length %u bits, dtr %u, rts %u\n", This->rdpdr_device[device_id].name, This->rdpdr_device[device_id].local_path, pser_inf->baud_rate, pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length, pser_inf->dtr, pser_inf->rts));
584*c2c66affSColin Finck
585*c2c66affSColin Finck pser_inf->ptermios->c_iflag &=
586*c2c66affSColin Finck ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
587*c2c66affSColin Finck pser_inf->ptermios->c_oflag &= ~OPOST;
588*c2c66affSColin Finck pser_inf->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
589*c2c66affSColin Finck pser_inf->ptermios->c_cflag &= ~(CSIZE | PARENB);
590*c2c66affSColin Finck pser_inf->ptermios->c_cflag |= CS8;
591*c2c66affSColin Finck
592*c2c66affSColin Finck tcsetattr(serial_fd, TCSANOW, pser_inf->ptermios);
593*c2c66affSColin Finck
594*c2c66affSColin Finck pser_inf->event_txempty = 0;
595*c2c66affSColin Finck pser_inf->event_cts = 0;
596*c2c66affSColin Finck pser_inf->event_dsr = 0;
597*c2c66affSColin Finck pser_inf->event_rlsd = 0;
598*c2c66affSColin Finck pser_inf->event_pending = 0;
599*c2c66affSColin Finck
600*c2c66affSColin Finck *handle = serial_fd;
601*c2c66affSColin Finck
602*c2c66affSColin Finck /* all read and writes should be non blocking */
603*c2c66affSColin Finck if (fcntl(*handle, F_SETFL, O_NONBLOCK) == -1)
604*c2c66affSColin Finck perror("fcntl");
605*c2c66affSColin Finck
606*c2c66affSColin Finck pser_inf->read_total_timeout_constant = 5;
607*c2c66affSColin Finck
608*c2c66affSColin Finck return STATUS_SUCCESS;
609*c2c66affSColin Finck }
610*c2c66affSColin Finck
611*c2c66affSColin Finck static NTSTATUS
serial_close(RDPCLIENT * This,NTHANDLE handle)612*c2c66affSColin Finck serial_close(RDPCLIENT * This, NTHANDLE handle)
613*c2c66affSColin Finck {
614*c2c66affSColin Finck int i = get_device_index(This, handle);
615*c2c66affSColin Finck if (i >= 0)
616*c2c66affSColin Finck This->rdpdr_device[i].handle = 0;
617*c2c66affSColin Finck
618*c2c66affSColin Finck rdpdr_abort_io(This, handle, 0, STATUS_TIMEOUT);
619*c2c66affSColin Finck close(handle);
620*c2c66affSColin Finck return STATUS_SUCCESS;
621*c2c66affSColin Finck }
622*c2c66affSColin Finck
623*c2c66affSColin Finck static NTSTATUS
serial_read(RDPCLIENT * This,NTHANDLE handle,uint8 * data,uint32 length,uint32 offset,uint32 * result)624*c2c66affSColin Finck serial_read(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
625*c2c66affSColin Finck {
626*c2c66affSColin Finck long timeout;
627*c2c66affSColin Finck SERIAL_DEVICE *pser_inf;
628*c2c66affSColin Finck struct termios *ptermios;
629*c2c66affSColin Finck #ifdef WITH_DEBUG_SERIAL
630*c2c66affSColin Finck int bytes_inqueue;
631*c2c66affSColin Finck #endif
632*c2c66affSColin Finck
633*c2c66affSColin Finck
634*c2c66affSColin Finck timeout = 90;
635*c2c66affSColin Finck pser_inf = get_serial_info(This, handle);
636*c2c66affSColin Finck ptermios = pser_inf->ptermios;
637*c2c66affSColin Finck
638*c2c66affSColin Finck /* Set timeouts kind of like the windows serial timeout parameters. Multiply timeout
639*c2c66affSColin Finck with requested read size */
640*c2c66affSColin Finck if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant)
641*c2c66affSColin Finck {
642*c2c66affSColin Finck timeout =
643*c2c66affSColin Finck (pser_inf->read_total_timeout_multiplier * length +
644*c2c66affSColin Finck pser_inf->read_total_timeout_constant + 99) / 100;
645*c2c66affSColin Finck }
646*c2c66affSColin Finck else if (pser_inf->read_interval_timeout)
647*c2c66affSColin Finck {
648*c2c66affSColin Finck timeout = (pser_inf->read_interval_timeout * length + 99) / 100;
649*c2c66affSColin Finck }
650*c2c66affSColin Finck
651*c2c66affSColin Finck /* If a timeout is set, do a blocking read, which times out after some time.
652*c2c66affSColin Finck It will make rdesktop less responsive, but it will improve serial performance, by not
653*c2c66affSColin Finck reading one character at a time. */
654*c2c66affSColin Finck if (timeout == 0)
655*c2c66affSColin Finck {
656*c2c66affSColin Finck ptermios->c_cc[VTIME] = 0;
657*c2c66affSColin Finck ptermios->c_cc[VMIN] = 0;
658*c2c66affSColin Finck }
659*c2c66affSColin Finck else
660*c2c66affSColin Finck {
661*c2c66affSColin Finck ptermios->c_cc[VTIME] = timeout;
662*c2c66affSColin Finck ptermios->c_cc[VMIN] = 1;
663*c2c66affSColin Finck }
664*c2c66affSColin Finck tcsetattr(handle, TCSANOW, ptermios);
665*c2c66affSColin Finck
666*c2c66affSColin Finck #if defined(WITH_DEBUG_SERIAL) && defined(TIOCINQ)
667*c2c66affSColin Finck ioctl(handle, TIOCINQ, &bytes_inqueue);
668*c2c66affSColin Finck DEBUG_SERIAL(("serial_read inqueue: %d expected %d\n", bytes_inqueue, length));
669*c2c66affSColin Finck #endif
670*c2c66affSColin Finck
671*c2c66affSColin Finck *result = read(handle, data, length);
672*c2c66affSColin Finck
673*c2c66affSColin Finck #ifdef WITH_DEBUG_SERIAL
674*c2c66affSColin Finck DEBUG_SERIAL(("serial_read Bytes %d\n", *result));
675*c2c66affSColin Finck if (*result > 0)
676*c2c66affSColin Finck hexdump(data, *result);
677*c2c66affSColin Finck #endif
678*c2c66affSColin Finck
679*c2c66affSColin Finck return STATUS_SUCCESS;
680*c2c66affSColin Finck }
681*c2c66affSColin Finck
682*c2c66affSColin Finck static NTSTATUS
serial_write(RDPCLIENT * This,NTHANDLE handle,uint8 * data,uint32 length,uint32 offset,uint32 * result)683*c2c66affSColin Finck serial_write(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
684*c2c66affSColin Finck {
685*c2c66affSColin Finck SERIAL_DEVICE *pser_inf;
686*c2c66affSColin Finck
687*c2c66affSColin Finck pser_inf = get_serial_info(This, handle);
688*c2c66affSColin Finck
689*c2c66affSColin Finck *result = write(handle, data, length);
690*c2c66affSColin Finck
691*c2c66affSColin Finck if (*result > 0)
692*c2c66affSColin Finck pser_inf->event_txempty = *result;
693*c2c66affSColin Finck
694*c2c66affSColin Finck DEBUG_SERIAL(("serial_write length %d, offset %d result %d\n", length, offset, *result));
695*c2c66affSColin Finck
696*c2c66affSColin Finck return STATUS_SUCCESS;
697*c2c66affSColin Finck }
698*c2c66affSColin Finck
699*c2c66affSColin Finck static NTSTATUS
serial_device_control(RDPCLIENT * This,NTHANDLE handle,uint32 request,STREAM in,STREAM out)700*c2c66affSColin Finck serial_device_control(RDPCLIENT * This, NTHANDLE handle, uint32 request, STREAM in, STREAM out)
701*c2c66affSColin Finck {
702*c2c66affSColin Finck int flush_mask, purge_mask;
703*c2c66affSColin Finck uint32 result, modemstate;
704*c2c66affSColin Finck uint8 immediate;
705*c2c66affSColin Finck SERIAL_DEVICE *pser_inf;
706*c2c66affSColin Finck struct termios *ptermios;
707*c2c66affSColin Finck
708*c2c66affSColin Finck if ((request >> 16) != FILE_DEVICE_SERIAL_PORT)
709*c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
710*c2c66affSColin Finck
711*c2c66affSColin Finck pser_inf = get_serial_info(This, handle);
712*c2c66affSColin Finck ptermios = pser_inf->ptermios;
713*c2c66affSColin Finck
714*c2c66affSColin Finck /* extract operation */
715*c2c66affSColin Finck request >>= 2;
716*c2c66affSColin Finck request &= 0xfff;
717*c2c66affSColin Finck
718*c2c66affSColin Finck switch (request)
719*c2c66affSColin Finck {
720*c2c66affSColin Finck case SERIAL_SET_BAUD_RATE:
721*c2c66affSColin Finck in_uint32_le(in, pser_inf->baud_rate);
722*c2c66affSColin Finck set_termios(pser_inf, handle);
723*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BAUD_RATE %d\n",
724*c2c66affSColin Finck pser_inf->baud_rate));
725*c2c66affSColin Finck break;
726*c2c66affSColin Finck case SERIAL_GET_BAUD_RATE:
727*c2c66affSColin Finck out_uint32_le(out, pser_inf->baud_rate);
728*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_BAUD_RATE %d\n",
729*c2c66affSColin Finck pser_inf->baud_rate));
730*c2c66affSColin Finck break;
731*c2c66affSColin Finck case SERIAL_SET_QUEUE_SIZE:
732*c2c66affSColin Finck in_uint32_le(in, pser_inf->queue_in_size);
733*c2c66affSColin Finck in_uint32_le(in, pser_inf->queue_out_size);
734*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d\n",
735*c2c66affSColin Finck pser_inf->queue_in_size, pser_inf->queue_out_size));
736*c2c66affSColin Finck break;
737*c2c66affSColin Finck case SERIAL_SET_LINE_CONTROL:
738*c2c66affSColin Finck in_uint8(in, pser_inf->stop_bits);
739*c2c66affSColin Finck in_uint8(in, pser_inf->parity);
740*c2c66affSColin Finck in_uint8(in, pser_inf->word_length);
741*c2c66affSColin Finck set_termios(pser_inf, handle);
742*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d\n", pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length));
743*c2c66affSColin Finck break;
744*c2c66affSColin Finck case SERIAL_GET_LINE_CONTROL:
745*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_LINE_CONTROL\n"));
746*c2c66affSColin Finck out_uint8(out, pser_inf->stop_bits);
747*c2c66affSColin Finck out_uint8(out, pser_inf->parity);
748*c2c66affSColin Finck out_uint8(out, pser_inf->word_length);
749*c2c66affSColin Finck break;
750*c2c66affSColin Finck case SERIAL_IMMEDIATE_CHAR:
751*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_IMMEDIATE_CHAR\n"));
752*c2c66affSColin Finck in_uint8(in, immediate);
753*c2c66affSColin Finck serial_write(This, handle, &immediate, 1, 0, &result);
754*c2c66affSColin Finck break;
755*c2c66affSColin Finck case SERIAL_CONFIG_SIZE:
756*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_CONFIG_SIZE\n"));
757*c2c66affSColin Finck out_uint32_le(out, 0);
758*c2c66affSColin Finck break;
759*c2c66affSColin Finck case SERIAL_GET_CHARS:
760*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_CHARS\n"));
761*c2c66affSColin Finck out_uint8a(out, pser_inf->chars, 6);
762*c2c66affSColin Finck break;
763*c2c66affSColin Finck case SERIAL_SET_CHARS:
764*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_CHARS\n"));
765*c2c66affSColin Finck in_uint8a(in, pser_inf->chars, 6);
766*c2c66affSColin Finck #ifdef WITH_DEBUG_SERIAL
767*c2c66affSColin Finck hexdump(pser_inf->chars, 6);
768*c2c66affSColin Finck #endif
769*c2c66affSColin Finck set_termios(pser_inf, handle);
770*c2c66affSColin Finck break;
771*c2c66affSColin Finck case SERIAL_GET_HANDFLOW:
772*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_HANDFLOW\n"));
773*c2c66affSColin Finck get_termios(pser_inf, handle);
774*c2c66affSColin Finck out_uint32_le(out, pser_inf->control);
775*c2c66affSColin Finck out_uint32_le(out, pser_inf->xonoff); /* Xon/Xoff */
776*c2c66affSColin Finck out_uint32_le(out, pser_inf->onlimit);
777*c2c66affSColin Finck out_uint32_le(out, pser_inf->offlimit);
778*c2c66affSColin Finck break;
779*c2c66affSColin Finck case SERIAL_SET_HANDFLOW:
780*c2c66affSColin Finck in_uint32_le(in, pser_inf->control);
781*c2c66affSColin Finck in_uint32_le(in, pser_inf->xonoff);
782*c2c66affSColin Finck in_uint32_le(in, pser_inf->onlimit);
783*c2c66affSColin Finck in_uint32_le(in, pser_inf->offlimit);
784*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_HANDFLOW %x %x %x %x\n",
785*c2c66affSColin Finck pser_inf->control, pser_inf->xonoff, pser_inf->onlimit,
786*c2c66affSColin Finck pser_inf->onlimit));
787*c2c66affSColin Finck set_termios(pser_inf, handle);
788*c2c66affSColin Finck break;
789*c2c66affSColin Finck case SERIAL_SET_TIMEOUTS:
790*c2c66affSColin Finck in_uint32(in, pser_inf->read_interval_timeout);
791*c2c66affSColin Finck in_uint32(in, pser_inf->read_total_timeout_multiplier);
792*c2c66affSColin Finck in_uint32(in, pser_inf->read_total_timeout_constant);
793*c2c66affSColin Finck in_uint32(in, pser_inf->write_total_timeout_multiplier);
794*c2c66affSColin Finck in_uint32(in, pser_inf->write_total_timeout_constant);
795*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d\n",
796*c2c66affSColin Finck pser_inf->read_interval_timeout,
797*c2c66affSColin Finck pser_inf->read_total_timeout_multiplier,
798*c2c66affSColin Finck pser_inf->read_total_timeout_constant));
799*c2c66affSColin Finck break;
800*c2c66affSColin Finck case SERIAL_GET_TIMEOUTS:
801*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d\n",
802*c2c66affSColin Finck pser_inf->read_interval_timeout,
803*c2c66affSColin Finck pser_inf->read_total_timeout_multiplier,
804*c2c66affSColin Finck pser_inf->read_total_timeout_constant));
805*c2c66affSColin Finck
806*c2c66affSColin Finck out_uint32(out, pser_inf->read_interval_timeout);
807*c2c66affSColin Finck out_uint32(out, pser_inf->read_total_timeout_multiplier);
808*c2c66affSColin Finck out_uint32(out, pser_inf->read_total_timeout_constant);
809*c2c66affSColin Finck out_uint32(out, pser_inf->write_total_timeout_multiplier);
810*c2c66affSColin Finck out_uint32(out, pser_inf->write_total_timeout_constant);
811*c2c66affSColin Finck break;
812*c2c66affSColin Finck case SERIAL_GET_WAIT_MASK:
813*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_WAIT_MASK %X\n",
814*c2c66affSColin Finck pser_inf->wait_mask));
815*c2c66affSColin Finck out_uint32(out, pser_inf->wait_mask);
816*c2c66affSColin Finck break;
817*c2c66affSColin Finck case SERIAL_SET_WAIT_MASK:
818*c2c66affSColin Finck in_uint32(in, pser_inf->wait_mask);
819*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_WAIT_MASK %X\n",
820*c2c66affSColin Finck pser_inf->wait_mask));
821*c2c66affSColin Finck break;
822*c2c66affSColin Finck case SERIAL_SET_DTR:
823*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_DTR\n"));
824*c2c66affSColin Finck ioctl(handle, TIOCMGET, &result);
825*c2c66affSColin Finck result |= TIOCM_DTR;
826*c2c66affSColin Finck ioctl(handle, TIOCMSET, &result);
827*c2c66affSColin Finck pser_inf->dtr = 1;
828*c2c66affSColin Finck break;
829*c2c66affSColin Finck case SERIAL_CLR_DTR:
830*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_DTR\n"));
831*c2c66affSColin Finck ioctl(handle, TIOCMGET, &result);
832*c2c66affSColin Finck result &= ~TIOCM_DTR;
833*c2c66affSColin Finck ioctl(handle, TIOCMSET, &result);
834*c2c66affSColin Finck pser_inf->dtr = 0;
835*c2c66affSColin Finck break;
836*c2c66affSColin Finck case SERIAL_SET_RTS:
837*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_RTS\n"));
838*c2c66affSColin Finck ioctl(handle, TIOCMGET, &result);
839*c2c66affSColin Finck result |= TIOCM_RTS;
840*c2c66affSColin Finck ioctl(handle, TIOCMSET, &result);
841*c2c66affSColin Finck pser_inf->rts = 1;
842*c2c66affSColin Finck break;
843*c2c66affSColin Finck case SERIAL_CLR_RTS:
844*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_RTS\n"));
845*c2c66affSColin Finck ioctl(handle, TIOCMGET, &result);
846*c2c66affSColin Finck result &= ~TIOCM_RTS;
847*c2c66affSColin Finck ioctl(handle, TIOCMSET, &result);
848*c2c66affSColin Finck pser_inf->rts = 0;
849*c2c66affSColin Finck break;
850*c2c66affSColin Finck case SERIAL_GET_MODEMSTATUS:
851*c2c66affSColin Finck modemstate = 0;
852*c2c66affSColin Finck #ifdef TIOCMGET
853*c2c66affSColin Finck ioctl(handle, TIOCMGET, &result);
854*c2c66affSColin Finck if (result & TIOCM_CTS)
855*c2c66affSColin Finck modemstate |= SERIAL_MS_CTS;
856*c2c66affSColin Finck if (result & TIOCM_DSR)
857*c2c66affSColin Finck modemstate |= SERIAL_MS_DSR;
858*c2c66affSColin Finck if (result & TIOCM_RNG)
859*c2c66affSColin Finck modemstate |= SERIAL_MS_RNG;
860*c2c66affSColin Finck if (result & TIOCM_CAR)
861*c2c66affSColin Finck modemstate |= SERIAL_MS_CAR;
862*c2c66affSColin Finck if (result & TIOCM_DTR)
863*c2c66affSColin Finck modemstate |= SERIAL_MS_DTR;
864*c2c66affSColin Finck if (result & TIOCM_RTS)
865*c2c66affSColin Finck modemstate |= SERIAL_MS_RTS;
866*c2c66affSColin Finck #endif
867*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X\n", modemstate));
868*c2c66affSColin Finck out_uint32_le(out, modemstate);
869*c2c66affSColin Finck break;
870*c2c66affSColin Finck case SERIAL_GET_COMMSTATUS:
871*c2c66affSColin Finck out_uint32_le(out, 0); /* Errors */
872*c2c66affSColin Finck out_uint32_le(out, 0); /* Hold reasons */
873*c2c66affSColin Finck
874*c2c66affSColin Finck result = 0;
875*c2c66affSColin Finck #ifdef TIOCINQ
876*c2c66affSColin Finck ioctl(handle, TIOCINQ, &result);
877*c2c66affSColin Finck #endif
878*c2c66affSColin Finck out_uint32_le(out, result); /* Amount in in queue */
879*c2c66affSColin Finck if (result)
880*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d\n",
881*c2c66affSColin Finck result));
882*c2c66affSColin Finck
883*c2c66affSColin Finck result = 0;
884*c2c66affSColin Finck #ifdef TIOCOUTQ
885*c2c66affSColin Finck ioctl(handle, TIOCOUTQ, &result);
886*c2c66affSColin Finck #endif
887*c2c66affSColin Finck out_uint32_le(out, result); /* Amount in out queue */
888*c2c66affSColin Finck if (result)
889*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d\n", result));
890*c2c66affSColin Finck
891*c2c66affSColin Finck out_uint8(out, 0); /* EofReceived */
892*c2c66affSColin Finck out_uint8(out, 0); /* WaitForImmediate */
893*c2c66affSColin Finck break;
894*c2c66affSColin Finck case SERIAL_PURGE:
895*c2c66affSColin Finck in_uint32(in, purge_mask);
896*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_PURGE purge_mask %X\n", purge_mask));
897*c2c66affSColin Finck flush_mask = 0;
898*c2c66affSColin Finck if (purge_mask & SERIAL_PURGE_TXCLEAR)
899*c2c66affSColin Finck flush_mask |= TCOFLUSH;
900*c2c66affSColin Finck if (purge_mask & SERIAL_PURGE_RXCLEAR)
901*c2c66affSColin Finck flush_mask |= TCIFLUSH;
902*c2c66affSColin Finck if (flush_mask != 0)
903*c2c66affSColin Finck tcflush(handle, flush_mask);
904*c2c66affSColin Finck if (purge_mask & SERIAL_PURGE_TXABORT)
905*c2c66affSColin Finck rdpdr_abort_io(This, handle, 4, STATUS_CANCELLED);
906*c2c66affSColin Finck if (purge_mask & SERIAL_PURGE_RXABORT)
907*c2c66affSColin Finck rdpdr_abort_io(This, handle, 3, STATUS_CANCELLED);
908*c2c66affSColin Finck break;
909*c2c66affSColin Finck case SERIAL_WAIT_ON_MASK:
910*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_WAIT_ON_MASK %X\n",
911*c2c66affSColin Finck pser_inf->wait_mask));
912*c2c66affSColin Finck pser_inf->event_pending = 1;
913*c2c66affSColin Finck if (serial_get_event(This, handle, &result))
914*c2c66affSColin Finck {
915*c2c66affSColin Finck DEBUG_SERIAL(("WAIT end event = %x\n", result));
916*c2c66affSColin Finck out_uint32_le(out, result);
917*c2c66affSColin Finck break;
918*c2c66affSColin Finck }
919*c2c66affSColin Finck return STATUS_PENDING;
920*c2c66affSColin Finck break;
921*c2c66affSColin Finck case SERIAL_SET_BREAK_ON:
922*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_ON\n"));
923*c2c66affSColin Finck tcsendbreak(handle, 0);
924*c2c66affSColin Finck break;
925*c2c66affSColin Finck case SERIAL_RESET_DEVICE:
926*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_RESET_DEVICE\n"));
927*c2c66affSColin Finck break;
928*c2c66affSColin Finck case SERIAL_SET_BREAK_OFF:
929*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_OFF\n"));
930*c2c66affSColin Finck break;
931*c2c66affSColin Finck case SERIAL_SET_XOFF:
932*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XOFF\n"));
933*c2c66affSColin Finck break;
934*c2c66affSColin Finck case SERIAL_SET_XON:
935*c2c66affSColin Finck DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XON\n"));
936*c2c66affSColin Finck tcflow(handle, TCION);
937*c2c66affSColin Finck break;
938*c2c66affSColin Finck default:
939*c2c66affSColin Finck unimpl("SERIAL IOCTL %d\n", request);
940*c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
941*c2c66affSColin Finck }
942*c2c66affSColin Finck
943*c2c66affSColin Finck return STATUS_SUCCESS;
944*c2c66affSColin Finck }
945*c2c66affSColin Finck
946*c2c66affSColin Finck BOOL
serial_get_event(RDPCLIENT * This,NTHANDLE handle,uint32 * result)947*c2c66affSColin Finck serial_get_event(RDPCLIENT * This, NTHANDLE handle, uint32 * result)
948*c2c66affSColin Finck {
949*c2c66affSColin Finck int index;
950*c2c66affSColin Finck SERIAL_DEVICE *pser_inf;
951*c2c66affSColin Finck int bytes;
952*c2c66affSColin Finck BOOL ret = False;
953*c2c66affSColin Finck
954*c2c66affSColin Finck *result = 0;
955*c2c66affSColin Finck index = get_device_index(This, handle);
956*c2c66affSColin Finck if (index < 0)
957*c2c66affSColin Finck return False;
958*c2c66affSColin Finck
959*c2c66affSColin Finck #ifdef TIOCINQ
960*c2c66affSColin Finck pser_inf = (SERIAL_DEVICE *) This->rdpdr_device[index].pdevice_data;
961*c2c66affSColin Finck
962*c2c66affSColin Finck ioctl(handle, TIOCINQ, &bytes);
963*c2c66affSColin Finck
964*c2c66affSColin Finck if (bytes > 0)
965*c2c66affSColin Finck {
966*c2c66affSColin Finck DEBUG_SERIAL(("serial_get_event Bytes %d\n", bytes));
967*c2c66affSColin Finck if (bytes > pser_inf->event_rlsd)
968*c2c66affSColin Finck {
969*c2c66affSColin Finck pser_inf->event_rlsd = bytes;
970*c2c66affSColin Finck if (pser_inf->wait_mask & SERIAL_EV_RLSD)
971*c2c66affSColin Finck {
972*c2c66affSColin Finck DEBUG_SERIAL(("Event -> SERIAL_EV_RLSD \n"));
973*c2c66affSColin Finck *result |= SERIAL_EV_RLSD;
974*c2c66affSColin Finck ret = True;
975*c2c66affSColin Finck }
976*c2c66affSColin Finck
977*c2c66affSColin Finck }
978*c2c66affSColin Finck
979*c2c66affSColin Finck if ((bytes > 1) && (pser_inf->wait_mask & SERIAL_EV_RXFLAG))
980*c2c66affSColin Finck {
981*c2c66affSColin Finck DEBUG_SERIAL(("Event -> SERIAL_EV_RXFLAG Bytes %d\n", bytes));
982*c2c66affSColin Finck *result |= SERIAL_EV_RXFLAG;
983*c2c66affSColin Finck ret = True;
984*c2c66affSColin Finck }
985*c2c66affSColin Finck if ((pser_inf->wait_mask & SERIAL_EV_RXCHAR))
986*c2c66affSColin Finck {
987*c2c66affSColin Finck DEBUG_SERIAL(("Event -> SERIAL_EV_RXCHAR Bytes %d\n", bytes));
988*c2c66affSColin Finck *result |= SERIAL_EV_RXCHAR;
989*c2c66affSColin Finck ret = True;
990*c2c66affSColin Finck }
991*c2c66affSColin Finck
992*c2c66affSColin Finck }
993*c2c66affSColin Finck else
994*c2c66affSColin Finck {
995*c2c66affSColin Finck pser_inf->event_rlsd = 0;
996*c2c66affSColin Finck }
997*c2c66affSColin Finck #endif
998*c2c66affSColin Finck
999*c2c66affSColin Finck #ifdef TIOCOUTQ
1000*c2c66affSColin Finck ioctl(handle, TIOCOUTQ, &bytes);
1001*c2c66affSColin Finck if ((bytes == 0)
1002*c2c66affSColin Finck && (pser_inf->event_txempty > 0) && (pser_inf->wait_mask & SERIAL_EV_TXEMPTY))
1003*c2c66affSColin Finck {
1004*c2c66affSColin Finck
1005*c2c66affSColin Finck DEBUG_SERIAL(("Event -> SERIAL_EV_TXEMPTY\n"));
1006*c2c66affSColin Finck *result |= SERIAL_EV_TXEMPTY;
1007*c2c66affSColin Finck ret = True;
1008*c2c66affSColin Finck }
1009*c2c66affSColin Finck pser_inf->event_txempty = bytes;
1010*c2c66affSColin Finck #endif
1011*c2c66affSColin Finck
1012*c2c66affSColin Finck ioctl(handle, TIOCMGET, &bytes);
1013*c2c66affSColin Finck if ((bytes & TIOCM_DSR) != pser_inf->event_dsr)
1014*c2c66affSColin Finck {
1015*c2c66affSColin Finck pser_inf->event_dsr = bytes & TIOCM_DSR;
1016*c2c66affSColin Finck if (pser_inf->wait_mask & SERIAL_EV_DSR)
1017*c2c66affSColin Finck {
1018*c2c66affSColin Finck DEBUG_SERIAL(("event -> SERIAL_EV_DSR %s\n",
1019*c2c66affSColin Finck (bytes & TIOCM_DSR) ? "ON" : "OFF"));
1020*c2c66affSColin Finck *result |= SERIAL_EV_DSR;
1021*c2c66affSColin Finck ret = True;
1022*c2c66affSColin Finck }
1023*c2c66affSColin Finck }
1024*c2c66affSColin Finck
1025*c2c66affSColin Finck if ((bytes & TIOCM_CTS) != pser_inf->event_cts)
1026*c2c66affSColin Finck {
1027*c2c66affSColin Finck pser_inf->event_cts = bytes & TIOCM_CTS;
1028*c2c66affSColin Finck if (pser_inf->wait_mask & SERIAL_EV_CTS)
1029*c2c66affSColin Finck {
1030*c2c66affSColin Finck DEBUG_SERIAL((" EVENT-> SERIAL_EV_CTS %s\n",
1031*c2c66affSColin Finck (bytes & TIOCM_CTS) ? "ON" : "OFF"));
1032*c2c66affSColin Finck *result |= SERIAL_EV_CTS;
1033*c2c66affSColin Finck ret = True;
1034*c2c66affSColin Finck }
1035*c2c66affSColin Finck }
1036*c2c66affSColin Finck
1037*c2c66affSColin Finck if (ret)
1038*c2c66affSColin Finck pser_inf->event_pending = 0;
1039*c2c66affSColin Finck
1040*c2c66affSColin Finck return ret;
1041*c2c66affSColin Finck }
1042*c2c66affSColin Finck
1043*c2c66affSColin Finck /* Read timeout for a given file descripter (device) when adding fd's to select() */
1044*c2c66affSColin Finck BOOL
serial_get_timeout(RDPCLIENT * This,NTHANDLE handle,uint32 length,uint32 * timeout,uint32 * itv_timeout)1045*c2c66affSColin Finck serial_get_timeout(RDPCLIENT * This, NTHANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
1046*c2c66affSColin Finck {
1047*c2c66affSColin Finck int index;
1048*c2c66affSColin Finck SERIAL_DEVICE *pser_inf;
1049*c2c66affSColin Finck
1050*c2c66affSColin Finck index = get_device_index(This, handle);
1051*c2c66affSColin Finck if (index < 0)
1052*c2c66affSColin Finck return True;
1053*c2c66affSColin Finck
1054*c2c66affSColin Finck if (This->rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
1055*c2c66affSColin Finck {
1056*c2c66affSColin Finck return False;
1057*c2c66affSColin Finck }
1058*c2c66affSColin Finck
1059*c2c66affSColin Finck pser_inf = (SERIAL_DEVICE *) This->rdpdr_device[index].pdevice_data;
1060*c2c66affSColin Finck
1061*c2c66affSColin Finck *timeout =
1062*c2c66affSColin Finck pser_inf->read_total_timeout_multiplier * length +
1063*c2c66affSColin Finck pser_inf->read_total_timeout_constant;
1064*c2c66affSColin Finck *itv_timeout = pser_inf->read_interval_timeout;
1065*c2c66affSColin Finck return True;
1066*c2c66affSColin Finck }
1067*c2c66affSColin Finck
1068*c2c66affSColin Finck DEVICE_FNS serial_fns = {
1069*c2c66affSColin Finck serial_create,
1070*c2c66affSColin Finck serial_close,
1071*c2c66affSColin Finck serial_read,
1072*c2c66affSColin Finck serial_write,
1073*c2c66affSColin Finck serial_device_control
1074*c2c66affSColin Finck };
1075