Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
9.5 KiB

  1. /*
  2. * title: ckUtils.cpp
  3. *
  4. * purpose: misc c-style utility functions
  5. *
  6. */
  7. #include "hidbatt.h"
  8. // utils
  9. NTSTATUS
  10. HidBattDoIoctlCompletion(
  11. IN PDEVICE_OBJECT pDeviceObject,
  12. IN PIRP pIrp,
  13. IN PVOID pDoIoCompletedEvent
  14. )
  15. {
  16. KeSetEvent((KEVENT *) pDoIoCompletedEvent,0, FALSE);
  17. return pIrp->IoStatus.Status;
  18. }
  19. ULONG CentiAmpSecsToMilliWattHours(ULONG CentiAmps,ULONG MilliVolts)
  20. {
  21. // conversion from Centiampsec to millWattHours
  22. // formula = (amps * volts / 3600) ^ (exponent correction)
  23. ULONG milliWattHours = CentiAmps;
  24. milliWattHours /= 100; // now have ampsec
  25. milliWattHours *= MilliVolts; // now have milliwattsec
  26. milliWattHours /= 3600; // milliwatthours
  27. HidBattPrint (HIDBATT_DATA, ("CentiAmpSecsToMilliWhatHours: CAs = 0x%08x, mV = 0x%08x, mWH = 0x%08x \n",
  28. CentiAmps, MilliVolts, milliWattHours ));
  29. return milliWattHours;
  30. }
  31. ULONG milliWattHoursToCentiAmpSecs(ULONG mwHours, ULONG MilliVolts)
  32. {
  33. // inverse of formula above
  34. ULONG AmpSecs = mwHours;
  35. AmpSecs *= 3600;
  36. AmpSecs /= MilliVolts;
  37. AmpSecs *= 100;
  38. HidBattPrint (HIDBATT_DATA, ("MilliWattHoursToCentiAmpSecs: mWH = 0x%08x, mV = 0x%08x, CAs = 0x%08x \n",
  39. mwHours, MilliVolts, AmpSecs ));
  40. return AmpSecs;
  41. }
  42. // subroutine to take a value, it's exponent and the desired exponent and correct the value
  43. ULONG CorrectExponent(ULONG ulBaseValue, SHORT sCurrExponent, SHORT sTargetExponent)
  44. {
  45. SHORT sCorrection;
  46. if(!ulBaseValue) return 0; // done all I can with zero
  47. sCorrection = sCurrExponent - sTargetExponent;
  48. if(!sCorrection) return ulBaseValue; // no correction
  49. if(sCorrection < 0)
  50. {
  51. for (; sCorrection < 0; sCorrection++) {
  52. ulBaseValue /= 10;
  53. }
  54. return ulBaseValue;
  55. } else {
  56. for (; sCorrection > 0; sCorrection--) {
  57. ulBaseValue *= 10;
  58. }
  59. return ulBaseValue;
  60. }
  61. }
  62. NTSTATUS
  63. DoIoctl(
  64. PDEVICE_OBJECT pDeviceObject,
  65. ULONG ulIOCTL,
  66. PVOID pInputBuffer,
  67. ULONG ulInputBufferLength,
  68. PVOID pOutputBuffer,
  69. ULONG ulOutputBufferLength,
  70. CHidDevice * pHidDevice)
  71. {
  72. IO_STATUS_BLOCK StatusBlock;
  73. NTSTATUS ntStatus;
  74. PIRP pIrp = NULL;
  75. PIO_STACK_LOCATION pNewStack;
  76. KEVENT IOCTLEvent;
  77. HIDDebugBreak(HIDBATT_BREAK_DEBUG);
  78. //CBatteryDevExt * pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
  79. KeInitializeEvent(&IOCTLEvent , NotificationEvent, FALSE);
  80. pIrp = IoBuildDeviceIoControlRequest(
  81. ulIOCTL,
  82. pDeviceObject,
  83. pInputBuffer,
  84. ulInputBufferLength,
  85. pOutputBuffer,
  86. ulOutputBufferLength,
  87. FALSE,
  88. &IOCTLEvent,
  89. &StatusBlock
  90. );
  91. if(!pIrp) return STATUS_NO_MEMORY;
  92. // stuff file control block if requested (non-null hid device ptr)
  93. if(pHidDevice)
  94. {
  95. pNewStack = IoGetNextIrpStackLocation(pIrp);
  96. pNewStack->FileObject = pHidDevice->m_pFCB;
  97. }
  98. ntStatus = IoCallDriver(pDeviceObject,pIrp);
  99. if(ntStatus == STATUS_PENDING)
  100. {
  101. KeWaitForSingleObject(&IOCTLEvent, Executive, KernelMode, FALSE, NULL);
  102. } else
  103. if(NT_ERROR(ntStatus)) return ntStatus;
  104. return StatusBlock.Status;
  105. }
  106. // This is a direct adaption of Ken Ray's function to populate the hid inforation structures
  107. PHID_DEVICE SetupHidData(
  108. IN PHIDP_PREPARSED_DATA pPreparsedData,
  109. IN OUT PHIDP_CAPS pCaps,
  110. PHIDP_LINK_COLLECTION_NODE pLinkNodes)
  111. {
  112. PHID_DEVICE pHidDevice;
  113. PHIDP_BUTTON_CAPS pButtonCaps;
  114. PHIDP_VALUE_CAPS pValueCaps;
  115. PHID_DATA pHidData;
  116. int iNumValues,i;
  117. USAGE usage;
  118. pHidDevice = (PHID_DEVICE) ExAllocatePoolWithTag(NonPagedPool,sizeof(HID_DEVICE),HidBattTag);
  119. if(!pHidDevice) return NULL;
  120. RtlZeroMemory(pHidDevice,sizeof(HID_DEVICE));
  121. //
  122. // At this point the client has a choice. It may chose to look at the
  123. // Usage and Page of the top level collection found in the HIDP_CAPS
  124. // structure. In this way it could just use the usages it knows about.
  125. // If either HidP_GetUsages or HidP_GetUsageValue return an error then
  126. // that particular usage does not exist in the report.
  127. // This is most likely the preferred method as the application can only
  128. // use usages of which it already knows.
  129. // In this case the app need not even call GetButtonCaps or GetValueCaps.
  130. //
  131. // In this example, however, we look for all of the usages in the device.
  132. //
  133. //
  134. // Allocate memory to hold the button and value capabilities.
  135. // NumberXXCaps is in terms of array elements.
  136. //
  137. if(pCaps->NumberInputButtonCaps)
  138. {
  139. pHidDevice->InputButtonCaps = pButtonCaps = (PHIDP_BUTTON_CAPS)
  140. ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberInputButtonCaps * sizeof (HIDP_BUTTON_CAPS),HidBattTag);
  141. if (pButtonCaps) {
  142. RtlZeroMemory(pButtonCaps,pCaps->NumberInputButtonCaps * sizeof(HIDP_BUTTON_CAPS));
  143. }
  144. }
  145. if(pCaps->NumberInputValueCaps)
  146. {
  147. pHidDevice->InputValueCaps = pValueCaps = (PHIDP_VALUE_CAPS)
  148. ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberInputValueCaps * sizeof (HIDP_VALUE_CAPS),HidBattTag);
  149. if (pValueCaps) {
  150. RtlZeroMemory(pValueCaps, pCaps->NumberInputValueCaps * sizeof (HIDP_VALUE_CAPS));
  151. }
  152. }
  153. //
  154. // Have the HidP_X functions fill in the capability structure arrays.
  155. //
  156. if(pButtonCaps)
  157. {
  158. HidP_GetButtonCaps (HidP_Input,
  159. pButtonCaps,
  160. &pCaps->NumberInputButtonCaps,
  161. pPreparsedData);
  162. }
  163. if(pValueCaps)
  164. {
  165. HidP_GetValueCaps (HidP_Input,
  166. pValueCaps,
  167. &pCaps->NumberInputValueCaps,
  168. pPreparsedData);
  169. }
  170. //
  171. // Depending on the device, some value caps structures may represent more
  172. // than one value. (A range). In the interest of being verbose, over
  173. // efficient we will expand these so that we have one and only one
  174. // struct _HID_DATA for each value.
  175. //
  176. // To do this we need to count up the total number of values are listed
  177. // in the value caps structure. For each element in the array we test
  178. // for range if it is a range then UsageMax and UsageMin describe the
  179. // usages for this range INCLUSIVE.
  180. //
  181. iNumValues = 0;
  182. for (i = 0; i < pCaps->NumberInputValueCaps; i++, pValueCaps++) {
  183. if ((pValueCaps) && (pValueCaps->IsRange)) {
  184. iNumValues += pValueCaps->Range.UsageMax - pValueCaps->Range.UsageMin + 1;
  185. } else {
  186. iNumValues++;
  187. }
  188. }
  189. //
  190. // setup Output Data buffers.
  191. //
  192. if(pCaps->NumberOutputButtonCaps)
  193. {
  194. pHidDevice->OutputButtonCaps = pButtonCaps = (PHIDP_BUTTON_CAPS)
  195. ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberOutputButtonCaps * sizeof (HIDP_BUTTON_CAPS),HidBattTag);
  196. HidP_GetButtonCaps (HidP_Output,
  197. pButtonCaps,
  198. &pCaps->NumberOutputButtonCaps,
  199. pPreparsedData);
  200. }
  201. iNumValues = 0;
  202. if(pCaps->NumberOutputValueCaps)
  203. {
  204. pHidDevice->OutputValueCaps = pValueCaps = (PHIDP_VALUE_CAPS)
  205. ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberOutputValueCaps * sizeof (HIDP_VALUE_CAPS),HidBattTag);
  206. HidP_GetValueCaps (HidP_Output,
  207. pValueCaps,
  208. &pCaps->NumberOutputValueCaps,
  209. pPreparsedData);
  210. for (i = 0; i < pCaps->NumberOutputValueCaps; i++, pValueCaps++) {
  211. if (pValueCaps->IsRange) {
  212. iNumValues += pValueCaps->Range.UsageMax
  213. - pValueCaps->Range.UsageMin + 1;
  214. } else {
  215. iNumValues++;
  216. }
  217. }
  218. }
  219. //
  220. // setup Feature Data buffers.
  221. //
  222. if(pCaps->NumberFeatureButtonCaps)
  223. {
  224. pHidDevice->FeatureButtonCaps = pButtonCaps = (PHIDP_BUTTON_CAPS)
  225. ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberFeatureButtonCaps * sizeof (HIDP_BUTTON_CAPS),HidBattTag);
  226. RtlZeroMemory(pButtonCaps, pCaps->NumberFeatureButtonCaps * sizeof(HIDP_BUTTON_CAPS));
  227. HidP_GetButtonCaps (HidP_Feature,
  228. pButtonCaps,
  229. &pCaps->NumberFeatureButtonCaps,
  230. pPreparsedData);
  231. }
  232. if(pCaps->NumberFeatureValueCaps)
  233. {
  234. pHidDevice->FeatureValueCaps = pValueCaps = (PHIDP_VALUE_CAPS)
  235. ExAllocatePoolWithTag (NonPagedPool, pCaps->NumberFeatureValueCaps * sizeof (HIDP_VALUE_CAPS),HidBattTag);
  236. RtlZeroMemory(pValueCaps, pCaps->NumberFeatureValueCaps * sizeof (HIDP_VALUE_CAPS));
  237. HidP_GetValueCaps (HidP_Feature,
  238. pValueCaps,
  239. &pCaps->NumberFeatureValueCaps,
  240. pPreparsedData);
  241. }
  242. iNumValues = 0;
  243. for (i = 0; i < pCaps->NumberFeatureValueCaps; i++, pValueCaps++) {
  244. if (pValueCaps->IsRange) {
  245. iNumValues += pValueCaps->Range.UsageMax
  246. - pValueCaps->Range.UsageMin + 1;
  247. } else {
  248. iNumValues++;
  249. }
  250. }
  251. return pHidDevice;
  252. }