Coverage Report

Created: 2024-05-20 06:11

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