1. Trang chủ
  2. » Công Nghệ Thông Tin

USB Complete fourth- P29 doc

10 150 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 205,53 KB

Nội dung

Chapter 10 256 In some cases, such as when looking for a HID-class device with a specific Ven- dor ID and Product ID, the application may need to request more information before deciding whether a retrieved device interface is the desired one. 8$ Definitions Public Structure SP_DEVICE_INTERFACE_DATA Dim cbSize As Int32 Dim InterfaceClassGuid As Guid Dim Flags As Int32 Dim Reserved As IntPtr End Structure <DllImport("setupapi.dll", SetLastError:=True)> _ Shared Function SetupDiEnumDeviceInterfaces _ (ByVal DeviceInfoSet As IntPtr, _ ByVal DeviceInfoData As IntPtr, _ ByRef InterfaceClassGuid As System.Guid, _ ByVal MemberIndex As Int32, _ ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA) _ As Boolean End Function Use Dim memberIndex As Int32 = 0 Dim MyDeviceInterfaceData As SP_DEVICE_INTERFACE_DATA Dim success As Boolean MyDeviceInterfaceData.cbSize = Marshal.SizeOf(MyDeviceInterfaceData) success = SetupDiEnumDeviceInterfaces _ (deviceInfoSet, _ IntPtr.Zero, _ myGuid, _ memberIndex, _ MyDeviceInterfaceData) Detecting Devices 257 8% Definitions internal struct SP_DEVICE_INTERFACE_DATA { internal Int32 cbSize; internal Guid InterfaceClassGuid; internal Int32 Flags; internal IntPtr Reserved; } [DllImport("setupapi.dll", SetLastError = true)] internal static extern Boolean SetupDiEnumDeviceInterfaces (IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData); Use Int32 memberIndex = 0; MyDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA(); Boolean success = false; MyDeviceInterfaceData.cbSize = = Marshal.SizeOf( MyDeviceInterfaceData ); success = SetupDiEnumDeviceInterfaces (deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref MyDeviceInterfaceData); &GVCKNU In the SP_DEVICE_INTERFACE_DATA structure, the cbSize parameter is the size of the structure in bytes. The Marshal.SizeOf method returns the struc- ture’s size. The myGuid and deviceInfoSet parameters are values retrieved previously. The DeviceInfoData parameter can be a pointer to an SP_DEVINFO_DATA struc- ture that limits the search to a particular device instance or a null pointer. The memberIndex parameter is an index to a structure in the deviceInfoSet array. The MyDeviceInterfaceData parameter is a pointer to the SP_DEVICE_INTERFACE_DATA structure that the function returns. The Chapter 10 258 structure identifies a device interface of the requested type. The function returns true on success. 4GSWGUVKPIC5VTWEVWTGYKVJVJG&GXKEG2CVJ0COG The SetupDiGetDeviceInterfaceDetail function returns a structure that con- tains a device path name for a device interface identified in an SP_DEVICE_INTERFACE_DATA structure. When calling this function for the first time, you don’t know the size in bytes of the DeviceInterfaceDetailData structure to pass in the DeviceInterfaceDetail- DataSize parameter. Yet the function won’t return the structure unless the func- tion call passes the correct size. The solution is to call the function twice. The first time, GetLastError returns the error The data area passed to a system call is too small, but the RequiredSize parameter contains the correct value for Device- InterfaceDetailDataSize. The second call passes the returned size value, and the function returns the structure. The code below doesn’t pass a structure for the DeviceInterfaceDetailData parameter. Instead, the code reserves a generic buffer, passes a pointer to the buffer, and extracts the device path name directly from the buffer. The code thus doesn’t require a structure declaration, but I’ve included one to show the contents of the returned buffer. 8$ Definitions Public Structure SP_DEVICE_INTERFACE_DETAIL_DATA Dim cbSize As Int32 Dim DevicePath As String End Structure <DllImport("setupapi.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ Shared Function SetupDiGetDeviceInterfaceDetail _ (ByVal DeviceInfoSet As IntPtr, _ ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, _ ByVal DeviceInterfaceDetailData As IntPtr, _ ByVal DeviceInterfaceDetailDataSize As Int32, _ ByRef RequiredSize As Int32, _ ByVal DeviceInfoData As IntPtr) _ As Boolean End Function Detecting Devices 259 Use Dim bufferSize As Int32 Dim detailDataBuffer As IntPtr Dim success As Boolean success = SetupDiGetDeviceInterfaceDetail _ (deviceInfoSet, _ MyDeviceInterfaceData, _ IntPtr.Zero, _ 0, _ bufferSize, _ IntPtr.Zero) detailDataBuffer = Marshal.AllocHGlobal(bufferSize) Marshal.WriteInt32 _ (detailDataBuffer, ConvertToInt32(IIf((IntPtr.Size = 4), 4 + Marshal.SystemDefaultCharSize, 8))) success = SetupDiGetDeviceInterfaceDetail _ (deviceInfoSet, _ MyDeviceInterfaceData, _ detailDataBuffer, _ bufferSize, _ bufferSize, _ IntPtr.Zero) 8% Definitions internal struct SP_DEVICE_INTERFACE_DETAIL_DATA { internal Int32 cbSize; internal String DevicePath; } [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] internal static extern Boolean SetupDiGetDeviceInterfaceDetail (IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData); Chapter 10 260 Use Int32 bufferSize = 0; IntPtr detailDataBuffer; Boolean success = false; success = SetupDiGetDeviceInterfaceDetail (deviceInfoSet, ref MyDeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero); detailDataBuffer = Marshal.AllocHGlobal( bufferSize ); Marshal.WriteInt32 (detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8); success = SetupDiGetDeviceInterfaceDetail (deviceInfoSet, ref MyDeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero); &GVCKNU After calling SetupDiGetDeviceInterfaceDetail, bufferSize contains the value to pass in the DeviceInterfaceDetailDataSize parameter in the next call. But before calling the function again, the code needs to take care of a few things. The second function call returns a pointer (detailDataBuffer) to an SP_DEVICE_INTERFACE_DETAIL_DATA structure in unmanaged mem- ory. The Marshal.AllocGlobal method uses the returned bufferSize value to allocate memory for the structure. The cbSize member of the structure passed in detailDataBuffer equals four bytes for cbSize plus the width of one character for the device path name (which is empty when passed to the function). The Marshal.WriteInt32 method copies the cbSize value into the first member of detailDataBuffer. The IIf function (Visual Basic) or “?” conditional operator (Visual C#) selects the correct value for 32- and 64-bit systems. Detecting Devices 261 The second call to SetupDiGetDeviceInterfaceDetail passes the pointer to detailDataBuffer and sets the deviceInterfaceDetailDataSize parameter equal to the bufferSize value returned previously in RequiredSize. When the function returns after the second call, detailDataBuffer points to a structure containing a device path name. 'ZVTCEVKPIVJG&GXKEG2CVJ0COG In detailDataBuffer, the first four bytes are the cbSize member. The string con- taining the device path name begins at the fifth byte. 8$ Dim devicePathName As String = "" Dim pDevicePathName As IntPtr = New IntPtr(detailDataBuffer.ToInt32 + 4) devicePathName = Marshal.PtrToStringAuto(pDevicePathName) Marshal.FreeHGlobal(detailDataBuffer) 8% String devicePathName = ""; IntPtr pDevicePathName = new IntPtr( detailDataBuffer.ToInt32() + 4 ); devicePathName = Marshal.PtrToStringAuto(pDevicePathName); Marshal.FreeHGlobal(detailDataBuffer); &GVCKNU The pDevicePathName variable points to the string in the buffer. The Mar- shal.PtrToString method retrieves the string from the buffer. When finished with the buffer, Marshal.FreeHGlobal frees the memory previously allocated for the buffer. %NQUKPI%QOOWPKECVKQPU When finished using the DeviceInfoSet returned by SetupDiGetClassDevs, the application should call SetupDiDestroyDeviceInfoList to free resources. 8$ Definitions <DllImport("setupapi.dll", SetLastError:=True)> _ Shared Function SetupDiDestroyDeviceInfoList _ (ByVal DeviceInfoSet As IntPtr) _ As Int32 End Function Chapter 10 262 Use SetupDiDestroyDeviceInfoList (deviceInfoSet) 8% Definitions [DllImport("setupapi.dll", SetLastError = true)] internal static extern Int32 SetupDiDestroyDeviceInfoList (IntPtr DeviceInfoSet); Use SetupDiDestroyDeviceInfoList( deviceInfoSet ); 1DVCKPKPIC*CPFNG An application can use a retrieved device path name to obtain a handle that enables communicating with the device. Table 10-2 shows API functions related to requesting a handle. 4GSWGUVKPIC%QOOWPKECVKQPU*CPFNG After retrieving a device path name, an application is ready to open communi- cations with the device. The CreateFile function requests a handle to an object, which can be a file or another resource managed by a driver that supports han- dle-based operations. For example, applications can request a handle to use in exchanging reports with HID-class devices. For devices that use the WinUSB driver, CreateFile obtains a handle the application uses to obtain a WinUSB device handle for accessing a device. The call to CreateFile can pass a SECURITY_ATTRIBUTES structure that can limit access to the handle or IntPtr.Zero if the function doesn’t need to limit access. Table 10-2: Applications can use CreateFile to request a handle to a device and CloseHandle to free the resources used by a handle. #2+(WPEVKQP & 2WTRQUG CloseHandle kernel32 Free resources reserved by CreateFile. To close handles for the SafeHandle and derived classes, use the Close method, which calls CloseHandle internally. CreateFile kernel32 Retrieve a handle for communicating with a device. Detecting Devices 263 8$ Definitions Friend Const FILE_ATTRIBUTE_NORMAL As Int32 = &H80 Friend Const FILE_FLAG_OVERLAPPED As Int32 = &H40000000 Friend Const FILE_SHARE_READ As Int32 = 1 Friend Const FILE_SHARE_WRITE As Int32 = 2 Friend Const GENERIC_READ As UInt32 = &H80000000UL Friend Const GENERIC_WRITE As UInt32 = &H40000000 Friend Const OPEN_EXISTING As Int32 = 3 <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ Shared Function CreateFile _ (ByVal lpFileName As String, _ ByVal dwDesiredAccess As UInt32, _ ByVal dwShareMode As Int32, _ ByVal lpSecurityAttributes As IntPtr, _ ByVal dwCreationDisposition As Int32, _ ByVal dwFlagsAndAttributes As Int32, _ ByVal hTemplateFile As Int32) _ As SafeFileHandle End Function Use Dim deviceHandle As SafeFileHandle deviceHandle = CreateFile _ (devicePathName, _ GENERIC_WRITE Or GENERIC_READ, _ FILE_SHARE_READ Or FILE_SHARE_WRITE, _ IntPtr.Zero, _ OPEN_EXISTING, _ FILE_ATTRIBUTE_NORMAL Or FILE_FLAG_OVERLAPPED, _ 0) 8% Definitions internal const Int32 FILE_ATTRIBUTE_NORMAL = 0X80; internal const Int32 FILE_FLAG_OVERLAPPED = 0X40000000; internal const Int32 FILE_SHARE_READ = 1; internal const Int32 FILE_SHARE_WRITE = 2; internal const UInt32 GENERIC_READ = 0X80000000; internal const UInt32 GENERIC_WRITE = 0X40000000; internal const Int32 OPEN_EXISTING = 3; Chapter 10 264 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] internal static extern SafeFileHandle CreateFile (String lpFileName, UInt32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, Int32 hTemplateFile); Use internal SafeFileHandle deviceHandle; deviceHandle = CreateFile (devicePathName, (GENERIC_WRITE | GENERIC_READ), FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0); &GVCKNU The function passes a pointer to the devicePathName string returned by Setup- DiGetDeviceInterfaceDetail. The dwDesiredAccess parameter requests read/write access to the device. The dwShareMode parameter allows other pro- cesses to access the device while the handle is open. The lpSecurityAttributes parameter is a null pointer (or a pointer to a SECURITY_ATTRIBUTES structure). The dwCreationDisposition parameter must be OPEN_EXISTING for devices. For use with the WinUSB driver, the dwFlagsAndAttributes param- eter must use FILE_FLAG_OVERLAPPED. The FILE_ATTRIBUTE_NORMAL attribute indicates that no other attributes such as hidden, read-only, or encrypted are set. The example passes zero for the unused hTemplate parameter. The function returns a SafeFileHandle object. %NQUKPIVJG*CPFNG When finished communicating with a device, the application should free the resources reserved by CreateFile. 8$ deviceHandle.Close() Detecting Devices 265 8% deviceHandle.Close(); &GVCKNU SafeFileHandle objects support the Close method, which marks the handle for releasing and freeing resources. The method calls the CloseHandle API func- tion internally. &GVGEVKPI#VVCEJOGPVCPF4GOQXCN Many applications find it useful to know when a device has been attached or removed. On detecting when a device is attached, the application can begin communicating with the device. On detecting when a device has been removed, the application can stop attempting to communicate until detecting reattach- ment. Windows provides device-notification functions for this purpose. #DQWV&GXKEG0QVKHKECVKQPU To request to be informed when a device is attached or removed, an applica- tion’s form can register to receive notification messages for devices in a device interface class. The operating system passes WM_DEVICECHANGE mes- sages to the form’s WndProc method (called WindowProc in C). An application can override WndProc in a form’s base class with a method that processes the messages and then passes them to the base class’s WndProc method. (The code below shows how to do this.) Each notification contains a device path name that the application can use to identify the device that the notification applies to. Table 10-3 lists the API functions used in registering for device notifications. The example that follows shows how to use the functions. 4GIKUVGTKPIHQT&GXKEG0QVKHKECVKQPU Applications use the RegisterDeviceNotification function to request to receive notification messages. The function requires a handle for the window or service that will receive the notifications, a pointer to a DEV_BROADCAST_DEVICEINTERFACE structure that holds information about the request, and flags to indicate whether the handle is for a window or service. In the DEV_BROADCAST_DEVICEINTERFACE structure passed to Regis- terDeviceNotification, the dbcc_devicetype member is set to DBT_DEVTYP_DEVICEINTERFACE to specify that the application wants . reports with HID-class devices. For devices that use the WinUSB driver, CreateFile obtains a handle the application uses to obtain a WinUSB device handle for accessing a device. The call to CreateFile. SECURITY_ATTRIBUTES structure). The dwCreationDisposition parameter must be OPEN_EXISTING for devices. For use with the WinUSB driver, the dwFlagsAndAttributes param- eter must use FILE_FLAG_OVERLAPPED. The FILE_ATTRIBUTE_NORMAL

Ngày đăng: 04/07/2014, 07:20

w