FreeRDP
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 
31 static 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 
122 static 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 */
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 {
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 */
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 {
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 }