Coverage Report

Created: 2025-07-01 06:46

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