Additional baud rates from termios.h
[libs/core.git] / source / io / unix / serial.cpp
1 #include <fcntl.h>
2 #include <termios.h>
3 #include <msp/core/systemerror.h>
4 #include <msp/strings/format.h>
5 #include "handle_private.h"
6 #include "serial.h"
7 #include "serial_private.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace IO {
13
14 void Serial::platform_init(const string &port)
15 {
16         string fn = port;
17         if(fn.compare(0, 5, "/dev/"))
18                 fn = "/dev/"+fn;
19
20         *handle = open(fn.c_str(), O_RDWR);
21         if(!handle)
22                 throw system_error(format("open(%s)", port));
23         mode = M_READ|M_WRITE;
24
25         termios t;
26         tcgetattr(*handle, &t);
27         t.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON);
28         t.c_lflag &= ~(ECHO|ICANON|ISIG|IEXTEN);
29         t.c_oflag &= ~(OPOST|OCRNL|ONOCR|ONLRET);
30         t.c_cc[VMIN] = 1;
31         t.c_cc[VTIME] = 0;
32         tcsetattr(*handle, TCSADRAIN, &t);
33 }
34
35
36 void Serial::DeviceState::get_from(const Handle &h)
37 {
38         tcgetattr(*h, &state);
39 }
40
41 void Serial::DeviceState::apply_to(const Handle &h)
42 {
43         if(tcsetattr(*h, TCSADRAIN, &state)==-1)
44                 throw system_error("tcsetattr");
45 }
46
47 void Serial::DeviceState::set_baud_rate(unsigned baud)
48 {
49         speed_t speed;
50         switch(baud)
51         {
52         case 0:      speed = B0; break;
53         case 50:     speed = B50; break;
54         case 75:     speed = B75; break;
55         case 110:    speed = B110; break;
56         case 134:    speed = B134; break;
57         case 150:    speed = B150; break;
58         case 200:    speed = B200; break;
59         case 300:    speed = B300; break;
60         case 600:    speed = B600; break;
61         case 1200:   speed = B1200; break;
62         case 1800:   speed = B1800; break;
63         case 2400:   speed = B2400; break;
64         case 4800:   speed = B4800; break;
65         case 9600:   speed = B9600; break;
66         case 19200:  speed = B19200; break;
67         case 38400:  speed = B38400; break;
68         case 57600:  speed = B57600; break;
69         case 115200: speed = B115200; break;
70         case 230400: speed = B230400; break;
71         case 460800: speed = B460800; break;
72         case 500000: speed = B500000; break;
73         case 576000: speed = B576000; break;
74         case 921600: speed = B921600; break;
75         case 1000000: speed = B1000000; break;
76         case 1152000: speed = B1152000; break;
77         case 1500000: speed = B1500000; break;
78         case 2000000: speed = B2000000; break;
79         case 2500000: speed = B2500000; break;
80         case 3000000: speed = B3000000; break;
81         case 3500000: speed = B3500000; break;
82         case 4000000: speed = B4000000; break;
83         default: throw invalid_argument("set_baud_rate");
84         }
85
86         cfsetospeed(&state, speed);
87         cfsetispeed(&state, speed);
88 }
89
90 void Serial::DeviceState::set_data_bits(unsigned bits)
91 {
92         tcflag_t flag;
93         switch(bits)
94         {
95         case 5: flag = CS5; break;
96         case 6: flag = CS6; break;
97         case 7: flag = CS7; break;
98         case 8: flag = CS8; break;
99         default: throw invalid_argument("set_data_bits");
100         }
101
102         state.c_cflag = (state.c_cflag&~CSIZE)|flag;
103 }
104
105 void Serial::DeviceState::set_parity(Serial::Parity par)
106 {
107         tcflag_t flag;
108         switch(par)
109         {
110         case Serial::NONE: flag = 0; break;
111         case Serial::EVEN: flag = PARENB; break;
112         case Serial::ODD:  flag = PARENB|PARODD; break;
113         default: throw invalid_argument("set_parity");
114         }
115
116         state.c_cflag = (state.c_cflag&~(PARENB|PARODD))|flag;
117 }
118
119 void Serial::DeviceState::set_stop_bits(unsigned bits)
120 {
121         tcflag_t flag;
122         switch(bits)
123         {
124         case 1: flag = 0; break;
125         case 2: flag = CSTOPB; break;
126         default: throw invalid_argument("set_stop_bits");
127         }
128
129         state.c_cflag = (state.c_cflag&~CSTOPB)|flag;
130 }
131
132 } // namespace IO
133 } // namespace MSp