|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
pnp.c
Abstract:
This module contains the code for finding, adding, removing, and identifying hid devices.
Environment:
Kernel & user mode
Revision History:
Nov-96 : Created by Kenneth D. Ray
--*/
#include <basetyps.h>
#include <stdlib.h>
#include <wtypes.h>
#include <setupapi.h>
#include "hidsdi.h"
#include "hid.h"
#include "mylog.h"
#include "mymem.h"
PHID_DEVICE gpHidDevices = NULL;
LONG OpenHidDevice ( IN HDEVINFO HardwareDeviceInfo, IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IN OUT PHID_DEVICE HidDevice );
VOID CloseHidDevice ( IN OUT PHID_DEVICE HidDevice );
VOID AddHidDevice ( IN PHID_DEVICE HidDevice );
VOID RemoveHidDevice ( IN PHID_DEVICE HidDevice );
PHID_DEVICE FindHidDeviceByDevInst ( IN DWORD DevInst );
LONG FindKnownHidDevices ( OUT PHID_DEVICE *pHidDevices, OUT PULONG pNumberHidDevices ) /*++
Routine Description: Do the required PnP things in order to find all the HID devices in the system at this time. --*/ { HDEVINFO hardwareDeviceInfo; SP_DEVICE_INTERFACE_DATA hidDeviceInterfaceData; SP_DEVINFO_DATA hidDeviceInfoData; ULONG i; PHID_DEVICE hidDevice; GUID hidGuid; LONG lResult;
LOG((PHONESP_TRACE, "FindKnownHidDevices - enter"));
HidD_GetHidGuid (&hidGuid);
*pHidDevices = NULL; *pNumberHidDevices = 0;
//
// Open a handle to the dev info list
//
hardwareDeviceInfo = SetupDiGetClassDevs ( &hidGuid, NULL, // Define no enumerator (global)
NULL, // Define no
(DIGCF_PRESENT | // Only Devices present
DIGCF_INTERFACEDEVICE)); // Function class devices.
if(hardwareDeviceInfo == INVALID_HANDLE_VALUE) { return GetLastError(); }
//
// Mark all existing hid devices as removed. Any of these that are still present
// will have this mark removed during enumeration below.
//
hidDevice = gpHidDevices;
while (hidDevice != NULL) { //
// Include existing devices in out count of hid devices
//
(*pNumberHidDevices)++;
hidDevice->bRemoved = TRUE; hidDevice = hidDevice->Next; }
i = 0;
hidDeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
while (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo, 0, // No care about specific PDOs
&hidGuid, i++, &hidDeviceInterfaceData)) { //
// We enumerated a hid device, first lets get the device instance
//
hidDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo, &hidDeviceInterfaceData, NULL, 0, NULL, &hidDeviceInfoData) // ERROR_INSUFFICIENT_BUFFER is alright because we passed in NULL
// for the device interface detail data structure.
|| (GetLastError() == ERROR_INSUFFICIENT_BUFFER) ) { LOG((PHONESP_TRACE, "FindKnownHidDevices - device instance %08x", hidDeviceInfoData.DevInst )); //
// Check that the hid device is not already in our list
//
if ((hidDevice = FindHidDeviceByDevInst(hidDeviceInfoData.DevInst)) == NULL) { //
// This is a new hid device
//
// Allocate a HID_DEVICE structure
//
hidDevice = (PHID_DEVICE) MemAlloc(sizeof(HID_DEVICE));
if(hidDevice == NULL) { LOG((PHONESP_TRACE, "FindKnownHidDevices - unable to allocate hid device")); SetupDiDestroyDeviceInfoList(hardwareDeviceInfo); return ERROR_OUTOFMEMORY; }
ZeroMemory(hidDevice, sizeof(HID_DEVICE));
//
// Mark this as new, so we can create a new phone for it later
//
hidDevice->bNew = TRUE; hidDevice->dwDevInst = hidDeviceInfoData.DevInst;
//
// Open the hid device
//
lResult = OpenHidDevice (hardwareDeviceInfo, &hidDeviceInterfaceData, hidDevice);
if(lResult == ERROR_SUCCESS) { //
// This is a good hid device
//
(*pNumberHidDevices)++;
//
// So add it to our hid list
//
AddHidDevice(hidDevice);
LOG((PHONESP_TRACE, "FindKnownHidDevices - new hid devive added")); } else { LOG((PHONESP_TRACE, "FindKnownHidDevices - OpenHidDevice failed %08x", lResult )); MemFree(hidDevice); } } else { LOG((PHONESP_TRACE, "FindKnownHidDevices - hid device already enumerated"));
//
// Clear the removed mark on this device, so we don't remove its phone later
//
hidDevice->bRemoved = FALSE; } } else { LOG((PHONESP_TRACE, "FindKnownHidDevices - SetupDiGetDeviceInterfaceDetail failed %08x", GetLastError() )); } }
lResult = GetLastError();
if (ERROR_NO_MORE_ITEMS != lResult) { LOG((PHONESP_TRACE, "FindKnownHidDevices - SetupDiEnumDeviceInterfaces failed %08x", lResult )); SetupDiDestroyDeviceInfoList(hardwareDeviceInfo); return lResult; }
LOG((PHONESP_TRACE, "FindKnownHidDevices - exit"));
*pHidDevices = gpHidDevices;
SetupDiDestroyDeviceInfoList(hardwareDeviceInfo); return ERROR_SUCCESS; }
LONG OpenHidDevice ( IN HDEVINFO HardwareDeviceInfo, IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IN OUT PHID_DEVICE HidDevice ) /*++
RoutineDescription: Given the HardwareDeviceInfo, representing a handle to the plug and play information, and deviceInfoData, representing a specific hid device, open that device and fill in all the relivant information in the given HID_DEVICE structure.
return if the open and initialization was successfull or not.
--*/ { ULONG predictedLength = 0; ULONG requiredLength = 0; LONG lResult;
//
// allocate a function class device data structure to receive the
// goods about this particular device.
//
LOG((PHONESP_TRACE,"OpenHidDevice - enter"));
SetupDiGetDeviceInterfaceDetail( HardwareDeviceInfo, DeviceInterfaceData, NULL, // probing so no output buffer yet
0, // probing so output buffer length of zero
&requiredLength, NULL // not interested in the specific dev-node
); predictedLength = requiredLength;
HidDevice->functionClassDeviceData = MemAlloc (predictedLength);
if (HidDevice->functionClassDeviceData == NULL) { LOG((PHONESP_TRACE,"OpenHidDevice - out of memory")); return ERROR_OUTOFMEMORY; }
HidDevice->functionClassDeviceData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
//
// Retrieve the information from Plug and Play.
//
if (! SetupDiGetDeviceInterfaceDetail ( HardwareDeviceInfo, DeviceInterfaceData, HidDevice->functionClassDeviceData, predictedLength, &requiredLength, NULL)) { MemFree(HidDevice->functionClassDeviceData); HidDevice->functionClassDeviceData = NULL; LOG((PHONESP_TRACE,"OpenHidDevice - SetupDiGetDeviceInterfaceDetail 2" " Failed: %d", GetLastError())); return GetLastError(); }
HidDevice->HidDevice = CreateFile ( HidDevice->functionClassDeviceData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING, // No special create flags
FILE_FLAG_OVERLAPPED, // No special attributes
NULL); // No template file
if (INVALID_HANDLE_VALUE == HidDevice->HidDevice) { LOG((PHONESP_TRACE,"OpenHidDevice - CreateFile Failed: %d", GetLastError()));
MemFree(HidDevice->functionClassDeviceData); HidDevice->functionClassDeviceData = NULL;
return GetLastError(); }
if (!HidD_GetPreparsedData (HidDevice->HidDevice, &HidDevice->Ppd)) { LOG((PHONESP_ERROR, "OpenHidDevice - HidD_GetPreparsedData failed"));
CloseHandle(HidDevice->HidDevice); HidDevice->HidDevice = NULL;
MemFree(HidDevice->functionClassDeviceData); HidDevice->functionClassDeviceData = NULL;
return ERROR_INVALID_DATA; }
if (!HidD_GetAttributes (HidDevice->HidDevice, &HidDevice->Attributes)) { LOG((PHONESP_ERROR, "OpenHidDevice - HidD_GetAttributes failed"));
CloseHandle(HidDevice->HidDevice); HidDevice->HidDevice = NULL;
MemFree(HidDevice->functionClassDeviceData); HidDevice->functionClassDeviceData = NULL;
HidD_FreePreparsedData (HidDevice->Ppd);
return ERROR_INVALID_DATA; }
if ((!HidP_GetCaps (HidDevice->Ppd, &HidDevice->Caps)) || (HidDevice->Caps.UsagePage != HID_USAGE_PAGE_TELEPHONY) || (HidDevice->Caps.Usage != HID_USAGE_TELEPHONY_PHONE) ) { LOG((PHONESP_TRACE, " HID USAGE PAGE NOT TELEPHONY " ));
CloseHandle(HidDevice->HidDevice); HidDevice->HidDevice = NULL;
MemFree(HidDevice->functionClassDeviceData); HidDevice->functionClassDeviceData = NULL;
HidD_FreePreparsedData (HidDevice->Ppd);
return ERROR_INVALID_DATA; } else { LOG((PHONESP_TRACE, " HID USAGE PAGE TELEPHONY " )); } //
// At this point the client has a choice. It may chose to look at the
// Usage and Page of the top level collection found in the HIDP_CAPS
// structure. In this way it could just use the usages it knows about.
// If either HidP_GetUsages or HidP_GetUsageValue return an error then
// that particular usage does not exist in the report.
// This is most likely the preferred method as the application can only
// use usages of which it already knows.
// In this case the app need not even call GetButtonCaps or GetValueCaps.
//
// In this example, however, we will call FillDeviceInfo to look for all
// of the usages in the device.
//
lResult = FillDeviceInfo(HidDevice); if(lResult != ERROR_SUCCESS) { LOG((PHONESP_ERROR, "OpenHidDevice - FillDeviceInfo failed"));
CloseHandle(HidDevice->HidDevice); HidDevice->HidDevice = NULL;
MemFree(HidDevice->functionClassDeviceData); HidDevice->functionClassDeviceData = NULL;
HidD_FreePreparsedData (HidDevice->Ppd);
return lResult; }
LOG((PHONESP_TRACE,"OpenHidDevice - exit"));
return ERROR_SUCCESS; }
LONG FillDeviceInfo( IN PHID_DEVICE HidDevice ) { USHORT numValues; USHORT numCaps; PHIDP_BUTTON_CAPS buttonCaps; PHIDP_VALUE_CAPS valueCaps; PHID_DATA data; ULONG i; USAGE usage;
//
// setup Input Data buffers.
//
//
// Allocate memory to hold on input report
//
LOG((PHONESP_TRACE,"FillDeviceInfo - enter"));
if ( ! ( HidDevice->InputReportBuffer = (PCHAR) MemAlloc (HidDevice->Caps.InputReportByteLength * sizeof (CHAR)) ) ) { return ERROR_OUTOFMEMORY; }
LOG((PHONESP_TRACE,"FillDeviceInfo - NumberInputButtonCaps %d", HidDevice->Caps.NumberInputButtonCaps));
//
// Allocate memory to hold the button and value capabilities.
// NumberXXCaps is in terms of array elements.
//
HidDevice->InputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS) MemAlloc (HidDevice->Caps.NumberInputButtonCaps * sizeof (HIDP_BUTTON_CAPS));
if ( ! buttonCaps) { MemFree(HidDevice->InputReportBuffer); return ERROR_OUTOFMEMORY; }
LOG((PHONESP_TRACE,"FillDeviceInfo - NumberInputValueCaps %d", HidDevice->Caps.NumberInputValueCaps));
HidDevice->InputValueCaps = valueCaps = (PHIDP_VALUE_CAPS) MemAlloc (HidDevice->Caps.NumberInputValueCaps * sizeof (HIDP_VALUE_CAPS));
if ( ! valueCaps) { MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); return ERROR_OUTOFMEMORY; } //
// Have the HidP_X functions fill in the capability structure arrays.
//
numCaps = HidDevice->Caps.NumberInputButtonCaps; HidP_GetButtonCaps (HidP_Input, buttonCaps, &numCaps, HidDevice->Ppd);
numCaps = HidDevice->Caps.NumberInputValueCaps; HidP_GetValueCaps (HidP_Input, valueCaps, &numCaps, HidDevice->Ppd);
//
// Depending on the device, some value caps structures may represent more
// than one value. (A range). In the interest of being verbose, over
// efficient, we will expand these so that we have one and only one
// struct _HID_DATA for each value.
//
// To do this we need to count up the total number of values are listed
// in the value caps structure. For each element in the array we test
// for range if it is a range then UsageMax and UsageMin describe the
// usages for this range INCLUSIVE.
//
numValues = 0; for (i = 0; i < HidDevice->Caps.NumberInputValueCaps; i++, valueCaps++) { if (valueCaps->IsRange) { numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1; } else { numValues++; } } valueCaps = HidDevice->InputValueCaps;
//
// Allocate a buffer to hold the struct _HID_DATA structures.
// One element for each set of buttons, and one element for each value
// found.
//
HidDevice->InputDataLength = HidDevice->Caps.NumberInputButtonCaps + numValues;
HidDevice->InputData = data = (PHID_DATA) MemAlloc (HidDevice->InputDataLength * sizeof (HID_DATA));
if( ! data ) { MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps); return ERROR_OUTOFMEMORY; }
//
// Fill in the button data
//
for (i = 0; i < HidDevice->Caps.NumberInputButtonCaps; i++, data++, buttonCaps++) { data->IsButtonData = TRUE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = buttonCaps->UsagePage;
if (buttonCaps->IsRange) { data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin; data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax; } else { data->ButtonData.UsageMin = data->ButtonData.UsageMax = buttonCaps -> NotRange.Usage; } data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength ( HidP_Input, buttonCaps->UsagePage, HidDevice->Ppd);
data->ButtonData.Usages = (PUSAGE) MemAlloc (data->ButtonData.MaxUsageLength * sizeof (USAGE));
// if MemAlloc fails release all previous allocated memory and return
// error
if ( data->ButtonData.Usages == NULL) { DWORD dwCnt; for(dwCnt = 0; dwCnt < i; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps); return ERROR_OUTOFMEMORY; }
data->ReportID = buttonCaps->ReportID; }
//
// Fill in the value data
//
for (i = 0; i < numValues; i++, valueCaps++) { if (valueCaps->IsRange) { for (usage = valueCaps->Range.UsageMin; usage <= valueCaps->Range.UsageMax; usage++) { data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = usage; data->ReportID = valueCaps->ReportID; data++; } } else { data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = valueCaps->NotRange.Usage; data->ReportID = valueCaps->ReportID; data++; } }
//
// setup Output Data buffers.
//
if ( ! ( HidDevice->OutputReportBuffer = (PCHAR) MemAlloc (HidDevice->Caps.OutputReportByteLength * sizeof (CHAR)) ) ) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps); return ERROR_OUTOFMEMORY; }
LOG((PHONESP_TRACE,"FillDeviceInfo - NumberOutputButtonCaps %d", HidDevice->Caps.NumberOutputButtonCaps));
HidDevice->OutputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS) MemAlloc(HidDevice->Caps.NumberOutputButtonCaps * sizeof (HIDP_BUTTON_CAPS)); if ( ! buttonCaps ) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps); MemFree(HidDevice->OutputReportBuffer); return ERROR_OUTOFMEMORY; }
LOG((PHONESP_TRACE,"FillDeviceInfo - NumberOutputValueCaps %d", HidDevice->Caps.NumberOutputValueCaps));
HidDevice->OutputValueCaps = valueCaps = (PHIDP_VALUE_CAPS) MemAlloc (HidDevice->Caps.NumberOutputValueCaps * sizeof (HIDP_VALUE_CAPS)); if ( ! valueCaps ) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps);
MemFree(HidDevice->OutputReportBuffer); MemFree(HidDevice->OutputButtonCaps);
return ERROR_OUTOFMEMORY; }
numCaps = HidDevice->Caps.NumberOutputButtonCaps;
HidP_GetButtonCaps (HidP_Output, buttonCaps, &numCaps, HidDevice->Ppd);
numCaps = HidDevice->Caps.NumberOutputValueCaps;
HidP_GetValueCaps (HidP_Output, valueCaps, &numCaps, HidDevice->Ppd);
numValues = 0; for (i = 0; i < HidDevice->Caps.NumberOutputValueCaps; i++, valueCaps++) { if (valueCaps->IsRange) { numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1; } else { numValues++; } } valueCaps = HidDevice->OutputValueCaps;
HidDevice->OutputDataLength = HidDevice->Caps.NumberOutputButtonCaps + numValues;
HidDevice->OutputData = data = (PHID_DATA) MemAlloc (HidDevice->OutputDataLength * sizeof (HID_DATA));
if ( ! data ) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps);
MemFree(HidDevice->OutputReportBuffer); MemFree(HidDevice->OutputButtonCaps); MemFree(HidDevice->OutputValueCaps); return ERROR_OUTOFMEMORY; }
for (i = 0; i < HidDevice->Caps.NumberOutputButtonCaps; i++, data++, buttonCaps++) {
data->IsButtonData = TRUE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = buttonCaps->UsagePage;
if (buttonCaps->IsRange) { data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin; data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax; } else { data->ButtonData.UsageMin = data->ButtonData.UsageMax = buttonCaps->NotRange.Usage; }
data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength ( HidP_Output, buttonCaps->UsagePage, HidDevice->Ppd); data->ButtonData.Usages = (PUSAGE) MemAlloc (data->ButtonData.MaxUsageLength * sizeof (USAGE)); if( ! data) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps);
for(dwCnt = 0; dwCnt < i; dwCnt++) { MemFree(HidDevice->OutputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->OutputData); MemFree(HidDevice->OutputReportBuffer); MemFree(HidDevice->OutputButtonCaps); MemFree(HidDevice->OutputValueCaps); return ERROR_OUTOFMEMORY; }
data->ReportID = buttonCaps->ReportID; }
for (i = 0; i < numValues; i++, valueCaps++) { if (valueCaps->IsRange) { for (usage = valueCaps->Range.UsageMin; usage <= valueCaps->Range.UsageMax; usage++) {
data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = usage; data->ReportID = valueCaps -> ReportID; data++; } } else { data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = valueCaps->NotRange.Usage; data->ReportID = valueCaps -> ReportID; data++; } }
//
// setup Feature Data buffers.
//
if ( ! ( HidDevice->FeatureReportBuffer = (PCHAR) MemAlloc (HidDevice->Caps.FeatureReportByteLength * sizeof (CHAR)) ) ) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps);
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberOutputButtonCaps; dwCnt++) { MemFree(HidDevice->OutputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->OutputData); MemFree(HidDevice->OutputReportBuffer); MemFree(HidDevice->OutputButtonCaps); MemFree(HidDevice->OutputValueCaps); return ERROR_OUTOFMEMORY; }
LOG((PHONESP_TRACE,"FillDeviceInfo - NumberFeatureButtonCaps %d", HidDevice->Caps.NumberFeatureButtonCaps));
if ( ! ( HidDevice->FeatureButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS) MemAlloc (HidDevice->Caps.NumberFeatureButtonCaps * sizeof (HIDP_BUTTON_CAPS)) ) ) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps);
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberOutputButtonCaps; dwCnt++) { MemFree(HidDevice->OutputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->OutputData); MemFree(HidDevice->OutputReportBuffer); MemFree(HidDevice->OutputButtonCaps); MemFree(HidDevice->OutputValueCaps); MemFree(HidDevice->FeatureReportBuffer);
return ERROR_OUTOFMEMORY; }
LOG((PHONESP_TRACE,"FillDeviceInfo - NumberFeatureValueCaps %d", HidDevice->Caps.NumberFeatureValueCaps));
HidDevice->FeatureValueCaps = valueCaps = (PHIDP_VALUE_CAPS) MemAlloc (HidDevice->Caps.NumberFeatureValueCaps * sizeof (HIDP_VALUE_CAPS));
if ( ! valueCaps) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps);
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberOutputButtonCaps; dwCnt++) { MemFree(HidDevice->OutputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->OutputData); MemFree(HidDevice->OutputReportBuffer); MemFree(HidDevice->OutputButtonCaps); MemFree(HidDevice->OutputValueCaps);
MemFree(HidDevice->FeatureReportBuffer); MemFree(HidDevice->FeatureButtonCaps); return ERROR_OUTOFMEMORY; }
numCaps = HidDevice->Caps.NumberFeatureButtonCaps; HidP_GetButtonCaps (HidP_Feature, buttonCaps, &numCaps, HidDevice->Ppd);
numCaps = HidDevice->Caps.NumberFeatureValueCaps; HidP_GetValueCaps (HidP_Feature, valueCaps, &numCaps, HidDevice->Ppd);
numValues = 0; for (i = 0; i < HidDevice->Caps.NumberFeatureValueCaps; i++, valueCaps++) { if (valueCaps->IsRange) { numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1; } else { numValues++; } } valueCaps = HidDevice->FeatureValueCaps;
HidDevice->FeatureDataLength = HidDevice->Caps.NumberFeatureButtonCaps + numValues;
HidDevice->FeatureData = data = (PHID_DATA) MemAlloc (HidDevice->FeatureDataLength * sizeof (HID_DATA)); if ( ! data ) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps);
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberOutputButtonCaps; dwCnt++) { MemFree(HidDevice->OutputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->OutputData); MemFree(HidDevice->OutputReportBuffer); MemFree(HidDevice->OutputButtonCaps); MemFree(HidDevice->OutputValueCaps); MemFree(HidDevice->FeatureReportBuffer); MemFree(HidDevice->FeatureButtonCaps); MemFree(HidDevice->FeatureValueCaps); return ERROR_OUTOFMEMORY; }
for ( i = 0; i < HidDevice->Caps.NumberFeatureButtonCaps; i++, data++, buttonCaps++) { data->IsButtonData = TRUE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = buttonCaps->UsagePage;
if (buttonCaps->IsRange) { data->ButtonData.UsageMin = buttonCaps->Range.UsageMin; data->ButtonData.UsageMax = buttonCaps->Range.UsageMax; } else { data->ButtonData.UsageMin = data->ButtonData.UsageMax = buttonCaps->NotRange.Usage; } data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength ( HidP_Feature, buttonCaps->UsagePage, HidDevice->Ppd); data->ButtonData.Usages = (PUSAGE) MemAlloc (data->ButtonData.MaxUsageLength * sizeof (USAGE));
if ( ! data->ButtonData.Usages ) { DWORD dwCnt; for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->InputData); MemFree(HidDevice->InputReportBuffer); MemFree(HidDevice->InputButtonCaps); MemFree(HidDevice->InputValueCaps);
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberOutputButtonCaps; dwCnt++) { MemFree(HidDevice->OutputData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->OutputData); MemFree(HidDevice->OutputReportBuffer); MemFree(HidDevice->OutputButtonCaps); MemFree(HidDevice->OutputValueCaps);
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberFeatureButtonCaps; dwCnt++) { MemFree(HidDevice->FeatureData[dwCnt].ButtonData.Usages); } MemFree(HidDevice->FeatureData); MemFree(HidDevice->FeatureReportBuffer); MemFree(HidDevice->FeatureButtonCaps); MemFree(HidDevice->FeatureValueCaps); return ERROR_OUTOFMEMORY; }
data->ReportID = buttonCaps->ReportID; }
for (i = 0; i < numValues; i++, valueCaps++) { if (valueCaps->IsRange) { for (usage = valueCaps->Range.UsageMin; usage <= valueCaps->Range.UsageMax; usage++) { data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = usage; data->ReportID = valueCaps->ReportID; data++; } } else { data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = valueCaps->NotRange.Usage; data->ReportID = valueCaps -> ReportID; data++; } }
LOG((PHONESP_TRACE,"FillDeviceInfo - exit"));
return ERROR_SUCCESS; }
VOID CloseHidDevices() { LOG((PHONESP_TRACE, "CloseHidDevices - enter"));
while (gpHidDevices != NULL) { CloseHidDevice(gpHidDevices); }
LOG((PHONESP_TRACE, "CloseHidDevices - exit"));
return; }
BOOL OpenHidFile ( IN PHID_DEVICE HidDevice ) { LOG((PHONESP_TRACE, "OpenHidFile - enter"));
if (HidDevice != NULL) { if (HidDevice->functionClassDeviceData != NULL) { HidDevice->HidDevice = CreateFile ( HidDevice->functionClassDeviceData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING, // No special create flags
FILE_FLAG_OVERLAPPED, // No special attributes
NULL); // No template file
if (INVALID_HANDLE_VALUE == HidDevice->HidDevice) { LOG((PHONESP_ERROR,"OpenHidFile - CreateFile failed: %d", GetLastError())); return FALSE; }
LOG((PHONESP_TRACE, "OpenHidFile - exit")); return TRUE; } }
LOG((PHONESP_WARN, "OpenHidFile - no device"));
return FALSE; }
BOOL CloseHidFile ( IN PHID_DEVICE HidDevice ) { LOG((PHONESP_TRACE, "CloseHidFile - enter"));
if (HidDevice != NULL) { if ((NULL != HidDevice->HidDevice) && (INVALID_HANDLE_VALUE != HidDevice->HidDevice)) { CloseHandle(HidDevice->HidDevice); HidDevice->HidDevice = NULL;
LOG((PHONESP_TRACE, "CloseHidFile - exit")); return TRUE; } }
LOG((PHONESP_WARN, "CloseHidFile - no device")); return FALSE; }
VOID CloseHidDevice ( IN PHID_DEVICE HidDevice ) { LOG((PHONESP_TRACE, "CloseHidDevice - enter"));
if (HidDevice != NULL) { if (NULL != HidDevice->functionClassDeviceData) { MemFree(HidDevice->functionClassDeviceData); }
if ((NULL != HidDevice -> HidDevice) && (INVALID_HANDLE_VALUE != HidDevice -> HidDevice)) { CloseHandle(HidDevice->HidDevice); HidDevice->HidDevice = NULL; }
if (NULL != HidDevice->Ppd) { HidD_FreePreparsedData(HidDevice->Ppd); HidDevice->Ppd = NULL; }
if (NULL != HidDevice->InputReportBuffer) { MemFree(HidDevice->InputReportBuffer); HidDevice->InputReportBuffer = NULL; }
if (NULL != HidDevice->InputData) { DWORD dwCnt;
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberInputButtonCaps; dwCnt++) { MemFree(HidDevice->InputData[dwCnt].ButtonData.Usages); HidDevice->InputData[dwCnt].ButtonData.Usages = NULL; }
MemFree(HidDevice->InputData); HidDevice->InputData = NULL; }
if (NULL != HidDevice->InputButtonCaps) { MemFree(HidDevice->InputButtonCaps); HidDevice->InputButtonCaps = NULL; }
if (NULL != HidDevice->InputValueCaps) { MemFree(HidDevice->InputValueCaps); HidDevice->InputValueCaps = NULL; }
if (NULL != HidDevice->OutputReportBuffer) { MemFree(HidDevice->OutputReportBuffer); HidDevice->OutputReportBuffer = NULL; }
if (NULL != HidDevice->OutputData) { DWORD dwCnt;
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberOutputButtonCaps; dwCnt++) { MemFree(HidDevice->OutputData[dwCnt].ButtonData.Usages); HidDevice->OutputData[dwCnt].ButtonData.Usages = NULL; }
MemFree(HidDevice->OutputData); HidDevice->OutputData = NULL; }
if (NULL != HidDevice->OutputButtonCaps) { MemFree(HidDevice->OutputButtonCaps); HidDevice->OutputButtonCaps = NULL; }
if (NULL != HidDevice->OutputValueCaps) { MemFree(HidDevice->OutputValueCaps); HidDevice->OutputValueCaps = NULL; }
if (NULL != HidDevice->FeatureReportBuffer) { MemFree(HidDevice->FeatureReportBuffer); HidDevice->FeatureReportBuffer = NULL; }
if (NULL != HidDevice->FeatureData) { DWORD dwCnt;
for(dwCnt = 0; dwCnt < HidDevice->Caps.NumberFeatureButtonCaps; dwCnt++) { MemFree(HidDevice->FeatureData[dwCnt].ButtonData.Usages); HidDevice->FeatureData[dwCnt].ButtonData.Usages = NULL; }
MemFree(HidDevice->FeatureData); HidDevice->FeatureData = NULL; }
if (NULL != HidDevice->FeatureButtonCaps) { MemFree(HidDevice->FeatureButtonCaps); HidDevice->FeatureButtonCaps = NULL; }
if (NULL != HidDevice->FeatureValueCaps) { MemFree(HidDevice->FeatureValueCaps); HidDevice->FeatureValueCaps = NULL; }
RemoveHidDevice(HidDevice); MemFree(HidDevice); }
LOG((PHONESP_TRACE, "CloseHidDevice - exit")); return; } VOID AddHidDevice ( IN PHID_DEVICE HidDevice ) { LOG((PHONESP_TRACE, "AddHidDevice - enter"));
HidDevice->Next = gpHidDevices; HidDevice->Prev = NULL;
if (gpHidDevices) { gpHidDevices->Prev = HidDevice; }
gpHidDevices = HidDevice;
LOG((PHONESP_TRACE, "AddHidDevice - exit")); }
VOID RemoveHidDevice ( IN PHID_DEVICE HidDevice ) { LOG((PHONESP_TRACE, "RemoveHidDevice - enter"));
if (HidDevice->Prev) { HidDevice->Prev->Next = HidDevice->Next; } else { // first in list
gpHidDevices = HidDevice->Next; }
if (HidDevice->Next) { HidDevice->Next->Prev = HidDevice->Prev; }
HidDevice->Next = NULL; HidDevice->Prev = NULL;
LOG((PHONESP_TRACE, "RemoveHidDevice - exit")); }
PHID_DEVICE FindHidDeviceByDevInst ( IN DWORD DevInst ) { PHID_DEVICE HidDevice = gpHidDevices;
LOG((PHONESP_TRACE, "FindHidDeviceByDevInst - enter"));
while (HidDevice != NULL) { if (HidDevice->dwDevInst == DevInst) { LOG((PHONESP_TRACE, "FindHidDeviceByDevInst - exit")); return HidDevice; }
HidDevice = HidDevice->Next; }
LOG((PHONESP_WARN, "FindHidDeviceByDevInst - not found")); return NULL; }
|