forked from mikepb/go-serial
-
Notifications
You must be signed in to change notification settings - Fork 0
/
linux_termios.c
132 lines (116 loc) · 3.4 KB
/
linux_termios.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* This file is part of the libserialport project.
*
* Copyright (C) 2013 Martin Ling <martin-libserialport@earth.li>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* At the time of writing, glibc does not support the Linux kernel interfaces
* for setting non-standard baud rates and flow control. We therefore have to
* prepare the correct ioctls ourselves, for which we need the declarations in
* linux/termios.h.
*
* We can't include linux/termios.h in serialport.c however, because its
* contents conflict with the termios.h provided by glibc. So this file exists
* to isolate the bits of code which use the kernel termios declarations.
*
* The details vary by architecture. Some architectures have c_ispeed/c_ospeed
* in struct termios, accessed with TCSETS/TCGETS. Others have these fields in
* struct termios2, accessed with TCSETS2/TCGETS2. Some architectures have the
* TCSETX/TCGETX ioctls used with struct termiox, others do not.
*/
#ifdef __linux__
#include <stdlib.h>
#include <linux/termios.h>
#include "linux_termios.h"
SP_PRIV unsigned long get_termios_get_ioctl(void)
{
#ifdef HAVE_TERMIOS2
return TCGETS2;
#else
return TCGETS;
#endif
}
SP_PRIV unsigned long get_termios_set_ioctl(void)
{
#ifdef HAVE_TERMIOS2
return TCSETS2;
#else
return TCSETS;
#endif
}
SP_PRIV size_t get_termios_size(void)
{
#ifdef HAVE_TERMIOS2
return sizeof(struct termios2);
#else
return sizeof(struct termios);
#endif
}
#if (defined(HAVE_TERMIOS_SPEED) || defined(HAVE_TERMIOS2_SPEED)) && defined(HAVE_BOTHER)
SP_PRIV int get_termios_speed(void *data)
{
#ifdef HAVE_TERMIOS2
struct termios2 *term = (struct termios2 *) data;
#else
struct termios *term = (struct termios *) data;
#endif
if (term->c_ispeed != term->c_ospeed)
return -1;
else
return term->c_ispeed;
}
SP_PRIV void set_termios_speed(void *data, int speed)
{
#ifdef HAVE_TERMIOS2
struct termios2 *term = (struct termios2 *) data;
#else
struct termios *term = (struct termios *) data;
#endif
term->c_cflag &= ~CBAUD;
term->c_cflag |= BOTHER;
term->c_ispeed = term->c_ospeed = speed;
}
#endif
#ifdef HAVE_TERMIOX
SP_PRIV size_t get_termiox_size(void)
{
return sizeof(struct termiox);
}
SP_PRIV int get_termiox_flow(void *data, int *rts, int *cts, int *dtr, int *dsr)
{
struct termiox *termx = (struct termiox *) data;
int flags = 0;
*rts = (termx->x_cflag & RTSXOFF);
*cts = (termx->x_cflag & CTSXON);
*dtr = (termx->x_cflag & DTRXOFF);
*dsr = (termx->x_cflag & DSRXON);
return flags;
}
SP_PRIV void set_termiox_flow(void *data, int rts, int cts, int dtr, int dsr)
{
struct termiox *termx = (struct termiox *) data;
termx->x_cflag &= ~(RTSXOFF | CTSXON | DTRXOFF | DSRXON);
if (rts)
termx->x_cflag |= RTSXOFF;
if (cts)
termx->x_cflag |= CTSXON;
if (dtr)
termx->x_cflag |= DTRXOFF;
if (dsr)
termx->x_cflag |= DSRXON;
}
#endif
#endif