FreeRDP
comm_sercx2_sys.c
1 
23 #include <winpr/assert.h>
24 #include <winpr/wlog.h>
25 
26 #include "comm_serial_sys.h"
27 #include "comm_sercx_sys.h"
28 
29 #include "comm_sercx2_sys.h"
30 
31 /* http://msdn.microsoft.com/en-us/library/dn265347%28v=vs.85%29.aspx
32  *
33  * SerCx2 does not support special characters. SerCx2 always completes
34  * an IOCTL_SERIAL_SET_CHARS request with a STATUS_SUCCESS status
35  * code, but does not set any special characters or perform any other
36  * operation in response to this request. For an
37  * IOCTL_SERIAL_GET_CHARS request, SerCx2 sets all the character
38  * values in the SERIAL_CHARS structure to null, and completes the
39  * request with a STATUS_SUCCESS status code.
40  */
41 
42 static BOOL set_serial_chars(WINPR_COMM* pComm, const SERIAL_CHARS* pSerialChars)
43 {
44  WINPR_ASSERT(pComm);
45  WINPR_ASSERT(pSerialChars);
46 
47  return TRUE;
48 }
49 
50 static BOOL get_serial_chars(WINPR_COMM* pComm, SERIAL_CHARS* pSerialChars)
51 {
52  WINPR_ASSERT(pComm);
53  WINPR_ASSERT(pSerialChars);
54 
55  ZeroMemory(pSerialChars, sizeof(SERIAL_CHARS));
56  return TRUE;
57 }
58 
59 /* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439605%28v=vs.85%29.aspx */
60 /* FIXME: only using the Serial.sys' events, complete the support of the remaining events */
61 static const ULONG SERCX2_SYS_SUPPORTED_EV_MASK =
62  SERIAL_EV_RXCHAR | SERIAL_EV_RXFLAG | SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | SERIAL_EV_DSR |
63  SERIAL_EV_RLSD | SERIAL_EV_BREAK | SERIAL_EV_ERR | SERIAL_EV_RING |
64  /* SERIAL_EV_PERR | */
65  SERIAL_EV_RX80FULL /*|
66  SERIAL_EV_EVENT1 |
67  SERIAL_EV_EVENT2*/
68  ;
69 
70 /* use Serial.sys for basis (not SerCx.sys) */
71 static BOOL set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask)
72 {
73  const SERIAL_DRIVER* pSerialSys = SerialSys_s();
74 
75  WINPR_ASSERT(pComm);
76  WINPR_ASSERT(pWaitMask);
77  WINPR_ASSERT(pSerialSys);
78 
79  const ULONG possibleMask = *pWaitMask & SERCX2_SYS_SUPPORTED_EV_MASK;
80 
81  if (possibleMask != *pWaitMask)
82  {
83  CommLog_Print(WLOG_WARN,
84  "Not all wait events supported (SerCx2.sys), requested events= 0x%08" PRIX32
85  ", possible events= 0x%08" PRIX32 "",
86  *pWaitMask, possibleMask);
87 
88  /* FIXME: shall we really set the possibleMask and return FALSE? */
89  pComm->WaitEventMask = possibleMask;
90  return FALSE;
91  }
92 
93  /* NB: All events that are supported by SerCx.sys are supported by Serial.sys*/
94  return pSerialSys->set_wait_mask(pComm, pWaitMask);
95 }
96 
97 static BOOL purge(WINPR_COMM* pComm, const ULONG* pPurgeMask)
98 {
99  const SERIAL_DRIVER* pSerialSys = SerialSys_s();
100 
101  WINPR_ASSERT(pComm);
102  WINPR_ASSERT(pPurgeMask);
103  WINPR_ASSERT(pSerialSys);
104 
105  /* http://msdn.microsoft.com/en-us/library/windows/hardware/ff546655%28v=vs.85%29.aspx */
106 
107  if ((*pPurgeMask & SERIAL_PURGE_RXCLEAR) && !(*pPurgeMask & SERIAL_PURGE_RXABORT))
108  {
109  CommLog_Print(WLOG_WARN,
110  "Expecting SERIAL_PURGE_RXABORT since SERIAL_PURGE_RXCLEAR is set");
111  SetLastError(ERROR_INVALID_DEVICE_OBJECT_PARAMETER);
112  return FALSE;
113  }
114 
115  if ((*pPurgeMask & SERIAL_PURGE_TXCLEAR) && !(*pPurgeMask & SERIAL_PURGE_TXABORT))
116  {
117  CommLog_Print(WLOG_WARN,
118  "Expecting SERIAL_PURGE_TXABORT since SERIAL_PURGE_TXCLEAR is set");
119  SetLastError(ERROR_INVALID_DEVICE_OBJECT_PARAMETER);
120  return FALSE;
121  }
122 
123  return pSerialSys->purge(pComm, pPurgeMask);
124 }
125 
126 /* specific functions only */
127 static SERIAL_DRIVER SerCx2Sys = {
128  .id = SerialDriverSerCx2Sys,
129  .name = _T("SerCx2.sys"),
130  .set_baud_rate = NULL,
131  .get_baud_rate = NULL,
132  .get_properties = NULL,
133  .set_serial_chars = set_serial_chars,
134  .get_serial_chars = get_serial_chars,
135  .set_line_control = NULL,
136  .get_line_control = NULL,
137  .set_handflow = NULL,
138  .get_handflow = NULL,
139  .set_timeouts = NULL,
140  .get_timeouts = NULL,
141  .set_dtr = NULL,
142  .clear_dtr = NULL,
143  .set_rts = NULL,
144  .clear_rts = NULL,
145  .get_modemstatus = NULL,
146  .set_wait_mask = set_wait_mask,
147  .get_wait_mask = NULL,
148  .wait_on_mask = NULL,
149  .set_queue_size = NULL,
150  .purge = purge,
151  .get_commstatus = NULL,
152  .set_break_on = NULL,
153  .set_break_off = NULL,
154  .set_xoff = NULL, /* not supported by SerCx2.sys */
155  .set_xon = NULL, /* not supported by SerCx2.sys */
156  .get_dtrrts = NULL,
157  .config_size = NULL, /* not supported by SerCx2.sys */
158  .immediate_char = NULL, /* not supported by SerCx2.sys */
159  .reset_device = NULL, /* not supported by SerCx2.sys */
160 };
161 
162 const SERIAL_DRIVER* SerCx2Sys_s(void)
163 {
164  /* SerCx2Sys completed with inherited functions from SerialSys or SerCxSys */
165  const SERIAL_DRIVER* pSerialSys = SerialSys_s();
166  const SERIAL_DRIVER* pSerCxSys = SerCxSys_s();
167  if (!pSerialSys || !pSerCxSys)
168  return NULL;
169 
170  SerCx2Sys.set_baud_rate = pSerialSys->set_baud_rate;
171  SerCx2Sys.get_baud_rate = pSerialSys->get_baud_rate;
172 
173  SerCx2Sys.get_properties = pSerialSys->get_properties;
174 
175  SerCx2Sys.set_line_control = pSerCxSys->set_line_control;
176  SerCx2Sys.get_line_control = pSerCxSys->get_line_control;
177 
178  /* Only SERIAL_CTS_HANDSHAKE, SERIAL_RTS_CONTROL and SERIAL_RTS_HANDSHAKE flags are really
179  * required by SerCx2.sys http://msdn.microsoft.com/en-us/library/jj680685%28v=vs.85%29.aspx
180  */
181  SerCx2Sys.set_handflow = pSerialSys->set_handflow;
182  SerCx2Sys.get_handflow = pSerialSys->get_handflow;
183 
184  SerCx2Sys.set_timeouts = pSerialSys->set_timeouts;
185  SerCx2Sys.get_timeouts = pSerialSys->get_timeouts;
186 
187  SerCx2Sys.set_dtr = pSerialSys->set_dtr;
188  SerCx2Sys.clear_dtr = pSerialSys->clear_dtr;
189 
190  SerCx2Sys.set_rts = pSerialSys->set_rts;
191  SerCx2Sys.clear_rts = pSerialSys->clear_rts;
192 
193  SerCx2Sys.get_modemstatus = pSerialSys->get_modemstatus;
194 
195  SerCx2Sys.set_wait_mask = pSerialSys->set_wait_mask;
196  SerCx2Sys.get_wait_mask = pSerialSys->get_wait_mask;
197  SerCx2Sys.wait_on_mask = pSerialSys->wait_on_mask;
198 
199  SerCx2Sys.set_queue_size = pSerialSys->set_queue_size;
200 
201  SerCx2Sys.get_commstatus = pSerialSys->get_commstatus;
202 
203  SerCx2Sys.set_break_on = pSerialSys->set_break_on;
204  SerCx2Sys.set_break_off = pSerialSys->set_break_off;
205 
206  SerCx2Sys.get_dtrrts = pSerialSys->get_dtrrts;
207 
208  return &SerCx2Sys;
209 }