3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/comm.c
6 * PURPOSE: Comm functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
9 * Robert Dickenson (robd@mok.lvcom.com)
12 * RDD (30/09/2002) implemented many function bodies to call serial driver.
13 * KJK (11/02/2003) implemented BuildCommDCB & BuildCommDCBAndTimeouts
19 #include <kernel32/kernel32.h>
21 /* BUILDCOMMDCB & BUILDCOMMDCBANDTIMEOUTS */
25 /* Pointer to a callback that handles a particular parameter */
26 typedef BOOL (*COMMDCB_PARAM_CALLBACK)
34 /* Symbolic flag of any length */
35 typedef struct _COMMDCB_PARAM_STRFLAG
37 UNICODE_STRING String;
39 } COMMDCB_PARAM_STRFLAG;
41 /* One char long symbolic flag */
42 typedef struct _COMMDCB_PARAM_CHARFLAG
46 } COMMDCB_PARAM_CHARFLAG;
49 /* stupid Borland C++ requires this */
50 #define _L(__S__) L ## __S__
52 /* Declare a parameter handler */
53 #define COMMDCB_PARAM_HANDLER(__P__) \
54 BOOL COMMDCB_ ## __P__ ## Param \
57 COMMTIMEOUTS * Timeouts, \
64 Lookup a string flag and return its numerical value. The flags array must be
65 sorted - a dichotomycal search is performed
67 BOOL COMMDCB_LookupStrFlag
69 UNICODE_STRING * Flag,
70 COMMDCB_PARAM_STRFLAG * Flags,
75 /* Lower and upper bound for dichotomycal search */
77 int nUpperBound = FlagCount - 1;
82 /* pick the element in the middle of the area of interest as the pivot */
83 int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2;
85 /* compare the string with the pivot */
86 nComparison = RtlCompareUnicodeString
89 &Flags[nCurFlag].String,
96 /* return the flag's value */
97 *Value = Flags[nCurFlag].Value;
102 /* string is less than */
103 else if(nComparison < 0)
106 restrict the search to the first half of the current slice, minus the pivot
108 nUpperBound = nCurFlag - 1;
112 /* string is greater than */
116 restrict the search to the second half of the current slice, minus the pivot
118 nLowerBound = nCurFlag + 1;
123 /* continue until the slice is empty */
124 while(nLowerBound <= nUpperBound);
126 /* string not found: failure */
132 Find the next character flag and return its numerical value. The flags array
133 must be sorted - a dichotomycal search is performed
135 BOOL COMMDCB_ParseCharFlag
138 COMMDCB_PARAM_CHARFLAG * Flags,
143 /* Lower and upper bound for dichotomycal search */
145 int nUpperBound = FlagCount - 1;
146 /* get the first character as the flag */
147 WCHAR wcFlag = (*StrTail)[0];
149 /* premature end of string, or the character is whitespace */
150 if(!wcFlag || iswspace(wcFlag))
154 /* uppercase the character for case-insensitive search */
155 wcFlag = towupper(wcFlag);
157 /* skip the character flag */
160 /* see COMMDCB_LookupStrFlag for a description of the algorithm */
164 int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2;
166 nComparison = wcFlag - towupper(Flags[nCurFlag].Char);
170 *Value = Flags[nCurFlag].Value;
174 else if(nComparison < 0)
176 nUpperBound = nCurFlag - 1;
180 nLowerBound = nCurFlag + 1;
183 while(nUpperBound >= nLowerBound);
185 /* flag not found: failure */
190 Find the next string flag and return its numerical value. The flags array must
191 be sorted - a dichotomycal search is performed
193 BOOL COMMDCB_ParseStrFlag
196 COMMDCB_PARAM_STRFLAG * Flags,
201 LPWSTR pwcNewTail = *StrTail;
202 UNICODE_STRING wstrFlag;
204 /* scan the string until the first space character or the terminating null */
205 while(pwcNewTail[0] && !iswspace(pwcNewTail[0]))
208 /* string flag empty */
209 if(pwcNewTail == *StrTail)
213 /* build the UNICODE_STRING description of the string flag */
214 wstrFlag.Buffer = *StrTail;
215 wstrFlag.Length = (pwcNewTail - *StrTail) * sizeof(WCHAR);
216 wstrFlag.MaximumLength = wstrFlag.Length;
218 /* skip the string flag */
219 *StrTail = pwcNewTail;
221 /* lookup the string flag's value and return it */
222 return COMMDCB_LookupStrFlag(&wstrFlag, Flags, FlagCount, Value);
226 Parse a boolean value in the symbolic form on/off
228 BOOL COMMDCB_ParseBool(LPWSTR * StrTail, BOOL * Value)
232 static COMMDCB_PARAM_STRFLAG a_BoolFlags[] =
234 { UNICODE_STRING_INITIALIZER(L"off"), FALSE },
235 { UNICODE_STRING_INITIALIZER(L"on"), TRUE }
238 /* try to recognize the next flag as a boolean */
239 bRetVal = COMMDCB_ParseStrFlag
243 sizeof(a_BoolFlags) / sizeof(a_BoolFlags[0]),
248 if(!bRetVal) return FALSE;
251 *Value = nValue ? TRUE : FALSE;
256 Parse a decimal integer
258 BOOL COMMDCB_ParseInt(LPWSTR * StrTail, DWORD * Value)
260 LPWSTR pwcPrevTail = *StrTail;
261 DWORD nValue = wcstoul(*StrTail, StrTail, 10);
263 /* no character was consumed: failure */
264 if(pwcPrevTail == *StrTail) return FALSE;
271 /* PARAMETER HANDLERS */
273 COMMDCB_PARAM_HANDLER(baud)
279 /* parse the baudrate */
280 if(!COMMDCB_ParseInt(StrTail, &nValue))
286 /* documented abbreviations */
287 case 11: Dcb->BaudRate = 110; break;
288 case 15: Dcb->BaudRate = 150; break;
289 case 30: Dcb->BaudRate = 300; break;
290 case 60: Dcb->BaudRate = 600; break;
291 case 12: Dcb->BaudRate = 1200; break;
292 case 24: Dcb->BaudRate = 2400; break;
293 case 48: Dcb->BaudRate = 4800; break;
294 case 96: Dcb->BaudRate = 9600; break;
295 case 19: Dcb->BaudRate = 19200; break;
297 default: Dcb->BaudRate = nValue; break;
300 /* if the stop bits haven't been specified explicitely */
303 /* default the stop bits to 2 for 110 baud */
304 if(Dcb->BaudRate == 110) Dcb->StopBits = TWOSTOPBITS;
305 /* else, default the stop bits to 1 */
306 else Dcb->StopBits = ONESTOPBIT;
314 COMMDCB_PARAM_HANDLER(data)
321 /* parse the data bits */
322 if(!COMMDCB_ParseInt(StrTail, &nValue))
326 /* value out of range: failure */
327 if(nValue < 5 || nValue > 8) return FALSE;
330 Dcb->ByteSize = nValue;
335 COMMDCB_PARAM_HANDLER(dtr)
339 static COMMDCB_PARAM_STRFLAG a_DTRFlags[] =
341 { UNICODE_STRING_INITIALIZER(L"hs"), DTR_CONTROL_HANDSHAKE },
342 { UNICODE_STRING_INITIALIZER(L"off"), DTR_CONTROL_DISABLE },
343 { UNICODE_STRING_INITIALIZER(L"on"), DTR_CONTROL_ENABLE }
350 bRetVal = COMMDCB_ParseStrFlag
354 sizeof(a_DTRFlags) / sizeof(a_DTRFlags[0]),
359 if(!bRetVal) return FALSE;
362 Dcb->fDtrControl = nValue;
367 COMMDCB_PARAM_HANDLER(idsr)
375 if(!COMMDCB_ParseBool(StrTail, &bValue))
380 Dcb->fDsrSensitivity = bValue;
385 COMMDCB_PARAM_HANDLER(octs)
393 if(!COMMDCB_ParseBool(StrTail, &bValue))
398 Dcb->fOutxCtsFlow = bValue;
403 COMMDCB_PARAM_HANDLER(odsr)
411 if(!COMMDCB_ParseBool(StrTail, &bValue))
416 Dcb->fOutxDsrFlow = bValue;
421 COMMDCB_PARAM_HANDLER(parity)
425 static COMMDCB_PARAM_CHARFLAG a_ParityFlags[] =
427 { L'e', EVENPARITY },
428 { L'm', MARKPARITY },
431 { L's', SPACEPARITY }
438 bRetVal = COMMDCB_ParseCharFlag
442 sizeof(a_ParityFlags) / sizeof(a_ParityFlags[0]),
447 if(!bRetVal) return FALSE;
450 Dcb->Parity = nValue;
455 COMMDCB_PARAM_HANDLER(rts)
459 static COMMDCB_PARAM_STRFLAG a_RTSFlags[] =
461 { UNICODE_STRING_INITIALIZER(L"hs"), RTS_CONTROL_HANDSHAKE },
462 { UNICODE_STRING_INITIALIZER(L"off"), RTS_CONTROL_DISABLE },
463 { UNICODE_STRING_INITIALIZER(L"on"), RTS_CONTROL_ENABLE },
464 { UNICODE_STRING_INITIALIZER(L"tg"), RTS_CONTROL_TOGGLE }
471 nRetVal = COMMDCB_ParseStrFlag
475 sizeof(a_RTSFlags) / sizeof(a_RTSFlags[0]),
480 if(!nRetVal) return FALSE;
483 Dcb->fRtsControl = nValue;
488 COMMDCB_PARAM_HANDLER(stop)
492 static COMMDCB_PARAM_STRFLAG a_StopFlags[] =
494 { UNICODE_STRING_INITIALIZER(L"1"), ONESTOPBIT },
495 { UNICODE_STRING_INITIALIZER(L"1.5"), ONE5STOPBITS },
496 { UNICODE_STRING_INITIALIZER(L"2"), TWOSTOPBITS }
502 bRetVal = COMMDCB_ParseStrFlag
506 sizeof(a_StopFlags) / sizeof(a_StopFlags[0]),
511 if(!bRetVal) return FALSE;
513 /* tell the baud= handler that the stop bits have been specified explicitely */
517 Dcb->StopBits = nValue;
522 COMMDCB_PARAM_HANDLER(to)
530 if(!COMMDCB_ParseBool(StrTail, &bValue))
534 /* for BuildCommDCB(), Timeouts is NULL */
537 /* why? no idea. All values taken from Windows 2000 with experimentation */
538 Timeouts->ReadIntervalTimeout = 0;
539 Timeouts->ReadTotalTimeoutMultiplier = 0;
540 Timeouts->ReadTotalTimeoutConstant = 0;
541 Timeouts->WriteTotalTimeoutMultiplier = 0;
544 if(bValue) Timeouts->WriteTotalTimeoutConstant = 60000;
546 else Timeouts->WriteTotalTimeoutConstant = 0;
554 COMMDCB_PARAM_HANDLER(xon)
562 if(!COMMDCB_ParseBool(StrTail, &bValue))
567 if(bValue) Dcb->fInX = Dcb->fOutX = TRUE;
569 else Dcb->fInX = Dcb->fOutX = FALSE;
576 #define COMMDCB_PARAM(__P__) \
578 UNICODE_STRING_INITIALIZER(_L(#__P__)), \
579 (ULONG_PTR)&COMMDCB_ ## __P__ ## Param \
584 BuildCommDCBAndTimeoutsW
588 LPCOMMTIMEOUTS lpCommTimeouts
591 /* tell the baud= handler that the stop bits should be defaulted */
592 BOOL bStopBitsSet = FALSE;
594 /* parameter validation */
595 if(lpDCB->DCBlength != sizeof(DCB)) goto InvalidParam;
598 lpDCB->StopBits = ONESTOPBIT;
601 The documentation for MODE says that data= defaults to 7, but BuildCommDCB
602 doesn't seem to set it
604 /* lpDCB->ByteSize = 7; */
610 towupper(lpDef[0]) == L'C' &&
612 towupper(lpDef[1]) == L'O' &&
614 towupper(lpDef[2]) == L'M'
622 /* premature end of string */
623 if(!lpDef[0]) goto InvalidParam;
626 if(!COMMDCB_ParseInt((LPWSTR *)&lpDef, &nDummy)) goto InvalidParam;
629 if(lpDef[0] == L':') ++ lpDef;
632 /* skip leading whitespace */
633 while(lpDef[0] && iswspace(lpDef[0])) ++ lpDef;
635 /* repeat until the end of the string */
638 static COMMDCB_PARAM_STRFLAG a_Params[] =
646 COMMDCB_PARAM(parity),
653 COMMDCB_PARAM_CALLBACK pCallback;
654 UNICODE_STRING wstrParam;
655 LPWSTR pwcPrevTail = (LPWSTR)lpDef;
657 /* get the parameter */
658 while(lpDef[0] && lpDef[0] != L'=') ++ lpDef;
660 /* premature end of string */
661 if(!lpDef[0]) goto InvalidParam;
663 /* build the parameter's UNICODE_STRING */
664 wstrParam.Buffer = pwcPrevTail;
665 wstrParam.Length = (lpDef - pwcPrevTail) * sizeof(WCHAR);
666 wstrParam.MaximumLength = wstrParam.Length;
671 /* lookup the callback for the parameter */
672 bRetVal = COMMDCB_LookupStrFlag
676 sizeof(a_Params) / sizeof(a_Params[0]),
677 (ULONG_PTR *)&pCallback
680 /* invalid parameter */
681 if(!bRetVal) goto InvalidParam;
683 /* call the callback to parse the parameter's argument */
684 if(!pCallback(lpDCB, lpCommTimeouts, &bStopBitsSet, (LPWSTR *)&lpDef))
688 /* skip trailing whitespace */
689 while(lpDef[0] && iswspace(lpDef[0])) ++ lpDef;
697 SetLastError(ERROR_INVALID_PARAMETER);
704 BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts)
709 UNICODE_STRING wstrDef;
711 RtlInitAnsiString(&strDef, (LPSTR)lpDef);
713 nErrCode = RtlAnsiStringToUnicodeString(&wstrDef, &strDef, TRUE);
715 if(!NT_SUCCESS(nErrCode))
717 SetLastErrorByStatus(nErrCode);
721 bRetVal = BuildCommDCBAndTimeoutsW(wstrDef.Buffer, lpDCB, lpCommTimeouts);
723 RtlFreeUnicodeString(&wstrDef);
730 BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB)
732 return BuildCommDCBAndTimeoutsA(lpDef, lpDCB, NULL);
737 BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB)
739 return BuildCommDCBAndTimeoutsW(lpDef, lpDCB, NULL);
744 ClearCommBreak(HANDLE hFile)
746 WINBOOL result = FALSE;
747 DWORD dwBytesReturned;
749 if (hFile == INVALID_HANDLE_VALUE) {
752 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
758 ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat)
760 WINBOOL result = FALSE;
761 DWORD dwBytesReturned;
763 if (hFile == INVALID_HANDLE_VALUE) {
764 //SetLastError(CE_MODE);
767 if (lpErrors == NULL) {
768 DPRINT("ERROR: GetCommState() - NULL Errors pointer\n");
771 // *lpErrors = CE_BREAK;
772 // *lpErrors = CE_FRAME;
773 // *lpErrors = CE_IOE;
774 // *lpErrors = CE_MODE;
775 // *lpErrors = CE_OVERRUN;
776 // *lpErrors = CE_RXOVER;
777 // *lpErrors = CE_RXPARITY;
778 // *lpErrors = CE_TXFULL;
780 CE_BREAK The hardware detected a break condition.
781 CE_FRAME The hardware detected a framing error.
782 CE_IOE An I/O error occurred during communications with the device.
783 CE_MODE The requested mode is not supported, or the hFile parameter is invalid. If this value is specified, it is the only valid error.
784 CE_OVERRUN A character-buffer overrun has occurred. The next character is lost.
785 CE_RXOVER An input buffer overflow has occurred. There is either no room in the input buffer, or a character was received after the end-of-file (EOF) character.
786 CE_RXPARITY The hardware detected a parity error.
787 CE_TXFULL The application tried to transmit a character, but the output buffer was full.
789 result = DeviceIoControl(hFile, IOCTL_SERIAL_RESET_DEVICE, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
791 if (lpStat != NULL) {
792 lpStat->fCtsHold = 0;
793 lpStat->fDsrHold = 0;
794 lpStat->fRlsdHold = 0;
795 lpStat->fXoffHold = 0;
796 lpStat->fXoffSent = 0;
800 lpStat->cbOutQue = 0;
807 CommConfigDialogA(LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
809 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
815 CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
817 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
823 EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
825 WINBOOL result = FALSE;
826 DWORD dwBytesReturned;
828 if (hFile == INVALID_HANDLE_VALUE) {
832 case CLRDTR: // Clears the DTR (data-terminal-ready) signal.
833 result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
835 case CLRRTS: // Clears the RTS (request-to-send) signal.
836 result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
838 case SETDTR: // Sends the DTR (data-terminal-ready) signal.
839 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
841 case SETRTS: // Sends the RTS (request-to-send) signal.
842 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
844 case SETXOFF: // Causes transmission to act as if an XOFF character has been received.
845 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XOFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
847 case SETXON: // Causes transmission to act as if an XON character has been received.
848 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
850 case SETBREAK: // Suspends character transmission and places the transmission line in a break state until the ClearCommBreak function is called (or EscapeCommFunction is called with the CLRBREAK extended function code). The SETBREAK extended function code is identical to the SetCommBreak function. Note that this extended function does not flush data that has not been transmitted.
851 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
853 case CLRBREAK: // Restores character transmission and places the transmission line in a nonbreak state. The CLRBREAK extended function code is identical to the ClearCommBreak function.
854 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
857 DPRINT("EscapeCommFunction() WARNING: unknown function code\n");
858 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
866 GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
868 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
874 GetCommMask(HANDLE hFile, LPDWORD lpEvtMask)
876 WINBOOL result = FALSE;
877 DWORD dwBytesReturned;
879 if (hFile == INVALID_HANDLE_VALUE) {
882 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_WAIT_MASK,
883 NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, NULL);
889 GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
891 WINBOOL result = FALSE;
892 DWORD dwBytesReturned;
894 if (hFile == INVALID_HANDLE_VALUE) {
897 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
898 NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL);
904 GetCommProperties(HANDLE hFile, LPCOMMPROP lpCommProp)
906 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
912 GetCommState(HANDLE hFile, LPDCB lpDCB)
914 WINBOOL result = FALSE;
915 DWORD dwBytesReturned;
917 SERIAL_BAUD_RATE BaudRate;
918 SERIAL_HANDFLOW HandFlow;
919 SERIAL_CHARS SpecialChars;
920 SERIAL_LINE_CONTROL LineControl;
922 DPRINT("GetCommState(%d, %p)\n", hFile, lpDCB);
924 if (hFile == INVALID_HANDLE_VALUE) {
925 DPRINT("ERROR: GetCommState() - INVALID_HANDLE_VALUE\n");
929 DPRINT("ERROR: GetCommState() - NULL DCB pointer\n");
932 if (lpDCB->DCBlength != sizeof(DCB)) {
933 DPRINT("ERROR: GetCommState() - Invalid DCB size\n");
937 // DPRINT(" GetCommState() CALLING DeviceIoControl\n");
938 // result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
939 // DPRINT(" GetCommState() DeviceIoControl returned %d\n", result);
941 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_BAUD_RATE,
942 NULL, 0, &BaudRate, sizeof(BaudRate),&dwBytesReturned, NULL);
943 if (!NT_SUCCESS(result)) {
944 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_BAUD_RATE) Failed.\n");
947 lpDCB->BaudRate = BaudRate.BaudRate;
949 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_HANDFLOW,
950 NULL, 0, &HandFlow, sizeof(HandFlow), &dwBytesReturned, NULL);
951 if (!NT_SUCCESS(result)) {
952 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_HANDFLOW) Failed.\n");
955 if (HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) {
956 lpDCB->fOutxCtsFlow = 1;
958 if (HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) {
959 lpDCB->fOutxDsrFlow = 1;
961 if (HandFlow.ControlHandShake & SERIAL_DTR_CONTROL) {
962 lpDCB->fDtrControl = 1;
964 if (HandFlow.ControlHandShake & SERIAL_DTR_HANDSHAKE) {
965 lpDCB->fDtrControl = 2;
967 if (HandFlow.ControlHandShake & SERIAL_RTS_CONTROL) {
968 lpDCB->fRtsControl = 1;
970 if (HandFlow.ControlHandShake & SERIAL_RTS_HANDSHAKE) {
971 lpDCB->fRtsControl = 2;
973 if (HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) {
974 lpDCB->fDsrSensitivity = 1;
976 if (HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) {
977 lpDCB->fAbortOnError = 1;
980 if (HandFlow.FlowReplace & SERIAL_ERROR_CHAR) {
981 lpDCB->fErrorChar = 1;
983 if (HandFlow.FlowReplace & SERIAL_NULL_STRIPPING) {
986 if (HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE) {
987 lpDCB->fTXContinueOnXoff = 1;
989 lpDCB->XonLim = HandFlow.XonLimit;
990 lpDCB->XoffLim = HandFlow.XoffLimit;
992 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_CHARS,
993 NULL, 0, &SpecialChars, sizeof(SpecialChars), &dwBytesReturned, NULL);
994 if (!NT_SUCCESS(result)) {
995 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_CHARS) Failed.\n");
999 lpDCB->EofChar = SpecialChars.EofChar;
1000 lpDCB->ErrorChar = SpecialChars.ErrorChar;
1001 // = SpecialChars.BreakChar;
1002 lpDCB->EvtChar = SpecialChars.EventChar;
1003 lpDCB->XonChar = SpecialChars.XonChar;
1004 lpDCB->XoffChar = SpecialChars.XoffChar;
1006 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_LINE_CONTROL,
1007 NULL, 0, &LineControl, sizeof(LineControl), &dwBytesReturned, NULL);
1008 if (!NT_SUCCESS(result)) {
1009 DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_LINE_CONTROL) Failed.\n");
1012 lpDCB->StopBits = LineControl.StopBits;
1013 lpDCB->Parity = LineControl.Parity;
1014 lpDCB->ByteSize = LineControl.WordLength;
1015 DPRINT("GetCommState() - COMPLETED SUCCESSFULLY\n");
1021 GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1023 WINBOOL result = FALSE;
1024 DWORD dwBytesReturned;
1026 if (hFile == INVALID_HANDLE_VALUE) {
1029 if (lpCommTimeouts == NULL) {
1032 result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_TIMEOUTS,
1034 lpCommTimeouts, sizeof(COMMTIMEOUTS),
1035 &dwBytesReturned, NULL);
1041 GetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
1043 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1049 GetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
1051 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1057 PurgeComm(HANDLE hFile, DWORD dwFlags)
1059 WINBOOL result = FALSE;
1060 DWORD dwBytesReturned;
1062 if (hFile == INVALID_HANDLE_VALUE) {
1065 result = DeviceIoControl(hFile, IOCTL_SERIAL_PURGE,
1066 &dwFlags, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL);
1072 SetCommBreak(HANDLE hFile)
1074 WINBOOL result = FALSE;
1075 DWORD dwBytesReturned;
1077 if (hFile == INVALID_HANDLE_VALUE) {
1080 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
1086 SetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize)
1088 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1094 SetCommMask(HANDLE hFile, DWORD dwEvtMask)
1096 WINBOOL result = FALSE;
1097 DWORD dwBytesReturned;
1099 if (hFile == INVALID_HANDLE_VALUE) {
1102 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_WAIT_MASK,
1103 &dwEvtMask, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL);
1109 SetCommState(HANDLE hFile, LPDCB lpDCB)
1111 WINBOOL result = FALSE;
1112 DWORD dwBytesReturned;
1114 SERIAL_BAUD_RATE BaudRate;
1115 SERIAL_HANDFLOW HandFlow;
1116 SERIAL_CHARS SpecialChars;
1117 SERIAL_LINE_CONTROL LineControl;
1119 DPRINT("SetCommState(%d, %p) - ENTERED\n", hFile, lpDCB);
1121 if (hFile == INVALID_HANDLE_VALUE) {
1122 DPRINT("SetCommState() - ERROR: INVALID_HANDLE_VALUE\n");
1125 if (lpDCB == NULL) {
1126 DPRINT("SetCommState() - ERROR: NULL DCB pointer passed\n");
1130 BaudRate.BaudRate = lpDCB->BaudRate;
1131 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BAUD_RATE,
1132 &BaudRate, sizeof(BaudRate), NULL, 0, &dwBytesReturned, NULL);
1133 if (!NT_SUCCESS(result)) {
1134 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_BAUD_RATE) Failed.\n");
1138 #define SERIAL_DTR_MASK ((ULONG)0x03)
1139 #define SERIAL_DTR_CONTROL ((ULONG)0x01)
1140 #define SERIAL_DTR_HANDSHAKE ((ULONG)0x02)
1141 #define SERIAL_CTS_HANDSHAKE ((ULONG)0x08)
1142 #define SERIAL_DSR_HANDSHAKE ((ULONG)0x10)
1143 #define SERIAL_DCD_HANDSHAKE ((ULONG)0x20)
1144 #define SERIAL_OUT_HANDSHAKEMASK ((ULONG)0x38)
1145 #define SERIAL_DSR_SENSITIVITY ((ULONG)0x40)
1146 #define SERIAL_ERROR_ABORT ((ULONG)0x80000000)
1147 #define SERIAL_CONTROL_INVALID ((ULONG)0x7fffff84)
1149 HandFlow.ControlHandShake = 0;
1151 if (lpDCB->fOutxCtsFlow) {
1152 HandFlow.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
1154 if (lpDCB->fOutxDsrFlow) {
1155 HandFlow.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
1157 if (lpDCB->fDtrControl) {
1158 HandFlow.ControlHandShake |= SERIAL_DTR_CONTROL;
1160 if (lpDCB->fDtrControl) {
1161 HandFlow.ControlHandShake |= SERIAL_DTR_HANDSHAKE;
1163 if (lpDCB->fRtsControl) {
1164 HandFlow.ControlHandShake |= SERIAL_RTS_CONTROL;
1166 if (lpDCB->fRtsControl) {
1167 HandFlow.ControlHandShake |= SERIAL_RTS_HANDSHAKE;
1169 if (lpDCB->fDsrSensitivity) {
1170 HandFlow.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
1172 if (lpDCB->fAbortOnError) {
1173 HandFlow.ControlHandShake |= SERIAL_ERROR_ABORT;
1176 #define SERIAL_AUTO_TRANSMIT ((ULONG)0x01)
1177 #define SERIAL_AUTO_RECEIVE ((ULONG)0x02)
1178 #define SERIAL_ERROR_CHAR ((ULONG)0x04)
1179 #define SERIAL_NULL_STRIPPING ((ULONG)0x08)
1180 #define SERIAL_BREAK_CHAR ((ULONG)0x10)
1181 #define SERIAL_RTS_MASK ((ULONG)0xc0)
1182 #define SERIAL_RTS_CONTROL ((ULONG)0x40)
1183 #define SERIAL_RTS_HANDSHAKE ((ULONG)0x80)
1184 #define SERIAL_TRANSMIT_TOGGLE ((ULONG)0xc0)
1185 #define SERIAL_XOFF_CONTINUE ((ULONG)0x80000000)
1186 #define SERIAL_FLOW_INVALID ((ULONG)0x7fffff20)
1188 HandFlow.FlowReplace = 0;
1189 if (lpDCB->fErrorChar) {
1190 HandFlow.FlowReplace |= SERIAL_ERROR_CHAR;
1193 HandFlow.FlowReplace |= SERIAL_NULL_STRIPPING;
1195 if (lpDCB->fTXContinueOnXoff) {
1196 HandFlow.FlowReplace |= SERIAL_XOFF_CONTINUE;
1198 HandFlow.XonLimit = lpDCB->XonLim;
1199 HandFlow.XoffLimit = lpDCB->XoffLim;
1200 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_HANDFLOW,
1201 &HandFlow, sizeof(HandFlow), NULL, 0, &dwBytesReturned, NULL);
1202 if (!NT_SUCCESS(result)) {
1203 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_HANDFLOW) Failed.\n");
1207 SpecialChars.EofChar = lpDCB->EofChar;
1208 SpecialChars.ErrorChar = lpDCB->ErrorChar;
1209 SpecialChars.BreakChar = 0;
1210 SpecialChars.EventChar = lpDCB->EvtChar;
1211 SpecialChars.XonChar = lpDCB->XonChar;
1212 SpecialChars.XoffChar = lpDCB->XoffChar;
1213 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_CHARS,
1214 &SpecialChars, sizeof(SpecialChars), NULL, 0, &dwBytesReturned, NULL);
1215 if (!NT_SUCCESS(result)) {
1216 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_CHARS) Failed.\n");
1220 LineControl.StopBits = lpDCB->StopBits;
1221 LineControl.Parity = lpDCB->Parity;
1222 LineControl.WordLength = lpDCB->ByteSize;
1223 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_LINE_CONTROL,
1224 &LineControl, sizeof(LineControl), NULL, 0, &dwBytesReturned, NULL);
1225 if (!NT_SUCCESS(result)) {
1226 DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_LINE_CONTROL) Failed.\n");
1230 DPRINT("SetCommState() - COMPLETED SUCCESSFULLY\n");
1236 SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1238 WINBOOL result = FALSE;
1239 DWORD dwBytesReturned;
1240 SERIAL_TIMEOUTS Timeouts;
1242 if (hFile == INVALID_HANDLE_VALUE) {
1245 if (lpCommTimeouts == NULL) {
1248 Timeouts.ReadIntervalTimeout = lpCommTimeouts->ReadIntervalTimeout;
1249 Timeouts.ReadTotalTimeoutMultiplier = lpCommTimeouts->ReadTotalTimeoutMultiplier;
1250 Timeouts.ReadTotalTimeoutConstant = lpCommTimeouts->ReadTotalTimeoutConstant;
1251 Timeouts.WriteTotalTimeoutMultiplier = lpCommTimeouts->WriteTotalTimeoutMultiplier;
1252 Timeouts.WriteTotalTimeoutConstant = lpCommTimeouts->WriteTotalTimeoutConstant;
1253 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_TIMEOUTS,
1254 &Timeouts, sizeof(Timeouts), NULL, 0, &dwBytesReturned, NULL);
1260 SetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
1262 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1268 SetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
1270 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1276 SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue)
1278 WINBOOL result = FALSE;
1279 DWORD dwBytesReturned;
1280 SERIAL_QUEUE_SIZE QueueSize;
1282 if (hFile == INVALID_HANDLE_VALUE) {
1285 QueueSize.InSize = dwInQueue;
1286 QueueSize.OutSize = dwOutQueue;
1287 result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_QUEUE_SIZE,
1288 &QueueSize, sizeof(QueueSize), NULL, 0, &dwBytesReturned, NULL);
1294 TransmitCommChar(HANDLE hFile, char cChar)
1296 WINBOOL result = FALSE;
1297 DWORD dwBytesReturned;
1299 if (hFile == INVALID_HANDLE_VALUE) {
1302 result = DeviceIoControl(hFile, IOCTL_SERIAL_IMMEDIATE_CHAR,
1303 &cChar, sizeof(cChar), NULL, 0, &dwBytesReturned, NULL);
1309 WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
1311 WINBOOL result = FALSE;
1312 DWORD dwBytesReturned;
1314 if (hFile == INVALID_HANDLE_VALUE) {
1317 if (lpEvtMask == NULL) {
1320 result = DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK,
1321 NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, lpOverlapped);