/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 | | #include <winpr/assert.h> |
24 | | #include <termios.h> |
25 | | |
26 | | #include <winpr/wlog.h> |
27 | | |
28 | | #include "comm_serial_sys.h" |
29 | | #include "comm_sercx_sys.h" |
30 | | |
31 | | static BOOL set_handflow(WINPR_COMM* pComm, const SERIAL_HANDFLOW* pHandflow) |
32 | 0 | { |
33 | 0 | SERIAL_HANDFLOW SerCxHandflow; |
34 | 0 | BOOL result = TRUE; |
35 | 0 | const SERIAL_DRIVER* pSerialSys = SerialSys_s(); |
36 | |
|
37 | 0 | memcpy(&SerCxHandflow, pHandflow, sizeof(SERIAL_HANDFLOW)); |
38 | | |
39 | | /* filter out unsupported bits by SerCx.sys |
40 | | * |
41 | | * http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx |
42 | | */ |
43 | |
|
44 | 0 | SerCxHandflow.ControlHandShake = |
45 | 0 | pHandflow->ControlHandShake & |
46 | 0 | (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE); |
47 | 0 | SerCxHandflow.FlowReplace = |
48 | 0 | pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE); |
49 | |
|
50 | 0 | if (SerCxHandflow.ControlHandShake != pHandflow->ControlHandShake) |
51 | 0 | { |
52 | 0 | if (pHandflow->ControlHandShake & SERIAL_DCD_HANDSHAKE) |
53 | 0 | { |
54 | 0 | CommLog_Print(WLOG_WARN, |
55 | 0 | "SERIAL_DCD_HANDSHAKE not supposed to be implemented by SerCx.sys"); |
56 | 0 | } |
57 | |
|
58 | 0 | if (pHandflow->ControlHandShake & SERIAL_DSR_SENSITIVITY) |
59 | 0 | { |
60 | 0 | CommLog_Print(WLOG_WARN, |
61 | 0 | "SERIAL_DSR_SENSITIVITY not supposed to be implemented by SerCx.sys"); |
62 | 0 | } |
63 | |
|
64 | 0 | if (pHandflow->ControlHandShake & SERIAL_ERROR_ABORT) |
65 | 0 | { |
66 | 0 | CommLog_Print(WLOG_WARN, |
67 | 0 | "SERIAL_ERROR_ABORT not supposed to be implemented by SerCx.sys"); |
68 | 0 | } |
69 | |
|
70 | 0 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
71 | 0 | result = FALSE; |
72 | 0 | } |
73 | |
|
74 | 0 | if (SerCxHandflow.FlowReplace != pHandflow->FlowReplace) |
75 | 0 | { |
76 | 0 | if (pHandflow->ControlHandShake & SERIAL_AUTO_TRANSMIT) |
77 | 0 | { |
78 | 0 | CommLog_Print(WLOG_WARN, |
79 | 0 | "SERIAL_AUTO_TRANSMIT not supposed to be implemented by SerCx.sys"); |
80 | 0 | } |
81 | |
|
82 | 0 | if (pHandflow->ControlHandShake & SERIAL_AUTO_RECEIVE) |
83 | 0 | { |
84 | 0 | CommLog_Print(WLOG_WARN, |
85 | 0 | "SERIAL_AUTO_RECEIVE not supposed to be implemented by SerCx.sys"); |
86 | 0 | } |
87 | |
|
88 | 0 | if (pHandflow->ControlHandShake & SERIAL_ERROR_CHAR) |
89 | 0 | { |
90 | 0 | CommLog_Print(WLOG_WARN, |
91 | 0 | "SERIAL_ERROR_CHAR not supposed to be implemented by SerCx.sys"); |
92 | 0 | } |
93 | |
|
94 | 0 | if (pHandflow->ControlHandShake & SERIAL_NULL_STRIPPING) |
95 | 0 | { |
96 | 0 | CommLog_Print(WLOG_WARN, |
97 | 0 | "SERIAL_NULL_STRIPPING not supposed to be implemented by SerCx.sys"); |
98 | 0 | } |
99 | |
|
100 | 0 | if (pHandflow->ControlHandShake & SERIAL_BREAK_CHAR) |
101 | 0 | { |
102 | 0 | CommLog_Print(WLOG_WARN, |
103 | 0 | "SERIAL_BREAK_CHAR not supposed to be implemented by SerCx.sys"); |
104 | 0 | } |
105 | |
|
106 | 0 | if (pHandflow->ControlHandShake & SERIAL_XOFF_CONTINUE) |
107 | 0 | { |
108 | 0 | CommLog_Print(WLOG_WARN, |
109 | 0 | "SERIAL_XOFF_CONTINUE not supposed to be implemented by SerCx.sys"); |
110 | 0 | } |
111 | |
|
112 | 0 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
113 | 0 | result = FALSE; |
114 | 0 | } |
115 | |
|
116 | 0 | if (!pSerialSys->set_handflow(pComm, &SerCxHandflow)) |
117 | 0 | return FALSE; |
118 | | |
119 | 0 | return result; |
120 | 0 | } |
121 | | |
122 | | static BOOL get_handflow(WINPR_COMM* pComm, SERIAL_HANDFLOW* pHandflow) |
123 | 0 | { |
124 | 0 | const SERIAL_DRIVER* pSerialSys = SerialSys_s(); |
125 | |
|
126 | 0 | BOOL result = pSerialSys->get_handflow(pComm, pHandflow); |
127 | | |
128 | | /* filter out unsupported bits by SerCx.sys |
129 | | * |
130 | | * http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx |
131 | | */ |
132 | |
|
133 | 0 | pHandflow->ControlHandShake = |
134 | 0 | pHandflow->ControlHandShake & |
135 | 0 | (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE); |
136 | 0 | pHandflow->FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE); |
137 | |
|
138 | 0 | return result; |
139 | 0 | } |
140 | | |
141 | | /* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439605%28v=vs.85%29.aspx */ |
142 | | static const ULONG SERCX_SYS_SUPPORTED_EV_MASK = SERIAL_EV_RXCHAR | |
143 | | /* SERIAL_EV_RXFLAG | */ |
144 | | SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | SERIAL_EV_DSR | |
145 | | SERIAL_EV_RLSD | SERIAL_EV_BREAK | SERIAL_EV_ERR | |
146 | | SERIAL_EV_RING /* | |
147 | | SERIAL_EV_PERR | |
148 | | SERIAL_EV_RX80FULL | |
149 | | SERIAL_EV_EVENT1 | |
150 | | SERIAL_EV_EVENT2*/ |
151 | | ; |
152 | | |
153 | | static BOOL set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask) |
154 | 0 | { |
155 | 0 | const SERIAL_DRIVER* pSerialSys = SerialSys_s(); |
156 | 0 | WINPR_ASSERT(pWaitMask); |
157 | | |
158 | 0 | const ULONG possibleMask = *pWaitMask & SERCX_SYS_SUPPORTED_EV_MASK; |
159 | |
|
160 | 0 | if (possibleMask != *pWaitMask) |
161 | 0 | { |
162 | 0 | CommLog_Print(WLOG_WARN, |
163 | 0 | "Not all wait events supported (SerCx.sys), requested events= 0x%08" PRIX32 |
164 | 0 | ", possible events= 0x%08" PRIX32 "", |
165 | 0 | *pWaitMask, possibleMask); |
166 | | |
167 | | /* FIXME: shall we really set the possibleMask and return FALSE? */ |
168 | 0 | pComm->WaitEventMask = possibleMask; |
169 | 0 | return FALSE; |
170 | 0 | } |
171 | | |
172 | | /* NB: All events that are supported by SerCx.sys are supported by Serial.sys*/ |
173 | 0 | return pSerialSys->set_wait_mask(pComm, pWaitMask); |
174 | 0 | } |
175 | | |
176 | | /* specific functions only */ |
177 | | static SERIAL_DRIVER SerCxSys = { |
178 | | .id = SerialDriverSerCxSys, |
179 | | .name = _T("SerCx.sys"), |
180 | | .set_baud_rate = NULL, |
181 | | .get_baud_rate = NULL, |
182 | | .get_properties = NULL, |
183 | | .set_serial_chars = NULL, |
184 | | .get_serial_chars = NULL, |
185 | | .set_line_control = NULL, |
186 | | .get_line_control = NULL, |
187 | | .set_handflow = set_handflow, |
188 | | .get_handflow = get_handflow, |
189 | | .set_timeouts = NULL, |
190 | | .get_timeouts = NULL, |
191 | | .set_dtr = NULL, |
192 | | .clear_dtr = NULL, |
193 | | .set_rts = NULL, |
194 | | .clear_rts = NULL, |
195 | | .get_modemstatus = NULL, |
196 | | .set_wait_mask = set_wait_mask, |
197 | | .get_wait_mask = NULL, |
198 | | .wait_on_mask = NULL, |
199 | | .set_queue_size = NULL, |
200 | | .purge = NULL, |
201 | | .get_commstatus = NULL, |
202 | | .set_break_on = NULL, |
203 | | .set_break_off = NULL, |
204 | | .set_xoff = NULL, |
205 | | .set_xon = NULL, |
206 | | .get_dtrrts = NULL, |
207 | | .config_size = NULL, /* not supported by SerCx.sys */ |
208 | | .immediate_char = NULL, |
209 | | .reset_device = NULL, /* not supported by SerCx.sys */ |
210 | | }; |
211 | | |
212 | | const SERIAL_DRIVER* SerCxSys_s(void) |
213 | 0 | { |
214 | | /* _SerCxSys completed with inherited functions from SerialSys */ |
215 | 0 | const SERIAL_DRIVER* pSerialSys = SerialSys_s(); |
216 | 0 | if (!pSerialSys) |
217 | 0 | return NULL; |
218 | | |
219 | 0 | SerCxSys.set_baud_rate = pSerialSys->set_baud_rate; |
220 | 0 | SerCxSys.get_baud_rate = pSerialSys->get_baud_rate; |
221 | |
|
222 | 0 | SerCxSys.get_properties = pSerialSys->get_properties; |
223 | |
|
224 | 0 | SerCxSys.set_serial_chars = pSerialSys->set_serial_chars; |
225 | 0 | SerCxSys.get_serial_chars = pSerialSys->get_serial_chars; |
226 | 0 | SerCxSys.set_line_control = pSerialSys->set_line_control; |
227 | 0 | SerCxSys.get_line_control = pSerialSys->get_line_control; |
228 | |
|
229 | 0 | SerCxSys.set_timeouts = pSerialSys->set_timeouts; |
230 | 0 | SerCxSys.get_timeouts = pSerialSys->get_timeouts; |
231 | |
|
232 | 0 | SerCxSys.set_dtr = pSerialSys->set_dtr; |
233 | 0 | SerCxSys.clear_dtr = pSerialSys->clear_dtr; |
234 | |
|
235 | 0 | SerCxSys.set_rts = pSerialSys->set_rts; |
236 | 0 | SerCxSys.clear_rts = pSerialSys->clear_rts; |
237 | |
|
238 | 0 | SerCxSys.get_modemstatus = pSerialSys->get_modemstatus; |
239 | |
|
240 | 0 | SerCxSys.set_wait_mask = pSerialSys->set_wait_mask; |
241 | 0 | SerCxSys.get_wait_mask = pSerialSys->get_wait_mask; |
242 | 0 | SerCxSys.wait_on_mask = pSerialSys->wait_on_mask; |
243 | |
|
244 | 0 | SerCxSys.set_queue_size = pSerialSys->set_queue_size; |
245 | |
|
246 | 0 | SerCxSys.purge = pSerialSys->purge; |
247 | |
|
248 | 0 | SerCxSys.get_commstatus = pSerialSys->get_commstatus; |
249 | |
|
250 | 0 | SerCxSys.set_break_on = pSerialSys->set_break_on; |
251 | 0 | SerCxSys.set_break_off = pSerialSys->set_break_off; |
252 | |
|
253 | 0 | SerCxSys.set_xoff = pSerialSys->set_xoff; |
254 | 0 | SerCxSys.set_xon = pSerialSys->set_xon; |
255 | |
|
256 | 0 | SerCxSys.get_dtrrts = pSerialSys->get_dtrrts; |
257 | |
|
258 | 0 | SerCxSys.immediate_char = pSerialSys->immediate_char; |
259 | |
|
260 | 0 | return &SerCxSys; |
261 | 0 | } |