xref: /reactos/boot/freeldr/fdebug/rs232.c (revision 2196a06f)
1 /*
2  *  FreeLoader - rs232.c
3  *
4  *  Copyright (C) 2003  Brian Palmer  <brianp@sginet.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include <windows.h>
22 #include <winioctl.h>
23 #include <tchar.h>
24 #include <stdio.h>
25 
26 #include "rs232.h"
27 
28 
29 HANDLE    hPortHandle = NULL;
30 
31 
32 BOOL Rs232OpenPortWin32(TCHAR* CommPort)
33 {
34     TCHAR    PortName[MAX_PATH];
35     DWORD    ErrorCode;
36 
37     // First check and make sure they don't already have the
38     // OBD2 connection open. We don't want to open things twice.
39     if (hPortHandle != NULL)
40     {
41         _tprintf(TEXT("Port handle not NULL. Must be already open. Returning FALSE...\n"));
42         return FALSE;
43     }
44 
45     _stprintf(PortName, TEXT("\\\\.\\%s"), CommPort);
46 
47     hPortHandle = CreateFile(PortName,
48                             GENERIC_READ|GENERIC_WRITE,
49                             0,
50                             0,
51                             OPEN_EXISTING,
52                             0,
53                             0);
54 
55     if (hPortHandle == INVALID_HANDLE_VALUE)
56     {
57         hPortHandle = NULL;
58         ErrorCode = GetLastError();
59 
60         _tprintf(TEXT("CreateFile(\"%s\") failed. GetLastError() = %lu.\n"), PortName, ErrorCode);
61 
62         return FALSE;
63     }
64 
65     return TRUE;
66 }
67 
68 BOOL Rs232ClosePortWin32(VOID)
69 {
70     HANDLE    hTempPortHandle = hPortHandle;
71 
72     hPortHandle = NULL;
73 
74     if (hTempPortHandle == NULL)
75     {
76         return FALSE;
77     }
78 
79     return CloseHandle(hTempPortHandle);
80 }
81 
82 // DeviceControlString
83 //   [in] Pointer to a null-terminated string that specifies device-control information.
84 //   The string must have the same form as the mode command's command-line arguments.
85 //
86 //   For example, the following string specifies a baud rate of 1200, no parity, 8 data bits, and 1 stop bit:
87 //   "baud=1200 parity=N data=8 stop=1"
88 //
89 //   The following string specifies a baud rate of 115200, no parity, 8 data bits, and 1 stop bit:
90 //   "115200,n,8,1"
91 //
92 //   The device name is ignored if it is included in the string, but it must specify a valid device, as follows:
93 //   "COM1: baud=1200 parity=N data=8 stop=1"
94 //
95 //   For further information on mode command syntax, refer to the end-user documentation for your operating system.
96 BOOL Rs232ConfigurePortWin32(TCHAR* DeviceControlString)
97 {
98     DCB        dcb;
99     DWORD    ErrorCode;
100 
101 #if 0
102     if (!GetCommState(hPortHandle, &dcb))
103     {
104         ErrorCode = GetLastError();
105 
106         _tprintf(TEXT("GetCommState() failed. GetLastError() = %lu.\n"), ErrorCode);
107 
108         return FALSE;
109     }
110 
111     dcb.BaudRate = BaudRate;
112     dcb.ByteSize = DataBits;
113     dcb.Parity = Parity;
114     dcb.StopBits = StopBits;
115     dcb.fBinary = TRUE;
116     dcb.fDsrSensitivity = FALSE;
117     dcb.fParity = (Parity == NOPARITY) ? FALSE : TRUE;
118     dcb.fOutX = FALSE;
119     dcb.fInX = FALSE;
120     dcb.fNull = FALSE;
121     dcb.fAbortOnError = TRUE;
122     dcb.fOutxCtsFlow = FALSE;
123     dcb.fOutxDsrFlow = FALSE;
124     dcb.fDtrControl = DTR_CONTROL_DISABLE;
125     dcb.fDsrSensitivity = FALSE;
126     dcb.fRtsControl = RTS_CONTROL_DISABLE;
127     dcb.fOutxCtsFlow = FALSE;
128     dcb.fOutxCtsFlow = FALSE;
129 #endif
130 
131     ZeroMemory(&dcb, sizeof(dcb));
132     dcb.DCBlength = sizeof(dcb);
133     if (!BuildCommDCB(DeviceControlString, &dcb))
134     {
135         ErrorCode = GetLastError();
136 
137         _tprintf(TEXT("BuildCommDCB() failed. GetLastError() = %lu.\n"), ErrorCode);
138 
139         return FALSE;
140     }
141 
142     if (!SetCommState(hPortHandle, &dcb))
143     {
144         ErrorCode = GetLastError();
145 
146         _tprintf(TEXT("SetCommState() failed. GetLastError() = %lu.\n"), ErrorCode);
147 
148         return FALSE;
149     }
150 
151     // Set the timeouts
152     if (!Rs232SetCommunicationTimeoutsWin32(MAXDWORD, 0, 0, 0, 0))
153     {
154         return FALSE;
155     }
156 
157     return TRUE;
158 }
159 
160 // Members
161 //  ReadIntervalTimeout
162 //   Specifies the maximum time, in milliseconds, allowed to elapse between the arrival of two characters on the communications line. During a ReadFile operation, the time period begins when the first character is received. If the interval between the arrival of any two characters exceeds this amount, the ReadFile operation is completed and any buffered data is returned. A value of zero indicates that interval time-outs are not used.
163 //   A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the characters that have already been received, even if no characters have been received.
164 //
165 //  ReadTotalTimeoutMultiplier
166 //   Specifies the multiplier, in milliseconds, used to calculate the total time-out period for read operations. For each read operation, this value is multiplied by the requested number of bytes to be read.
167 //  ReadTotalTimeoutConstant
168 //   Specifies the constant, in milliseconds, used to calculate the total time-out period for read operations. For each read operation, this value is added to the product of the ReadTotalTimeoutMultiplier member and the requested number of bytes.
169 //   A value of zero for both the ReadTotalTimeoutMultiplier and ReadTotalTimeoutConstant members indicates that total time-outs are not used for read operations.
170 //
171 //  WriteTotalTimeoutMultiplier
172 //   Specifies the multiplier, in milliseconds, used to calculate the total time-out period for write operations. For each write operation, this value is multiplied by the number of bytes to be written.
173 //  WriteTotalTimeoutConstant
174 //   Specifies the constant, in milliseconds, used to calculate the total time-out period for write operations. For each write operation, this value is added to the product of the WriteTotalTimeoutMultiplier member and the number of bytes to be written.
175 //   A value of zero for both the WriteTotalTimeoutMultiplier and WriteTotalTimeoutConstant members indicates that total time-outs are not used for write operations.
176 //
177 // Remarks
178 //  If an application sets ReadIntervalTimeout and ReadTotalTimeoutMultiplier to MAXDWORD and sets ReadTotalTimeoutConstant to a value greater than zero and less than MAXDWORD, one of the following occurs when the ReadFile function is called:
179 //
180 //   If there are any characters in the input buffer, ReadFile returns immediately with the characters in the buffer.
181 //   If there are no characters in the input buffer, ReadFile waits until a character arrives and then returns immediately.
182 //   If no character arrives within the time specified by ReadTotalTimeoutConstant, ReadFile times out.
183 BOOL Rs232SetCommunicationTimeoutsWin32(DWORD ReadIntervalTimeout, DWORD ReadTotalTimeoutMultiplier, DWORD ReadTotalTimeoutConstant, DWORD WriteTotalTimeoutMultiplier, DWORD WriteTotalTimeoutConstant)
184 {
185     COMMTIMEOUTS    ct;
186     DWORD            ErrorCode;
187 
188     if (!GetCommTimeouts(hPortHandle, &ct))
189     {
190         ErrorCode = GetLastError();
191 
192         _tprintf(TEXT("GetCommTimeouts() failed. GetLastError() = %lu.\n"), ErrorCode);
193 
194         return FALSE;
195     }
196 
197     ct.ReadIntervalTimeout = ReadIntervalTimeout;
198     ct.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant;
199     ct.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier;
200     ct.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant;
201     ct.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier;
202 
203     if (!SetCommTimeouts(hPortHandle, &ct))
204     {
205         ErrorCode = GetLastError();
206 
207         _tprintf(TEXT("SetCommTimeouts() failed. GetLastError() = %lu.\n"), ErrorCode);
208 
209         return FALSE;
210     }
211 
212     return TRUE;
213 }
214 
215 BOOL Rs232ReadByteWin32(BYTE* DataByte)
216 {
217     DWORD    BytesRead = 0;
218     DWORD    ErrorCode;
219 
220     // If ReadFile() fails then report error
221     if (!ReadFile(hPortHandle, DataByte, 1, &BytesRead, NULL))
222     {
223         ErrorCode = GetLastError();
224 
225         _tprintf(TEXT("ReadFile() failed. GetLastError() = %lu.\n"), ErrorCode);
226 
227         return FALSE;
228     }
229 
230     // If ReadFile() succeeds, but BytesRead isn't 1
231     // then a timeout occurred.
232     if (BytesRead != 1)
233     {
234         return FALSE;
235     }
236 
237     return TRUE;
238 }
239 
240 BOOL Rs232WriteByteWin32(BYTE DataByte)
241 {
242     DWORD    BytesWritten = 0;
243     BOOL    Success;
244     DWORD    ErrorCode;
245 
246     Success = WriteFile(hPortHandle, &DataByte, 1, &BytesWritten, NULL);
247 
248     if (!Success || BytesWritten != 1)
249     {
250         ErrorCode = GetLastError();
251 
252         _tprintf(TEXT("WriteFile() failed. GetLastError() = %lu.\n"), ErrorCode);
253 
254         return FALSE;
255     }
256 
257     return TRUE;
258 }
259