|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
feature.c
Abstract
Feature handling routines
Author:
Ervin P.
Environment:
Kernel mode only
Revision History:
--*/
#include "pch.h"
#if 0
/*
******************************************************************************** * HidpGetSetFeatureComplete ******************************************************************************** * * */ NTSTATUS HidpGetSetFeatureComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PHIDCLASS_DEVICE_EXTENSION hidDeviceExtension = (PHIDCLASS_DEVICE_EXTENSION)Context; PHID_XFER_PACKET featurePacket = Irp->UserBuffer; NTSTATUS status = Irp->IoStatus.Status;
DBG_COMMON_ENTRY()
ASSERT(hidDeviceExtension->isClientPdo);
if (featurePacket){
DBG_RECORD_FEATURE(featurePacket->reportId, IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode, TRUE)
/*
* Free the feature packet. */ ExFreePool(featurePacket); Irp->UserBuffer = NULL; }
if (NT_SUCCESS(status)){ FDO_EXTENSION *fdoExt = &hidDeviceExtension->pdoExt.deviceFdoExt->fdoExt; if (fdoExt->deviceDesc.ReportIDs[0].ReportID == 0){ /*
* Since this collection only has one report, * we deleted the report id (which is known implicitly) * on the way down. We now have to bump the return * value to indicate that one more byte was sent or received. */ (ULONG)Irp->IoStatus.Information++; } }
/*
* If the lower driver returned PENDING, mark our stack location as pending also. */ if (Irp->PendingReturned){ IoMarkIrpPending(Irp); }
DBG_COMMON_EXIT() return status; }
/*
******************************************************************************** * HidpGetSetFeature ******************************************************************************** * * There are not many differences between reading and writing a feature at this level, * so we have one function do both. * * controlCode is either IOCTL_HID_GET_FEATURE or IOCTL_HID_SET_FEATURE. * * Note: This function cannot be pageable because it is called * from the IOCTL dispatch routine, which can get called * at DISPATCH_LEVEL. * */ NTSTATUS HidpGetSetFeature( IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp, IN ULONG controlCode, OUT BOOLEAN *sentIrp) { FDO_EXTENSION *fdoExt; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION currentIrpSp, nextIrpSp; PFILE_OBJECT fileObject; PHIDCLASS_FILE_EXTENSION fileExtension;
DBG_COMMON_ENTRY()
ASSERT(HidDeviceExtension->isClientPdo); fdoExt = &HidDeviceExtension->pdoExt.deviceFdoExt->fdoExt; currentIrpSp = IoGetCurrentIrpStackLocation(Irp); nextIrpSp = IoGetNextIrpStackLocation(Irp);
*sentIrp = FALSE;
/*
* Get the file extension. */ ASSERT(currentIrpSp->FileObject); fileObject = currentIrpSp->FileObject; if(!fileObject->FsContext) { DBGWARN(("Attempted to get/set feature with no file extension")) return STATUS_PRIVILEGE_NOT_HELD; } fileExtension = (PHIDCLASS_FILE_EXTENSION)fileObject->FsContext; ASSERT(fileExtension->Signature == HIDCLASS_FILE_EXTENSION_SIG);
/*
* Check security. */ if (fileExtension->SecurityCheck){ PHIDP_COLLECTION_DESC collectionDesc;
/*
* Get our collection description. */ collectionDesc = GetCollectionDesc(fdoExt, fileExtension->CollectionNumber); if (collectionDesc){
/*
* Make sure that there is a feature report on this collection * (or that we allow feature reads on a non-feature ctn for this device). */ if ((collectionDesc->FeatureLength > 0) || (fdoExt->deviceSpecificFlags & DEVICE_FLAG_ALLOW_FEATURE_ON_NON_FEATURE_COLLECTION)){
PUCHAR featureBuf; ULONG featureBufLen;
switch (controlCode){ case IOCTL_HID_GET_FEATURE: featureBufLen = currentIrpSp->Parameters.DeviceIoControl.OutputBufferLength; featureBuf = HidpGetSystemAddressForMdlSafe(Irp->MdlAddress); break; case IOCTL_HID_SET_FEATURE: featureBuf = Irp->AssociatedIrp.SystemBuffer; featureBufLen = currentIrpSp->Parameters.DeviceIoControl.InputBufferLength; break; default: TRAP; status = STATUS_INVALID_PARAMETER; featureBuf = NULL; featureBufLen = 0; }
if (featureBuf && featureBufLen){ PHIDP_REPORT_IDS reportIdent; UCHAR reportId;
/*
* The client includes the report id as the first byte of the report. * We send down the report byte only if the device has multiple * report IDs (i.e. the report id is not implicit). */ reportId = featureBuf[0]; if (fdoExt->deviceDesc.ReportIDs[0].ReportID == 0){ DBGASSERT((reportId == 0), ("Report Id should be zero, acutal id = %d", reportId), FALSE) featureBuf++; featureBufLen--; }
/*
* Try to find a matching feature report for this device. */ reportIdent = GetReportIdentifier(fdoExt, reportId);
/*
* Check the buffer length against the * feature length in the report identifier. */ if (reportIdent){ if (reportIdent->FeatureLength){ switch (controlCode){ case IOCTL_HID_GET_FEATURE: /*
* The buffer must be big enough for the report. */ if (featureBufLen < reportIdent->FeatureLength){ ASSERT(!(PVOID)"feature buf must be at least feature size for get-feature."); reportIdent = NULL; } break; case IOCTL_HID_SET_FEATURE: /*
* The buffer must be big enough for the report. * It CAN be larger, and it is up to us to use * the correct report size from the report identifier. */ if (featureBufLen < reportIdent->FeatureLength){ ASSERT(!(PVOID)"feature buf must be exact size for set-feature."); reportIdent = NULL; } else { featureBufLen = reportIdent->FeatureLength; } break; } } else { /*
* This report id is not for a feature report. */ reportIdent = NULL; } }
if (reportIdent || (fdoExt->deviceSpecificFlags & DEVICE_FLAG_ALLOW_FEATURE_ON_NON_FEATURE_COLLECTION)){
PHID_XFER_PACKET featurePacket = ALLOCATEPOOL(NonPagedPool, sizeof(HID_XFER_PACKET));
if (featurePacket){
featurePacket->reportBuffer = featureBuf; featurePacket->reportBufferLen = featureBufLen; featurePacket->reportId = reportId;
Irp->UserBuffer = featurePacket;
/*
* Prepare the next (lower) IRP stack location. * This will be HIDUSB's "current" stack location. */ nextIrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; nextIrpSp->Parameters.DeviceIoControl.IoControlCode = controlCode;
/*
* Note - input/output is relative to IOCTL servicer */ switch (controlCode){ case IOCTL_HID_GET_FEATURE: nextIrpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(HID_XFER_PACKET); break; case IOCTL_HID_SET_FEATURE: nextIrpSp->Parameters.DeviceIoControl.InputBufferLength = sizeof(HID_XFER_PACKET); break; default: TRAP; }
DBG_RECORD_FEATURE(reportId, controlCode, FALSE)
status = HidpCallDriverSynchronous(fdoExt->fdo, Irp); if (!NT_SUCCESS(status)){ DBGWARN(("HidpGetSetFeature: usb returned status %xh.", status)) } DBG_RECORD_FEATURE(reportId, controlCode, TRUE) ExFreePool(featurePacket); *sentIrp = FALSE; // needs to be completed again
} else { ASSERT(featurePacket); status = STATUS_INSUFFICIENT_RESOURCES; } } else { DBGASSERT(reportIdent, ("Some yahoo sent invalid data in ioctl %x", controlCode), FALSE) status = STATUS_DATA_ERROR; } } else if (NT_SUCCESS(status)) { DBGASSERT(featureBuf, ("Feature buffer is invalid"), FALSE) DBGASSERT(featureBufLen, ("Feature buffer length is invalid"), FALSE) status = STATUS_INVALID_BUFFER_SIZE; } } else { ASSERT(collectionDesc->FeatureLength); status = STATUS_INVALID_DEVICE_REQUEST; } } else { ASSERT(collectionDesc); status = STATUS_DEVICE_NOT_CONNECTED; } } else { ASSERT(fileExtension->SecurityCheck); status = STATUS_PRIVILEGE_NOT_HELD; }
DBGSUCCESS(status, FALSE) DBG_COMMON_EXIT()
return status; }
#endif
|