]> git.tdb.fi Git - libs/core.git/blob - source/io/unix/serial.cpp
Avoid closing handles twice
[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         default: throw invalid_argument("set_baud_rate");
72         }
73
74         cfsetospeed(&state, speed);
75         cfsetispeed(&state, speed);
76 }
77
78 void Serial::DeviceState::set_data_bits(unsigned bits)
79 {
80         tcflag_t flag;
81         switch(bits)
82         {
83         case 5: flag = CS5; break;
84         case 6: flag = CS6; break;
85         case 7: flag = CS7; break;
86         case 8: flag = CS8; break;
87         default: throw invalid_argument("set_data_bits");
88         }
89
90         state.c_cflag = (state.c_cflag&~CSIZE)|flag;
91 }
92
93 void Serial::DeviceState::set_parity(Serial::Parity par)
94 {
95         tcflag_t flag;
96         switch(par)
97         {
98         case Serial::NONE: flag = 0; break;
99         case Serial::EVEN: flag = PARENB; break;
100         case Serial::ODD:  flag = PARENB|PARODD; break;
101         default: throw invalid_argument("set_parity");
102         }
103
104         state.c_cflag = (state.c_cflag&~(PARENB|PARODD))|flag;
105 }
106
107 void Serial::DeviceState::set_stop_bits(unsigned bits)
108 {
109         tcflag_t flag;
110         switch(bits)
111         {
112         case 1: flag = 0; break;
113         case 2: flag = CSTOPB; break;
114         default: throw invalid_argument("set_stop_bits");
115         }
116
117         state.c_cflag = (state.c_cflag&~CSTOPB)|flag;
118 }
119
120 } // namespace IO
121 } // namespace MSp