Implement controls for file descriptor inheritance
[libs/core.git] / source / io / serial.cpp
1 #include "serial.h"
2 #include "serial_private.h"
3
4 using namespace std;
5
6 namespace Msp {
7 namespace IO {
8
9 Serial::Serial(const string &descr):
10         reader(handle, 1024)
11 {
12         string::size_type comma = descr.find(',');
13         string port = descr.substr(0, comma);
14
15         platform_init(port);
16
17         if(comma!=string::npos)
18         {
19                 try
20                 {
21                         set_parameters(descr.substr(comma+1));
22                 }
23                 catch(...)
24                 {
25                         close();
26                         throw;
27                 }
28         }
29
30         set_events(P_INPUT);
31 }
32
33 Serial::~Serial()
34 {
35         close();
36 }
37
38 void Serial::close()
39 {
40         sys_close(handle);
41 }
42
43 void Serial::set_block(bool b)
44 {
45         adjust_mode(mode, M_NONBLOCK, !b);
46         sys_set_blocking(handle, b);
47 }
48
49 void Serial::set_inherit(bool i)
50 {
51         adjust_mode(mode, M_INHERIT, i);
52         sys_set_inherit(handle, i);
53 }
54
55 void Serial::set_baud_rate(unsigned rate)
56 {
57         DeviceState state;
58         state.get_from(handle);
59         state.set_baud_rate(rate);
60         state.apply_to(handle);
61 }
62
63 void Serial::set_data_bits(unsigned bits)
64 {
65         DeviceState state;
66         state.get_from(handle);
67         state.set_data_bits(bits);
68         state.apply_to(handle);
69 }
70
71 void Serial::set_parity(Parity par)
72 {
73         DeviceState state;
74         state.get_from(handle);
75         state.set_parity(par);
76         state.apply_to(handle);
77 }
78
79 void Serial::set_stop_bits(unsigned bits)
80 {
81         DeviceState state;
82         state.get_from(handle);
83         state.set_stop_bits(bits);
84         state.apply_to(handle);
85 }
86
87 void Serial::set_parameters(const string &params)
88 {
89         unsigned i;
90         for(i=0; i<params.size() && isdigit(params[i]); ++i) ;
91         if(i+4!=params.size() || params[i]!=',')
92                 throw invalid_argument("Serial::set_parameters");
93         if(params[i+1]<'5' || params[i+1]>'8')
94                 throw invalid_argument("Serial::set_parameters data_bits");
95         if(params[i+2]!='N' && params[i+2]!='E' && params[i+2]!='O')
96                 throw invalid_argument("Serial::set_parameters parity");
97         if(params[i+3]!='1' && params[i+3]!='2')
98                 throw invalid_argument("Serial::set_parameters stop_bits");
99
100         DeviceState state;
101         state.get_from(handle);
102         state.set_baud_rate(lexical_cast<unsigned>(params.substr(0, i)));
103         state.set_data_bits(params[i+1]-'0');
104         state.set_parity((params[i+2]=='E' ? EVEN : params[i+2]=='O' ? ODD : NONE));
105         state.set_stop_bits(params[i+3]-'0');
106         state.apply_to(handle);
107 }
108
109 unsigned Serial::do_write(const char *buf, unsigned size)
110 {
111         if(size==0)
112                 return 0;
113
114         return sys_write(handle, buf, size);
115 }
116
117 unsigned Serial::do_read(char *buf, unsigned size)
118 {
119         if(size==0)
120                 return 0;
121
122         unsigned ret = reader.read(buf, size);
123         if(ret==0)
124                 set_eof();
125
126         return ret;
127 }
128
129 const Handle &Serial::get_handle(Mode m)
130 {
131         check_access(m);
132         return handle;
133 }
134
135 } // namespace IO
136 } // namespace Msp