FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
comm_sercx_sys.c
1
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
31static BOOL set_handflow(WINPR_COMM* pComm, const SERIAL_HANDFLOW* pHandflow)
32{
33 SERIAL_HANDFLOW SerCxHandflow;
34 BOOL result = TRUE;
35 const SERIAL_DRIVER* pSerialSys = SerialSys_s();
36
37 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 SerCxHandflow.ControlHandShake =
45 pHandflow->ControlHandShake &
46 (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
47 SerCxHandflow.FlowReplace =
48 pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
49
50 if (SerCxHandflow.ControlHandShake != pHandflow->ControlHandShake)
51 {
52 if (pHandflow->ControlHandShake & SERIAL_DCD_HANDSHAKE)
53 {
54 CommLog_Print(WLOG_WARN,
55 "SERIAL_DCD_HANDSHAKE not supposed to be implemented by SerCx.sys");
56 }
57
58 if (pHandflow->ControlHandShake & SERIAL_DSR_SENSITIVITY)
59 {
60 CommLog_Print(WLOG_WARN,
61 "SERIAL_DSR_SENSITIVITY not supposed to be implemented by SerCx.sys");
62 }
63
64 if (pHandflow->ControlHandShake & SERIAL_ERROR_ABORT)
65 {
66 CommLog_Print(WLOG_WARN,
67 "SERIAL_ERROR_ABORT not supposed to be implemented by SerCx.sys");
68 }
69
70 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
71 result = FALSE;
72 }
73
74 if (SerCxHandflow.FlowReplace != pHandflow->FlowReplace)
75 {
76 if (pHandflow->ControlHandShake & SERIAL_AUTO_TRANSMIT)
77 {
78 CommLog_Print(WLOG_WARN,
79 "SERIAL_AUTO_TRANSMIT not supposed to be implemented by SerCx.sys");
80 }
81
82 if (pHandflow->ControlHandShake & SERIAL_AUTO_RECEIVE)
83 {
84 CommLog_Print(WLOG_WARN,
85 "SERIAL_AUTO_RECEIVE not supposed to be implemented by SerCx.sys");
86 }
87
88 if (pHandflow->ControlHandShake & SERIAL_ERROR_CHAR)
89 {
90 CommLog_Print(WLOG_WARN,
91 "SERIAL_ERROR_CHAR not supposed to be implemented by SerCx.sys");
92 }
93
94 if (pHandflow->ControlHandShake & SERIAL_NULL_STRIPPING)
95 {
96 CommLog_Print(WLOG_WARN,
97 "SERIAL_NULL_STRIPPING not supposed to be implemented by SerCx.sys");
98 }
99
100 if (pHandflow->ControlHandShake & SERIAL_BREAK_CHAR)
101 {
102 CommLog_Print(WLOG_WARN,
103 "SERIAL_BREAK_CHAR not supposed to be implemented by SerCx.sys");
104 }
105
106 if (pHandflow->ControlHandShake & SERIAL_XOFF_CONTINUE)
107 {
108 CommLog_Print(WLOG_WARN,
109 "SERIAL_XOFF_CONTINUE not supposed to be implemented by SerCx.sys");
110 }
111
112 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
113 result = FALSE;
114 }
115
116 if (!pSerialSys->set_handflow(pComm, &SerCxHandflow))
117 return FALSE;
118
119 return result;
120}
121
122static BOOL get_handflow(WINPR_COMM* pComm, SERIAL_HANDFLOW* pHandflow)
123{
124 const SERIAL_DRIVER* pSerialSys = SerialSys_s();
125
126 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 pHandflow->ControlHandShake =
134 pHandflow->ControlHandShake &
135 (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
136 pHandflow->FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
137
138 return result;
139}
140
141/* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439605%28v=vs.85%29.aspx */
142static 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
153static BOOL set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask)
154{
155 const SERIAL_DRIVER* pSerialSys = SerialSys_s();
156 WINPR_ASSERT(pWaitMask);
157
158 const ULONG possibleMask = *pWaitMask & SERCX_SYS_SUPPORTED_EV_MASK;
159
160 if (possibleMask != *pWaitMask)
161 {
162 CommLog_Print(WLOG_WARN,
163 "Not all wait events supported (SerCx.sys), requested events= 0x%08" PRIX32
164 ", possible events= 0x%08" PRIX32 "",
165 *pWaitMask, possibleMask);
166
167 /* FIXME: shall we really set the possibleMask and return FALSE? */
168 pComm->WaitEventMask = possibleMask;
169 return FALSE;
170 }
171
172 /* NB: All events that are supported by SerCx.sys are supported by Serial.sys*/
173 return pSerialSys->set_wait_mask(pComm, pWaitMask);
174}
175
176/* specific functions only */
177static 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
212const SERIAL_DRIVER* SerCxSys_s(void)
213{
214 /* _SerCxSys completed with inherited functions from SerialSys */
215 const SERIAL_DRIVER* pSerialSys = SerialSys_s();
216 if (!pSerialSys)
217 return NULL;
218
219 SerCxSys.set_baud_rate = pSerialSys->set_baud_rate;
220 SerCxSys.get_baud_rate = pSerialSys->get_baud_rate;
221
222 SerCxSys.get_properties = pSerialSys->get_properties;
223
224 SerCxSys.set_serial_chars = pSerialSys->set_serial_chars;
225 SerCxSys.get_serial_chars = pSerialSys->get_serial_chars;
226 SerCxSys.set_line_control = pSerialSys->set_line_control;
227 SerCxSys.get_line_control = pSerialSys->get_line_control;
228
229 SerCxSys.set_timeouts = pSerialSys->set_timeouts;
230 SerCxSys.get_timeouts = pSerialSys->get_timeouts;
231
232 SerCxSys.set_dtr = pSerialSys->set_dtr;
233 SerCxSys.clear_dtr = pSerialSys->clear_dtr;
234
235 SerCxSys.set_rts = pSerialSys->set_rts;
236 SerCxSys.clear_rts = pSerialSys->clear_rts;
237
238 SerCxSys.get_modemstatus = pSerialSys->get_modemstatus;
239
240 SerCxSys.set_wait_mask = pSerialSys->set_wait_mask;
241 SerCxSys.get_wait_mask = pSerialSys->get_wait_mask;
242 SerCxSys.wait_on_mask = pSerialSys->wait_on_mask;
243
244 SerCxSys.set_queue_size = pSerialSys->set_queue_size;
245
246 SerCxSys.purge = pSerialSys->purge;
247
248 SerCxSys.get_commstatus = pSerialSys->get_commstatus;
249
250 SerCxSys.set_break_on = pSerialSys->set_break_on;
251 SerCxSys.set_break_off = pSerialSys->set_break_off;
252
253 SerCxSys.set_xoff = pSerialSys->set_xoff;
254 SerCxSys.set_xon = pSerialSys->set_xon;
255
256 SerCxSys.get_dtrrts = pSerialSys->get_dtrrts;
257
258 SerCxSys.immediate_char = pSerialSys->immediate_char;
259
260 return &SerCxSys;
261}