/*++ 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 #include #include #include #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; }