|
|
Comments and Discussions
|
|
 |

|
Hi,
I have a need to create a virtual com port. I would like to simulate a device connection so that I can feed the data to this virtual port.
Can any one help me please.
-srinivas,
|
|
|
|

|
Hi,
This code could be useful...
However, I just discovered that it doesn't see my modems. I have four modems connected - three via USB (USB GSM modems) and one as a PCMCIA (also GSM). All of these present a virtual COM port, but none are visible with your app. They are also not visible in DeviceManager's list of COM/LPT ports, but the virtual COM port number may be seen from the modem settings dialogs (also in DevMan).
Any ideas ?
/Per
|
|
|
|

|
if I need to enumerate serial ports in the system, I use a registry key:
HKLM\HARDWARE\DEVICEMAP\SERIALCOMM
I think it's simplier then using Device Manager? are there some inconvenients using my method?
|
|
|
|

|
IVANOV Alexei wrote:
I think it's simplier then using Device Manager? are there some inconvenients using my method?
Of course, you can.
But my article is not about enumeration serial ports.
More valuable point it is FIFO control.
And using Device Manager in my article more valuable than FIFO control.
Via Device Manager it is posible to enumerate all Windows devices as
system Device Manager do it. It is posible to find ports/IO/memory addresses
of devices also.
And I demonstrate it in another articles in codeproject.
So this article only first in this series.
|
|
|
|

|
I wrote a program using exactly the registry method. It works great with one hitch, it never sees COM10! I'm using RegQueryValueEx to read the registry values. Anytime I have an entry that should return COM10 the RegQueryValueEx function gives me a return value of ERROR_MORE_DATA. Otherwise, it seems to work great. I've tested it up to COM35 and it enumerated all of them (except 10).
|
|
|
|

|
Hello,
Great code, changed it a little, but works well. I was wondering, will it detect USB-serial adapters? If not, what changes would be needed. Thanks!
Jon
|
|
|
|

