|
|
/*
* title: ckUtils.cpp * * purpose: misc c-style utility functions * */
#include "hidbatt.h"
// utils
NTSTATUS HidBattDoIoctlCompletion( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pDoIoCompletedEvent ) {
KeSetEvent((KEVENT *) pDoIoCompletedEvent,0, FALSE); return pIrp->IoStatus.Status;
}
ULONG CentiAmpSecsToMilliWattHours(ULONG CentiAmps,ULONG MilliVolts) { // conversion from Centiampsec to millWattHours
// formula = (amps * volts / 3600) ^ (exponent correction)
ULONG milliWattHours = CentiAmps; milliWattHours /= 100; // now have ampsec
milliWattHours *= MilliVolts; // now have milliwattsec
milliWattHours /= 3600; // milliwatthours
HidBattPrint (HIDBATT_DATA, ("CentiAmpSecsToMilliWhatHours: CAs = 0x%08x, mV = 0x%08x, mWH = 0x%08x \n", CentiAmps, MilliVolts, milliWattHours )); return milliWattHours; }
ULONG milliWattHoursToCentiAmpSecs(ULONG mwHours, ULONG MilliVolts) { // inverse of formula above
ULONG AmpSecs = mwHours; AmpSecs *= 3600; AmpSecs /= MilliVolts; AmpSecs *= 100;
HidBattPrint (HIDBATT_DATA, ("MilliWattHoursToCentiAmpSecs: mWH = 0x%08x, mV = 0x%08x, CAs = 0x%08x \n", mwHours, MilliVolts, AmpSecs )); return AmpSecs; }
// subroutine to take a value, it's exponent and the desired exponent and correct the value
ULONG CorrectExponent(ULONG ulBaseValue, SHORT sCurrExponent, SHORT sTargetExponent) { SHORT sCorrection; if(!ulBaseValue) return 0; // done all I can with zero
sCorrection = sCurrExponent - sTargetExponent; if(!sCorrection) return ulBaseValue; // no correction
if(sCorrection < 0) { for (; sCorrection < 0; sCorrection++) { ulBaseValue /= 10; } return ulBaseValue; } else { for (; sCorrection > 0; sCorrection--) { ulBaseValue *= 10; } return ulBaseValue; } }
NTSTATUS DoIoctl( PDEVICE_OBJECT pDeviceObject, ULONG ulIOCTL, PVOID pInputBuffer, ULONG ulInputBufferLength, PVOID pOutputBuffer, ULONG ulOutputBufferLength, CHidDevice * pHidDevice) { IO_STATUS_BLOCK StatusBlock; NTSTATUS ntStatus; PIRP pIrp = NULL; PIO_STACK_LOCATION pNewStack; KEVENT IOCTLEvent;
HIDDebugBreak(HIDBATT_BREAK_DEBUG); //CBatteryDevExt * pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
KeInitializeEvent(&IOCTLEvent , NotificationEvent, FALSE); pIrp = IoBuildDeviceIoControlRequest( ulIOCTL, pDeviceObject, pInputBuffer, ulInputBufferLength, pOutputBuffer, ulOutputBufferLength, FALSE, &IOCTLEvent, &StatusBlock );
if(!pIrp) return STATUS_NO_MEMORY; // stuff file control block if requested (non-null hid device ptr)
if(pHidDevice) { pNewStack = IoGetNextIrpStackLocation(pIrp); pNewStack->FileObject = pHidDevice->m_pFCB; }
ntStatus = IoCallDriver(pDeviceObject,pIrp); if(ntStatus == STATUS_PENDING) { KeWaitForSingleObject(&IOCTLEvent, Executive, KernelMode, FALSE, NULL); } else if(NT_ERROR(ntStatus)) return ntStatus;
return StatusBlock.Status; }
// This is a direct adaption of Ken Ray's function to populate the hid inforation structures
PHID_DEVICE SetupHidData( IN PHIDP_PREPARSED_DATA pPreparsedData, IN OUT PHIDP_CAPS pCaps, PHIDP_LINK_COLLECTION_NODE pLinkNodes) { PHID_DEVICE pHidDevice; PHIDP_BUTTON_CAPS pButtonCaps; PHIDP_VALUE_CAPS pValueCaps; PHID_DATA pHidData; int iNumValues,i; USAGE usage;
pHidDevice = (PHID_DEVICE) ExAllocatePoolWithTag(NonPagedPool,sizeof(HID_DEVICE),HidBattTag); if(!pHidDevice) return NULL; RtlZeroMemory(pHidDevice,sizeof(HID_DEVICE)); //
// 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 look for all of the usages in the device.
//
//
// Allocate memory to hold the button and value capabilities.
// NumberXXCaps is in terms of array elements.
//
if(pCaps->NumberInputButtonCaps) { pHidDevice->InputButtonCaps = pButtonCaps = (PHIDP_BUTTON_CAPS) ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberInputButtonCaps * sizeof (HIDP_BUTTON_CAPS),HidBattTag); if (pButtonCaps) { RtlZeroMemory(pButtonCaps,pCaps->NumberInputButtonCaps * sizeof(HIDP_BUTTON_CAPS)); } } if(pCaps->NumberInputValueCaps) { pHidDevice->InputValueCaps = pValueCaps = (PHIDP_VALUE_CAPS) ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberInputValueCaps * sizeof (HIDP_VALUE_CAPS),HidBattTag);
if (pValueCaps) { RtlZeroMemory(pValueCaps, pCaps->NumberInputValueCaps * sizeof (HIDP_VALUE_CAPS)); } }
//
// Have the HidP_X functions fill in the capability structure arrays.
//
if(pButtonCaps) { HidP_GetButtonCaps (HidP_Input, pButtonCaps, &pCaps->NumberInputButtonCaps, pPreparsedData); }
if(pValueCaps) { HidP_GetValueCaps (HidP_Input, pValueCaps, &pCaps->NumberInputValueCaps, pPreparsedData); }
//
// 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.
//
iNumValues = 0; for (i = 0; i < pCaps->NumberInputValueCaps; i++, pValueCaps++) { if ((pValueCaps) && (pValueCaps->IsRange)) { iNumValues += pValueCaps->Range.UsageMax - pValueCaps->Range.UsageMin + 1; } else { iNumValues++; } }
//
// setup Output Data buffers.
//
if(pCaps->NumberOutputButtonCaps) { pHidDevice->OutputButtonCaps = pButtonCaps = (PHIDP_BUTTON_CAPS) ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberOutputButtonCaps * sizeof (HIDP_BUTTON_CAPS),HidBattTag); HidP_GetButtonCaps (HidP_Output, pButtonCaps, &pCaps->NumberOutputButtonCaps, pPreparsedData); } iNumValues = 0;
if(pCaps->NumberOutputValueCaps) { pHidDevice->OutputValueCaps = pValueCaps = (PHIDP_VALUE_CAPS) ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberOutputValueCaps * sizeof (HIDP_VALUE_CAPS),HidBattTag); HidP_GetValueCaps (HidP_Output, pValueCaps, &pCaps->NumberOutputValueCaps, pPreparsedData); for (i = 0; i < pCaps->NumberOutputValueCaps; i++, pValueCaps++) { if (pValueCaps->IsRange) { iNumValues += pValueCaps->Range.UsageMax - pValueCaps->Range.UsageMin + 1; } else { iNumValues++; } } }
//
// setup Feature Data buffers.
//
if(pCaps->NumberFeatureButtonCaps) { pHidDevice->FeatureButtonCaps = pButtonCaps = (PHIDP_BUTTON_CAPS) ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberFeatureButtonCaps * sizeof (HIDP_BUTTON_CAPS),HidBattTag); RtlZeroMemory(pButtonCaps, pCaps->NumberFeatureButtonCaps * sizeof(HIDP_BUTTON_CAPS)); HidP_GetButtonCaps (HidP_Feature, pButtonCaps, &pCaps->NumberFeatureButtonCaps, pPreparsedData); } if(pCaps->NumberFeatureValueCaps) { pHidDevice->FeatureValueCaps = pValueCaps = (PHIDP_VALUE_CAPS) ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberFeatureValueCaps * sizeof (HIDP_VALUE_CAPS),HidBattTag); RtlZeroMemory(pValueCaps, pCaps->NumberFeatureValueCaps * sizeof (HIDP_VALUE_CAPS)); HidP_GetValueCaps (HidP_Feature, pValueCaps, &pCaps->NumberFeatureValueCaps, pPreparsedData);
}
iNumValues = 0; for (i = 0; i < pCaps->NumberFeatureValueCaps; i++, pValueCaps++) { if (pValueCaps->IsRange) { iNumValues += pValueCaps->Range.UsageMax - pValueCaps->Range.UsageMin + 1; } else { iNumValues++; } }
return pHidDevice; }
|