📄 hid.hpp
字号:
/*++
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.
Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
Module Name:
hid.hpp
Abstract:
USB Human Interface Device (HID) class driver sample.
Functions:
Notes:
--*/
#ifndef _HID_HPP_
#define _HID_HPP_
// Make sure we know about DirectInput
#include <hiddi.hpp>
// Debug zone defs
#ifdef DEBUG
#define ZONE_INIT DEBUGZONE(0)
#define ZONE_ATTACH DEBUGZONE(1)
#define ZONE_CONFIG DEBUGZONE(2)
#define ZONE_REPORT DEBUGZONE(3)
#define ZONE_MOUSE DEBUGZONE(4)
#define ZONE_KEYBD DEBUGZONE(5)
#define ZONE_JOYSTICK DEBUGZONE(6)
#define ZONE_EVENTS DEBUGZONE(7)
#define ZONE_FUNCTION DEBUGZONE(13)
#define ZONE_WARNING DEBUGZONE(14)
#define ZONE_ERROR DEBUGZONE(15)
#endif
#define UnusedParameter(x) x = x
// There is a bug in the version of OHCI.DLL shipped in CE 2.1 where the HID class
// descriptor is not returned if it appears after the endpoint descriptors. Include
// code to work around this in case we distribute a HID driver as an add on for 2.1.
#define OHCI_DESC_BUG_WORKAROUND 1
const DWORD gcBitsPerByte = 8;
const DWORD gcBitsPerInt32 = 32;
const DWORD gcJoyRepeatTimeMS = 6;
const DWORD gcKeyFirstRepeatTimeMS = 400;
const DWORD gcKeyRepeatTimeMS = 50;
const UINT gcInitialMaxNumDevices = 4;
const BYTE gcInvalidOffset = 0xFF;
const UINT gcConfigStatusNewDevice = 0;
const UINT gcConfigStatusGettingConfigDesc = 1;
const UINT gcConfigStatusGettingReport = 2;
const UINT gcConfigStatusConfigured = 3;
const UINT gcSignalStatusNone = 0x00;
const UINT gcSignalStatusCtrlPending = 0x01;
const UINT gcSignalStatusIntrPending = 0x02;
const UINT gcSignalStatusCtrlSignaled = 0x04;
const UINT gcSignalStatusIntrSignaled = 0x08;
const UINT gcSignalStatusIntr = gcSignalStatusIntrPending | gcSignalStatusIntrSignaled;
const UINT gcSignalStatusCtrl = gcSignalStatusCtrlPending | gcSignalStatusCtrlSignaled;
// 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
#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 ()
struct SParseState;
struct SDataDescription;
//struct SDiData;
struct SHidDevice
{
USB_HANDLE hDevice;
USB_PIPE hIntrPipe;
USB_TRANSFER hIntrTransfer;
USB_TRANSFER hCtrlTransfer;
DWORD dwId; // despite that this is a dword, DirectInput expects it to fit in 16 bits.
UINT configStatus;
UINT signalStatus;
PBYTE pDataBuffer;
UINT dataBufferSize;
BOOL bValid;
UINT intrBufferSize;
UCHAR bConfigurationValue;
UCHAR bMaxPacketSize;
USHORT wReportDescriptorLength;
BOOL bSendToInterface;
UCHAR endptOrIntrNum;
BOOL bRepeating;
DWORD dwRepeatDeadline;
WORD wDeviceUsagePage;
WORD wDeviceUsage;
DWORD dwDeviceType;
int attachCount;
BOOL bAcquired;
BOOL bHaveFormat;
DWORD dwBufCount;
HANDLE hDIWakeup;
CRITICAL_SECTION csLock;
PBYTE pUserData;
DWORD userDataSize;
SDataDescription *pstDataDescriptionHead;
ULONG LedState;
};
class CHid
{
public:
CHid();
~CHid();
BOOL Initialize(LPCUSB_FUNCS lpUsbFuncs);
static ULONG CALLBACK
HidThreadStub(
PVOID context);
static DWORD CALLBACK
ControlCompletionStub(
LPVOID lpvNotifyParameter);
static DWORD CALLBACK
InterruptCompletionStub(
LPVOID lpvNotifyParameter);
SHidDevice *
HidNewDevice(
USB_HANDLE hDevice,
LPCUSB_INTERFACE lpInterface,
UCHAR bMaxPacketSize0);
BOOL
IOControl(
DWORD dwCode,
PBYTE pInpBuf, DWORD dwInpLen,
PBYTE pOutBuf, DWORD dwOutLen, PDWORD pdwActualOutLen);
BOOL
HidCloseDevice(
SHidDevice *pHidDevice);
UINT m_curDevices;
private:
BOOL
ParseReportDescriptor(
SHidDevice *pstHidDevice);
BOOL
ParseMouse(
SParseState *pstState,
UINT8 type,
UINT32 data);
BOOL
ParseKeyboard(
SParseState *pstState,
UINT8 type,
UINT32 data);
BOOL
ParseJoystick(
SParseState *pstState,
UINT8 type,
UINT32 data);
SDataDescription*
AllocateDescriptionStruct(
SDataDescription **ppstDataDescriptionHead);
SDataDescription*
DeallocateDescriptionStruct(
SDataDescription *pstDataDescription);
#ifdef OHCI_DESC_BUG_WORKAROUND
BOOL
GetConfigDesc(
SHidDevice *pstHidDevice,
UINT size);
BOOL
ParseConfigDesc(
SHidDevice *pstHidDevice);
#endif
BOOL
SetReport(
SHidDevice *pstHidDevice,
DWORD reportId,
PVOID pData,
WORD lenData);
BOOL
SetIdle(
SHidDevice *pstHidDevice,
DWORD reportId,
DWORD idleRateMS);
// A misnomer. This really gets the Report Descriptor.
BOOL
GetReport(
SHidDevice *pstHidDevice);
BOOL
SubmitInterrupt(
SHidDevice *pstHidDevice);
BOOL
InterpretData(
SHidDevice *pstHidDevice);
DWORD
ConvertDataToDword(
UINT startBit,
UINT length,
BOOL bSigned,
BYTE *pBuffer);
BOOL
InterpretDataAsJoystick(
SHidDevice *pstHidDevice,
PBYTE pDataBuffer,
SDataDescription *pstData);
BOOL
InterpretDataAsMouse(
SHidDevice *pstHidDevice,
PBYTE pDataBuffer,
SDataDescription *pstData);
BOOL
InterpretDataAsKeyboard(
SHidDevice *pstHidDevice,
PBYTE pDataBuffer,
SDataDescription *pstData);
BOOL
HandleRepeat(
SHidDevice *pstHidDevice);
BOOL
KeyboardRepeat(
SHidDevice *pstHidDevice,
SDataDescription *pstData);
BOOL
HandleUnplug(
SHidDevice *pstHidDevice);
BOOL
KeyboardUnplug(
SHidDevice *pstHidDevice,
SDataDescription *pstData);
void
HandleChordKeys(
SHidDevice *pstHidDevice,
UINT8 data,
SDataDescription *pstData);
void
HandleArrayKeys(
SHidDevice *pstHidDevice,
PUCHAR data,
SDataDescription *pstData);
void
KeyboardEvent(
UINT8 vkCode,
BOOL bDown);
// Helper methods to implement ioctls for DirectInput
BOOL EnumerateDevices (PBYTE inbuf, DWORD inlen, PBYTE buf, DWORD len, PDWORD retlen);
BOOL EnumerateObjects (PBYTE inbuf, DWORD inlen, PBYTE buf, DWORD len, PDWORD retlen);
BOOL SetFormat (PBYTE inbuf, DWORD inlen, PBYTE buf, DWORD len, PDWORD retlen);
BOOL TransferEvent (PBYTE inbuf, DWORD inlen, PBYTE buf, DWORD len, PDWORD retlen);
BOOL UserAttach (PBYTE inbuf, DWORD inlen, PBYTE buf, DWORD len, PDWORD retlen);
BOOL GetUserData (PBYTE inbuf, DWORD inlen, PBYTE buf, DWORD len, PDWORD retlen);
BOOL Acquire (PBYTE inbuf, DWORD inlen, PBYTE buf, DWORD len, PDWORD retlen);
// BOOL Poll (PBYTE inbuf, DWORD inlen, PBYTE buf, DWORD len, PDWORD retlen);
void DumpDataDescription(SDataDescription *pstData);
void ClearMouseAxes(SHidDevice *pstHidDevice);
DWORD SetTimeout();
DWORD HidThread(void);
LPCUSB_FUNCS m_lpUsbFuncs;
BOOL m_bClosing;
CRITICAL_SECTION m_csDeviceLock;
SHidDevice **m_ppDevices;
UINT m_curMaxNumDevices;
HANDLE m_hEvent;
HANDLE m_hThread;
HANDLE m_hOSDevice; // opaque: returned by ActivateDevice, passed to DeactivateDevice
};
const UINT gcMaxJoyAxes = 7;
const UINT gcMaxMouseAxes = 3;
const UINT gcXAxis = 0;
const UINT gcYAxis = 1;
const UINT gcZAxis = 2;
const UINT gcRxAxis = 3;
const UINT gcRyAxis = 4;
const UINT gcRzAxis = 5;
const UINT gcThrottleAxis = 6;
const UINT gcAxisToDITypeTable[] =
{
gcHiddiObjectTypeXAxis,
gcHiddiObjectTypeYAxis,
gcHiddiObjectTypeZAxis,
gcHiddiObjectTypeRxAxis,
gcHiddiObjectTypeRyAxis,
gcHiddiObjectTypeRzAxis,
gcHiddiObjectTypeSlider
};
const UINT gcJoyFirstAxisId = 0;
const UINT gcJoyPovId = gcMaxJoyAxes;
const UINT gcJoyFirstButtonId = gcJoyPovId + 1;
const UINT gcMouseFirstAxisId = 0;
const UINT gcMouseFirstButtonId = gcMaxMouseAxes;
// We want to report data as going from 0 to range. So we've set the
// offset to logicalMin, the min to 0 and the max to logicalMax - offset.
struct SAxisInfo
{
INT32 min;
INT32 max;
UINT16 wUsagePage;
UINT16 wUsage;
UINT8 startBit;
UINT8 length;
UINT8 offset;
};
//struct SDiData
//{
// DWORD dwTimestamp;
// PBYTE buffer;
// SDiData *pNext;
//};
const UINT gcHatIncrements = 36000;
struct SJoystickInfo
{
SAxisInfo *pAxes[gcMaxJoyAxes];
UINT8 buttonsStartBit;
UINT8 buttonsLength;
UINT8 altButtonsStartBit;
UINT8 altButtonsLength;
PBYTE pButtonOffsets;
UINT8 hatStartBit;
UINT8 hatLength;
UINT8 hatMin;
UINT8 hatMax;
UINT8 hatOffset;
};
struct SMouseInfo
{
SAxisInfo *pAxes[gcMaxMouseAxes];
PBYTE pButtonOffsets;
DWORD prevButtons;
UINT8 buttonsStartBit;
UINT8 buttonsLength;
};
const UINT gcMaxKeybdChordLength = 1; // byte
const UINT gcMaxKeybdChordEntries = gcMaxKeybdChordLength * 8; //8 bits per byte
// Assume a max of 8 simultaneous non-chord keys.
const BYTE gcKeyUserBufferSize = gcMaxKeybdChordEntries + 8;
struct SKeyboardInfo
{
UINT8 chordStartByte;
UINT8 chordLength;
UINT8 pressedChords;
UINT8 arrayStartByte;
UINT8 arrayLength;
UINT8 *pressedKeys;
UINT8 LastRepeated;
UINT8 numPressedKeys;
};
typedef BOOL
(CHid::*PFN_PARSE_HANDLER)(
SParseState *pstState,
UINT8 type,
UINT32 data);
const UINT gcDeviceTypeUndefined = 0;
const UINT gcDeviceTypeKeyboard = 1;
const UINT gcDeviceTypeMouse = 2;
const UINT gcDeviceTypeJoystick = 3;
struct SDataDescription
{
PFN_PARSE_HANDLER pfnParseHandler;
UINT deviceType;
UINT reportId;
SDataDescription *pNext;
union
{
SMouseInfo mouse;
SKeyboardInfo keybd;
SJoystickInfo joy;
};
};
const UINT gcMaxUsagesPerMain = 16;
struct SParseState
{
// Global items
UINT32 usagePage;
UINT32 reportSize;
UINT32 reportCount;
UINT32 reportId;
INT32 logicalMin;
INT32 logicalMax;
INT32 physicalMin;
INT32 physicalMax;
// Local items
UINT32 usage[gcMaxUsagesPerMain];
INT32 usageMin;
INT32 usageMax;
// Other
UINT32 curBit;
UINT32 nextFreeUsage;
SDataDescription *pstData;
SParseState *pNext;
};
inline void
CopyStateGlobals(
SParseState *to,
SParseState *from)
{
to->usagePage = from->usagePage;
to->reportSize = from->reportSize;
to->reportCount = from->reportCount;
to->reportId = from->reportId;
to->logicalMin = from->logicalMin;
to->logicalMax = from->logicalMax;
to->physicalMin = from->physicalMin;
to->physicalMax = from->physicalMax;
}
#endif // _HID_HPP_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -