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).


 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 );
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.)
   
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))
  
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:


&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,如需转载请自行联系原作者

相关文章
|
存储 安全 前端开发
USB Image Tool:Windows下的直接写盘利器 【开源硬件佳软介绍 #2】
这个问题,我们从磁盘结构讲起。磁盘内部所有的存储区域,必然分为分区表和数据区域两大块。而数据区域按分区表分区后,每个分区还被文件系统封装和管理[注B]:
2413 1
USB Image Tool:Windows下的直接写盘利器 【开源硬件佳软介绍 #2】
|
Windows
微软提供Windows USB/DVD Download Tool:刻录WINDOWS安装系统到U盘
微软提供Windows USB/DVD Download Tool:刻录WINDOWS安装系统到U盘
176 0
|
Linux Windows
报错:Web server failed to start. Port 9002 was already in use.端口被占用解决(Windows)
报错:Web server failed to start. Port 9002 was already in use.端口被占用解决(Windows)
663 0
|
Windows
微软提供Windows USB/DVD Download Tool:刻录WINDOWS安装系统到U盘
微软提供Windows USB/DVD Download Tool:刻录WINDOWS安装系统到U盘
223 0
|
Windows 搜索推荐
提示Windows Phone IP over USB Transport (IpOverUsbSvc)未运行,如何解决
原文:提示Windows Phone IP over USB Transport (IpOverUsbSvc)未运行,如何解决 uwp项目在安装测试时提示,“引导“Device”失败。
1944 0
下一篇
无影云桌面