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