Seeking USB Serial Com Port in Windows Automatically : via PID VID

After you read previous article, you might know how to operate a com port in Windows.



   But that example requires programmer (or user, if you modified that example being able to support inputting command line) to set a com port number, it is not consummate. I will fill the flaw in here.





You need to check the device enumeration path zeroth.In here, I use CH340 (USB com port chip from China), I assure there is only one CH340 connected to the computer, I could seek the comport via pid(product id) and vid (vendor
id).

Seeking USB Serial Com Port in Windows Automatically : via PID VID

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYwNjE3MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center">

If you do not know what is vid/pid : Briefly say, it is USB device firmware replying computer what device it is in seral number. We could use pid/vid + google to indentify the device, even there is no correspending driver.Seeking USB Serial Com Port in Windows Automatically : via PID VID







 You need to set hSerial as invalid in the begining of that code:

hSerial = INVALID_HANDLE_VALUE;

And you should replace that as the code below:

 hSerial = CreateFile(&comPortName[0], GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

as

 if(0 == strncmp(&comPortName[0], "\\\\.\\COM0", MAX_STR_LEN))
{
unsigned int i; COMMCONFIG comConfig;
DWORD dwSize;
dwSize = sizeof(comConfig); ZeroMemory(&comConfig, sizeof(COMMCONFIG)); for(i = 1; i< 256; i++){
TCHAR comName[16]; sprintf(&comName[0], "COM%d", i); if(FALSE != GetDefaultCommConfig(&comName[0], &comConfig, &dwSize))
printf("found %s\n", &comName[0]);
}/*for */ } if(0 == strncmp(&comPortName[0], "\\\\.\\COM0", MAX_STR_LEN))
{
DWORD dwGuids;
GUID *pGuids; HDEVINFO hDevInfo;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
SP_DEVINFO_DATA devInfoData;
unsigned int index; dwGuids = 0; isSuc = SetupDiClassGuidsFromName("Ports", NULL, 0, &dwGuids); pGuids = (GUID*)malloc(dwGuids*sizeof(GUID));
ZeroMemory(pGuids, dwGuids*sizeof(GUID));
isSuc = SetupDiClassGuidsFromName("Ports", pGuids, dwGuids, &dwGuids); hDevInfo = SetupDiGetClassDevs(pGuids, NULL, NULL,
/*DIGCF_ALLCLASSES | DIGCF_PRESENT |*/ DIGCF_DEVICEINTERFACE); index = 0; ZeroMemory(&devInfoData, sizeof(SP_DEVINFO_DATA));
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); while(SetupDiEnumDeviceInfo(hDevInfo, index, &devInfoData))
{ TCHAR szDeviceInstanceID[1024]; index++; isSuc = CM_Get_Device_ID(devInfoData.DevInst,
&szDeviceInstanceID[0] , sizeof(szDeviceInstanceID), 0); //printf("%s\n", &szDeviceInstanceID[0]); if(0 == strncmp(&szDeviceInstanceID[0], "USB\\VID_1A86&PID_7523",
strlen("USB\\VID_1A86&PID_7523")) )
{ DWORD requiredSize;
GUID classGuid; SP_DEVICE_INTERFACE_DATA devInterfaceData;
SP_DEVICE_INTERFACE_DETAIL_DATA *pDevInterfaceDetailData; printf("&szDeviceInstanceID[0] = %s\n", &szDeviceInstanceID[0]); ZeroMemory(&devInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA)); devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
classGuid = devInfoData.ClassGuid; isSuc = SetupDiEnumDeviceInterfaces(hDevInfo, &devInfoData, pGuids,
0, &devInterfaceData); isSuc = SetupDiGetDeviceInterfaceDetail(hDevInfo,
&devInterfaceData, NULL, NULL, &requiredSize, NULL); //printf ("%s\n", GetLastErrorMessage( GetLastError() ) ); pDevInterfaceDetailData = (SP_INTERFACE_DEVICE_DETAIL_DATA*)malloc(requiredSize); pDevInterfaceDetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); isSuc = SetupDiGetDeviceInterfaceDetail( hDevInfo,
&devInterfaceData, pDevInterfaceDetailData, requiredSize,
&requiredSize, &devInfoData); printf("devInterfaceDetailData.DevicePath = %s\n",
pDevInterfaceDetailData->DevicePath); hSerial = CreateFile(pDevInterfaceDetailData->DevicePath,
GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL ); free(pDevInterfaceDetailData); pDevInterfaceDetailData = NULL; if(INVALID_HANDLE_VALUE != hSerial)
break;
}
} free(pGuids); pGuids = NULL;
SetupDiDestroyDeviceInfoList(hDevInfo); if(INVALID_HANDLE_VALUE == hSerial)
{
printf("auto seeking com number fail!!\n");
return 0;
}
}
else /*non auto seeking com port*/
{
hSerial = CreateFile(&comPortName[0], GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
}/*if auto seeking com port*/

("\\\\.\\COM0" be  auto-seeking mode in here.)

blogID=6543025294777699729" target="_blank" style="clear:right; margin-bottom:1em; margin-left:1em; float:right">



You have to modify the USB\\VID_1A86&PID_7523 as your device's.



( If you use FTDI's FT232B  or FT232R, that should be



FTDIBUS\\VID_0403+PID_6001



Seeking USB Serial Com Port in Windows Automatically : via PID VIDSeeking USB Serial Com Port in Windows Automatically : via PID VID



)









That would support auto-seeking com-port.



Note the line :

        while(SetupDiEnumDeviceInfo(hDevInfo, index, &devInfoData))

You would find NOT ONLY one device as VID_1A86&PID_7523, even you have plugged only one CH340. If you print that seeking result (it is just the line : printf("&szDeviceInstanceID[0] = %s\n", &szDeviceInstanceID[0]);), you would watch the printing as:



blogID=6543025294777699729" target="_blank" style="clear:left; margin-right:1em; margin-bottom:1em; float:left">

blogID=6543025294777699729" target="_blank" style="clear:left; margin-right:1em; margin-bottom:1em; float:left">

&szDeviceInstanceID[0] = USB\VID_1A86&PID_7523\6&123E8975&0&1
devInterfaceDetailData.DevicePath = \\?\usb#vid_1a86&pid_7523#6&123e8975&0&1#{4d
36e978-e325-11ce-bfc1-08002be10318}
&szDeviceInstanceID[0] = USB\VID_1A86&PID_7523\6&123E8975&0&2
devInterfaceDetailData.DevicePath = \\? \usb#vid_1a86&pid_7523#6&123e8975&0&2#{4d
36e978-e325-11ce-bfc1-08002be10318}
&szDeviceInstanceID[0] = USB\VID_1A86&PID_7523\6&123E8975&0&3
devInterfaceDetailData.DevicePath = \\? \usb#vid_1a86&pid_7523#6&123e8975&0&3#{4d
36e978-e325-11ce-bfc1-08002be10318}
&szDeviceInstanceID[0] = USB\VID_1A86&PID_7523\6&123E8975&0&4
devInterfaceDetailData.DevicePath = \\? \usb#vid_1a86&pid_7523#6&123e8975&0&4#{4d
36e978-e325-11ce-bfc1-08002be10318}
&szDeviceInstanceID[0] = USB\VID_1A86&PID_7523\6&123E8975&0&5
devInterfaceDetailData.DevicePath = \\?\usb#vid_1a86&pid_7523#6&123e8975&0&5#{4d
36e978-e325-11ce-bfc1-08002be10318}
&szDeviceInstanceID[0] = USB\VID_1A86&PID_7523\7&107B0B49&0&2
devInterfaceDetailData.DevicePath = \\?\usb#vid_1a86&pid_7523#7&107b0b49&0&2#{4d
36e978-e325-11ce-bfc1-08002be10318}
&szDeviceInstanceID[0] = USB\VID_1A86&PID_7523\7&14F85601&0&1
devInterfaceDetailData.DevicePath = \\?\usb#vid_1a86&pid_7523#7&14f85601&0&1#{4d
36e978-e325-11ce-bfc1-08002be10318}

I do not know why Windows lists so much device path. AlI I could do, is to try opening each. you could find that the actual one's last 4 characters (like &0&4, &0&2..etc) would change with port number, that depends on which
USB socket you plug.


上一篇:设计模式之桥接模式(Bridge)--结构模型


下一篇:Zabbix的LLD功能--Low-level discovery