/*++ Copyright (c) 2000 Microsoft Corporation Module Name: smbpoll.c Abstract: Device polling for SMB Host Controller Driver for ALI chipset Author: Michael Hills Environment: Notes: Revision History: --*/ #include "smbalip.h" VOID SmbAliPollDpc ( IN struct _KDPC *Dpc, IN struct _SMB_CLASS* SmbClass, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ); VOID SmbAliPollWorker ( IN PDEVICE_OBJECT DeviceObject, IN struct _SMB_CLASS* SmbClass ); //LARGE_INTEGER SmbAlertPollRate = {-1*SECONDS, -1}; // 1 second poll rate LARGE_INTEGER SmbDevicePollRate = {-5*SECONDS, -1}; // 5 second poll rate LONG SmbDevicePollPeriod = 5000; // 5000 ms = 5 sec // address, command, protocol, valid_data, last_data SMB_ALI_POLL_ENTRY SmbDevicePollList [2] = { {0x0b, 0x16, SMB_READ_WORD, FALSE, 0}, // battery, BatteryStatus() {0x09, 0x13, SMB_READ_WORD, FALSE, 0} // charger, ChargerStatus() }; VOID SmbAliStartDevicePolling ( IN struct _SMB_CLASS* SmbClass ) { PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport); AliData->PollList = SmbDevicePollList; AliData->PollListCount = sizeof (SmbDevicePollList)/sizeof(SMB_ALI_POLL_ENTRY); AliData->PollWorker = IoAllocateWorkItem (SmbClass->DeviceObject); KeInitializeTimer (&AliData->PollTimer); KeInitializeDpc (&AliData->PollDpc, SmbAliPollDpc, SmbClass); KeInitializeEvent (&AliData->PollWorkerActive, NotificationEvent, TRUE); KeSetTimerEx (&AliData->PollTimer, SmbDevicePollRate, SmbDevicePollPeriod, &AliData->PollDpc); } VOID SmbAliStopDevicePolling ( IN struct _SMB_CLASS* SmbClass ) { PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport); KeCancelTimer (&AliData->PollTimer); if (KeResetEvent(&AliData->PollWorkerActive) == 0) { KeWaitForSingleObject (&AliData->PollWorkerActive, Executive, KernelMode, FALSE, NULL); } } VOID SmbAliPollDpc ( IN struct _KDPC *Dpc, IN struct _SMB_CLASS* SmbClass, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) { PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport); if (KeResetEvent(&AliData->PollWorkerActive) != 0) { IoQueueWorkItem (AliData->PollWorker, SmbAliPollWorker, DelayedWorkQueue, SmbClass); } } VOID SmbAliPollWorker ( IN PDEVICE_OBJECT DeviceObject, IN struct _SMB_CLASS* SmbClass ) { PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport); PIRP irp; SMB_REQUEST smbRequest; IO_STATUS_BLOCK ioStatus; KEVENT event; ULONG i; KeInitializeEvent (&event, SynchronizationEvent, FALSE); SmbPrint(SMB_TRACE, ("SmbAliPollWorker: Entered\n")); for (i = 0; i < AliData->PollListCount; i++) { smbRequest.Protocol = AliData->PollList[i].Protocol; smbRequest.Address = AliData->PollList[i].Address; smbRequest.Command = AliData->PollList[i].Command; irp = IoBuildDeviceIoControlRequest ( SMB_BUS_REQUEST, SmbClass->DeviceObject, &smbRequest, sizeof (smbRequest), &smbRequest, sizeof (smbRequest), TRUE, &event, &ioStatus); if (!irp) { continue; } IoCallDriver (SmbClass->DeviceObject, irp); KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL); if (!NT_SUCCESS(ioStatus.Status)) { continue; } if (smbRequest.Status != SMB_STATUS_OK) { if (AliData->PollList[i].ValidData) { AliData->PollList[i].ValidData = FALSE; } } else { //BUGBUG: only supports word protocols if ((!AliData->PollList[i].ValidData) || (AliData->PollList[i].LastData != *((PUSHORT)smbRequest.Data))) { AliData->PollList[i].ValidData = TRUE; AliData->PollList[i].LastData = *((PUSHORT)smbRequest.Data); SmbPrint(SMB_TRACE, ("SmbAliPollWorker: Alarm: Address 0x%02x Data 0x%04x\n", AliData->PollList[i].Address, AliData->PollList[i].LastData)); SmbClassLockDevice (SmbClass); SmbClassAlarm (SmbClass, AliData->PollList[i].Address, AliData->PollList[i].LastData); SmbClassUnlockDevice (SmbClass); } SmbPrint(SMB_TRACE, ("SmbAliPollWorker: AlarmData: Address 0x%02x Data 0x%04x\n", AliData->PollList[i].Address, AliData->PollList[i].LastData)); } } KeSetEvent (&AliData->PollWorkerActive, 0, FALSE); }