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.

229 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. oempen.c
  5. Abstract: Contains OEM specific functions.
  6. Environment:
  7. Kernel mode
  8. Author:
  9. Michael Tsang (MikeTs) 13-Apr-2000
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. #ifdef ALLOC_PRAGMA
  14. #endif //ifdef ALLOC_PRAGMA
  15. UCHAR gReportDescriptor[32] = {
  16. 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
  17. 0x09, 0x01, // USAGE (Consumer Control)
  18. 0xa1, 0x01, // COLLECTION (Application)
  19. 0x09, 0x03, // USAGE (Programmable Buttons)
  20. 0xa1, 0x00, // COLLECTION (Physical)
  21. 0x05, 0x09, // USAGE_PAGE (Button)
  22. 0x19, 0x01, // USAGE_MINIMUM (Button 1)
  23. 0x29, 0x06, // USAGE_MAXIMUM (Button 6)
  24. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  25. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  26. 0x95, 0x06, // REPORT_COUNT (6)
  27. 0x75, 0x01, // REPORT_SIZE (1)
  28. 0x81, 0x00, // INPUT (Data,Ary,Abs)
  29. 0x95, 0x02, // REPORT_COUNT (2)
  30. 0x81, 0x03, // INPUT (Cnst,Var,Abs)
  31. 0xc0, // END_COLLECTION
  32. 0xc0 // END_COLLECTION
  33. };
  34. HID_DESCRIPTOR gHidDescriptor =
  35. {
  36. sizeof(HID_DESCRIPTOR), //bLength
  37. HID_HID_DESCRIPTOR_TYPE, //bDescriptorType
  38. HID_REVISION, //bcdHID
  39. 0, //bCountry - not localized
  40. 1, //bNumDescriptors
  41. { //DescriptorList[0]
  42. HID_REPORT_DESCRIPTOR_TYPE, //bReportType
  43. sizeof(gReportDescriptor) //wReportLength
  44. }
  45. };
  46. PWSTR gpwstrManufacturerID = L"Microsoft";
  47. PWSTR gpwstrProductID = L"Tablet PC Buttons";
  48. PWSTR gpwstrSerialNumber = L"0";
  49. /*****************************************************************************
  50. *
  51. * @doc EXTERNAL
  52. *
  53. * @func BOOLEAN | OemInterruptServiceRoutine |
  54. * Interrupt service routine for the button device.
  55. *
  56. * @parm IN PKINTERRUPT | Interrupt | Points to the interrupt object.
  57. * @parm IN PDEVICE_EXTENSION | DevExt | Points to the device extension.
  58. *
  59. * @rvalue SUCCESS | returns TRUE - it's our interrupt.
  60. * @rvalue FAILURE | returns FALSE - it's not our interrupt.
  61. *
  62. *****************************************************************************/
  63. BOOLEAN EXTERNAL
  64. OemInterruptServiceRoutine(
  65. IN PKINTERRUPT Interrupt,
  66. IN PDEVICE_EXTENSION DevExt
  67. )
  68. {
  69. PROCNAME("OemInterruptServiceRoutine")
  70. BOOLEAN rc = FALSE;
  71. UCHAR ButtonState;
  72. ENTER(1, ("(Interrupt=%p,DevExt=%p)\n", Interrupt, DevExt));
  73. UNREFERENCED_PARAMETER(Interrupt);
  74. //
  75. // Note: the action of reading the button state will also clear
  76. // the interrupt.
  77. //
  78. ButtonState = READBUTTONSTATE(DevExt);
  79. if ((ButtonState & BUTTON_INTERRUPT_MASK) &&
  80. ((ButtonState & BUTTON_STATUS_MASK)!= DevExt->LastButtonState))
  81. {
  82. DBGPRINT(1, ("Button interrupt (Buttons=%x)\n", ButtonState));
  83. DevExt->LastButtonState = ButtonState & BUTTON_STATUS_MASK;
  84. DevExt->dwfHBut |= HBUTF_DEBOUNCE_TIMER_SET;
  85. KeSetTimer(&DevExt->DebounceTimer,
  86. DevExt->DebounceTime,
  87. &DevExt->TimerDpc);
  88. DBGPRINT(3, ("Button Interrupt (ButtonState=%x)\n", ButtonState));
  89. rc = TRUE;
  90. }
  91. EXIT(1, ("=%x\n", rc));
  92. return rc;
  93. } //OemInterruptServiceRoutine
  94. /*****************************************************************************
  95. *
  96. * @doc EXTERNAL
  97. *
  98. * @func VOID | OemButtonDebounceDpc |
  99. * Timer DPC routine to handle button debounce.
  100. *
  101. * @parm IN PKDPC | Dpc | Points to the DPC object.
  102. * @parm IN PDEVICE_EXTENSION | DevExt | Points to the device extension.
  103. * @parm IN PVOID | SysArg1 | System argument 1.
  104. * @parm IN PVOID | SysArg2 | System arugment 2.
  105. *
  106. * @rvalue None.
  107. *
  108. *****************************************************************************/
  109. VOID EXTERNAL
  110. OemButtonDebounceDpc(
  111. IN PKDPC Dpc,
  112. IN PDEVICE_EXTENSION DevExt,
  113. IN PVOID SysArg1,
  114. IN PVOID SysArg2
  115. )
  116. {
  117. PROCNAME("OemButtonDebounceDpc")
  118. UCHAR ButtonState;
  119. ENTER(2, ("(Dpc=%p,DevExt=%p,SysArg1=%p,SysArg2=%p)\n",
  120. Dpc, DevExt, SysArg1, SysArg2));
  121. UNREFERENCED_PARAMETER(Dpc);
  122. UNREFERENCED_PARAMETER(SysArg1);
  123. UNREFERENCED_PARAMETER(SysArg2);
  124. ButtonState = READBUTTONSTATE(DevExt) & BUTTON_STATUS_MASK;
  125. if (ButtonState == DevExt->LastButtonState)
  126. {
  127. PIRP irp = NULL;
  128. KIRQL OldIrql;
  129. PLIST_ENTRY plist;
  130. PDRIVER_CANCEL OldCancelRoutine;
  131. if (ButtonState & DevExt->StuckButtonsMask)
  132. {
  133. if (DevExt->bStuckCount >= MAX_STUCK_COUNT)
  134. {
  135. DBGPRINT(1, ("Clearing stuck buttons (Buttons=%x,StuckMask=%x)\n",
  136. ButtonState, DevExt->StuckButtonsMask));
  137. ButtonState &= ~DevExt->StuckButtonsMask;
  138. }
  139. else
  140. {
  141. DBGPRINT(1, ("Detected stuck buttons (Buttons=%x,StuckMask=%x,Count=%d)\n",
  142. ButtonState, DevExt->StuckButtonsMask,
  143. DevExt->bStuckCount));
  144. DevExt->bStuckCount++;
  145. }
  146. }
  147. else if (DevExt->StuckButtonsMask != 0)
  148. {
  149. //
  150. // The button has unstuck after all???
  151. //
  152. DBGPRINT(1, ("Button has unstuck (Buttons=%x,StuckMask=%x)\n",
  153. ButtonState, DevExt->StuckButtonsMask));
  154. DevExt->bStuckCount = 0;
  155. }
  156. DevExt->dwfHBut &= ~HBUTF_DEBOUNCE_TIMER_SET;
  157. KeAcquireSpinLock(&DevExt->SpinLock, &OldIrql);
  158. if (!IsListEmpty(&DevExt->PendingIrpList))
  159. {
  160. plist = RemoveHeadList(&DevExt->PendingIrpList);
  161. irp = CONTAINING_RECORD(plist, IRP, Tail.Overlay.ListEntry);
  162. OldCancelRoutine = IoSetCancelRoutine(irp, NULL);
  163. ASSERT(OldCancelRoutine == ReadReportCanceled);
  164. }
  165. KeReleaseSpinLock(&DevExt->SpinLock, OldIrql);
  166. if (irp != NULL)
  167. {
  168. POEM_INPUT_REPORT report = (POEM_INPUT_REPORT)irp->UserBuffer;
  169. //
  170. // Tell the system that we are not idling.
  171. //
  172. PoSetSystemState(ES_USER_PRESENT);
  173. report->ButtonState = ButtonState;
  174. irp->IoStatus.Information = sizeof(OEM_INPUT_REPORT);
  175. irp->IoStatus.Status = STATUS_SUCCESS;
  176. IoReleaseRemoveLock(&DevExt->RemoveLock, irp);
  177. IoCompleteRequest(irp, IO_NO_INCREMENT);
  178. DBGPRINT(3, ("Button Event (ButtonState=%x)\n", ButtonState));
  179. }
  180. else
  181. {
  182. WARNPRINT(("no pending ReadReport irp, must have been canceled\n"));
  183. }
  184. }
  185. else
  186. {
  187. DBGPRINT(3, ("button state is unstable, try again (PrevState=%x,NewState=%x)\n",
  188. DevExt->LastButtonState, ButtonState));
  189. DevExt->LastButtonState = ButtonState;
  190. KeSetTimer(&DevExt->DebounceTimer,
  191. DevExt->DebounceTime,
  192. &DevExt->TimerDpc);
  193. }
  194. EXIT(2, ("!\n"));
  195. return;
  196. } //OemButtonDebounceDpc