|
I am not sure what you mean.
Exist way to enumerate all devices in configuration.
You can find my solution for this (C# for .NET) in codeproject:
.NET - Diving into System Programming (Parts 1,2,3).
http://www.codeproject.com/csharp/DivingSysProg1.asp
http://www.codeproject.com/csharp/DivingSysProg2.asp
http://www.codeproject.com/csharp/DivingSysProg3.asp
The similar code for Borland C++ Builder in BDN
codecentral (you need registration for download only):
Hardware configuration in Windows
http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=20338
Really, the question - is system Device Manager can see
what you want see via application. If yes the you can
try the way what I use.
|
|
|
|

|
Yes it will work for USB-serial adapters, I have two running off of my computer and it recognizes them as COM ports.
|
|
|
|

|
hi,
do u know how to disable a device,such as modem or network adapter in an
application?
thanks
|
|
|
|

|
I answered in my previous message:
"
You can use CM_Set_HW_Prof_Flags function from cfgmgr32.dll with flag CSCONFIGFLAG_DISABLE or CSCONFIGFLAG_DO_NOT_CREATE. See also my another articles about working with device configuration (C#):
http://www.codeproject.com/csharp/DivingSysProg1.asp
http://www.codeproject.com/csharp/DivingSysProg2.asp
http://www.codeproject.com/csharp/DivingSysProg3.asp
"
If I will have some time I'll create article about it put it in codeproject on next or after next week.
|
|
|
|

|
Use DevCon.exe u can control it from your application, also u can get the code and put it into your code
visit my blog danielbcr.blogspot.com
Lancelot Electronic Developer
|
|
|
|

|
This is a general question regarding serial ports..
How do you actually release and claim a serial port e.g. COM5.
I have implemented a VirtualSerialPort and everytime I use a different port e.g. COM5, COM6 the ports stay registered in the registry.
Is there a way of releasing those ports without having to delete them from the registry?
Anyone have a clue?
Hint: Actually I want to change the status of the COM port in the "Port Settings->Advanced->Com Port Number" from "(in use)"
into a clear field for each COM port
P.S. CreateFile does not give you a handle if e.g. COM5 port was used by a device which is not present. So this port must be released in some way first..
|
|
|
|

|
You can use CM_Set_HW_Prof_Flags function from cfgmgr32.dll with flag CSCONFIGFLAG_DISABLE or CSCONFIGFLAG_DO_NOT_CREATE. See also my another articles about working with device configuration (C#):
http://www.codeproject.com/csharp/DivingSysProg1.asp
http://www.codeproject.com/csharp/DivingSysProg2.asp
http://www.codeproject.com/csharp/DivingSysProg3.asp
|
|
|
|

|
hello everybody
i tried to use the code with 'microsoft visual c++' (version 6.0, sp5), but it doesn't link. has someone a working example using visual c++? what is needed to link successfully?
thanks!
here the error:
--------------------Configuration: Test - Win32 Release--------------------
Linking...
TestDlg.obj : error LNK2001: unresolved external symbol __imp__SetupDiGetClassDevsA@16
TestDlg.obj : error LNK2001: unresolved external symbol __imp__SetupDiClassGuidsFromNameA@16
TestDlg.obj : error LNK2001: unresolved external symbol __imp__SetupDiDestroyDeviceInfoList@4
TestDlg.obj : error LNK2001: unresolved external symbol __imp__SetupDiEnumDeviceInfo@12
Release/Test.exe : fatal error LNK1120: 4 unresolved externals
Error executing link.exe.
|
|
|
|

|
If you can't use early binding you can use late binding via LoadLibrary, GetProcAddress the same way as you can see in code above in the article.
|
|
|
|

|
Hi,
Even am facing a lot of problems while linking.
It would be really wonderful if this could be packed into a small example(VC++ dsw) and shared across so that anyone can understand what the problems are with their usage.
kalpu
|
|
|
|

|
For me it easy to do in C# but not VC...
Hm...
Well, may be about one or two day when I study VC
I put app. here.
Regards.
|
|
|
|

|
You need to download Microsoft's DDK (Driver Development Kit) for whatever platform you intend using. The library "Setupapi.lib" from the DDK provides these functions.
Graham.
|
|
|
|

|
Hi,
I am using SetupDi functions in VC++ environment. Even though I include DDK's setupapi.lib file it is giving the following errors:
unresolved external symbol __imp__SetupDiDestroyDeviceInfoList@4
unresolved external symbol __imp__SetupDiGetDeviceInterfaceDetailA@24
unresolved external symbol __imp__SetupDiEnumDeviceInterfaces@20
unresolved external symbol __imp__SetupDiGetClassDevsA@16
Please help.
|
|
|
|

|
I have now time but hope on the begin of the next week to put code for VC++ here.
|
|
|
|

|
if anyone still cares, here's a kind of wrapper class for VC 6.0 (with slightly modified code and also only the enumeration stuff...).
link the setupapi library to your project to get this working:
PortEnumerator.h:
#ifndef PORT_ENUMERATOR_H_INCLUDED
#define PORT_ENUMERATOR_H_INCLUDED
#define MAX_NAME_PORTS 256
#define RegDisposition_OpenExisting (0x00000001) // open key only if exists
#define CM_REGISTRY_HARDWARE (0x00000000)
typedef DWORD (WINAPI *CM_Open_DevNode_Key)(DWORD, DWORD, DWORD, DWORD, ::PHKEY, DWORD);
class CPortEnumerator {
public:
CPortEnumerator();
~CPortEnumerator();
bool BeginEnum();
bool EnumNext(CString& portName, int& portNumber);
void EndEnum();
private:
HANDLE hDeviceInfoSet;
static HANDLE CPortEnumerator::beginEnumeratePorts(VOID);
static bool CPortEnumerator::enumeratePortsNext(HANDLE DeviceInfoSet, LPTSTR lpBuffer, int& portNo);
static void CPortEnumerator::endEnumeratePorts(HANDLE DeviceInfoSet);
};
#endif //PORT_ENUMERATOR_H_INCLUDED
PortEnumerator.cpp:
#include
#include
#include "PortEnumerator.h"
CPortEnumerator::CPortEnumerator()
{
hDeviceInfoSet = INVALID_HANDLE_VALUE;
}
CPortEnumerator::~CPortEnumerator()
{
_ASSERT(INVALID_HANDLE_VALUE == hDeviceInfoSet); //failed to call EndEnum if this asserts
}
bool CPortEnumerator::BeginEnum()
{
_ASSERT (INVALID_HANDLE_VALUE == hDeviceInfoSet);
hDeviceInfoSet = beginEnumeratePorts();
return (INVALID_HANDLE_VALUE != hDeviceInfoSet);
}
bool CPortEnumerator::EnumNext(CString& portName, int& portNumber)
{
int portNo;
LPTSTR buffer[MAX_NAME_PORTS];
_ASSERT (INVALID_HANDLE_VALUE != hDeviceInfoSet);
if (!enumeratePortsNext(hDeviceInfoSet, (LPTSTR)buffer, portNo))
return false;
portName.Format("%s", buffer);
portNumber = portNo;
return true;
}
void CPortEnumerator::EndEnum()
{
endEnumeratePorts(hDeviceInfoSet);
hDeviceInfoSet = INVALID_HANDLE_VALUE;
}
/*static*/ HANDLE CPortEnumerator::beginEnumeratePorts()
{
_GUID* buf;
HDEVINFO deviceInfoSet;
BOOL guidTest=FALSE;
DWORD requiredSize = 0;
guidTest = SetupDiClassGuidsFromNameA("Ports", 0, 0, &requiredSize);
if (requiredSize < 1)
return INVALID_HANDLE_VALUE;
buf = (_GUID*) malloc(requiredSize * sizeof(GUID));
//get GUID of the ports class:
guidTest = SetupDiClassGuidsFromNameA("Ports", buf, requiredSize * sizeof(GUID), &requiredSize);
if (!guidTest)
return INVALID_HANDLE_VALUE;
//get devices within ports class:
deviceInfoSet = SetupDiGetClassDevs(buf, NULL, NULL, DIGCF_PRESENT);
free(buf);
return deviceInfoSet;
}
/*static*/ bool CPortEnumerator::enumeratePortsNext(HANDLE deviceInfoSet, LPTSTR lpBuffer, int& portNo)
{
int res1;
int numport;
static int numDev = 0;
static HINSTANCE cfgMan;
unsigned char devName[MAX_NAME_PORTS]={0};
SP_DEVINFO_DATA deviceInfoData = {0};
static CM_Open_DevNode_Key openDevNodeKey=NULL;
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!deviceInfoSet || !lpBuffer)
return false;
if (openDevNodeKey == NULL) {
cfgMan = LoadLibrary("cfgmgr32");
if (!cfgMan)
return false;
openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan, "CM_Open_DevNode_Key");
if (!openDevNodeKey) {
FreeLibrary(cfgMan);
return false;
}
numDev=0;
}
while(TRUE) {
HKEY keyDevice;
DWORD len;
res1 = SetupDiEnumDeviceInfo(deviceInfoSet, numDev, &deviceInfoData);
if (!res1) {
SetupDiDestroyDeviceInfoList(deviceInfoSet);
FreeLibrary(cfgMan);
openDevNodeKey = NULL;
return false;
}
res1 = openDevNodeKey(deviceInfoData.DevInst, KEY_QUERY_VALUE, 0,
RegDisposition_OpenExisting, &keyDevice, CM_REGISTRY_HARDWARE);
if (res1 != ERROR_SUCCESS)
return false;
len = MAX_NAME_PORTS;
res1 = RegQueryValueEx(keyDevice, "portname", NULL, NULL, devName, &len);
RegCloseKey(keyDevice);
if (res1 != ERROR_SUCCESS)
return false;
numDev++;
if (memicmp(devName, "com", 3))
continue;
numport = atoi( (const char*) (devName + 3) );
if (numport > 0 && numport <= 256) {
strcpy(lpBuffer, (const char*)devName);
portNo = numport;
return true;
}
FreeLibrary(cfgMan);
openDevNodeKey = NULL;
return false;
}
}
/*static*/ void CPortEnumerator::endEnumeratePorts(HANDLE deviceInfoSet)
{
SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
daniel.
|
|
|
|
|

|
I'm mainly assembly not C++ language programmer but anyway I don't see the reasoning to use a class when you put static variables into its member functions. This way you cannot have more than one instance of that class which renders the whole idea of using classes pointless. You could simply use the original functions from the article.
Here is how the class has to be constructed (MS Visual Studio 2008, VC++):
PortEnum.h:
#pragma once
#include <setupapi.h>
#define MAX_NAME_PORTS 7
#define RegDisposition_OpenExisting (0x00000001) #define CM_REGISTRY_HARDWARE (0x00000000)
typedef DWORD (WINAPI *CM_Open_DevNode_Key)(DWORD, DWORD, DWORD, DWORD, PHKEY, DWORD);
class CEnumComPorts
{
HDEVINFO hDeviceInfoSet;
CM_Open_DevNode_Key OpenDevNodeKey;
HINSTANCE CfgMgr;
unsigned numDev;
public:
CEnumComPorts();
~CEnumComPorts();
int GetNextPort(LPTSTR);
inline void Reset(void);
};
PortEnum.cpp:
#include "PortEnum.h"
CEnumComPorts::CEnumComPorts() : hDeviceInfoSet(INVALID_HANDLE_VALUE), OpenDevNodeKey(NULL), CfgMgr(NULL), numDev(0)
{
DWORD RequiredSize = 0;
PCTSTR Ports = TEXT("Ports");
SetupDiClassGuidsFromName(TEXT("Ports"),0,0,&RequiredSize);
if (!RequiredSize) return;
void *buf = _malloca(RequiredSize*sizeof(GUID));
if (!SetupDiClassGuidsFromName(Ports,(LPGUID) buf,RequiredSize*sizeof(GUID),&RequiredSize))
{
_freea(buf);
return;
}
hDeviceInfoSet = SetupDiGetClassDevs((LPGUID) buf,NULL,NULL,DIGCF_PRESENT);
_freea(buf);
if (hDeviceInfoSet == INVALID_HANDLE_VALUE) return;
CfgMgr = LoadLibrary(TEXT("cfgmgr32"));
if (CfgMgr) OpenDevNodeKey = (CM_Open_DevNode_Key) GetProcAddress(CfgMgr,"CM_Open_DevNode_Key");
}
CEnumComPorts::~CEnumComPorts()
{
if (CfgMgr) FreeLibrary(CfgMgr);
if (hDeviceInfoSet != INVALID_HANDLE_VALUE) SetupDiDestroyDeviceInfoList(hDeviceInfoSet);
}
int CEnumComPorts::GetNextPort(LPTSTR pBuffer)
{
TCHAR DevName[MAX_NAME_PORTS] = {0};
SP_DEVINFO_DATA DeviceInfoData = {0};
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!hDeviceInfoSet || !pBuffer) return -1;
while (TRUE)
{
HKEY KeyDevice;
if (!SetupDiEnumDeviceInfo(hDeviceInfoSet,numDev,&DeviceInfoData)) return 1;
if (OpenDevNodeKey(DeviceInfoData.DevInst,KEY_QUERY_VALUE,0,RegDisposition_OpenExisting,&KeyDevice,CM_REGISTRY_HARDWARE) != ERROR_SUCCESS) return 1;
DWORD len = MAX_NAME_PORTS*sizeof(TCHAR);
LONG res = RegQueryValueEx(
KeyDevice, TEXT("portname"), NULL, NULL, (LPBYTE) DevName, &len );
RegCloseKey(KeyDevice);
numDev++;
if (res != ERROR_SUCCESS || _tcsncicmp(DevName,TEXT("com"),3)) continue;
if (_tstoi(DevName + 3) < 256)
{
_tcscpy_s(pBuffer,MAX_NAME_PORTS,DevName);
return 0;
}
return 1;
}
}
void CEnumComPorts::Reset(void)
{
numDev = 0;
}
Viruslavmodified on Thursday, March 4, 2010 7:25 AM
|
|
|
|

|
Tnx for the article - the enumeration of devices was very handy... There is however one small bug which prevents using the function multiple times. In the EnumeratePortsNext function, the static numDev variable is not reset when the static OpenDevNodeKey is NULL (when a new enumeration starts) - so you immediately return that there are no more devices.
This is what I made of it:
if (!OpenDevNodeKey) {
CfgMan = LoadLibrary("cfgmgr32");
if (!CfgMan)
return FALSE;
OpenDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(CfgMan,"CM_Open_DevNode_Key");
if(!OpenDevNodeKey) {
FreeLibrary(CfgMan);
return FALSE;
}
numDev=0;
}
|
|
|
|

|
Hi,
Thank you for feedback
I improve it about week.
Best Regards.
Vladimir.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
Article explains how to enumerate serial ports and manage FIFO using Device Manager and Configuration Manager.
| Type | Article |
| Licence | CPOL |
| First Posted | 21 May 2003 |
| Views | 166,288 |
| Bookmarked | 62 times |
|
|