mirror of
https://github.com/reactos/reactos.git
synced 2024-11-18 21:13:52 +00:00
547 lines
13 KiB
C
547 lines
13 KiB
C
/*
|
|
* ReactOS Hid User Library
|
|
* Copyright (C) 2004-2005 ReactOS Team
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
* PROJECT: ReactOS Hid User Library
|
|
* FILE: lib/hid/hid.c
|
|
* PURPOSE: ReactOS Hid User Library
|
|
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
|
|
*
|
|
* UPDATE HISTORY:
|
|
* 07/12/2004 Created
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <winbase.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
HINSTANCE hDllInstance;
|
|
|
|
/* device interface GUID for HIDClass devices */
|
|
const GUID HidClassGuid = {0x4D1E55B2, 0xF16F, 0x11CF, {0x88,0xCB,0x00,0x11,0x11,0x00,0x00,0x30}};
|
|
|
|
BOOL WINAPI
|
|
DllMain(HINSTANCE hinstDLL,
|
|
DWORD dwReason,
|
|
LPVOID lpvReserved)
|
|
{
|
|
switch(dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
hDllInstance = hinstDLL;
|
|
break;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_FlushQueue EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_FlushQueue(IN HANDLE HidDeviceObject)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_FLUSH_QUEUE,
|
|
NULL, 0,
|
|
NULL, 0,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_FreePreparsedData EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_FreePreparsedData(IN PHIDP_PREPARSED_DATA PreparsedData)
|
|
{
|
|
return (LocalFree((HLOCAL)PreparsedData) == NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetAttributes EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetAttributes(IN HANDLE HidDeviceObject,
|
|
OUT PHIDD_ATTRIBUTES Attributes)
|
|
{
|
|
HID_COLLECTION_INFORMATION hci;
|
|
DWORD RetLen;
|
|
|
|
if(!DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION,
|
|
NULL, 0,
|
|
&hci, sizeof(HID_COLLECTION_INFORMATION),
|
|
&RetLen, NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* copy the fields */
|
|
Attributes->Size = sizeof(HIDD_ATTRIBUTES);
|
|
Attributes->VendorID = hci.VendorID;
|
|
Attributes->ProductID = hci.ProductID;
|
|
Attributes->VersionNumber = hci.VersionNumber;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidP_GetButtonCaps EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
NTSTATUS WINAPI
|
|
HidP_GetButtonCaps(IN HIDP_REPORT_TYPE ReportType,
|
|
OUT PHIDP_BUTTON_CAPS ButtonCaps,
|
|
IN OUT PUSHORT ButtonCapsLength,
|
|
IN PHIDP_PREPARSED_DATA PreparsedData)
|
|
{
|
|
return HidP_GetSpecificButtonCaps(ReportType, 0, 0, 0, ButtonCaps,
|
|
ButtonCapsLength, PreparsedData);
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetFeature EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetFeature(IN HANDLE HidDeviceObject,
|
|
OUT PVOID ReportBuffer,
|
|
IN ULONG ReportBufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_FEATURE,
|
|
NULL, 0,
|
|
ReportBuffer, ReportBufferLength,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetHidGuid EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
VOID WINAPI
|
|
HidD_GetHidGuid(OUT LPGUID HidGuid)
|
|
{
|
|
*HidGuid = HidClassGuid;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetInputReport EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetInputReport(IN HANDLE HidDeviceObject,
|
|
IN OUT PVOID ReportBuffer,
|
|
IN ULONG ReportBufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INPUT_REPORT,
|
|
NULL, 0,
|
|
ReportBuffer, ReportBufferLength,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetManufacturerString EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetManufacturerString(IN HANDLE HidDeviceObject,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_MANUFACTURER_STRING,
|
|
NULL, 0,
|
|
Buffer, BufferLength,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetNumInputBuffers EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetNumInputBuffers(IN HANDLE HidDeviceObject,
|
|
OUT PULONG NumberBuffers)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS,
|
|
NULL, 0,
|
|
NumberBuffers, sizeof(ULONG),
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetPhysicalDescriptor EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetPhysicalDescriptor(IN HANDLE HidDeviceObject,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_GET_PHYSICAL_DESCRIPTOR,
|
|
NULL, 0,
|
|
Buffer, BufferLength,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetPreparsedData EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetPreparsedData(IN HANDLE HidDeviceObject,
|
|
OUT PHIDP_PREPARSED_DATA *PreparsedData)
|
|
{
|
|
HID_COLLECTION_INFORMATION hci;
|
|
DWORD RetLen;
|
|
BOOLEAN Ret;
|
|
|
|
if(PreparsedData == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if(!DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION,
|
|
NULL, 0,
|
|
&hci, sizeof(HID_COLLECTION_INFORMATION),
|
|
&RetLen, NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
*PreparsedData = LocalAlloc(LHND, hci.DescriptorSize);
|
|
if(*PreparsedData == NULL)
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
Ret = DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
|
|
NULL, 0,
|
|
*PreparsedData, hci.DescriptorSize,
|
|
&RetLen, NULL) != 0;
|
|
|
|
if(!Ret)
|
|
{
|
|
/* FIXME - Free the buffer in case we failed to get the descriptor? */
|
|
LocalFree((HLOCAL)*PreparsedData);
|
|
}
|
|
#if 0
|
|
else
|
|
{
|
|
/* should we truncate the memory in case RetLen < hci.DescriptorSize? */
|
|
}
|
|
#endif
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetProductString EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetProductString(IN HANDLE HidDeviceObject,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_PRODUCT_STRING,
|
|
NULL, 0,
|
|
Buffer, BufferLength,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_GetSerialNumberString EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetSerialNumberString(IN HANDLE HidDeviceObject,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_SERIALNUMBER_STRING,
|
|
NULL, 0,
|
|
Buffer, BufferLength,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidP_GetValueCaps EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
NTSTATUS WINAPI
|
|
HidP_GetValueCaps(IN HIDP_REPORT_TYPE ReportType,
|
|
OUT PHIDP_VALUE_CAPS ValueCaps,
|
|
IN OUT PUSHORT ValueCapsLength,
|
|
IN PHIDP_PREPARSED_DATA PreparsedData)
|
|
{
|
|
return HidP_GetSpecificValueCaps(ReportType, 0, 0, 0, ValueCaps,
|
|
ValueCapsLength, PreparsedData);
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_Hello EXPORTED
|
|
*
|
|
* Undocumented easter egg function. It fills the buffer with "Hello\n"
|
|
* and returns number of bytes filled in (lstrlen(Buffer) + 1 == 7)
|
|
*
|
|
* Bugs: - doesn't check Buffer for NULL
|
|
* - always returns 7 even if BufferLength < 7 but doesn't produce a buffer overflow
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
ULONG WINAPI
|
|
HidD_Hello(OUT PCHAR Buffer,
|
|
IN ULONG BufferLength)
|
|
{
|
|
const CHAR HelloString[] = "Hello\n";
|
|
|
|
if(BufferLength > 0)
|
|
{
|
|
memcpy(Buffer, HelloString, min(sizeof(HelloString), BufferLength));
|
|
}
|
|
|
|
return sizeof(HelloString);
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_SetFeature EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_SetFeature(IN HANDLE HidDeviceObject,
|
|
IN PVOID ReportBuffer,
|
|
IN ULONG ReportBufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_FEATURE,
|
|
ReportBuffer, ReportBufferLength,
|
|
NULL, 0,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_SetNumInputBuffers EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_SetNumInputBuffers(IN HANDLE HidDeviceObject,
|
|
IN ULONG NumberBuffers)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS,
|
|
&NumberBuffers, sizeof(ULONG),
|
|
NULL, 0,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* HidD_SetOutputReport EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_SetOutputReport(IN HANDLE HidDeviceObject,
|
|
IN PVOID ReportBuffer,
|
|
IN ULONG ReportBufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_OUTPUT_REPORT,
|
|
ReportBuffer, ReportBufferLength,
|
|
NULL, 0,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
/*
|
|
* HidD_GetIndexedString EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetIndexedString(IN HANDLE HidDeviceObject,
|
|
IN ULONG StringIndex,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INDEXED_STRING,
|
|
&StringIndex, sizeof(ULONG),
|
|
Buffer, BufferLength,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
/*
|
|
* HidD_GetMsGenreDescriptor EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetMsGenreDescriptor(IN HANDLE HidDeviceObject,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLength)
|
|
{
|
|
DWORD RetLen;
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_MS_GENRE_DESCRIPTOR,
|
|
0, 0,
|
|
Buffer, BufferLength,
|
|
&RetLen, NULL) != 0;
|
|
}
|
|
|
|
/*
|
|
* HidD_GetConfiguration EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_GetConfiguration(IN HANDLE HidDeviceObject,
|
|
OUT PHIDD_CONFIGURATION Configuration,
|
|
IN ULONG ConfigurationLength)
|
|
{
|
|
|
|
// magic cookie
|
|
Configuration->cookie = (PVOID)HidD_GetConfiguration;
|
|
|
|
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_DRIVER_CONFIG,
|
|
0, 0,
|
|
&Configuration->size, ConfigurationLength - sizeof(ULONG),
|
|
(PULONG)&Configuration->cookie, NULL) != 0;
|
|
}
|
|
|
|
/*
|
|
* HidD_SetConfiguration EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
BOOLEAN WINAPI
|
|
HidD_SetConfiguration(IN HANDLE HidDeviceObject,
|
|
IN PHIDD_CONFIGURATION Configuration,
|
|
IN ULONG ConfigurationLength)
|
|
{
|
|
BOOLEAN Ret = FALSE;
|
|
|
|
if (Configuration->cookie == (PVOID)HidD_GetConfiguration)
|
|
{
|
|
Ret = DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_DRIVER_CONFIG,
|
|
0, 0,
|
|
(PVOID)&Configuration->size, ConfigurationLength - sizeof(ULONG),
|
|
(PULONG)&Configuration->cookie, NULL) != 0;
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/*
|
|
* HidP_GetUsagesEx EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HIDAPI
|
|
NTSTATUS WINAPI
|
|
HidP_GetUsagesEx(IN HIDP_REPORT_TYPE ReportType,
|
|
IN USHORT LinkCollection,
|
|
OUT PUSAGE_AND_PAGE ButtonList,
|
|
IN OUT ULONG *UsageLength,
|
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
|
IN PCHAR Report,
|
|
IN ULONG ReportLength)
|
|
{
|
|
return HidP_GetUsages(ReportType, ButtonList->UsagePage, LinkCollection, &ButtonList->Usage, UsageLength, PreparsedData, Report, ReportLength);
|
|
}
|
|
|
|
|
|
/* EOF */
|