~ubuntu-branches/ubuntu/edgy/rdesktop/edgy-security

« back to all changes in this revision

Viewing changes to serial.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Johnston
  • Date: 2004-02-04 17:52:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040204175226-87kz4bzs1nimji68
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <unistd.h>
 
2
#include <fcntl.h>
 
3
#include <termios.h>
 
4
#include "rdesktop.h"
 
5
 
 
6
#define FILE_DEVICE_SERIAL_PORT         0x1b
 
7
 
 
8
#define SERIAL_SET_BAUD_RATE            1
 
9
#define SERIAL_SET_QUEUE_SIZE           2
 
10
#define SERIAL_SET_LINE_CONTROL         3
 
11
#define SERIAL_SET_BREAK_ON             4
 
12
#define SERIAL_SET_BREAK_OFF            5
 
13
#define SERIAL_IMMEDIATE_CHAR           6
 
14
#define SERIAL_SET_TIMEOUTS             7
 
15
#define SERIAL_GET_TIMEOUTS             8
 
16
#define SERIAL_SET_DTR                  9
 
17
#define SERIAL_CLR_DTR                  10
 
18
#define SERIAL_RESET_DEVICE             11
 
19
#define SERIAL_SET_RTS                  12
 
20
#define SERIAL_CLR_RTS                  13
 
21
#define SERIAL_SET_XOFF                 14
 
22
#define SERIAL_SET_XON                  15
 
23
#define SERIAL_GET_WAIT_MASK            16
 
24
#define SERIAL_SET_WAIT_MASK            17
 
25
#define SERIAL_WAIT_ON_MASK             18
 
26
#define SERIAL_PURGE                    19
 
27
#define SERIAL_GET_BAUD_RATE            20
 
28
#define SERIAL_GET_LINE_CONTROL         21
 
29
#define SERIAL_GET_CHARS                22
 
30
#define SERIAL_SET_CHARS                23
 
31
#define SERIAL_GET_HANDFLOW             24
 
32
#define SERIAL_SET_HANDFLOW             25
 
33
#define SERIAL_GET_MODEMSTATUS          26
 
34
#define SERIAL_GET_COMMSTATUS           27
 
35
#define SERIAL_XOFF_COUNTER             28
 
36
#define SERIAL_GET_PROPERTIES           29
 
37
#define SERIAL_GET_DTRRTS               30
 
38
#define SERIAL_LSRMST_INSERT            31
 
39
#define SERIAL_CONFIG_SIZE              32
 
40
#define SERIAL_GET_COMMCONFIG           33
 
41
#define SERIAL_SET_COMMCONFIG           34
 
42
#define SERIAL_GET_STATS                35
 
43
#define SERIAL_CLEAR_STATS              36
 
44
#define SERIAL_GET_MODEM_CONTROL        37
 
45
#define SERIAL_SET_MODEM_CONTROL        38
 
46
#define SERIAL_SET_FIFO_CONTROL         39
 
47
 
 
48
#define STOP_BITS_1                     0
 
49
#define STOP_BITS_2                     2
 
50
 
 
51
#define NO_PARITY                       0
 
52
#define ODD_PARITY                      1
 
53
#define EVEN_PARITY                     2
 
54
 
 
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;
 
63
 
 
64
static BOOL
 
65
get_termios(void)
 
66
{
 
67
        speed_t speed;
 
68
 
 
69
        if (tcgetattr(serial_fd, &termios) == -1)
 
70
                return False;
 
71
 
 
72
        speed = cfgetispeed(&termios);
 
73
        switch (speed)
 
74
        {
 
75
#ifdef B75
 
76
                case B75:
 
77
                        baud_rate = 75;
 
78
                        break;
 
79
#endif
 
80
#ifdef B110
 
81
                case B110:
 
82
                        baud_rate = 110;
 
83
                        break;
 
84
#endif
 
85
#ifdef B134
 
86
                case B134:
 
87
                        baud_rate = 134;
 
88
                        break;
 
89
#endif
 
90
#ifdef B150
 
91
                case B150:
 
92
                        baud_rate = 150;
 
93
                        break;
 
94
#endif
 
95
#ifdef B300
 
96
                case B300:
 
97
                        baud_rate = 300;
 
98
                        break;
 
99
#endif
 
100
#ifdef B600
 
101
                case B600:
 
102
                        baud_rate = 600;
 
103
                        break;
 
104
#endif
 
105
#ifdef B1200
 
106
                case B1200:
 
107
                        baud_rate = 1200;
 
108
                        break;
 
109
#endif
 
110
#ifdef B1800
 
111
                case B1800:
 
112
                        baud_rate = 1800;
 
113
                        break;
 
114
#endif
 
115
#ifdef B2400
 
116
                case B2400:
 
117
                        baud_rate = 2400;
 
118
                        break;
 
119
#endif
 
120
#ifdef B4800
 
121
                case B4800:
 
122
                        baud_rate = 4800;
 
123
                        break;
 
124
#endif
 
125
#ifdef B9600
 
126
                case B9600:
 
127
                        baud_rate = 9600;
 
128
                        break;
 
129
#endif
 
130
#ifdef B19200
 
131
                case B19200:
 
132
                        baud_rate = 19200;
 
133
                        break;
 
134
#endif
 
135
#ifdef B38400
 
136
                case B38400:
 
137
                        baud_rate = 38400;
 
138
                        break;
 
139
#endif
 
140
#ifdef B57600
 
141
                case B57600:
 
142
                        baud_rate = 57600;
 
143
                        break;
 
144
#endif
 
145
#ifdef B115200
 
146
                case B115200:
 
147
                        baud_rate = 115200;
 
148
                        break;
 
149
#endif
 
150
                default:
 
151
                        baud_rate = 0;
 
152
                        break;
 
153
        }
 
154
 
 
155
        speed = cfgetospeed(&termios);
 
156
        dtr = (speed == B0) ? 0 : 1;
 
157
 
 
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)
 
