zoukankan      html  css  js  c++  java
  • 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
    ", &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
    ", &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
    ", &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
    ", 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
    ", 
         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!!
    ");
       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 ", &szDeviceInstanceID[0]);), you would watch the printing as:


    &szDeviceInstanceID[0] = USBVID_1A86&PID_75236&123E8975&0&1
    devInterfaceDetailData.DevicePath = \?usb#vid_1a86&pid_7523#6&123e8975&0&1#{4d
    36e978-e325-11ce-bfc1-08002be10318}
    &szDeviceInstanceID[0] = USBVID_1A86&PID_75236&123E8975&0&2
    devInterfaceDetailData.DevicePath = \?

    usb#vid_1a86&pid_7523#6&123e8975&0&2#{4d 36e978-e325-11ce-bfc1-08002be10318} &szDeviceInstanceID[0] = USBVID_1A86&PID_75236&123E8975&0&3 devInterfaceDetailData.DevicePath = \?

    usb#vid_1a86&pid_7523#6&123e8975&0&3#{4d 36e978-e325-11ce-bfc1-08002be10318} &szDeviceInstanceID[0] = USBVID_1A86&PID_75236&123E8975&0&4 devInterfaceDetailData.DevicePath = \?

    usb#vid_1a86&pid_7523#6&123e8975&0&4#{4d 36e978-e325-11ce-bfc1-08002be10318} &szDeviceInstanceID[0] = USBVID_1A86&PID_75236&123E8975&0&5 devInterfaceDetailData.DevicePath = \?usb#vid_1a86&pid_7523#6&123e8975&0&5#{4d 36e978-e325-11ce-bfc1-08002be10318} &szDeviceInstanceID[0] = USBVID_1A86&PID_75237&107B0B49&0&2 devInterfaceDetailData.DevicePath = \?usb#vid_1a86&pid_7523#7&107b0b49&0&2#{4d 36e978-e325-11ce-bfc1-08002be10318} &szDeviceInstanceID[0] = USBVID_1A86&PID_75237&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.


    
  • 相关阅读:
    Leetcode264. Ugly Number II丑数2
    Leetcode221. Maximal Square最大正方形
    223. Rectangle Area
    Leetcode216. Combination Sum III组合总数3
    Leetcode200. Number of Islands岛屿的个数
    Leetcode199. Binary Tree Right Side View二叉树的右视图
    Leetcode179. Largest Number最大数
    从零开始学Linux系统(二)之基本操作指令
    从零开始学Linux系统(四)之Vi/Vim操作指令
    MySQL基础原创笔记(二)
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5314407.html
Copyright © 2011-2022 走看看