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).
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.
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 );
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.)
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
)
That would support auto-seeking com-port.
Note the line :
while(SetupDiEnumDeviceInfo(hDevInfo, index, &devInfoData))
&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.
本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5314407.html,如需转载请自行联系原作者