163
        {
 
164
                case CS5:
 
165
                        word_length = 5;
 
166
                        break;
 
167
                case CS6:
 
168
                        word_length = 6;
 
169
                        break;
 
170
                case CS7:
 
171
                        word_length = 7;
 
172
                        break;
 
173
                default:
 
174
                        word_length = 8;
 
175
                        break;
 
176
        }
 
177
 
 
178
        return True;
 
179
}
 
180
 
 
181
static void
 
182
set_termios(void)
 
183
{
 
184
        speed_t speed;
 
185
 
 
186
        switch (baud_rate)
 
187
        {
 
188
#ifdef B75
 
189
                case 75:
 
190
                        speed = B75;
 
191
                        break;
 
192
#endif
 
193
#ifdef B110
 
194
                case 110:
 
195
                        speed = B110;
 
196
                        break;
 
197
#endif
 
198
#ifdef B134
 
199
                case 134:
 
200
                        speed = B134;
 
201
                        break;
 
202
#endif
 
203
#ifdef B150
 
204
                case 150:
 
205
                        speed = B150;
 
206
                        break;
 
207
#endif
 
208
#ifdef B300
 
209
                case 300:
 
210
                        speed = B300;
 
211
                        break;
 
212
#endif
 
213
#ifdef B600
 
214
                case 600:
 
215
                        speed = B600;
 
216
                        break;
 
217
#endif
 
218
#ifdef B1200
 
219
                case 1200:
 
220
                        speed = B1200;
 
221
                        break;
 
222
#endif
 
223
#ifdef B1800
 
224
                case 1800:
 
225
                        speed = B1800;
 
226
                        break;
 
227
#endif
 
228
#ifdef B2400
 
229
                case 2400:
 
230
                        speed = B2400;
 
231
                        break;
 
232
#endif
 
233
#ifdef B4800
 
234
                case 4800:
 
235
                        speed = B4800;
 
236
                        break;
 
237
#endif
 
238
#ifdef B9600
 
239
                case 9600:
 
240
                        speed = B9600;
 
241
                        break;
 
242
#endif
 
243
#ifdef B19200
 
244
                case 19200:
 
245
                        speed = B19200;
 
246
                        break;
 
247
#endif
 
248
#ifdef B38400
 
249
                case 38400:
 
250
                        speed = B38400;
 
251
                        break;
 
252
#endif
 
253
#ifdef B57600
 
254
                case 57600:
 
255
                        speed = B57600;
 
256
                        break;
 
257
#endif
 
258
#ifdef B115200
 
259
                case 115200:
 
260
                        speed = B115200;
 
261
                        break;
 
262
#endif
 
263
                default:
 
264
                        speed = B0;
 
265
                        break;
 
266
        }
 
267
 
 
268
        /* on systems with separate ispeed and ospeed, we can remember the speed
 
269
           in ispeed while changing DTR with ospeed */
 
270
        cfsetispeed(&termios, speed);
 
271
        cfsetospeed(&termios, dtr ? speed : 0);
 
272
 
 
273
        termios.c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE);
 
274
        switch (stop_bits)
 
275
        {
 
276
                case STOP_BITS_2:
 
277
                        termios.c_cflag |= CSTOPB;
 
278
                        break;
 
279
        }
 
280
        switch (parity)
 
281
        {
 
282
                case EVEN_PARITY:
 
283
                        termios.c_cflag |= PARENB;
 
284
                        break;
 
285
                case ODD_PARITY:
 
286
                        termios.c_cflag |= PARENB | PARODD;
 
287
                        break;
 
288
        }
 
289
        switch (word_length)
 
