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 (!GetCommState(hPortHandle, &dcb)) 102 { 103 ErrorCode = GetLastError(); 104 105 _tprintf(TEXT("GetCommState() failed. GetLastError() = %lu.\n"), ErrorCode); 106 107 return FALSE; 108 } 109 110 dcb.BaudRate = BaudRate; 111 dcb.ByteSize = DataBits; 112 dcb.Parity = Parity; 113 dcb.StopBits = StopBits; 114 dcb.fBinary = TRUE; 115 dcb.fDsrSensitivity = FALSE; 116 dcb.fParity = (Parity == NOPARITY) ? FALSE : TRUE; 117 dcb.fOutX = FALSE; 118 dcb.fInX = FALSE; 119 dcb.fNull = FALSE; 120 dcb.fAbortOnError = TRUE; 121 dcb.fOutxCtsFlow = FALSE; 122 dcb.fOutxDsrFlow = FALSE; 123 dcb.fDtrControl = DTR_CONTROL_DISABLE; 124 dcb.fDsrSensitivity = FALSE; 125 dcb.fRtsControl = RTS_CONTROL_DISABLE; 126 dcb.fOutxCtsFlow = FALSE; 127 dcb.fOutxCtsFlow = FALSE;*/ 128 129 130 memset(&dcb, 0, sizeof(DCB)); 131 dcb.DCBlength = sizeof(dcb); 132 if (!BuildCommDCB(DeviceControlString, &dcb)) 133 { 134 ErrorCode = GetLastError(); 135 136 _tprintf(TEXT("BuildCommDCB() failed. GetLastError() = %lu.\n"), ErrorCode); 137 138 return FALSE; 139 } 140 141 if (!SetCommState(hPortHandle, &dcb)) 142 { 143 ErrorCode = GetLastError(); 144 145 _tprintf(TEXT("SetCommState() failed. GetLastError() = %lu.\n"), ErrorCode); 146 147 return FALSE; 148 } 149 150 // Set the timeouts 151 if (!Rs232SetCommunicationTimeoutsWin32(MAXDWORD, 0, 0, 0, 0)) 152 { 153 return FALSE; 154 } 155 156 return TRUE; 157 } 158 159 // Members 160 // ReadIntervalTimeout 161 // 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. 162 // 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. 163 // 164 // ReadTotalTimeoutMultiplier 165 // 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. 166 // ReadTotalTimeoutConstant 167 // 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. 168 // A value of zero for both the ReadTotalTimeoutMultiplier and ReadTotalTimeoutConstant members indicates that total time-outs are not used for read operations. 169 // 170 // WriteTotalTimeoutMultiplier 171 // 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. 172 // WriteTotalTimeoutConstant 173 // 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. 174 // A value of zero for both the WriteTotalTimeoutMultiplier and WriteTotalTimeoutConstant members indicates that total time-outs are not used for write operations. 175 // 176 // Remarks 177 // 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: 178 // 179 // If there are any characters in the input buffer, ReadFile returns immediately with the characters in the buffer. 180 // If there are no characters in the input buffer, ReadFile waits until a character arrives and then returns immediately. 181 // If no character arrives within the time specified by ReadTotalTimeoutConstant, ReadFile times out. 182 BOOL Rs232SetCommunicationTimeoutsWin32(DWORD ReadIntervalTimeout, DWORD ReadTotalTimeoutMultiplier, DWORD ReadTotalTimeoutConstant, DWORD WriteTotalTimeoutMultiplier, DWORD WriteTotalTimeoutConstant) 183 { 184 COMMTIMEOUTS ct; 185 DWORD ErrorCode; 186 187 if (!GetCommTimeouts(hPortHandle, &ct)) 188 { 189 ErrorCode = GetLastError(); 190 191 _tprintf(TEXT("GetCommTimeouts() failed. GetLastError() = %lu.\n"), ErrorCode); 192 193 return FALSE; 194 } 195 196 ct.ReadIntervalTimeout = ReadIntervalTimeout; 197 ct.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant; 198 ct.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier; 199 ct.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant; 200 ct.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier; 201 202 if (!SetCommTimeouts(hPortHandle, &ct)) 203 { 204 ErrorCode = GetLastError(); 205 206 _tprintf(TEXT("SetCommTimeouts() failed. GetLastError() = %lu.\n"), ErrorCode); 207 208 return FALSE; 209 } 210 211 return TRUE; 212 } 213 214 BOOL Rs232ReadByteWin32(BYTE* DataByte) 215 { 216 DWORD BytesRead = 0; 217 DWORD ErrorCode; 218 219 // If ReadFile() fails then report error 220 if (!ReadFile(hPortHandle, DataByte, 1, &BytesRead, NULL)) 221 { 222 ErrorCode = GetLastError(); 223 224 _tprintf(TEXT("ReadFile() failed. GetLastError() = %lu.\n"), ErrorCode); 225 226 return FALSE; 227 } 228 229 // If ReadFile() succeeds, but BytesRead isn't 1 230 // then a timeout occurred. 231 if (BytesRead != 1) 232 { 233 return FALSE; 234 } 235 236 return TRUE; 237 } 238 239 BOOL Rs232WriteByteWin32(BYTE DataByte) 240 { 241 DWORD BytesWritten = 0; 242 BOOL Success; 243 DWORD ErrorCode; 244 245 Success = WriteFile(hPortHandle, &DataByte, 1, &BytesWritten, NULL); 246 247 if (!Success || BytesWritten != 1) 248 { 249 ErrorCode = GetLastError(); 250 251 _tprintf(TEXT("WriteFile() failed. GetLastError() = %lu.\n"), ErrorCode); 252 253 return FALSE; 254 } 255 256 return TRUE; 257 } 258