windows-nt/Source/XPSP1/NT/drivers/wdm/input/tabletpc/buttons/oembutton.c

230 lines
7.3 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
oempen.c
Abstract: Contains OEM specific functions.
Environment:
Kernel mode
Author:
Michael Tsang (MikeTs) 13-Apr-2000
Revision History:
--*/
#include "pch.h"
#ifdef ALLOC_PRAGMA
#endif //ifdef ALLOC_PRAGMA
UCHAR gReportDescriptor[32] = {
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x03, // USAGE (Programmable Buttons)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x06, // USAGE_MAXIMUM (Button 6)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
HID_DESCRIPTOR gHidDescriptor =
{
sizeof(HID_DESCRIPTOR), //bLength
HID_HID_DESCRIPTOR_TYPE, //bDescriptorType
HID_REVISION, //bcdHID
0, //bCountry - not localized
1, //bNumDescriptors
{ //DescriptorList[0]
HID_REPORT_DESCRIPTOR_TYPE, //bReportType
sizeof(gReportDescriptor) //wReportLength
}
};
PWSTR gpwstrManufacturerID = L"Microsoft";
PWSTR gpwstrProductID = L"Tablet PC Buttons";
PWSTR gpwstrSerialNumber = L"0";
/*****************************************************************************
*
* @doc EXTERNAL
*
* @func BOOLEAN | OemInterruptServiceRoutine |
* Interrupt service routine for the button device.
*
* @parm IN PKINTERRUPT | Interrupt | Points to the interrupt object.
* @parm IN PDEVICE_EXTENSION | DevExt | Points to the device extension.
*
* @rvalue SUCCESS | returns TRUE - it's our interrupt.
* @rvalue FAILURE | returns FALSE - it's not our interrupt.
*
*****************************************************************************/
BOOLEAN EXTERNAL
OemInterruptServiceRoutine(
IN PKINTERRUPT Interrupt,
IN PDEVICE_EXTENSION DevExt
)
{
PROCNAME("OemInterruptServiceRoutine")
BOOLEAN rc = FALSE;
UCHAR ButtonState;
ENTER(1, ("(Interrupt=%p,DevExt=%p)\n", Interrupt, DevExt));
UNREFERENCED_PARAMETER(Interrupt);
//
// Note: the action of reading the button state will also clear
// the interrupt.
//
ButtonState = READBUTTONSTATE(DevExt);
if ((ButtonState & BUTTON_INTERRUPT_MASK) &&
((ButtonState & BUTTON_STATUS_MASK)!= DevExt->LastButtonState))
{
DBGPRINT(1, ("Button interrupt (Buttons=%x)\n", ButtonState));
DevExt->LastButtonState = ButtonState & BUTTON_STATUS_MASK;
DevExt->dwfHBut |= HBUTF_DEBOUNCE_TIMER_SET;
KeSetTimer(&DevExt->DebounceTimer,
DevExt->DebounceTime,
&DevExt->TimerDpc);
DBGPRINT(3, ("Button Interrupt (ButtonState=%x)\n", ButtonState));
rc = TRUE;
}
EXIT(1, ("=%x\n", rc));
return rc;
} //OemInterruptServiceRoutine
/*****************************************************************************
*
* @doc EXTERNAL
*
* @func VOID | OemButtonDebounceDpc |
* Timer DPC routine to handle button debounce.
*
* @parm IN PKDPC | Dpc | Points to the DPC object.
* @parm IN PDEVICE_EXTENSION | DevExt | Points to the device extension.
* @parm IN PVOID | SysArg1 | System argument 1.
* @parm IN PVOID | SysArg2 | System arugment 2.
*
* @rvalue None.
*
*****************************************************************************/
VOID EXTERNAL
OemButtonDebounceDpc(
IN PKDPC Dpc,
IN PDEVICE_EXTENSION DevExt,
IN PVOID SysArg1,
IN PVOID SysArg2
)
{
PROCNAME("OemButtonDebounceDpc")
UCHAR ButtonState;
ENTER(2, ("(Dpc=%p,DevExt=%p,SysArg1=%p,SysArg2=%p)\n",
Dpc, DevExt, SysArg1, SysArg2));
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(SysArg1);
UNREFERENCED_PARAMETER(SysArg2);
ButtonState = READBUTTONSTATE(DevExt) & BUTTON_STATUS_MASK;
if (ButtonState == DevExt->LastButtonState)
{
PIRP irp = NULL;
KIRQL OldIrql;
PLIST_ENTRY plist;
PDRIVER_CANCEL OldCancelRoutine;
if (ButtonState & DevExt->StuckButtonsMask)
{
if (DevExt->bStuckCount >= MAX_STUCK_COUNT)
{
DBGPRINT(1, ("Clearing stuck buttons (Buttons=%x,StuckMask=%x)\n",
ButtonState, DevExt->StuckButtonsMask));
ButtonState &= ~DevExt->StuckButtonsMask;
}
else
{
DBGPRINT(1, ("Detected stuck buttons (Buttons=%x,StuckMask=%x,Count=%d)\n",
ButtonState, DevExt->StuckButtonsMask,
DevExt->bStuckCount));
DevExt->bStuckCount++;
}
}
else if (DevExt->StuckButtonsMask != 0)
{
//
// The button has unstuck after all???
//
DBGPRINT(1, ("Button has unstuck (Buttons=%x,StuckMask=%x)\n",
ButtonState, DevExt->StuckButtonsMask));
DevExt->bStuckCount = 0;
}
DevExt->dwfHBut &= ~HBUTF_DEBOUNCE_TIMER_SET;
KeAcquireSpinLock(&DevExt->SpinLock, &OldIrql);
if (!IsListEmpty(&DevExt->PendingIrpList))
{
plist = RemoveHeadList(&DevExt->PendingIrpList);
irp = CONTAINING_RECORD(plist, IRP, Tail.Overlay.ListEntry);
OldCancelRoutine = IoSetCancelRoutine(irp, NULL);
ASSERT(OldCancelRoutine == ReadReportCanceled);
}
KeReleaseSpinLock(&DevExt->SpinLock, OldIrql);
if (irp != NULL)
{
POEM_INPUT_REPORT report = (POEM_INPUT_REPORT)irp->UserBuffer;
//
// Tell the system that we are not idling.
//
PoSetSystemState(ES_USER_PRESENT);
report->ButtonState = ButtonState;
irp->IoStatus.Information = sizeof(OEM_INPUT_REPORT);
irp->IoStatus.Status = STATUS_SUCCESS;
IoReleaseRemoveLock(&DevExt->RemoveLock, irp);
IoCompleteRequest(irp, IO_NO_INCREMENT);
DBGPRINT(3, ("Button Event (ButtonState=%x)\n", ButtonState));
}
else
{
WARNPRINT(("no pending ReadReport irp, must have been canceled\n"));
}
}
else
{
DBGPRINT(3, ("button state is unstable, try again (PrevState=%x,NewState=%x)\n",
DevExt->LastButtonState, ButtonState));
DevExt->LastButtonState = ButtonState;
KeSetTimer(&DevExt->DebounceTimer,
DevExt->DebounceTime,
&DevExt->TimerDpc);
}
EXIT(2, ("!\n"));
return;
} //OemButtonDebounceDpc