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