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

USB Complete fourth- P36 docx

10 164 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

4GRQTV6[RG #2+WPEVKQP 6TCPUHGT6[RG Input ReadFile Interrupt IN HidD_GetInputReport Windows XP and later Control with Get Report request Output WriteFile Interrupt OUT if available; other

Trang 1

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

T h e p r e p a r s e d D a t a p a r a m e t e r i s t h e p o i n t e r r e t u r n e d b y 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.

Trang 2

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 physlog-ical 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.

5GPFKPICPF4GEGKXKPI4GRQTVU

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 4GRQTV6[RG #2+(WPEVKQP 6TCPUHGT6[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

Trang 3

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)

Trang 4

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

Trang 5

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.

4GCFKPICP+PRWV4GRQTVHTQOVJG&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

Trang 6

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 funcapplica-tion 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

Trang 7

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

Trang 8

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)

Trang 9

' 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;

Trang 10

[ 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