~ubuntu-branches/debian/stretch/rdesktop/stretch

« back to all changes in this revision

Viewing changes to serial.c

  • Committer: Bazaar Package Importer
  • Author(s): Tomas Fasth
  • Date: 2005-05-24 13:31:34 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050524133134-6hn24gprfmo91sfv
Tags: 1.4.1-1
New upstream release.

Show diffs side-by-side

added added

removed removed

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