📄 usbhid.h
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
usbhid.h
Abstract:
USB Client Driver for Human Interface Device (HID) Class.
Functions:
Notes:
--*/
#ifndef _USBHID_H_
#define _USBHID_H_
#include <windows.h>
#include <usbdi.h>
//#include "usbclient.h"
//#include "utils.h"
#include "hidpddi.h"
#include "hiddbg.h"
#include "queue.h"
#include "hiddi.h"
#define DRIVER_NAME _T("USBHID.DLL")
#define DEVICE_PREFIX _T("HID")
#define CLASS_NAME_SZ _T("Hid_Class")
#define CLIENT_REGKEY_SZ _T("Drivers\\USB\\ClientDrivers\\") CLASS_NAME_SZ
#define DEFAULT_SZ _T("Default")
#define LOAD_CLIENTS_PATH_SZ _T("Drivers\\HID\\LoadClients")
#define DLL_VALUE_SZ _T("Dll")
#define USB_HID_SIG 'HBSU' // "USBH" tag
#define USB_HID_CLIENT_SIG 'CDIH' // "HIDC" tag
#define MANUAL_RESET_EVENT TRUE
#define AUTO_RESET_EVENT FALSE
// Class-specific definitions (from the HID specification).
// Must use IssueVendorTransfer to make these requests.
#define USB_REQUEST_HID_GET_REPORT 0x01
#define USB_REQUEST_HID_GET_IDLE 0x02
#define USB_REQUEST_HID_GET_PROTOCOL 0x03
#define USB_REQUEST_HID_SET_REPORT 0x09
#define USB_REQUEST_HID_SET_IDLE 0x0A
#define USB_REQUEST_HID_SET_PROTOCOL 0x0B
#define HID_DESCRIPTOR_TYPE 0x21
#define HID_REPORT_DESCRIPTOR_TYPE 0x22
#define HID_INTERFACE_NO_SUBCLASS 0x00
#define HID_INTERFACE_BOOT_SUBCLASS 0x01
#define HID_BOOT_PROTOCOL 0x00
#define HID_REPORT_PROTOCOL 0x01
#pragma pack (1)
typedef struct _HID_DESCRIPTOR
{
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdHID;
UCHAR bCountryCode;
UCHAR bNumDescriptors;
UCHAR bClassDescriptorType;
USHORT wDescriptorLength;
} HID_DESCRIPTOR, *PHID_DESCRIPTOR;
#pragma pack ()
typedef struct _FLAGS {
UCHAR Open : 1; // bits 0
UCHAR UnloadPending : 1; // bits 1
UCHAR Reserved : 6; // bits 2-7
} FLAGS, *PFLAGS;
struct _HID_CLIENT_HANDLE;
//
// Our notion of a Pipe
//
typedef struct _PIPE {
//
// USB Pipe handle received from the stack
//
USB_PIPE hPipe;
//
// Endpoint's Address
//
UCHAR bIndex;
//
// Endpoint's wMaxPacketSize
//
USHORT wMaxPacketSize;
//
// Completion Event
//
HANDLE hEvent;
} PIPE, *PPIPE;
typedef struct _USBHID_CONTEXT {
//
// We use a Signature (defined above) for validation
//
ULONG Sig;
//
// sync object for this instance
//
CRITICAL_SECTION csLock;
#ifdef DEBUG
// The current depth of csLock
INT cInCS;
#endif
//
// USB handle to the device
//
USB_HANDLE hUsbDevice;
//
// USBD Function table
//
LPCUSB_FUNCS pUsbFuncs;
//
// Fields from USB_INTERFACE that we need
//
LPCUSB_INTERFACE pUsbInterface;
//
// Interrupt In Pipe
//
PIPE InterruptIn;
//
// completion signal used for endpoint 0 (control)
//
HANDLE hEP0Event;
//
// Signals the device has been closed.
//
HANDLE hThread;
//
// FLAGS
//
FLAGS Flags;
// Regarding fSendToInterface. The original HID spec said that the Hid
// descriptor would come after the interface and endpoint descriptors.
// It also said that class specific commands should be sent to the endpoint.
// The next spec said that the HID descriptor would come after the interface
// descriptor (not at the end) and that commands should be sent to the
// interface, not to the endpoint. So, I'm assuming that if I find the
// Hid descriptor after the interface, the device is following the new spec
// and I should send commands to the interface. Otherwise, I'll send them
// to the endpoint, as stated in the old spec.
BOOL fSendToInterface;
// Our parsed report descriptor data
PHIDP_DEVICE_DESC phidpDeviceDesc;
// The queues used to send data to HID clients
HidTLCQueue *pQueues;
// The structures passed to HID clients as a handle
_HID_CLIENT_HANDLE *pClientHandles;
} USBHID_CONTEXT, *PUSBHID_CONTEXT;
//
// Is the pointer a valid PUSBHID_CONTEXT
//
#define VALID_CONTEXT( p ) \
( p && (USB_HID_SIG == p->Sig) )
// This is what gets passed to HID clients as a handle
typedef struct _HID_CLIENT_HANDLE {
// We use a Signature (defined above) for validation
ULONG Sig;
HINSTANCE hInst;
LPVOID lpvNotifyParameter;
PUSBHID_CONTEXT pUsbHid;
PHIDP_PREPARSED_DATA phidpPreparsedData;
HidTLCQueue *pQueue;
HID_DRIVER_SETTINGS driverSettings;
LPVOID lpvContext;
} HID_CLIENT_HANDLE, *PHID_CLIENT_HANDLE;
// Is the pointer a valid PHID_CLIENT_HANDLE
#define VALID_CLIENT_HANDLE( p ) \
( p && (USB_HID_CLIENT_SIG == p->Sig) )
// The size in bytes of the global array of devices
#define HID_ARRAY_BYTE_SIZE(count) (sizeof(PUSBHID_CONTEXT) * count)
//
// USB_DRIVER_SETTINGS
//
// As specified in the HID spec, HID class devices are identified in
// the interface descriptor, so we only need to specify the
// dwInterfaceClass field.
//
#define DRIVER_SETTINGS \
sizeof(USB_DRIVER_SETTINGS), \
USB_NO_INFO, \
USB_NO_INFO, \
USB_NO_INFO, \
USB_NO_INFO, \
USB_NO_INFO, \
USB_NO_INFO, \
USB_DEVICE_CLASS_HUMAN_INTERFACE, \
USB_NO_INFO, \
USB_NO_INFO
#define RegOpenKey(hkey, lpsz, phk) \
RegOpenKeyEx((hkey), (lpsz), 0, 0, (phk))
#ifdef DEBUG
//
// ***** Debug utility functions *****
//
HLOCAL
HidAlloc(
SIZE_T cb
);
HLOCAL
HidFree(
LPVOID ptr
);
BOOL
IsHidDataLocked(
void
);
void
LockHidData(
void
);
// Leaves the global access cs
void
ReleaseHidData(
void
);
BOOL
IsHidContextLocked(
const USBHID_CONTEXT *pUsbHid
);
void
LockHidContext(
USBHID_CONTEXT *pUsbHid
);
void
ReleaseHidContext(
USBHID_CONTEXT *pUsbHid
);
void
ValidateHidContext(
PUSBHID_CONTEXT pUsbHid
);
void
ValidateHidGlobals(
void
);
void
ValidateClientHandle(
PHID_CLIENT_HANDLE pHidClient
);
void
DumpHIDDeviceDescription(
const HIDP_DEVICE_DESC *phidpDeviceDesc
);
// Data dumping macros
#define DUMP_USB_DEVICE_DESCRIPTOR( d ) { \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("USB_DEVICE_DESCRIPTOR:\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("----------------------\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bLength: 0x%x\n"), d.bLength )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bDescriptorType: 0x%x\n"), d.bDescriptorType )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bcdUSB: 0x%x\n"), d.bcdUSB )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bDeviceClass: 0x%x\n"), d.bDeviceClass )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bDeviceSubClass: 0x%x\n"), d.bDeviceSubClass )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bDeviceProtocol: 0x%x\n"), d.bDeviceProtocol )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bMaxPacketSize0: 0x%x\n"), d.bMaxPacketSize0 )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("idVendor: 0x%x\n"), d.idVendor )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("idProduct: 0x%x\n"), d.idProduct )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bcdDevice: 0x%x\n"), d.bcdDevice )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("iManufacturer: 0x%x\n"), d.iManufacturer )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("iProduct: 0x%x\n"), d.iProduct )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("iSerialNumber: 0x%x\n"), d.iSerialNumber )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bNumConfigurations: 0x%x\n"), d.bNumConfigurations )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("\n"))); \
}
#define DUMP_USB_CONFIGURATION_DESCRIPTOR( c ) { \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("USB_CONFIGURATION_DESCRIPTOR:\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("-----------------------------\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bLength: 0x%x\n"), c.bLength )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bDescriptorType: 0x%x\n"), c.bDescriptorType )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("wTotalLength: 0x%x\n"), c.wTotalLength )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bNumInterfaces: 0x%x\n"), c.bNumInterfaces )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bConfigurationValue: 0x%x\n"), c.bConfigurationValue )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("iConfiguration: 0x%x\n"), c.iConfiguration )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bmAttributes: 0x%x\n"), c.bmAttributes )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("MaxPower: 0x%x\n"), c.MaxPower )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("\n"))); \
}
#define DUMP_USB_INTERFACE_DESCRIPTOR( i, _index ) { \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("USB_INTERFACE_DESCRIPTOR[%d]:\n"), _index )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("-------------------------\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bLength: 0x%x\n"), i.bLength )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bDescriptorType: 0x%x\n"), i.bDescriptorType )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bInterfaceNumber: 0x%x\n"), i.bInterfaceNumber )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bAlternateSetting: 0x%x\n"), i.bAlternateSetting )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bNumEndpoints: 0x%x\n"), i.bNumEndpoints )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bInterfaceClass: 0x%x\n"), i.bInterfaceClass )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bInterfaceSubClass: 0x%x\n"), i.bInterfaceSubClass )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bInterfaceProtocol: 0x%x\n"), i.bInterfaceProtocol )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("iInterface: 0x%x\n"), i.iInterface )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("\n"))); \
}
#define DUMP_USB_ENDPOINT_DESCRIPTOR( e ) { \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("USB_ENDPOINT_DESCRIPTOR:\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("-----------------------------\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bLength: 0x%x\n"), e.bLength )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bDescriptorType: 0x%x\n"), e.bDescriptorType )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bEndpointAddress: 0x%x\n"), e.bEndpointAddress )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bmAttributes: 0x%x\n"), e.bmAttributes )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("wMaxPacketSize: 0x%x\n"), e.wMaxPacketSize )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bInterval: 0x%x\n"), e.bInterval ));\
DEBUGMSG( ZONE_USB_PARSE, (TEXT("\n"))); \
}
#define DUMP_USB_HID_DESCRIPTOR( h ) { \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("USB_HID_DESCRIPTOR:\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("-----------------------------\n"))); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bLength: 0x%x\n"), h.bLength )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bDescriptorType: 0x%x\n"), h.bDescriptorType )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bcdHID: 0x%x\n"), h.bcdHID )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bCountryCode: 0x%x\n"), h.bCountryCode )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bNumDescriptors: 0x%x\n"), h.bNumDescriptors )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("bClassDescriptorType: 0x%x\n"), h.bClassDescriptorType )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("wDescriptorLength: 0x%x\n"), h.wDescriptorLength )); \
DEBUGMSG( ZONE_USB_PARSE, (TEXT("\n"))); \
}
#else
#define LockHidData() EnterCriticalSection(&g_csHidLock)
#define ReleaseHidData() LeaveCriticalSection(&g_csHidLock)
#define ValidateHidGlobals()
#define ValidateHidContext(ptr)
#define ValidateClientHandle(ptr)
#define DumpHIDDeviceDescription(x)
#define LockHidContext(x) EnterCriticalSection(&x->csLock);
#define ReleaseHidContext(x) LeaveCriticalSection(&x->csLock);
#define HidAlloc(cb) LocalAlloc(LMEM_FIXED, cb)
#define HidFree(ptr) LocalFree(ptr)
#define DUMP_USB_DEVICE_DESCRIPTOR( p )
#define DUMP_USB_CONFIGURATION_DESCRIPTOR( c )
#define DUMP_USB_INTERFACE_DESCRIPTOR( i, index )
#define DUMP_USB_ENDPOINT_DESCRIPTOR( e )
#define DUMP_USB_HID_DESCRIPTOR( h )
#endif // DEBUG
#endif // _USBHID_H_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -