スキップしてメイン コンテンツへ

 none
How to use CreateFile to open a handle to an external USB device RRS feed

  • 質問

  • I am trying to open a USB printer through SetupDi calls and then call the GUID through CreateFile. I can call SetupDiGetDeviceRegistry Property and loop through all my computer's devices and compare the SPDRP_DEVICEDESC (the description of the device) to find the device that I want. After I find the right device, I get the SP_DEVINFO_DATA.ClassGuid of that device. However, when I call CreateFile with the ClassGuid as a parameter, it doesn't work. Should I not be using the ClassGuid? Should I look for some other property instead?
    • 移動 Helen Zhao 2011年11月8日 4:01 (From:Visual C++ General)
    2011年11月2日 10:42

すべての返信

  • Hi Dwigt,

    Along with DDK(Driver Develepment Kit) there a sample source available(UsbView).

    C:\WinDDK\6001.18002\src\usb\usbview(Path in my machine)

    UsbView is good sample application which enumerate all usb devices through USB Host Controller and show all device detail in a tree control.

    it uses CreateFile() to get handle to HostController .

    Following are the steps used for enumeration

        (1) Enumerate Host Controllers and Root Hubs
        Host controllers currently have symbolic link names of the form HCDx,
        where x starts at 0.  Use CreateFile() to open each host controller
        symbolic link. 

     

       wsprintf(HCName, "\\\\.\\HCD%d", HCNum);
    
    hHCDev = CreateFile(HCName,
                                GENERIC_WRITE,
                                FILE_SHARE_WRITE,
                                NULL,
                                OPEN_EXISTING,
                                0,
                                NULL);
    
    
    
    


        After a host controller has been opened, send the host controller an
        IOCTL_USB_GET_ROOT_HUB_NAME request to get the symbolic link name of
        the root hub that is part of the host controller.

        (2) Enumerate Hubs (Root Hubs and External Hubs)
        Given the name of a hub, use CreateFile() to hub the hub.  Send the
        hub an IOCTL_USB_GET_NODE_INFORMATION request to get info about the
        hub, such as the number of downstream ports.

     Please go through the code and that will help you to get your details.

    (In order to understand the code correctly please go through USB protocol http://www.beyondlogic.org/usbnutshell/usb-in-a-nutshell.pdf)

    Thanks,

    Bhash

    2011年11月2日 15:24
  • Hi Dwigt,

     If you want to open usb device directly ,use symbolic link like the following way.

    LPCWSTR path = L"\\\\?\\USB#VID_0483&PID_2434#6&26c545a4&0&1#{4d36e979-e325-11ce-bfc1-08002be10318}";   
    hFile = CreateFile(path, 0, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);   
    
    

    Here the classguid used is for a printer.

    you can use according to your device type

     Thanks,

    Bhash

     

    2011年11月2日 15:44
  • Hi,
     
    Welcome to the MSDN Forum.
     
    According to your description, I'd like to move your thread to "Windows Hardware WDK and Driver Development" forum, because it is a problem related to WDK.
     
    Thank you for your understanding.
    Best regards,

    Helen Zhao[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    2011年11月8日 3:58
  • Dwigt wrote:
    >
    >I am trying to open a USB printer through SetupDi calls and then call
    >the GUID through CreateFile.
     
    And what do you hope to do with that handle once you have it?  Unless you
    know the printer's control language, you're just going to send gibberish.
     
    >After I find the right device, I get the SP_DEVINFO_DATA.ClassGuid of
    >that device. However, when I call CreateFile with the ClassGuid as a
    >parameter, it doesn't work. Should I not be using the ClassGuid?
     
    No, the class GUID is the same for all printers.  You should be using
    DevicePath from the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
    --
    Tim Roberts, timr@probo.com
    Providenza & Boekelheide, Inc.
     

    Tim Roberts, VC++ MVP Providenza & Boekelheide, Inc.
    2011年11月8日 5:22
  • And what do you hope to do with that handle once you have it?  Unless you know the printer's control language, you're just going to send gibberish.

    I am going to use the WriteFile command to send it the same control codes in hexidecimal that are listed in its Programmer's Manual along with lines of standard text.

     

    You should be using DevicePath from the SP_DEVICE_INTERFACE_DETAIL_DATA structure

    And then I call CreateFile using the DevicePath as the first parameter (LPCTSTR lpFileName)?

    2011年11月9日 3:47
  • Here is my code so far:

    #include <iostream>
    #include <string>
    #include <Windows.h>
    #include <windows.h>
    #include <setupapi.h>
    #include <devguid.h>
    
    // Link with SetupAPI.Lib.
    #pragma comment (lib, "setupapi.lib")
    
    int main()
    {
    	const GUID* ClassGuid = &GUID_DEVCLASS_USB;
    
    	// The SetupDiGetClassDevs function retrieves a device information set
    	//   that contains all devices of a specified class
    	// Create a HDEVINFO with all present devices.
    	HDEVINFO hDevInfo = SetupDiGetClassDevsA(ClassGuid,
    	                                         NULL, // Enumerator
    	                                         NULL,
    	                                         DIGCF_PRESENT);
    
    	if (hDevInfo == INVALID_HANDLE_VALUE)
    	{
    		// Insert error handling here.
    		DWORD last_error = GetLastError();
    		std::cout << "SetupDiGetClassDevs() returned INVALID_HANDLE_VALUE, error: "
    				  << last_error << "\n";
    		std::cin.get();
    		return 1;
    	}
    
    	std::cout << "hDevInfo retrieved successfully.\n";
    
    	// Enumerate through all devices in Set.
    
    	SP_DEVINFO_DATA DeviceInfoData;
    	DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    	PSP_DEVINFO_DATA pDeviceInfoData = &DeviceInfoData;
    
    	DWORD MemberIndex;
    
    	// This for loop executes 18 times, which is correct since there are
    	// 18 items listed in my Device Manager under "Universal Serial Bus Controllers"
    	for (MemberIndex = 0;
    		 SetupDiEnumDeviceInfo(hDevInfo,
    							   MemberIndex,
    							   pDeviceInfoData) == TRUE;
    		 MemberIndex++)
    	{
    		SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
    		DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    		PSP_DEVICE_INTERFACE_DATA pDeviceInterfaceData = &DeviceInterfaceData;
    
    		DWORD InnerMemberIndex;
    		for (InnerMemberIndex = 0;
    			 SetupDiEnumDeviceInterfaces(hDevInfo,
    										 pDeviceInfoData,
    										 ClassGuid,
    										 InnerMemberIndex,
    										 pDeviceInterfaceData) == TRUE;
    			 InnerMemberIndex++)
    		{
    			std::cout << "In inner for loop\n";
    		}
    
    		DWORD last_error_number_inner_for_loop = GetLastError();
    		CHAR last_error_message_inner_for_loop[512];
    		FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0,
    			last_error_number_inner_for_loop, 0,
    			last_error_message_inner_for_loop,
    			1024, NULL);
    
    		std::cout << "End enumerate through calls to SetupDiGetEnumDeviceInterfaces. Error message: "
    			<< last_error_message_inner_for_loop << "\n";
    	}
    
    	std::cout << "end outer for loop: MemberIndex: " << MemberIndex << "\n";
    	std::cin.get();
    	return 0;
    }
    

    The inner for loop never executes because the calls to SetupDiEnumDeviceInterfaces always fail. What am I doing wrong?

    2011年11月9日 21:38
  • GUID_DEVCLASS_USB is a device class GUID, not a device interface GUID. you also want to specify DIGCF_DEVICEINTERFACE as a flag to the call to SetupDiGetClassDevs.  Note that there is no generic usb device interface guid either. the fact that it is usb is not interesting, that is not the device interface you use to talk to  the driver
    d -- This posting is provided "AS IS" with no warranties, and confers no rights.
    2011年11月9日 21:57
  • Dwigt wrote:
    >
    >I am going to use the WriteFile command to send it the same control codes
    >in hexidecimal that are listed in its Programmer's Manual along with
    >lines of standard text.
     
    And how do you expect to do that without interfering with the standard
    driver, which also thinks it can write those control codes?  The printer
    driver believe it owns the printer.
     
    >>You should be using DevicePath from the SP_DEVICE_INTERFACE_DETAIL_DATA structure
    >
    >And then I call CreateFile using the DevicePath as the first parameter (LPCTSTR lpFileName)?
     
    Yes.
    --
    Tim Roberts, timr@probo.com
    Providenza & Boekelheide, Inc.
     

    Tim Roberts, VC++ MVP Providenza & Boekelheide, Inc.
    2011年11月10日 4:26
  • OK so I'm finally able to get all the DevicePaths using the PSP_DEVICE_INTERFACE_DETAIL_DATA. Now my question is: At the start I initialize the InterfaceGuid that is a parameter to SetupDiGetClassDevs. I have the following choices:

    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_CDCHANGER;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_CDROM;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_COMPORT;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_DISK;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_FLOPPY;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_HIDDEN_VOLUME;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_MEDIUMCHANGER;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_STORAGEPORT;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_TAPE;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_VOLUME;
    const GUID* InterfaceGuid = &GUID_DEVINTERFACE_WRITEONCEDISK;
    

    Which one should I choose for a USB printer? Or is there another one that I don't know about?

    2011年11月10日 4:26
  • Dwigt wrote:
    >
    >OK so I'm finally able to get all the DevicePaths using the
    >PSP_DEVICE_INTERFACE_DETAIL_DATA. Now my question is: At the start
    >I initialize the InterfaceGuid that is a parameter to
    >SetupDiGetClassDevs. I have the following choices:
     
    I'm not convinced that printers expose a particular device interface.  I
    think you'll need to search for GUID_DEVCLASS_PRINTER, which does not use
    the device interface flag.
    --
    Tim Roberts, timr@probo.com
    Providenza & Boekelheide, Inc.
     

    Tim Roberts, VC++ MVP Providenza & Boekelheide, Inc.
    2011年11月12日 7:11