290
        {
 
291
                case 5:
 
292
                        termios.c_cflag |= CS5;
 
293
                        break;
 
294
                case 6:
 
295
                        termios.c_cflag |= CS6;
 
296
                        break;
 
297
                case 7:
 
298
                        termios.c_cflag |= CS7;
 
299
                        break;
 
300
                default:
 
301
                        termios.c_cflag |= CS8;
 
302
                        break;
 
303
        }
 
304
 
 
305
        tcsetattr(serial_fd, TCSANOW, &termios);
 
306
}
 
307
 
 
308
static NTSTATUS
 
309
serial_create(HANDLE * handle)
 
310
{
 
311
        /* XXX do we have to handle concurrent open attempts? */
 
312
        serial_fd = open("/dev/ttyS0", O_RDWR);
 
313
        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;
 
348
        uint8 immediate;
 
349
 
 
350
        if ((request >> 16) != FILE_DEVICE_SERIAL_PORT)
 
351
                return STATUS_INVALID_PARAMETER;
 
352
 
 
353
        /* extract operation */
 
354
        request >>= 2;
 
355
        request &= 0xfff;
 
356
 
 
357
        printf("SERIAL IOCTL %d\n", request);
 
358
 
 
359
        switch (request)
 
360
        {
 
361
                case SERIAL_SET_BAUD_RATE:
 
362
                        in_uint32_le(in, baud_rate);
 
363
                        set_termios();
 
364
                        break;
 
365
                case SERIAL_GET_BAUD_RATE:
 
366
                        out_uint32_le(out, baud_rate);
 
367
                        break;
 
368
                case SERIAL_SET_QUEUE_SIZE:
 
369
                        in_uint32_le(in, queue_in_size);
 
370
                        in_uint32_le(in, queue_out_size);
 
371
                        break;
 
372
                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();
 
377
                        break;
 
378
                case SERIAL_GET_LINE_CONTROL:
 
379
                        out_uint8(out, stop_bits);
 
380
                        out_uint8(out, parity);
 
381
                        out_uint8(out, word_length);
 
382
                        break;
 
383
                case SERIAL_IMMEDIATE_CHAR:
 
384
                        in_uint8(in, immediate);
 
385
                        serial_write(handle, &immediate, 1, &result);
 
386
                        break;
 
387
                case SERIAL_CONFIG_SIZE:
 
388
                        out_uint32_le(out, 0);
 
389
                        break;
 
390
                case SERIAL_GET_CHARS:
 
391
                        out_uint8s(out, 6);
 
392
                        break;
 
393
                case SERIAL_SET_CHARS:
 
394
                        in_uint8s(in, 6);
 
395
                        break;
 
396
                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);
 
401
                        break;
 
402
                case SERIAL_SET_HANDFLOW:
 
403
                        in_uint8s(in, 16);
 
404
                        break;
 
405
                case SERIAL_SET_TIMEOUTS:
 
406
                        in_uint8s(in, 20);
 
407
                        break;
 
408
                case SERIAL_GET_TIMEOUTS:
 
409
                        out_uint8s(out, 20);
 
410
                        break;
 
411
                case SERIAL_GET_WAIT_MASK:
 
412
                        out_uint32(out, wait_mask);
 
413
                        break;
 
414
                case SERIAL_SET_WAIT_MASK:
 
415
                        in_uint32(in, wait_mask);
 
416
                        break;
 
417
                case SERIAL_SET_DTR:
 
418
                        dtr = 1;
 
419
                        set_termios();
 
420
                        break;
 
421
                case SERIAL_CLR_DTR:
 
422
                        dtr = 0;
 
423
                        set_termios();
 
424
                        break;
 
425
#if 0
 
426
                case SERIAL_WAIT_ON_MASK:
 
427
                        /* XXX implement me */
 
428
                        break;
 
429
                case SERIAL_SET_BREAK_ON:
 
430
                        tcsendbreak(serial_fd, 0);
 
431
                        break;
 
432
                case SERIAL_PURGE:
 
433
                        in_uint32(purge_mask);
 
434
                        /* tcflush */
 
435
                        break;
 
436
                case SERIAL_RESET_DEVICE:
 
437
                case SERIAL_SET_BREAK_OFF:
 
438
                case SERIAL_SET_RTS:
 
439
                case SERIAL_CLR_RTS:
 
440
                case SERIAL_SET_XOFF:
 
441
                case SERIAL_SET_XON:
 
442
                        /* ignore */
 
443
                        break;
 
444
#endif
 
445
 
 
446
                default:
 
447
                        unimpl("SERIAL IOCTL %d\n", request);
 
448
                        return STATUS_INVALID_PARAMETER;
 
449
        }
 
450
 
 
451
        return STATUS_SUCCESS;
 
452
}
 
453
 
 
454
DEVICE_FNS serial_fns = {
 
455
        serial_create,
 
456
        serial_close,
 
457
        serial_read,
 
458
        serial_write,
 
459
        serial_device_control
 
460
};