/src/FreeRDP/winpr/libwinpr/comm/comm_sercx_sys.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * WinPR: Windows Portable Runtime |
3 | | * Serial Communication API |
4 | | * |
5 | | * Copyright 2011 O.S. Systems Software Ltda. |
6 | | * Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br> |
7 | | * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com> |
8 | | * Copyright 2014 Hewlett-Packard Development Company, L.P. |
9 | | * |
10 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
11 | | * you may not use this file except in compliance with the License. |
12 | | * You may obtain a copy of the License at |
13 | | * |
14 | | * http://www.apache.org/licenses/LICENSE-2.0 |
15 | | * |
16 | | * Unless required by applicable law or agreed to in writing, software |
17 | | * distributed under the License is distributed on an "AS IS" BASIS, |
18 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
19 | | * See the License for the specific language governing permissions and |
20 | | * limitations under the License. |
21 | | */ |
22 | | |
23 | | #if defined __linux__ && !defined ANDROID |
24 | | |
25 | | #include <winpr/assert.h> |
26 | | #include <termios.h> |
27 | | |
28 | | #include <winpr/wlog.h> |
29 | | |
30 | | #include "comm_serial_sys.h" |
31 | | #include "comm_sercx_sys.h" |
32 | | |
33 | | static BOOL _set_handflow(WINPR_COMM* pComm, const SERIAL_HANDFLOW* pHandflow) |
34 | 0 | { |
35 | 0 | SERIAL_HANDFLOW SerCxHandflow; |
36 | 0 | BOOL result = TRUE; |
37 | 0 | SERIAL_DRIVER* pSerialSys = SerialSys_s(); |
38 | |
|
39 | 0 | memcpy(&SerCxHandflow, pHandflow, sizeof(SERIAL_HANDFLOW)); |
40 | | |
41 | | /* filter out unsupported bits by SerCx.sys |
42 | | * |
43 | | * http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx |
44 | | */ |
45 | |
|
46 | 0 | SerCxHandflow.ControlHandShake = |
47 | 0 | pHandflow->ControlHandShake & |
48 | 0 | (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE); |
49 | 0 | SerCxHandflow.FlowReplace = |
50 | 0 | pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE); |
51 | |
|
52 | 0 | if (SerCxHandflow.ControlHandShake != pHandflow->ControlHandShake) |
53 | 0 | { |
54 | 0 | if (pHandflow->ControlHandShake & SERIAL_DCD_HANDSHAKE) |
55 | 0 | { |
56 | 0 | CommLog_Print(WLOG_WARN, |
57 | 0 | "SERIAL_DCD_HANDSHAKE not supposed to be implemented by SerCx.sys"); |
58 | 0 | } |
59 | |
|
60 | 0 | if (pHandflow->ControlHandShake & SERIAL_DSR_SENSITIVITY) |
61 | 0 | { |
62 | 0 | CommLog_Print(WLOG_WARN, |
63 | 0 | "SERIAL_DSR_SENSITIVITY not supposed to be implemented by SerCx.sys"); |
64 | 0 | } |
65 | |
|
66 | 0 | if (pHandflow->ControlHandShake & SERIAL_ERROR_ABORT) |
67 | 0 | { |
68 | 0 | CommLog_Print(WLOG_WARN, |
69 | 0 | "SERIAL_ERROR_ABORT not supposed to be implemented by SerCx.sys"); |
70 | 0 | } |
71 | |
|
72 | 0 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
73 | 0 | result = FALSE; |
74 | 0 | } |
75 | |
|
76 | 0 | if (SerCxHandflow.FlowReplace != pHandflow->FlowReplace) |
77 | 0 | { |
78 | 0 | if (pHandflow->ControlHandShake & SERIAL_AUTO_TRANSMIT) |
79 | 0 | { |
80 | 0 | CommLog_Print(WLOG_WARN, |
81 | 0 | "SERIAL_AUTO_TRANSMIT not supposed to be implemented by SerCx.sys"); |
82 | 0 | } |
83 | |
|
84 | 0 | if (pHandflow->ControlHandShake & SERIAL_AUTO_RECEIVE) |
85 | 0 | { |
86 | 0 | CommLog_Print(WLOG_WARN, |
87 | 0 | "SERIAL_AUTO_RECEIVE not supposed to be implemented by SerCx.sys"); |
88 | 0 | } |
89 | |
|
90 | 0 | if (pHandflow->ControlHandShake & SERIAL_ERROR_CHAR) |
91 | 0 | { |
92 | 0 | CommLog_Print(WLOG_WARN, |
93 | 0 | "SERIAL_ERROR_CHAR not supposed to be implemented by SerCx.sys"); |
94 | 0 | } |
95 | |
|
96 | 0 | if (pHandflow->ControlHandShake & SERIAL_NULL_STRIPPING) |
97 | 0 | { |
98 | 0 | CommLog_Print(WLOG_WARN, |
99 | 0 | "SERIAL_NULL_STRIPPING not supposed to be implemented by SerCx.sys"); |
100 | 0 | } |
101 | |
|
102 | 0 | if (pHandflow->ControlHandShake & SERIAL_BREAK_CHAR) |
103 | 0 | { |
104 | 0 | CommLog_Print(WLOG_WARN, |
105 | 0 | "SERIAL_BREAK_CHAR not supposed to be implemented by SerCx.sys"); |
106 | 0 | } |
107 | |
|
108 | 0 | if (pHandflow->ControlHandShake & SERIAL_XOFF_CONTINUE) |
109 | 0 | { |
110 | 0 | CommLog_Print(WLOG_WARN, |
111 | 0 | "SERIAL_XOFF_CONTINUE not supposed to be implemented by SerCx.sys"); |
112 | 0 | } |
113 | |
|
114 | 0 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
115 | 0 | result = FALSE; |
116 | 0 | } |
117 | |
|
118 | 0 | if (!pSerialSys->set_handflow(pComm, &SerCxHandflow)) |
119 | 0 | return FALSE; |
120 | | |
121 | 0 | return result; |
122 | 0 | } |
123 | | |
124 | | static BOOL _get_handflow(WINPR_COMM* pComm, SERIAL_HANDFLOW* pHandflow) |
125 | 0 | { |
126 | 0 | BOOL result = 0; |
127 | 0 | SERIAL_DRIVER* pSerialSys = SerialSys_s(); |
128 | |
|
129 | 0 | result = pSerialSys->get_handflow(pComm, pHandflow); |
130 | | |
131 | | /* filter out unsupported bits by SerCx.sys |
132 | | * |
133 | | * http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx |
134 | | */ |
135 | |
|
136 | 0 | pHandflow->ControlHandShake = |
137 | 0 | pHandflow->ControlHandShake & |
138 | 0 | (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE); |
139 | 0 | pHandflow->FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE); |
140 | |
|
141 | 0 | return result; |
142 | 0 | } |
143 | | |
144 | | /* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439605%28v=vs.85%29.aspx */ |
145 | | static const ULONG _SERCX_SYS_SUPPORTED_EV_MASK = SERIAL_EV_RXCHAR | |
146 | | /* SERIAL_EV_RXFLAG | */ |
147 | | SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | |
148 | | SERIAL_EV_DSR | SERIAL_EV_RLSD | SERIAL_EV_BREAK | |
149 | | SERIAL_EV_ERR | SERIAL_EV_RING /* | |
150 | | SERIAL_EV_PERR | |
151 | | SERIAL_EV_RX80FULL | |
152 | | SERIAL_EV_EVENT1 | |
153 | | SERIAL_EV_EVENT2*/ |
154 | | ; |
155 | | |
156 | | static BOOL _set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask) |
157 | 0 | { |
158 | 0 | ULONG possibleMask = 0; |
159 | 0 | SERIAL_DRIVER* pSerialSys = SerialSys_s(); |
160 | |
|
161 | 0 | possibleMask = *pWaitMask & _SERCX_SYS_SUPPORTED_EV_MASK; |
162 | |
|
163 | 0 | if (possibleMask != *pWaitMask) |
164 | 0 | { |
165 | 0 | CommLog_Print(WLOG_WARN, |
166 | 0 | "Not all wait events supported (SerCx.sys), requested events= 0x%08" PRIX32 |
167 | 0 | ", possible events= 0x%08" PRIX32 "", |
168 | 0 | *pWaitMask, possibleMask); |
169 | | |
170 | | /* FIXME: shall we really set the possibleMask and return FALSE? */ |
171 | 0 | pComm->WaitEventMask = possibleMask; |
172 | 0 | return FALSE; |
173 | 0 | } |
174 | | |
175 | | /* NB: All events that are supported by SerCx.sys are supported by Serial.sys*/ |
176 | 0 | return pSerialSys->set_wait_mask(pComm, pWaitMask); |
177 | 0 | } |
178 | | |
179 | | /* specific functions only */ |
180 | | static SERIAL_DRIVER _SerCxSys = { |
181 | | .id = SerialDriverSerCxSys, |
182 | | .name = _T("SerCx.sys"), |
183 | | .set_baud_rate = NULL, |
184 | | .get_baud_rate = NULL, |
185 | | .get_properties = NULL, |
186 | | .set_serial_chars = NULL, |
187 | | .get_serial_chars = NULL, |
188 | | .set_line_control = NULL, |
189 | | .get_line_control = NULL, |
190 | | .set_handflow = _set_handflow, |
191 | | .get_handflow = _get_handflow, |
192 | | .set_timeouts = NULL, |
193 | | .get_timeouts = NULL, |
194 | | .set_dtr = NULL, |
195 | | .clear_dtr = NULL, |
196 | | .set_rts = NULL, |
197 | | .clear_rts = NULL, |
198 | | .get_modemstatus = NULL, |
199 | | .set_wait_mask = _set_wait_mask, |
200 | | .get_wait_mask = NULL, |
201 | | .wait_on_mask = NULL, |
202 | | .set_queue_size = NULL, |
203 | | .purge = NULL, |
204 | | .get_commstatus = NULL, |
205 | | .set_break_on = NULL, |
206 | | .set_break_off = NULL, |
207 | | .set_xoff = NULL, |
208 | | .set_xon = NULL, |
209 | | .get_dtrrts = NULL, |
210 | | .config_size = NULL, /* not supported by SerCx.sys */ |
211 | | .immediate_char = NULL, |
212 | | .reset_device = NULL, /* not supported by SerCx.sys */ |
213 | | }; |
214 | | |
215 | | SERIAL_DRIVER* SerCxSys_s(void) |
216 | 0 | { |
217 | | /* _SerCxSys completed with inherited functions from SerialSys */ |
218 | 0 | SERIAL_DRIVER* pSerialSys = SerialSys_s(); |
219 | 0 | if (!pSerialSys) |
220 | 0 | return NULL; |
221 | | |
222 | 0 | _SerCxSys.set_baud_rate = pSerialSys->set_baud_rate; |
223 | 0 | _SerCxSys.get_baud_rate = pSerialSys->get_baud_rate; |
224 | |
|
225 | 0 | _SerCxSys.get_properties = pSerialSys->get_properties; |
226 | |
|
227 | 0 | _SerCxSys.set_serial_chars = pSerialSys->set_serial_chars; |
228 | 0 | _SerCxSys.get_serial_chars = pSerialSys->get_serial_chars; |
229 | 0 | _SerCxSys.set_line_control = pSerialSys->set_line_control; |
230 | 0 | _SerCxSys.get_line_control = pSerialSys->get_line_control; |
231 | |
|
232 | 0 | _SerCxSys.set_timeouts = pSerialSys->set_timeouts; |
233 | 0 | _SerCxSys.get_timeouts = pSerialSys->get_timeouts; |
234 | |
|
235 | 0 | _SerCxSys.set_dtr = pSerialSys->set_dtr; |
236 | 0 | _SerCxSys.clear_dtr = pSerialSys->clear_dtr; |
237 | |
|
238 | 0 | _SerCxSys.set_rts = pSerialSys->set_rts; |
239 | 0 | _SerCxSys.clear_rts = pSerialSys->clear_rts; |
240 | |
|
241 | 0 | _SerCxSys.get_modemstatus = pSerialSys->get_modemstatus; |
242 | |
|
243 | 0 | _SerCxSys.set_wait_mask = pSerialSys->set_wait_mask; |
244 | 0 | _SerCxSys.get_wait_mask = pSerialSys->get_wait_mask; |
245 | 0 | _SerCxSys.wait_on_mask = pSerialSys->wait_on_mask; |
246 | |
|
247 | 0 | _SerCxSys.set_queue_size = pSerialSys->set_queue_size; |
248 | |
|
249 | 0 | _SerCxSys.purge = pSerialSys->purge; |
250 | |
|
251 | 0 | _SerCxSys.get_commstatus = pSerialSys->get_commstatus; |
252 | |
|
253 | 0 | _SerCxSys.set_break_on = pSerialSys->set_break_on; |
254 | 0 | _SerCxSys.set_break_off = pSerialSys->set_break_off; |
255 | |
|
256 | 0 | _SerCxSys.set_xoff = pSerialSys->set_xoff; |
257 | 0 | _SerCxSys.set_xon = pSerialSys->set_xon; |
258 | |
|
259 | 0 | _SerCxSys.get_dtrrts = pSerialSys->get_dtrrts; |
260 | |
|
261 | 0 | _SerCxSys.immediate_char = pSerialSys->immediate_char; |
262 | |
|
263 | 0 | return &_SerCxSys; |
264 | 0 | } |
265 | | |
266 | | #endif /* __linux__ */ |