[Com0com-cvs] hub4com ReadMe.txt, NONE, 1.1 comparams.cpp, NONE, 1.1 comio.h, NONE, 1.1 comport.cpp
The virtual serial port driver for Windows.
Brought to you by:
vfrolov
From: Vyacheslav F. <vf...@us...> - 2007-01-23 09:13:16
|
Update of /cvsroot/com0com/hub4com In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv24272 Added Files: ReadMe.txt comparams.cpp comio.h comport.cpp utils.cpp comhub.h hub4com.vcproj comparams.h hub4com.rc utils.h comhub.cpp hub4com.cpp comport.h comio.cpp precomp.h version.h Log Message: Initial revision --- NEW FILE: comport.cpp --- /* * $Id: comport.cpp,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: comport.cpp,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #include "precomp.h" #include "comport.h" #include "comhub.h" #include "comio.h" /////////////////////////////////////////////////////////////// ComPort::ComPort(ComHub &_hub) : handle(INVALID_HANDLE_VALUE), hub(_hub), writeQueued(0) { } BOOL ComPort::Open(const char *pPath, const ComParams &comParams) { if (handle != INVALID_HANDLE_VALUE) return FALSE; while (writeQueued) { if (SleepEx(5000, TRUE) != WAIT_IO_COMPLETION) return FALSE; } writeLost = 0; string path(pPath); name = path.substr(path.rfind('\\') + 1); handle = ::OpenComPort(pPath, comParams); return handle != INVALID_HANDLE_VALUE; } BOOL ComPort::Start() { if (handle == INVALID_HANDLE_VALUE) return FALSE; ReadOverlapped *pOverlapped; pOverlapped = new ReadOverlapped(*this); if (!pOverlapped) return FALSE; if (!pOverlapped->StartRead()) { delete pOverlapped; return FALSE; } cout << "Started " << name << endl; return TRUE; } BOOL ComPort::Write(LPCVOID pData, DWORD len) { if (handle == INVALID_HANDLE_VALUE) { writeLost += len; return FALSE; } WriteOverlapped *pOverlapped; pOverlapped = new WriteOverlapped(*this, pData, len); if (!pOverlapped) return FALSE; if (writeQueued > 256) PurgeComm(handle, PURGE_TXABORT|PURGE_TXCLEAR); if (!pOverlapped->StartWrite()) { delete pOverlapped; return FALSE; } //cout << "Started Write " << pOverlapped->i << " " << path << " " << len << " " << writeQueued << endl; return TRUE; } void ComPort::OnRead(LPCVOID pBuf, DWORD done) { hub.Write(this, pBuf, done); } void ComPort::LostReport() { if (writeLost) { writeLostTotal += writeLost; cout << "Write lost: " << name << " " << writeLost << " total " << writeLostTotal << endl; writeLost = 0; } } /////////////////////////////////////////////////////////////// --- NEW FILE: comparams.cpp --- /* * $Id: comparams.cpp,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: comparams.cpp,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #include "precomp.h" #include "comparams.h" /////////////////////////////////////////////////////////////// ComParams::ComParams() : baudRate(CBR_19200), byteSize(8), parity(NOPARITY), stopBits(ONESTOPBIT) { } BOOL ComParams::SetParity(const char *pParity) { switch (*pParity) { case 'n': parity = NOPARITY; break; case 'o': parity = ODDPARITY; break; case 'e': parity = EVENPARITY; break; case 'm': parity = MARKPARITY; break; case 's': parity = SPACEPARITY; break; case 'd': parity = -1; break; default : return FALSE; } return TRUE; } BOOL ComParams::SetStopBits(const char *pStopBits) { switch (*pStopBits) { case '1': if ((pStopBits[1] == '.' || pStopBits[1] == ',') && pStopBits[2] == '5') stopBits = ONE5STOPBITS; else stopBits = ONESTOPBIT; break; case '2': stopBits = TWOSTOPBITS; break; case 'd': stopBits = -1; break; default : return FALSE; } return TRUE; } const char *ComParams::ParityStr(int parity) { switch (parity) { case NOPARITY: return "no"; case ODDPARITY: return "odd"; case EVENPARITY: return "even"; case MARKPARITY: return "mark"; case SPACEPARITY: return "space"; case -1: return "default"; } return "?"; } const char *ComParams::StopBitsStr(int stopBits) { switch (stopBits) { case ONESTOPBIT: return "1"; case ONE5STOPBITS: return "1.5"; case TWOSTOPBITS: return "2"; case -1: return "default"; } return "?"; } const char *ComParams::BaudRateLst() { return "a positive number or d[efault]"; } const char *ComParams::ByteSizeLst() { return "a positive number or d[efault]"; } const char *ComParams::ParityLst() { return "n[o], o[dd], e[ven], m[ark], s[pace] or d[efault]"; } const char *ComParams::StopBitsLst() { return "1, 1.5, 2 or d[efault]"; } /////////////////////////////////////////////////////////////// --- NEW FILE: hub4com.vcproj --- <?xml version="1.0" encoding="windows-1251"?> <VisualStudioProject ProjectType="Visual C++" Version="8,00" Name="hub4com" ProjectGUID="{AC4EC208-ED55-4F9D-ACDD-A57642C3C296}" RootNamespace="hub4com" Keyword="Win32Proj" > <Platforms> <Platform Name="Win32" /> </Platforms> <ToolFiles> </ToolFiles> <Configurations> <Configuration Name="Debug|Win32" OutputDirectory="Debug" IntermediateDirectory="Debug" ConfigurationType="1" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" /> <Tool Name="VCXMLDataGeneratorTool" /> <Tool Name="VCWebServiceProxyGeneratorTool" /> <Tool Name="VCMIDLTool" /> <Tool Name="VCCLCompilerTool" Optimization="0" PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" UsePrecompiledHeader="0" PrecompiledHeaderFile="" WarningLevel="4" Detect64BitPortabilityProblems="true" DebugInformationFormat="4" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLinkerTool" LinkIncremental="2" GenerateDebugInformation="true" SubSystem="1" TargetMachine="1" /> <Tool Name="VCALinkTool" /> <Tool Name="VCManifestTool" /> <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" /> <Tool Name="VCFxCopTool" /> <Tool Name="VCAppVerifierTool" /> <Tool Name="VCWebDeploymentTool" /> <Tool Name="VCPostBuildEventTool" /> </Configuration> <Configuration Name="Release|Win32" OutputDirectory="Release" IntermediateDirectory="Release" ConfigurationType="1" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" /> <Tool Name="VCXMLDataGeneratorTool" /> <Tool Name="VCWebServiceProxyGeneratorTool" /> <Tool Name="VCMIDLTool" /> <Tool Name="VCCLCompilerTool" PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE" RuntimeLibrary="2" UsePrecompiledHeader="0" PrecompiledHeaderFile="" WarningLevel="4" Detect64BitPortabilityProblems="true" DebugInformationFormat="3" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLinkerTool" LinkIncremental="2" GenerateDebugInformation="true" SubSystem="1" OptimizeReferences="2" EnableCOMDATFolding="2" TargetMachine="1" /> <Tool Name="VCALinkTool" /> <Tool Name="VCManifestTool" /> <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" /> <Tool Name="VCFxCopTool" /> <Tool Name="VCAppVerifierTool" /> <Tool Name="VCWebDeploymentTool" /> <Tool Name="VCPostBuildEventTool" /> </Configuration> </Configurations> <References> </References> <Files> <Filter Name="Header Files" Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > <File RelativePath=".\comhub.h" > </File> <File RelativePath=".\comio.h" > </File> <File RelativePath=".\comparams.h" > </File> <File RelativePath=".\comport.h" > </File> <File RelativePath=".\precomp.h" > </File> <File RelativePath=".\utils.h" > </File> <File RelativePath=".\version.h" > </File> </Filter> <Filter Name="Resource Files" Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" > <File RelativePath=".\hub4com.rc" > </File> </Filter> <Filter Name="Source Files" Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > <File RelativePath=".\comhub.cpp" > </File> <File RelativePath=".\comio.cpp" > </File> <File RelativePath=".\comparams.cpp" > </File> <File RelativePath=".\comport.cpp" > </File> <File RelativePath=".\hub4com.cpp" > </File> <File RelativePath=".\utils.cpp" > </File> </Filter> </Files> <Globals> </Globals> </VisualStudioProject> --- NEW FILE: hub4com.rc --- /* * $Id: hub4com.rc,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: hub4com.rc,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #include <windows.h> #include "version.h" #define VER_FILEVERSION H4C_V1,H4C_V2,H4C_V3,H4C_V4 #define VER_PRODUCTVERSION_STR H4C_VERSION_STR #define VER_LEGALCOPYRIGHT_YEARS H4C_COPYRIGHT_YEARS #define VER_COMPANYNAME_STR "Vyacheslav Frolov\0" #define VER_LEGALCOPYRIGHT_STR "Copyright (c) " VER_LEGALCOPYRIGHT_YEARS " " VER_COMPANYNAME_STR #define VER_PRODUCTNAME_STR "HUB for COM ports" #ifdef _DEBUG #define VER_DEBUG_STR " (debug version)" #define VER_FILEFLAGS VS_FF_DEBUG #else #define VER_DEBUG_STR "" #define VER_FILEFLAGS 0 #endif #define VER_FILEDESCRIPTION_STR VER_PRODUCTNAME_STR VER_DEBUG_STR #define VER_INTERNALNAME_STR "hub4com\0" #define VER_ORIGINALFILENAME_STR "hub4com.exe\0" #define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #define VER_FILEOS VOS_NT_WINDOWS32 #define VER_FILETYPE VFT_APP #define VER_FILESUBTYPE 0 #include <common.ver> --- NEW FILE: hub4com.cpp --- /* * $Id: hub4com.cpp,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: hub4com.cpp,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #include "precomp.h" #include "comparams.h" #include "comhub.h" #include "utils.h" /////////////////////////////////////////////////////////////// static void Usage(const char *pProgName) { cerr << "Usage:" << endl << " " << pProgName << " [options] \\\\.\\<port0> \\\\.\\<port1> ..." << endl << endl << "Common options:" << endl << " --help - show this help." << endl << endl << "COM port options:" << endl << " --baud=<b> - set baud rate to <b> (default is " << ComParams().BaudRate() << ")," << endl << " where <b> is " << ComParams::BaudRateLst() << "." << endl << " --data=<d> - set data bits to <d> (default is " << ComParams().ByteSize() << "), where <d> is" << endl << " " << ComParams::ByteSizeLst() << "." << endl << " --parity=<p> - set parity to <p> (default is " << ComParams::ParityStr(ComParams().Parity()) << "), where <p> is" << endl << " " << ComParams::ParityLst() << "." << endl << " --stop=<s> - set stop bits to <s> (default is " << ComParams::StopBitsStr(ComParams().StopBits()) << "), where <s> is" << endl << " " << ComParams::StopBitsLst() << "." << endl << " The value d[efault] above means to use current COM port settings." << endl << endl << "Route options:" << endl << " --route=<LstR>:<LstL> - send data received from any ports from <LstR> to" << endl << " all ports from <LstL>." << endl << " --bi-route=<LstR>:<LstL> - send data received from any ports from <LstR> to" << endl << " all ports from <LstL> and vice versa." << endl << " --no-route=<LstR>:<LstL> - do not send data received from any ports from" << endl << " <LstR> to ports from <LstL>." << endl << " The syntax of <LstR> and <LstL> above: <P1>[,<P2>...]" << endl << " The <Pn> above is a zero based position number of port or All." << endl << " If no any route option specified, then the options --route=0:All --route=1:0" << endl << " used by default (route data from first port to all ports and from second" << endl << " port to first port)." << endl << endl << "Examples:" << endl << " " << pProgName << " \\\\.\\COM1 \\\\.\\CNCB1 \\\\.\\CNCB2" << endl << " " << pProgName << " --route=All:All \\\\.\\CNCB0 \\\\.\\CNCB1 \\\\.\\CNCB2" << endl ; exit(1); } /////////////////////////////////////////////////////////////// static BOOL Route(ComHub &hub, const char *pListFrom, const char *pListTo, BOOL noRoute) { char *pTmpListFrom = _strdup(pListFrom); char *pTmpListTo = _strdup(pListTo); if (!pTmpListFrom || !pTmpListTo) { cerr << "No enough memory." << endl; exit(2); } BOOL res = TRUE; char *pSave1; for (char *pFrom = STRTOK_R(pTmpListFrom, ",", &pSave1) ; pFrom ; pFrom = STRTOK_R(NULL, ",", &pSave1)) { int iFrom; if (_stricmp(pFrom, "All") == 0) { iFrom = -1; } else if (!StrToInt(pFrom, &iFrom) || iFrom < 0 || iFrom >= hub.NumPorts()) { res = FALSE; break; } char *pSave2; for (char *pTo = STRTOK_R(pTmpListTo, ",", &pSave2) ; pTo ; pTo = STRTOK_R(NULL, ",", &pSave2)) { int iTo; if (_stricmp(pTo, "All") == 0) { iTo = -1; } else if (!StrToInt(pTo, &iTo) || iTo < 0 || iTo >= hub.NumPorts()) { res = FALSE; break; } hub.RouteData(iFrom, iTo, noRoute); } } free(pTmpListTo); free(pTmpListFrom); return res; } /////////////////////////////////////////////////////////////// static void Route(ComHub &hub, const char *pParam, BOOL biDirection, BOOL noRoute) { char *pTmp = _strdup(pParam); if (!pTmp) { cerr << "No enough memory." << endl; exit(2); } char *pSave; const char *pListR = STRTOK_R(pTmp, ":", &pSave); const char *pListL = STRTOK_R(NULL, ":", &pSave); if (!pListR || !pListL || !Route(hub, pListR, pListL, noRoute) || (biDirection && !Route(hub, pListL, pListR, noRoute))) { cerr << "Invalid route " << pParam << endl; exit(1); } free(pTmp); } /////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { int i; for (i = 1 ; i < argc ; i++) { if (GetParam(argv[i], "--") == NULL) break; } ComHub hub(argc - i); BOOL defaultRouteData = TRUE; char **pArgs = &argv[1]; ComParams comParams; while (argc > 1) { const char *pArg = GetParam(*pArgs, "--"); if (!pArg) break; const char *pParam; if ((pParam = GetParam(pArg, "help")) != NULL && *pParam == 0) { Usage(argv[0]); } else if ((pParam = GetParam(pArg, "baud=")) != NULL) { comParams.SetBaudRate(pParam); } else if ((pParam = GetParam(pArg, "data=")) != NULL) { comParams.SetByteSize(pParam); } else if ((pParam = GetParam(pArg, "parity=")) != NULL) { if (!comParams.SetParity(pParam)) { cerr << "Unknown parity value " << pParam << endl; exit(1); } } else if ((pParam = GetParam(pArg, "stop=")) != NULL) { if (!comParams.SetStopBits(pParam)) { cerr << "Unknown stop bits value " << pParam << endl; exit(1); } } else if ((pParam = GetParam(pArg, "route=")) != NULL) { defaultRouteData = FALSE; Route(hub, pParam, FALSE, FALSE); } else if ((pParam = GetParam(pArg, "bi-route=")) != NULL) { defaultRouteData = FALSE; Route(hub, pParam, TRUE, FALSE); } else if ((pParam = GetParam(pArg, "no-route=")) != NULL) { defaultRouteData = FALSE; Route(hub, pParam, FALSE, TRUE); } else { cerr << "Unknown option " << pArg << endl; exit(1); } pArgs++; argc--; } if (argc < 2) Usage(argv[0]); if (defaultRouteData) { hub.RouteData(0, -1, FALSE); hub.RouteData(1, 0, FALSE); } for (i = 1 ; i < argc ; i++) { if (!hub.PlugIn(i - 1, pArgs[i - 1], comParams)) return 1; } hub.RouteDataReport(); if (hub.StartAll()) { DWORD nextReportTime = 0; for (;;) { SleepEx(5000, TRUE); DWORD time = GetTickCount(); if ((nextReportTime - time - 1) > 10000) { hub.LostReport(); nextReportTime = time + 5000; } } } return 1; } /////////////////////////////////////////////////////////////// --- NEW FILE: utils.h --- /* * $Id: utils.h,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: utils.h,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #ifndef _C0C_UTILS_H_ #define _C0C_UTILS_H_ char *STRTOK_R(char *pStr, const char *pDelims, char **ppSave); BOOL StrToInt(const char *pStr, int *pNum); const char *GetParam(const char *pArg, const char *pPattern); #endif /* _C0C_UTILS_H_ */ --- NEW FILE: comport.h --- /* * $Id: comport.h,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: comport.h,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #ifndef _COMPORT_H #define _COMPORT_H /////////////////////////////////////////////////////////////// class ComHub; class ComParams; /////////////////////////////////////////////////////////////// class ComPort { public: ComPort(ComHub &_hub); BOOL Open(const char *pPath, const ComParams &comParams); BOOL Start(); BOOL Write(LPCVOID pData, DWORD len); void OnRead(LPCVOID pBuf, DWORD done); const string &Name() const { return name; } HANDLE Handle() const { return handle; } DWORD &WriteQueued() { return writeQueued; } DWORD &WriteLost() { return writeLost; } void LostReport(); private: string name; HANDLE handle; ComHub &hub; DWORD writeQueued; DWORD writeLost; DWORD writeLostTotal; }; /////////////////////////////////////////////////////////////// #endif // _COMPORT_H --- NEW FILE: comio.h --- /* * $Id: comio.h,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: comio.h,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #ifndef _COMIO_H #define _COMIO_H /////////////////////////////////////////////////////////////// class ComPort; class ComParams; /////////////////////////////////////////////////////////////// HANDLE OpenComPort(const char *pPath, const ComParams &comParams); /////////////////////////////////////////////////////////////// class ReadOverlapped : private OVERLAPPED { public: ReadOverlapped(ComPort &_port) : port(_port) {} BOOL StartRead(); private: static VOID CALLBACK OnRead( DWORD err, DWORD done, LPOVERLAPPED pOverlapped); ComPort &port; BYTE buf[64]; int i; static int iNext; }; class WriteOverlapped : private OVERLAPPED { public: WriteOverlapped(ComPort &_port, const void *_pBuf, DWORD _len); ~WriteOverlapped(); BOOL StartWrite(); private: static VOID CALLBACK OnWrite( DWORD err, DWORD done, LPOVERLAPPED pOverlapped); ComPort &port; BYTE *pBuf; DWORD len; int i; static int iNext; }; /////////////////////////////////////////////////////////////// #endif // _COMIO_H --- NEW FILE: comparams.h --- /* * $Id: comparams.h,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: comparams.h,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #ifndef _COMPARAMS_H #define _COMPARAMS_H /////////////////////////////////////////////////////////////// class ComParams { public: ComParams(); void SetBaudRate(const char *pBaudRate) { baudRate = atol(pBaudRate); } void SetByteSize(const char *pByteSize) { byteSize = atoi(pByteSize); } BOOL SetParity(const char *pParity); BOOL SetStopBits(const char *pStopBits); static const char *ParityStr(int parity); static const char *StopBitsStr(int stopBits); static const char *BaudRateLst(); static const char *ByteSizeLst(); static const char *ParityLst(); static const char *StopBitsLst(); long BaudRate() const { return baudRate; } int ByteSize() const { return byteSize; } int Parity() const { return parity; } int StopBits() const { return stopBits; } private: long baudRate; int byteSize; int parity; int stopBits; }; /////////////////////////////////////////////////////////////// #endif // _COMPARAMS_H --- NEW FILE: comhub.h --- /* * $Id: comhub.h,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: comhub.h,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #ifndef _COMHUB_H #define _COMHUB_H /////////////////////////////////////////////////////////////// class ComPort; class ComParams; /////////////////////////////////////////////////////////////// typedef vector<ComPort*> ComPorts; typedef multimap<ComPort*, ComPort*> ComPortMap; /////////////////////////////////////////////////////////////// class ComHub { public: ComHub(int num); BOOL PlugIn(int n, const char *pPath, const ComParams &comParams); BOOL StartAll(); void Write(ComPort *pFromPort, LPCVOID pData, DWORD len); void LostReport(); void RouteData(int iFrom, int iTo, BOOL noRoute); void RouteDataReport(); int NumPorts() { return (int)ports.size(); } private: ComPorts ports; ComPortMap routeDataMap; }; /////////////////////////////////////////////////////////////// #endif // _COMHUB_H --- NEW FILE: precomp.h --- /* * $Id: precomp.h,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: precomp.h,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #ifndef _PRECOMP_H_ #define _PRECOMP_H_ #include <windows.h> #include <string> #include <vector> #include <iostream> #include <map> using namespace std; #pragma warning(disable:4512) // assignment operator could not be generated #endif /* _PRECOMP_H_ */ --- NEW FILE: utils.cpp --- /* * $Id: utils.cpp,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: utils.cpp,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #include "precomp.h" #include "utils.h" /////////////////////////////////////////////////////////////// static BOOL IsDelim(char c, const char *pDelims) { while (*pDelims) { if (c == *pDelims++) return TRUE; } return FALSE; } char *STRTOK_R(char *pStr, const char *pDelims, char **ppSave) { if (!pStr) pStr = *ppSave; while (IsDelim(*pStr, pDelims)) pStr++; if (!*pStr) { *ppSave = pStr; return NULL; } char *pToken = pStr; while (*pStr && !IsDelim(*pStr, pDelims)) pStr++; if (*pStr) *pStr++ = 0; *ppSave = pStr; return pToken; } /////////////////////////////////////////////////////////////// BOOL StrToInt(const char *pStr, int *pNum) { BOOL res = FALSE; int num; int sign = 1; switch (*pStr) { case '-': sign = -1; case '+': pStr++; break; } for (num = 0 ;; pStr++) { switch (*pStr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': num = num*10 + (*pStr - '0'); res = TRUE; continue; case 0: break; default: res = FALSE; } break; } if (pNum) *pNum = num*sign; return res; } /////////////////////////////////////////////////////////////// const char *GetParam(const char *pArg, const char *pPattern) { size_t lenPattern = strlen(pPattern); if (_strnicmp(pArg, pPattern, lenPattern) != 0) return NULL; return pArg + lenPattern; } /////////////////////////////////////////////////////////////// --- NEW FILE: version.h --- /* * $Id: version.h,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _H4C_VERSION_H_ #define _H4C_VERSION_H_ #define H4C_COPYRIGHT_YEARS "2006-2007" #define H4C_V1 1 #define H4C_V2 0 #define H4C_V3 0 #define H4C_V4 0 #define MK_VERSION_STR1(V1, V2, V3, V4) #V1 "." #V2 "." #V3 "." #V4 #define MK_VERSION_STR(V1, V2, V3, V4) MK_VERSION_STR1(V1, V2, V3, V4) #define H4C_VERSION_STR MK_VERSION_STR(H4C_V1, H4C_V2, H4C_V3, H4C_V4) #endif /* _H4C_VERSION_H_ */ --- NEW FILE: comhub.cpp --- /* * $Id: comhub.cpp,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: comhub.cpp,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #include "precomp.h" #include "comhub.h" #include "comport.h" /////////////////////////////////////////////////////////////// typedef pair <ComPort*, ComPort*> ComPortPair; /////////////////////////////////////////////////////////////// static ComPortMap::iterator FindPair(ComPortMap &map, ComPortPair &pair) { ComPortMap::iterator i; for (i = map.find(pair.first) ; i != map.end() ; i++) { if (i->first != pair.first) return map.end(); if (i->second == pair.second) break; } return i; } /////////////////////////////////////////////////////////////// ComHub::ComHub(int num) { for (int i = 0 ; i < num ; i++) { ComPort *pPort = new ComPort(*this); if (!pPort) { cerr << "Can't create ComPort " << i << endl; break; } ports.push_back(pPort); } } BOOL ComHub::PlugIn(int n, const char *pPath, const ComParams &comParams) { ComPort *pPort = ports.at(n); if (!pPort->Open(pPath, comParams)) return FALSE; return TRUE; } BOOL ComHub::StartAll() { BOOL res = TRUE; for (ComPorts::const_iterator i = ports.begin() ; i != ports.end() ; i++) { if (!(*i)->Start()) res = FALSE; } return res; } void ComHub::Write(ComPort *pFromPort, LPCVOID pData, DWORD len) { ComPortMap::const_iterator i; for (i = routeDataMap.find(pFromPort) ; i != routeDataMap.end() ; i++) { if (i->first != pFromPort) break; i->second->Write(pData, len); } } void ComHub::LostReport() { for (ComPorts::const_iterator i = ports.begin() ; i != ports.end() ; i++) (*i)->LostReport(); } void ComHub::RouteData(int iFrom, int iTo, BOOL noRoute) { if (iFrom < 0) { for (int iF = 0 ; iF < (int)ports.size() ; iF++) { if(iTo < 0) { for (int iT = 0 ; iT < (int)ports.size() ; iT++) RouteData(iF, iT, noRoute); } else { RouteData(iF, iTo, noRoute); } } } else { if(iTo < 0) { for (int iT = 0 ; iT < (int)ports.size() ; iT++) RouteData(iFrom, iT, noRoute); } else if (iFrom != iTo || noRoute) { ComPortPair pair(ports.at(iFrom), ports.at(iTo)); for (;;) { ComPortMap::iterator i = FindPair(routeDataMap, pair); if (i == routeDataMap.end()) { if (!noRoute) routeDataMap.insert(pair); break; } else if (noRoute) { routeDataMap.erase(i); } else { break; } } } } } void ComHub::RouteDataReport() { if (!routeDataMap.size()) { cout << "No route for data" << endl; return; } ComPort *pLastPort = NULL; for (ComPortMap::const_iterator i = routeDataMap.begin() ; i != routeDataMap.end() ; i++) { if (pLastPort != i->first) { if (pLastPort) cout << endl; cout << "Route data " << i->first->Name() << " -->"; pLastPort = i->first; } cout << " " << i->second->Name(); } if (pLastPort) cout << endl; } /////////////////////////////////////////////////////////////// --- NEW FILE: ReadMe.txt --- =========================== HUB for COM ports (hub4com) =========================== INTRODUCTION ============ The HUB for COM ports (hub4com) is a Windows application and is a part of the com0com project. It allows to send data received from one COM port to a number of COM ports and vice versa. In conjunction with the com0com driver the hub4com makes it possible to handle data from a single serial device by a number of different applications. The homepage for com0com project is http://com0com.sourceforge.net/. BUILDING ======== Start Microsoft Visual C++ 2005 with hub4com.vcproj file. Set Active Configuration to hub4com - Win32 Release. Build hub4com.exe. TESTING ======= 1. With the com0com driver create three virtual COM port pairs with port names CNCA0, CNCB0, CNCA1, CNCB1, CNCA2 and CNCB2 (see com0com's ReadMe.txt file for details). 2. Start the hub4com.exe on CNCB0, CNCB1 and CNCB2 ports: hub4com --route=All:All \\.\CNCB0 \\.\CNCB1 \\.\CNCB2 3. Start the HyperTerminal on CNCA0 port. 4. Start the HyperTerminal on CNCA1 port. 5. Start the HyperTerminal on CNCA2 port. 6. The data typed to any HyperTerminal window should be printed on the others HyperTerminal windows. EXAMPLE OF USAGE ================ You have serial device that connected to your computer via COM1 port and you'd like to handle its data by two applications. You can do it this way: 1. With the com0com driver create two virtual COM port pairs with port names CNCA0, CNCB0, CNCA1 and CNCB1 (see com0com's ReadMe.txt for details). 2. Start the hub4com.exe on COM1, CNCB0 and CNCB1 ports: hub4com \\.\COM1 \\.\CNCB1 \\.\CNCB2 It will send data received from COM1 port to CNCB0 and CNCB1 ports and it will send data received from CNCB0 port to COM1 port. 3. Start the applications on CNCA0 and CNCA1 ports. --- NEW FILE: comio.cpp --- /* * $Id: comio.cpp,v 1.1 2007/01/23 09:13:10 vfrolov Exp $ * * Copyright (c) 2006-2007 Vyacheslav Frolov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Log: comio.cpp,v $ * Revision 1.1 2007/01/23 09:13:10 vfrolov * Initial revision * * */ #include "precomp.h" #include "comio.h" #include "comport.h" #include "comparams.h" /////////////////////////////////////////////////////////////// static void TraceError(DWORD err, const char *pFmt, ...) { 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 handle, DCB *dcb) { dcb->DCBlength = sizeof(*dcb); if (!GetCommState(handle, dcb)) { TraceError(GetLastError(), "GetCommState()"); return FALSE; } return TRUE; } static BOOL mySetCommState(HANDLE handle, DCB *dcb) { if (!SetCommState(handle, dcb)) { TraceError(GetLastError(), "SetCommState()"); return FALSE; } return TRUE; } /////////////////////////////////////////////////////////////// HANDLE OpenComPort(const char *pPath, const ComParams &comParams) { HANDLE handle = CreateFile(pPath, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (handle == INVALID_HANDLE_VALUE) { TraceError(GetLastError(), "OpenComPort(): CreateFile(\"%s\")", pPath); return INVALID_HANDLE_VALUE; } DCB dcb; if (!myGetCommState(handle, &dcb)) { CloseHandle(handle); return INVALID_HANDLE_VALUE; } if (comParams.BaudRate() > 0) dcb.BaudRate = (DWORD)comParams.BaudRate(); if (comParams.ByteSize() > 0) dcb.ByteSize = (BYTE)comParams.ByteSize(); if (comParams.Parity() >= 0) dcb.Parity = (BYTE)comParams.Parity(); if (comParams.StopBits() >= 0) dcb.StopBits = (BYTE)comParams.StopBits(); dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fDsrSensitivity = FALSE; dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.fParity = FALSE; dcb.fNull = FALSE; dcb.fAbortOnError = FALSE; dcb.fErrorChar = FALSE; if (!mySetCommState(handle, &dcb)) { CloseHandle(handle); return INVALID_HANDLE_VALUE; } COMMTIMEOUTS timeouts; if (!GetCommTimeouts(handle, &timeouts)) { TraceError(GetLastError(), "OpenComPort(): GetCommTimeouts()"); CloseHandle(handle); return INVALID_HANDLE_VALUE; } timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; timeouts.ReadTotalTimeoutConstant = MAXDWORD - 1; timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 0; if (!SetCommTimeouts(handle, &timeouts)) { TraceError(GetLastError(), "OpenComPort(): SetCommTimeouts()"); CloseHandle(handle); return INVALID_HANDLE_VALUE; } cout << "Open(" << "\"" << pPath << "\", baud=" << (unsigned)dcb.BaudRate << ", data=" << (unsigned)dcb.ByteSize << ", parity=" << ComParams::ParityStr(dcb.Parity) << ", stop=" << ComParams::StopBitsStr(dcb.StopBits) << ") - OK" << endl; return handle; } /////////////////////////////////////////////////////////////// int ReadOverlapped::iNext = 0; int WriteOverlapped::iNext = 0; /////////////////////////////////////////////////////////////// WriteOverlapped::WriteOverlapped(ComPort &_port, const void *_pBuf, DWORD _len) : port(_port), len(_len) { pBuf = new BYTE[len]; for (DWORD i = 0 ; i < len ; i++) { pBuf[i] = ((const BYTE *)_pBuf)[i]; } } WriteOverlapped::~WriteOverlapped() { if (pBuf) delete [] pBuf; } VOID CALLBACK WriteOverlapped::OnWrite( DWORD err, DWORD done, LPOVERLAPPED pOverlapped) { WriteOverlapped &overlapped = *(WriteOverlapped *)pOverlapped; if (err != ERROR_SUCCESS && err != ERROR_OPERATION_ABORTED) TraceError(err, "WriteOverlapped::OnWrite: %s", overlapped.port.Name().c_str()); if (overlapped.len > done) overlapped.port.WriteLost() += overlapped.len - done; overlapped.port.WriteQueued() -= overlapped.len; delete &overlapped; } BOOL WriteOverlapped::StartWrite() { ::memset((OVERLAPPED *)this, 0, sizeof(OVERLAPPED)); i = iNext++; if (!pBuf) { return FALSE; } if (::WriteFileEx(port.Handle(), pBuf, len, this, OnWrite)) { port.WriteQueued() += len; return TRUE; } return FALSE; } /////////////////////////////////////////////////////////////// VOID CALLBACK ReadOverlapped::OnRead( DWORD err, DWORD done, LPOVERLAPPED pOverlapped) { ReadOverlapped &overlapped = *(ReadOverlapped *)pOverlapped; if (err == ERROR_SUCCESS) overlapped.port.OnRead(overlapped.buf, done); else TraceError(err, "ReadOverlapped::OnRead(): %s", overlapped.port.Name().c_str()); overlapped.StartRead(); } BOOL ReadOverlapped::StartRead() { ::memset((OVERLAPPED *)this, 0, sizeof(OVERLAPPED)); i = iNext++; if (::ReadFileEx(port.Handle(), buf, sizeof(buf), this, OnRead)) { return TRUE; } TraceError(GetLastError(), "ReadOverlapped::StartRead(): ReadFileEx() %s", port.Name().c_str()); return FALSE; } /////////////////////////////////////////////////////////////// |