📄 serial.cpp
字号:
#include "precomp.hxx"
#include <winerror.h>
#include "serial.h"
#include "util.h"
static PWSTR pPrinter = TEXT("SiPix PocketPrinter A6");
static PWSTR pPort = NULL;
static HANDLE g_hPrint = INVALID_HANDLE_VALUE;
HANDLE
PortInitialize(
PWSTR sPort
)
{
#ifndef _WIN32_WCE_EMULATION
// DWORD dwStat;
DCB PortDCB;
COMMTIMEOUTS CommTimeouts;
// TCHAR szTmp[100];
int iTimeOut;
HKEY hk;
DWORD cTimeOut;
DWORD dwType;
// NOTE: Need to check if there is already a print session open.
PortClose(INVALID_HANDLE_VALUE);
if ((pPort = (PWSTR)malloc(max((lstrlen(sPort) + 1), 6) * sizeof(TCHAR)))) {
lstrcpy(pPort, sPort);
}
if (!pPort) {
SetLastError(ERROR_OUTOFMEMORY);
return INVALID_HANDLE_VALUE;
}
lstrcpy(pPort + 4, TEXT(":"));
// Open the serial port.
g_hPrint = CreateFile( pPort, // Pointer to the name of the port
GENERIC_WRITE|GENERIC_READ, // Access (read/write) mode
0, // Share mode
NULL, // Pointer to the security attribute
OPEN_EXISTING, // How to open the serial port
FILE_ATTRIBUTE_NORMAL,// Port attributes
NULL); // Handle to port with attribute
// to copy
// If it fails to open the port, return FALSE.
if (g_hPrint == INVALID_HANDLE_VALUE)
{
SetLastError(ERROR_UNKNOWN_PORT);
return INVALID_HANDLE_VALUE;
}
PortDCB.DCBlength = sizeof(DCB);
// Get the default port setting information.
GetCommState (g_hPrint, &PortDCB);
// Change the DCB structure settings.
PortDCB.BaudRate = CBR_115200; // Current baud
PortDCB.fBinary = TRUE; // Binary mode; no EOF check
PortDCB.fParity = FALSE; // Enable parity checking.
PortDCB.fOutxCtsFlow = TRUE; // No CTS output flow control
PortDCB.fOutxDsrFlow = TRUE; // No DSR output flow control
PortDCB.fDtrControl = DTR_CONTROL_HANDSHAKE; // DTR flow control type
PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity
PortDCB.fTXContinueOnXoff = FALSE; // XOFF continues Tx
PortDCB.fOutX = FALSE; // No XON/XOFF out flow control
PortDCB.fInX = FALSE; // No XON/XOFF in flow control
PortDCB.fErrorChar = FALSE; // Disable error replacement.
PortDCB.fNull = FALSE; // Disable null stripping.
PortDCB.fRtsControl = RTS_CONTROL_HANDSHAKE; // RTS flow control
PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on error
PortDCB.XonLim = 2048;
PortDCB.XoffLim = 512;
PortDCB.ByteSize = 8; // Number of bits/bytes, 4-8
PortDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space
PortDCB.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2
PortDCB.XonChar = 0x11;
PortDCB.XoffChar = 0x13;
PortDCB.ErrorChar = 0;
PortDCB.EofChar = 0;
PortDCB.EvtChar = 0;
// Configure the port according to the specifications of the DCB
// structure.
if (!SetCommState (g_hPrint, &PortDCB))
{
SetLastError(ERROR_UNKNOWN_PORT);
CloseHandle(g_hPrint);
g_hPrint = INVALID_HANDLE_VALUE;
return INVALID_HANDLE_VALUE;
}
// Retrieve the time-out parameters for all read and write operations
// on the port.
GetCommTimeouts (g_hPrint, &CommTimeouts);
iTimeOut = 45;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("PrintSettings"), 0, KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS) {
cTimeOut = sizeof(iTimeOut);
if ((RegQueryValueEx(hk, TEXT("TimeOut"), 0, &dwType, (PBYTE)&iTimeOut, &cTimeOut) != ERROR_SUCCESS) ||
(cTimeOut != sizeof(iTimeOut)) || (dwType != REG_DWORD)) {
iTimeOut = 45;
}
RegCloseKey(hk);
}
// Change the COMMTIMEOUTS structure settings.
CommTimeouts.ReadIntervalTimeout = 200;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 5000;
CommTimeouts.WriteTotalTimeoutMultiplier = 0;
CommTimeouts.WriteTotalTimeoutConstant = iTimeOut * 1000;
// Set the time-out parameters for all read and write operations
// on the port.
if (!SetCommTimeouts (g_hPrint, &CommTimeouts))
{
SetLastError(ERROR_UNKNOWN_PORT);
CloseHandle(g_hPrint);
g_hPrint = INVALID_HANDLE_VALUE;
return INVALID_HANDLE_VALUE;
}
SetupComm(g_hPrint, 16, 16);
// Direct the port to perform extended functions SETDTR and SETRTS.
// SETDTR: Sends the DTR (data-terminal-ready) signal.
// SETRTS: Sends the RTS (request-to-send) signal.
EscapeCommFunction(g_hPrint, SETDTR);
EscapeCommFunction(g_hPrint, SETRTS);
#endif //_WIN32_WCE_EMULATION
return (HANDLE)PRINT_SERIAL_PORT;
}
BOOL
PortWrite(
HANDLE h,
LPCVOID lpBuffer,
DWORD dwLength
)
{
#ifndef _WIN32_WCE_EMULATION
DWORD dwNumBytesWritten;
DWORD dwIndex, dwLast;
// static DWORD dwLastStat=0;
DWORD dwStat=0;
ULONG nTimeout=0;
ULONG nTimeoutPlus=0;
static DWORD dwSleepRes=0;
COMMTIMEOUTS CommTimeouts;
GetCommTimeouts (g_hPrint, &CommTimeouts);
if (dwSleepRes == 0)
{
int n=GetTickCount();
for (int i=0; i<3; i++)
Sleep(1);
int m=GetTickCount();
dwSleepRes = (m-n)/3;
if (m == n)
dwSleepRes = 1;
}
if (h != (HANDLE)PRINT_SERIAL_PORT) {
SetLastError(ERROR_UNKNOWN_PORT);
return FALSE;
}
if (g_hPrint == (HANDLE)INVALID_HANDLE_VALUE) {
SetLastError(ERROR_WRITE_FAULT);
return FALSE;
}
if (!lpBuffer) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
for (dwIndex=dwLast=0; dwIndex<dwLength; dwIndex++)
{
BOOL bSucc=GetCommModemStatus(g_hPrint, &dwStat);
/*
if (dwStat != dwLastStat)
{
TCHAR szMsg[MAX_PATH];
wsprintf(szMsg, TEXT("%X->%X"), dwLastStat, dwStat);
MessageBox(GetFocus(), szMsg, TEXT(""), MB_OK);
dwLastStat = dwStat;
}
*/
if (!(dwStat&MS_CTS_ON))
{
if (nTimeout == 0)
{
nTimeoutPlus = (dwIndex-dwLast)*100;
dwLast = dwIndex;
}
Sleep(1);
nTimeout += dwSleepRes;
dwIndex--;
}
else
{
nTimeout = 0;
WriteFile(g_hPrint, (BYTE*)lpBuffer+dwIndex, 1, &dwNumBytesWritten, NULL);
if (dwNumBytesWritten != 1)
{
CloseHandle(g_hPrint);
g_hPrint = (HANDLE)INVALID_HANDLE_VALUE;
return FALSE;
}
// Sleep(1);
}
if (nTimeout >= CommTimeouts.WriteTotalTimeoutConstant+nTimeoutPlus)
{
if (!ReportPrinterStatus(PRINTER_E_TIMEOUT, pPort, pPrinter, 0))
{
CloseHandle(g_hPrint);
g_hPrint = (HANDLE)INVALID_HANDLE_VALUE;
return FALSE;
}
nTimeout = 0;
nTimeoutPlus = 0;
}
}
#endif // _WIN32_WCE_EMULATION
return TRUE;
}
VOID
PortClose(
HANDLE h
)
{
if (g_hPrint != INVALID_HANDLE_VALUE)
{
CloseHandle(g_hPrint);
g_hPrint = INVALID_HANDLE_VALUE;
}
if (pPort) {
free(pPort);
pPort = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -