|
|
//**************************************************************************
//
// IOCTL.C -- Xena Gaming Project
//
// Version 3.XX
//
// Copyright (c) 1997 Microsoft Corporation. All rights reserved.
//
// @doc
// @module IOCTL.C | Routines to support internal ioctl queries
//**************************************************************************
#include "msgame.h"
//---------------------------------------------------------------------------
// Alloc_text pragma to specify routines that can be paged out.
//---------------------------------------------------------------------------
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, MSGAME_GetDeviceDescriptor)
#pragma alloc_text (PAGE, MSGAME_GetReportDescriptor)
#pragma alloc_text (PAGE, MSGAME_GetAttributes)
#endif
//---------------------------------------------------------------------------
// @func Process the Control IRPs sent to this device
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @parm PIRP | pIrp | Pointer to IO request packet
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_Internal_Ioctl (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION pDevExt; PIO_STACK_LOCATION pIrpStack;
MsGamePrint ((DBG_VERBOSE, "%s: %s_Internal_Ioctl Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get pointer to current location in pIrp
//
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
//
// Get a pointer to the device extension
//
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
//
// Increment IRP count to hold driver removes
//
InterlockedIncrement (&pDevExt->IrpCount);
//
// Check if we've been removed and bounce request
//
if (pDevExt->Removed) { //
// Someone sent us another IRP after removed
//
MsGamePrint ((DBG_SEVERE, "%s: internal Irp after device removed\n", MSGAME_NAME)); ASSERT (FALSE);
if (!InterlockedDecrement (&pDevExt->IrpCount)) KeSetEvent (&pDevExt->RemoveEvent, 0, FALSE);
pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_DELETE_PENDING; IoCompleteRequest (pIrp, IO_NO_INCREMENT); return (STATUS_DELETE_PENDING); }
//
// Process HID internal IO request
//
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_DEVICE_DESCRIPTOR\n", MSGAME_NAME)); ntStatus = MSGAME_GetDeviceDescriptor (DeviceObject, pIrp); break;
case IOCTL_HID_GET_REPORT_DESCRIPTOR: MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_REPORT_DESCRIPTOR\n", MSGAME_NAME)); ntStatus = MSGAME_GetReportDescriptor (DeviceObject, pIrp); break;
case IOCTL_HID_READ_REPORT: MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_READ_REPORT\n", MSGAME_NAME)); ntStatus = MSGAME_ReadReport (DeviceObject, pIrp); break;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES: MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_DEVICE_ATTRIBUTES\n", MSGAME_NAME)); ntStatus = MSGAME_GetAttributes (DeviceObject, pIrp); break;
case IOCTL_HID_ACTIVATE_DEVICE: case IOCTL_HID_DEACTIVATE_DEVICE: MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_(DE)ACTIVATE_DEVICE\n", MSGAME_NAME)); ntStatus = STATUS_SUCCESS; break;
case IOCTL_HID_GET_FEATURE: MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_GET_FEATURE\n", MSGAME_NAME)); ntStatus = MSGAME_GetFeature (DeviceObject, pIrp); break;
case IOCTL_HID_SET_FEATURE: MsGamePrint ((DBG_VERBOSE, "%s: IOCTL_HID_SET_FEATURE\n", MSGAME_NAME)); ntStatus = STATUS_NOT_SUPPORTED; break;
default: MsGamePrint ((DBG_CONTROL, "%s: Unknown or unsupported IOCTL (%x)\n", MSGAME_NAME, pIrpStack->Parameters.DeviceIoControl.IoControlCode)); ntStatus = STATUS_NOT_SUPPORTED; break; }
//
// Set real return status in pIrp
//
pIrp->IoStatus.Status = ntStatus;
//
// Complete Irp
//
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
//
// Decrement IRP count for device removes
//
if (!InterlockedDecrement (&pDevExt->IrpCount)) KeSetEvent (&pDevExt->RemoveEvent, 0, FALSE);
//
// Return status
//
MsGamePrint ((DBG_VERBOSE, "%s: %s_Internal_Ioctl Exit = %x\n", MSGAME_NAME, MSGAME_NAME, ntStatus)); return (STATUS_SUCCESS); }
//---------------------------------------------------------------------------
// @func Processes the HID getdevice descriptor IRP
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @parm PIRP | pIrp | Pointer to IO request packet
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_GetDeviceDescriptor (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION pDevExt; PIO_STACK_LOCATION pIrpStack;
PAGED_CODE ();
MsGamePrint ((DBG_INFORM, "%s: %s_GetDeviceDescriptor Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get a pointer to the current location in the Irp
//
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
//
// Get a pointer to the device extension
//
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
//
// Get device descriptor into HIDCLASS buffer
//
ntStatus = DEVICE_GetDeviceDescriptor ( &pDevExt->PortInfo, pIrp->UserBuffer, pIrpStack->Parameters.DeviceIoControl.OutputBufferLength, &pIrp->IoStatus.Information);
//
// Return status
//
MsGamePrint ((DBG_INFORM, "%s: %s_GetDeviceDescriptor Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus)); return (ntStatus); }
//---------------------------------------------------------------------------
// @func Processes the HID get report descriptor IRP
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @parm PIRP | pIrp | Pointer to IO request packet
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_GetReportDescriptor (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) { PDEVICE_EXTENSION pDevExt; PIO_STACK_LOCATION pIrpStack; NTSTATUS ntStatus;
PAGED_CODE ();
MsGamePrint ((DBG_INFORM, "%s: %s_GetReportDescriptor Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get a pointer to the current location in the Irp
//
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
//
// Get a pointer to the device extension
//
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
//
// Get report descriptor into HIDCLASS buffer
//
ntStatus = DEVICE_GetReportDescriptor ( &pDevExt->PortInfo, pIrp->UserBuffer, pIrpStack->Parameters.DeviceIoControl.OutputBufferLength, &pIrp->IoStatus.Information);
//
// Return status
//
MsGamePrint ((DBG_INFORM, "%s: %s_GetReportDescriptor Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus)); return (ntStatus); }
//---------------------------------------------------------------------------
// @func Processes the HID get attributes IRP
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @parm PIRP | pIrp | Pointer to IO request packet
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_GetAttributes (PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION pDevExt; PIO_STACK_LOCATION irpStack; PHID_DEVICE_ATTRIBUTES pDevAtt;
PAGED_CODE ();
MsGamePrint ((DBG_INFORM, "%s: %s_GetAttributes Entry\n", MSGAME_NAME, MSGAME_NAME));
//
// Get a pointer to the current location in the Irp
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get a pointer to the device extension
//
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject); pDevAtt = (PHID_DEVICE_ATTRIBUTES) Irp->UserBuffer;
ASSERT(sizeof(HID_DEVICE_ATTRIBUTES) == irpStack->Parameters.DeviceIoControl.OutputBufferLength);
//
// Fill in HID device attributes
//
pDevAtt->Size = sizeof (HID_DEVICE_ATTRIBUTES); pDevAtt->VendorID = MSGAME_VENDOR_ID; pDevAtt->ProductID = GET_DEVICE_ID(&pDevExt->PortInfo); pDevAtt->VersionNumber = MSGAME_VERSION_NUMBER;
//
// Report how many bytes were copied
//
Irp->IoStatus.Information = sizeof (HID_DEVICE_ATTRIBUTES);
//
// Return status
//
MsGamePrint ((DBG_INFORM, "%s: %s_GetAttributes Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus)); return (ntStatus); }
//---------------------------------------------------------------------------
// @func Processes the HID get device features IRP
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @parm PIRP | pIrp | Pointer to IO request packet
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_GetFeature (PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION pDevExt; PIO_STACK_LOCATION irpStack; PHID_XFER_PACKET Packet; PUCHAR Report;
MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Entry\n", MSGAME_NAME, MSGAME_NAME));
//
// Get a pointer to the current location in the Irp
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get a pointer to the device extension
//
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
//
// Get pointer to feature packet
//
Packet = (PHID_XFER_PACKET)Irp->UserBuffer;
//
// Test packet size in case version error
//
ASSERT (irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(HID_XFER_PACKET));
//
// Setup return values (return HidReportId even on errors)
//
Report = Packet->reportBuffer; *(PHID_REPORT_ID)Report++ = (HID_REPORT_ID)Packet->reportId; Irp->IoStatus.Information = sizeof (HID_REPORT_ID);
//
// Check if device has been removed
//
if (pDevExt->Removed || pDevExt->Surprised) { MsGamePrint ((DBG_SEVERE, "%s: %s_GetFeature On Removed Device!\n", MSGAME_NAME, MSGAME_NAME)); return (STATUS_DELETE_PENDING); }
//
// Check if device being removed
//
if (pDevExt->Removing) { MsGamePrint ((DBG_SEVERE, "%s: %s_GetFeature On Device Pending Removal!\n", MSGAME_NAME, MSGAME_NAME)); return (STATUS_DELETE_PENDING); }
//
// Call mini-driver to process
//
MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Report Id = %lu\n", MSGAME_NAME, MSGAME_NAME, Packet->reportId)); ntStatus = DEVICE_GetFeature (&pDevExt->PortInfo, Packet->reportId, Report, Packet->reportBufferLen, &Irp->IoStatus.Information);
//
// Return status
//
MsGamePrint ((DBG_INFORM, "%s: %s_GetFeature Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus)); return (ntStatus); }
//---------------------------------------------------------------------------
// @func Processes the HID read report IRP
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @parm PIRP | pIrp | Pointer to IO request packet
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_ReadReport (IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) { NTSTATUS ntStatus = STATUS_PENDING; PDEVICE_EXTENSION pDevExt; PIO_STACK_LOCATION pIrpStack; PIO_STACK_LOCATION nextStack; KIRQL OldIrql; PUCHAR Report;
MsGamePrint ((DBG_VERBOSE, "%s: %s_ReadReport Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get a pointer to the device extension.
//
pDevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
//
// Get stack location
//
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
//
// Setup return values (return HidReportId even on errors)
//
Report = pIrp->UserBuffer; if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength > sizeof (DEVICE_PACKET)) { *(PHID_REPORT_ID)Report++ = (HID_REPORT_ID)MSGAME_INPUT_JOYINFOEX; pIrp->IoStatus.Information = sizeof (HID_REPORT_ID); } else pIrp->IoStatus.Information = 0;
//
// Check if device has been removed
//
if (pDevExt->Removed || pDevExt->Surprised) { MsGamePrint ((DBG_SEVERE, "%s: %s_ReadReport On Removed Device!\n", MSGAME_NAME, MSGAME_NAME)); return (STATUS_DELETE_PENDING); }
//
// Check if device being removed
//
if (pDevExt->Removing) { MsGamePrint ((DBG_SEVERE, "%s: %s_ReadReport On Device Pending Removal!\n", MSGAME_NAME, MSGAME_NAME)); return (STATUS_DELETE_PENDING); }
//
// Poll the device layer
//
ntStatus = DEVICE_ReadReport ( &pDevExt->PortInfo, Report, pIrpStack->Parameters.DeviceIoControl.OutputBufferLength, &pIrp->IoStatus.Information);
//
// Check status for device changes
//
switch (ntStatus) { case STATUS_SIBLING_ADDED: //
// Tell GameEnum to Create a Device
//
ntStatus = MSGAME_CreateDevice (DeviceObject); break;
case STATUS_SIBLING_REMOVED: //
// Tell GameEnum to Remove a Device
//
ntStatus = MSGAME_RemoveDevice (DeviceObject); break;
case STATUS_DEVICE_CHANGED: //
// Tell GameEnum to Create a New Device
//
ntStatus = MSGAME_ChangeDevice (DeviceObject); break; }
//
// Return status
//
MsGamePrint ((DBG_VERBOSE, "%s: %s_ReadReport Exit = 0x%x\n", MSGAME_NAME, MSGAME_NAME, ntStatus)); return (ntStatus); }
|