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

USB Complete fourth- P36 docx

10 163 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 192,41 KB

Nội dung

Chapter 13 326 8% Definitions internal struct HIDP_CAPS { internal Int16 Usage; internal Int16 UsagePage; internal Int16 InputReportByteLength; internal Int16 OutputReportByteLength; internal Int16 FeatureReportByteLength; [ MarshalAs( UnmanagedType.ByValArray, SizeConst=17 ) ] internal Int16[] Reserved; internal Int16 NumberLinkCollectionNodes; internal Int16 NumberInputButtonCaps; internal Int16 NumberInputValueCaps; internal Int16 NumberInputDataIndices; internal Int16 NumberOutputButtonCaps; internal Int16 NumberOutputValueCaps; internal Int16 NumberOutputDataIndices; internal Int16 NumberFeatureButtonCaps; internal Int16 NumberFeatureValueCaps; internal Int16 NumberFeatureDataIndices; } [ DllImport( "hid.dll", SetLastError=true ) ] internal static extern Int32 HidP_GetCaps ( IntPtr PreparsedData, ref HIDP_CAPS Capabilities ); Use internal HIDP_CAPS Capabilities; Int32 result = 0; result = HidP_GetCaps( preparsedData, ref Capabilities ); &GVCKNU The preparsedData parameter is the pointer returned by HidD_GetPreparsedData. When the function returns, the application can examine and use whatever values are of interest in the Capabilities structure. For example, to look for a joystick, look for UsagePage = 0001h and Usage = 0004h. The ReportByteLength items are useful when setting buffer sizes for sending and receiving reports. Human Interface Devices: Host Application 327 )GVVKPIVJG%CRCDKNKVKGUQHVJG$WVVQPUCPF8CNWGU An application can also retrieve the capabilities of each button and value in a report. HidP_GetValueCaps returns a pointer to an array of structures contain- ing information about the values in a report. The NumberInputValueCaps property of the HIDP_CAPS structure is the number of structures returned by HidP_GetValueCaps. The items in the structures include many values obtained from the HID’s report descriptor as described in Chapter 12. The items include the Report ID, whether a value is absolute or relative, whether a value has a null state, and log- ical and physical minimums and maximums. A LinkCollection identifier dis- tinguishes between controls with the same Usage and Usage Page in the same collection. In a similar way, the HidP_GetButtonCaps function can retrieve information about a report’s buttons. The information is stored in a HidP_ButtonCaps structure. Not every application needs to retrieve this infor- mation. 5GPFKPICPF4GEGKXKPI4GRQTVU The previous API functions help in finding and learning about a device that matches what the application is looking for. On finding a device of interest, the application and device are ready to exchange data in reports. Table 13-3 showed API functions for exchanging reports. Table 13-6 summa- rizes the transfer types the host uses with different report types. The application doesn’t have to know or care which transfer type or endpoint the driver uses. Table 13-6: The transfer type used to send or receive a report can vary with the API function, operating system edition, and available endpoints. 4GRQTV6[RG #2+(WPEVKQP 6TCPUHGT6[RG Input ReadFile Interrupt IN HidD_GetInputReport (Windows XP and later) Control with Get Report request Output WriteFile Interrupt OUT if available; otherwise control with Set Report request HidD_SetOutputReport (Windows XP and later) Control with Set Report request Feature IN HidD_GetFeature Control with Get Report request Feature OUT HidD_SetFeature Control with Set Report request Chapter 13 328 5GPFKPICP1WVRWV4GRQTVVQVJG&GXKEG On obtaining a handle and learning the number of bytes in an Output report, an application can send a report to the HID. The application places the data to send in a buffer and calls WriteFile. 8$ Definitions <DllImport("kernel32.dll", SetLastError:=True)> _ Shared Function WriteFile _ (ByVal hFile As SafeFileHandle, _ ByVal lpBuffer() As Byte, _ ByVal nNumberOfBytesToWrite As Int32, _ ByRef lpNumberOfBytesWritten As Int32, _ ByVal lpOverlapped As IntPtr) _ As Boolean End Function Use Dim numberOfBytesWritten As Int32 = 0 Dim outputReportBuffer() As Byte = Nothing Dim success As Boolean ' Set the size of the Output report buffer. Array.Resize(outputReportBuffer, Capabilities.OutputReportByteLength) ' Store the Report ID in the first byte of the buffer: outputReportBuffer(0) = 0 ' Store the report data following the Report ID. Example: outputReportBuffer(1) = 85 outputReportBuffer(2) = 83 outputReportBuffer(3) = 66 ' Send the report. success = WriteFile _ (deviceHandle, _ outputReportBuffer, _ outputReportBuffer.Length, _ numberOfBytesWritten, _ IntPtr.Zero) Human Interface Devices: Host Application 329 8% Definitions [ DllImport( "kernel32.dll", SetLastError=true ) ] internal static extern Boolean WriteFile ( SafeFileHandle hFile, Byte[] lpBuffer, Int32 nNumberOfBytesToWrite, ref Int32 lpNumberOfBytesWritten, IntPtr lpOverlapped ); Use Int32 numberOfBytesWritten = 0; Byte[] outputReportBuffer = null; Boolean success = false; // Set the size of the Output report buffer. Array.Resize(ref outFeatureReportBuffer, Capabilities.FeatureReportByteLength); // Store the Report ID in the first byte of the buffer: outputReportBuffer[ 0 ] = 0; // Store the report data following the Report ID. Example: outputReportBuffer[ 1 ] = 85; outputReportBuffer[ 2 ] = 83; outputReportBuffer[ 3 ] = 66; // Send the report. success = WriteFile (deviceHandle, outputReportBuffer, outputReportBuffer.Length, ref numberOfBytesWritten, IntPtr.Zero); &GVCKNU In the call to WriteFile, the hFile parameter is a handle returned by CreateFile. The lpBuffer parameter is a byte array that contains the report ID followed by the report data. The nNumberOfBytesToWrite parameter specifies how many bytes to write and should equal the OutputReportByteLength property of the Chapter 13 330 HIDP_CAPS structure retrieved with HidP_GetCaps. This value is the report size in bytes plus one byte for the Report ID. The lpOverlapped parameter is a null pointer in this example, but WriteFile can use overlapped I/O as described in the following section on ReadFile. Over- lapped I/O can prevent the application’s thread from hanging if the HID’s interrupt OUT endpoint NAKs endlessly. In normal operation, the endpoint should accept received data with little delay. On success, the function returns true with lpNumberOfBytesWritten pointing to the number of bytes the function wrote to the HID. If the interface supports only the default Report ID of zero, the Report ID doesn’t transmit on the bus, but the Report ID must always be the first byte in the buffer the application passes to WriteFile. When sending a report to an interrupt endpoint, WriteFile returns on success or error and will wait endlessly if the endpoint continues to NAK the report data. When sending a report via the control endpoint, WriteFile returns on suc- cess, an error, or a timeout if the endpoint continues to NAK the report data. A returned error message of CRC Error indicates that the host controller attempted to send the report, but the device didn’t respond as expected. Despite the message, the problem isn’t likely to be due to an error detected in a CRC calculation. The error is more likely to be due to a firmware problem that keeps the endpoint from accepting the report data. If WriteFile doesn’t return at all, the interrupt OUT endpoint possibly isn’t configured to ACK the report data. 4GCFKPICP+PRWV4GRQTVHTQOVJG&GXKEG The complement to WriteFile is ReadFile. After obtaining a handle to the HID interface and learning the size of the largest Input report, an application can use ReadFile to read an Input report from a device. When called using non-overlapped I/O, ReadFile is a blocking call. If an appli- cation calls the function when the HID driver’s Input buffer is empty, the call- ing thread waits until a report is available, the user closes the application from the Task Manager, or the user removes the device from the bus. An overlapped, or asynchronous, read operation can keep an application’s main thread from hanging as it waits for a report. With an overlapped read, ReadFile returns immediately whether a report is available or not. If the function doesn’t return a report, the application can call WaitForSingleObject with a specified timeout. WaitForSingleObject returns Human Interface Devices: Host Application 331 when a report is available or on a timeout or other error. On a timeout or error, the application can try again or call the CancelIo function to cancel the read operation. This approach works well if reports are normally available without delay but the application needs to regain control if for some reason there is no report. To prevent long delays waiting for WaitForSingleObject to return, an applica- tion can set the timeout to zero and call the function repeatedly in a loop or at intervals, triggered by a timer. The function returns immediately whether or not a report is available, and the application can perform other tasks in the loop or between timer events. To improve performance, an application can call ReadFile in a separate thread that notifies the main thread when a report is available. A .NET application can define an asynchronous delegate and use the BeginInvoke method to call a method that calls ReadFile in a different thread. BeginInvoke can specify a call- back routine that executes in the application’s main thread when the method that has called ReadFile returns. The callback routine can retrieve the returned report and use the received data as needed. This example uses overlapped reads with a timeout: 8$ Definitions Friend Const FILE_FLAG_OVERLAPPED As Int32 = &H40000000 Friend Const GENERIC_READ As UInt32 = &H80000000UL Friend Const GENERIC_WRITE As UInt32 = &H40000000 Friend Const WAIT_OBJECT_0 As Int32 = 0 Friend Const WAIT_TIMEOUT As Int32 = &H102 <DllImport("kernel32.dll", SetLastError:=True)> _ Shared Function CancelIo _ (ByVal hFile As SafeFileHandle) _ As Int32 End Function <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ Shared Function CreateEvent _ (ByVal SecurityAttributes As IntPtr, _ ByVal bManualReset As Boolean, _ ByVal bInitialState As Boolean, _ ByVal lpName As String) _ As IntPtr End Function Chapter 13 332 <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ Shared Function GetOverlappedResult _ (ByVal hFile As SafeFileHandle, _ ByVal lpOverlapped As IntPtr, _ ByRef lpNumberOfBytesTransferred As Int32, _ ByVal bWait As Boolean) _ As Boolean End Function <DllImport("kernel32.dll", SetLastError:=True)> _ Shared Function ReadFile _ (ByVal hFile As SafeFileHandle, _ ByVal lpBuffer As IntPtr, _ ByVal nNumberOfBytesToRead As Int32, _ ByRef lpNumberOfBytesRead As Int32, _ ByVal lpOverlapped As IntPtr) _ As Boolean End Function <DllImport("kernel32.dll", SetLastError:=True)> _ Shared Function WaitForSingleObject _ (ByVal hHandle As IntPtr, _ ByVal dwMilliseconds As Int32) _ As Int32 End Function Use Dim eventObject As IntPtr Dim HidOverlapped As New NativeOverlapped Dim inputReportBuffer() As Byte = Nothing Dim numberOfBytesRead As Int32 Dim result As Int32 Dim success As Boolean Dim unManagedBuffer As IntPtr Dim unManagedOverlapped As IntPtr Array.Resize(inputReportBuffer, Capabilities.InputReportByteLength) Human Interface Devices: Host Application 333 eventObject = CreateEvent (IntPtr.Zero, False, False, String.Empty) HidOverlapped.OffsetLow = 0 HidOverlapped.OffsetHigh = 0 HidOverlapped.EventHandle = eventObject unManagedBuffer = Marshal.AllocHGlobal(inputReportBuffer.Length) unManagedOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(HidOverlapped)) Marshal.StructureToPtr(HidOverlapped, unManagedOverlapped, False) readHandle = CreateFile _ (devicePathName, _ GENERIC_READ, _ FILE_SHARE_READ Or FILE_SHARE_WRITE, _ IntPtr.Zero, _ OPEN_EXISTING, _ FILE_FLAG_OVERLAPPED, _ 0) success = ReadFile _ (readHandle, _ unManagedBuffer, _ inputReportBuffer.Length, _ numberOfBytesRead, _ unManagedOverlapped) Chapter 13 334 ' If ReadFile returned True, a report is available. Otherwise, check for completion. If Not (success) Then result = WaitForSingleObject(eventObject, 3000) Select Case result Case WAIT_OBJECT_0 success = True GetOverlappedResult _ (readHandle, _ unManagedOverlapped, _ numberOfBytesRead, _ False) Case WAIT_TIMEOUT CancelIo(readHandle) Case Else CancelIo(readHandle) End Select End If If success Then ' A report was received. ' Copy the received data to inputReportBuffer for the application to use. Marshal.Copy _ (unManagedBuffer, inputReportBuffer, 0, numberOfBytesRead) End If Marshal.FreeHGlobal(unManagedOverlapped) Marshal.FreeHGlobal(unManagedBuffer) 8% Definitions internal const Int32 FILE_FLAG_OVERLAPPED = 0X40000000; internal const UInt32 GENERIC_READ = 0X80000000;; internal const UInt32 GENERIC_WRITE = 0X40000000; internal const Int32 WAIT_OBJECT_0 = 0; internal const Int32 WAIT_TIMEOUT = 0X102; Human Interface Devices: Host Application 335 [ DllImport( "kernel32.dll", SetLastError=true ) ] internal static extern Int32 CancelIo ( SafeFileHandle hFile ); [ DllImport( "kernel32.dll", CharSet=CharSet.Auto, SetLastError=true ) ] internal static extern IntPtr CreateEvent ( IntPtr SecurityAttributes, Boolean bManualReset, Boolean bInitialState, String lpName ); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern Boolean GetOverlappedResult (SafeFileHandle hFile, IntPtr lpOverlapped, ref Int32 lpNumberOfBytesTransferred, Boolean bWait); [ DllImport( "kernel32.dll", SetLastError=true ) ] internal static extern Boolean ReadFile ( SafeFileHandle hFile, IntPtr lpBuffer, Int32 nNumberOfBytesToRead, ref Int32 lpNumberOfBytesRead, IntPtr lpOverlapped ); [ DllImport( "kernel32.dll", SetLastError=true ) ] internal static extern Int32 WaitForSingleObject ( IntPtr hHandle, Int32 dwMilliseconds ); Use IntPtr eventObject= IntPtr.Zero; NativeOverlapped HidOverlapped = new NativeOverlapped(); Byte[] inputReportBuffer = null; Int32 numberOfBytesRead = 0; Int32 result = 0; Boolean success = false; IntPtr unManagedBuffer = IntPtr.Zero; IntPtr unManagedOverlapped = IntPtr.Zero; Array.Resize(ref inputReportBuffer, Capabilities.InputReportByteLength);

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

TỪ KHÓA LIÊN QUAN

w