#include #include #include #include "..\com0com\include\cncext.h" /////////////////////////////////////////////////////////////// static void TraceLastError(const char *pFmt, ...) { DWORD err = GetLastError(); va_list va; va_start(va, pFmt); vfprintf(stderr, pFmt, va); va_end(va); fprintf(stderr, " ERROR %s (%lu)\n", strerror(err), (unsigned long)err); } /////////////////////////////////////////////////////////////// static BOOL myGetCommState(HANDLE hC0C, DCB *dcb) { dcb->DCBlength = sizeof(*dcb); if (!GetCommState(hC0C, dcb)) { TraceLastError("GetCommState()"); return FALSE; } return TRUE; } static BOOL mySetCommState(HANDLE hC0C, DCB *dcb) { if (!SetCommState(hC0C, dcb)) { TraceLastError("SetCommState()"); return FALSE; } return TRUE; } /////////////////////////////////////////////////////////////// static HANDLE OpenC0C(LPCTSTR path) { HANDLE hC0C = CreateFile(path, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hC0C == INVALID_HANDLE_VALUE) { printf("CreateFile('%s') ERROR\n", path); return INVALID_HANDLE_VALUE; } DCB dcb; if (!myGetCommState(hC0C, &dcb)) { CloseHandle(hC0C); return INVALID_HANDLE_VALUE; } dcb.BaudRate = CBR_19200; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.fOutxCtsFlow = TRUE; dcb.fOutxDsrFlow = FALSE; dcb.fDsrSensitivity = TRUE; dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.XonChar = 0x11; dcb.XoffChar = 0x13; dcb.fParity = FALSE; dcb.fNull = FALSE; dcb.fAbortOnError = FALSE; dcb.fErrorChar = FALSE; if (!mySetCommState(hC0C, &dcb)) { CloseHandle(hC0C); return INVALID_HANDLE_VALUE; } COMMTIMEOUTS timeouts; if (!GetCommTimeouts(hC0C, &timeouts)) { printf("GetCommTimeouts() ERROR\n"); CloseHandle(hC0C); return INVALID_HANDLE_VALUE; } timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; timeouts.ReadTotalTimeoutConstant = MAXDWORD - 1; timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 0; if (!SetCommTimeouts(hC0C, &timeouts)) { printf("SetCommTimeouts() ERROR\n"); CloseHandle(hC0C); return INVALID_HANDLE_VALUE; } printf("Open '%s' - OK\n", path); return hC0C; } /////////////////////////////////////////////////////////////// #define IOCTL_SERIAL_GET_MODEM_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,37,METHOD_BUFFERED,FILE_ANY_ACCESS) #define IOCTL_SERIAL_SET_MODEM_CONTROL CTL_CODE(FILE_DEVICE_SERIAL_PORT,38,METHOD_BUFFERED,FILE_ANY_ACCESS) /////////////////////////////////////////////////////////////// BOOL IsExtended(HANDLE hC0C) { BYTE inBufIoctl[C0CE_SIGNATURE_SIZE]; memcpy(inBufIoctl, C0CE_SIGNATURE, C0CE_SIGNATURE_SIZE); BYTE outBuf[sizeof(ULONG) + C0CE_SIGNATURE_SIZE]; DWORD returned; if (!DeviceIoControl(hC0C, IOCTL_SERIAL_GET_MODEM_CONTROL, inBufIoctl, sizeof(inBufIoctl), outBuf, sizeof(outBuf), &returned, NULL)) { TraceLastError("IOCTL_SERIAL_GET_MODEM_CONTROL"); return FALSE; } if (returned >= (sizeof(ULONG) + C0CE_SIGNATURE_SIZE) && memcmp(outBuf + sizeof(ULONG), C0CE_SIGNATURE, C0CE_SIGNATURE_SIZE) == 0) { printf("OK: The driver supports extended IOCTL_SERIAL_xET_MODEM_CONTROL.\n"); return TRUE; } printf("FAIL: The driver does not support extended IOCTL_SERIAL_xET_MODEM_CONTROL.\n"); return FALSE; } /////////////////////////////////////////////////////////////// BOOL ShowModemControl(HANDLE hC0C) { ULONG control; DWORD returned; if (!DeviceIoControl(hC0C, IOCTL_SERIAL_GET_MODEM_CONTROL, NULL, 0, &control, sizeof(control), &returned, NULL)) { TraceLastError("IOCTL_SERIAL_GET_MODEM_CONTROL"); return FALSE; } if (returned == sizeof(control)) { printf("control=0x%lX.\n", (long)control); return TRUE; } printf("FAIL: returned %lu != sizeof control %lu.\n", (long)returned, (long)sizeof(control)); return FALSE; } /////////////////////////////////////////////////////////////// BOOL SetModemControl(HANDLE hC0C, ULONG control, ULONG mask) { printf("set control=0x%lX with mask=0x%lX.\n", (long)control, (long)mask); BYTE inBufIoctl[sizeof(ULONG) + sizeof(ULONG) + C0CE_SIGNATURE_SIZE]; ((ULONG *)inBufIoctl)[0] = control; ((ULONG *)inBufIoctl)[1] = mask; memcpy(inBufIoctl + sizeof(ULONG) + sizeof(ULONG), C0CE_SIGNATURE, C0CE_SIGNATURE_SIZE); DWORD returned; if (!DeviceIoControl(hC0C, IOCTL_SERIAL_SET_MODEM_CONTROL, inBufIoctl, sizeof(inBufIoctl), NULL, 0, &returned, NULL)) { TraceLastError("IOCTL_SERIAL_SET_MODEM_CONTROL"); return FALSE; } return ShowModemControl(hC0C); } /////////////////////////////////////////////////////////////// void InC0C(HANDLE hC0C) { if (!IsExtended(hC0C)) { printf("Continue? (y/n) [n]: "); if (getchar() != 'y') return; } if (!ShowModemControl(hC0C)) return; Sleep(2000); if (!SetModemControl(hC0C, -1, SERIAL_IOC_MCR_OUT1)) // set OUT1 return; Sleep(2000); if (!SetModemControl(hC0C, 0, SERIAL_IOC_MCR_OUT1)) // clear OUT1 return; Sleep(2000); if (!SetModemControl(hC0C, 0, SERIAL_IOC_MCR_OUT2)) // clear OUT2 return; Sleep(2000); if (!SetModemControl(hC0C, -1, SERIAL_IOC_MCR_OUT2)) // set OUT2 return; Sleep(2000); if (!SetModemControl(hC0C, SERIAL_IOC_MCR_OUT1, SERIAL_IOC_MCR_OUT1|SERIAL_IOC_MCR_OUT2)) // set OUT1 and clear OUT2 return; Sleep(2000); if (!SetModemControl(hC0C, SERIAL_IOC_MCR_OUT2, SERIAL_IOC_MCR_OUT1|SERIAL_IOC_MCR_OUT2)) // clear OUT1 and set OUT2 return; Sleep(2000); printf("-- OK --\n"); } /////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage:\n"); printf(" %s \\\\.\\\n", argv[1]); return 1; } HANDLE hC0C = OpenC0C(argv[1]); if (hC0C == INVALID_HANDLE_VALUE) return 2; InC0C(hC0C); CloseHandle(hC0C); return 0; }