313 lines
8.6 KiB
C
313 lines
8.6 KiB
C
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ioctl.c
|
|
|
|
Abstract:
|
|
|
|
USB device driver for Intel/Microsoft diagnostic apps
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
PURPOSE.
|
|
|
|
Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
|
|
|
|
|
|
Revision History:
|
|
|
|
5-4-96 : created
|
|
7-21-97 : Added Chapter 11 IOCTL's (t-toddca)
|
|
|
|
--*/
|
|
|
|
#define DRIVER
|
|
|
|
|
|
#include "wdm.h"
|
|
#include "stdarg.h"
|
|
#include "stdio.h"
|
|
|
|
// Enable 1-byte alignment in structs
|
|
#pragma pack (push,1)
|
|
#include "usb100.h"
|
|
#include "usbdi.h"
|
|
#include "usbdlib.h"
|
|
#include "usbioctl.h"
|
|
#pragma pack (pop) //disable 1-byte alignment
|
|
|
|
#include "opaque.h"
|
|
|
|
// Enable 1-byte alignment in structs
|
|
#pragma pack (push,1)
|
|
#include "ioctl.h"
|
|
#include "chap9drv.h"
|
|
#include "USBDIAG.h"
|
|
#pragma pack (pop) //disable 1-byte alignment
|
|
|
|
extern USBD_VERSION_INFORMATION gVersionInformation;
|
|
|
|
NTSTATUS
|
|
USBDIAG_ProcessIOCTL(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to the device object for this instance of the 82930
|
|
devcice.
|
|
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
PVOID ioBuffer;
|
|
ULONG inputBufferLength;
|
|
ULONG outputBufferLength;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
ULONG ioControlCode;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
USBDIAG_KdPrint(("USBDIAG.SYS: IRP_MJ_DEVICE_CONTROL\n"));
|
|
//
|
|
// Get a pointer to the current location in the Irp. This is where
|
|
// the function codes and parameters are located.
|
|
//
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
//
|
|
// Get a pointer to the device extension
|
|
//
|
|
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
//USBDIAG_KdPrint(("USBDIAG.SYS: DeviceObj: %X | DeviceExt: %X\n",DeviceObject, DeviceObject->DeviceExtension));
|
|
|
|
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
|
|
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
|
|
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
|
|
|
|
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
USBDIAG_KdPrint(("USBDIAG.SYS: IOControlCode: %X\n", ioControlCode));
|
|
|
|
//
|
|
// Handle Ioctls from User mode
|
|
//
|
|
|
|
switch (ioControlCode) {
|
|
|
|
case IOCTL_USBDIAG_GET_USBDI_VERSION:
|
|
{
|
|
PULONG pulUSBDIVersion = (PULONG)ioBuffer;
|
|
|
|
*pulUSBDIVersion = gVersionInformation.USBDI_Version;
|
|
|
|
Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(ULONG);
|
|
}
|
|
break;
|
|
|
|
case IOCTL_USBDIAG_CHAP9_GET_DEVHANDLE:
|
|
|
|
{
|
|
//
|
|
// inputs - ptr to _REQ_DEVICE_HANDLES structure
|
|
// with devicehandle set to the last handle
|
|
// returned or NULL.
|
|
|
|
// outputs -
|
|
//
|
|
|
|
struct _REQ_DEVICE_HANDLES *reqDeviceHandles;
|
|
PDEVICE_LIST_ENTRY device;
|
|
PDEVICE_EXTENSION localDeviceExtension;
|
|
PDEVICE_OBJECT deviceObject;
|
|
|
|
//USBDIAG_KdPrint(("USBDIAG.SYS: IOCTL_USBDIAG_CHAP9_GET_DEVHANDLE\n"));
|
|
|
|
// walk our list of PDOs and find the current one
|
|
// if cuurent is NULL return the first PDO in our list
|
|
// if current can not be found then return NULL for next_device
|
|
|
|
reqDeviceHandles = ioBuffer;
|
|
|
|
//
|
|
// Check that the buffer length is of the appropriate size
|
|
//
|
|
|
|
if (inputBufferLength < sizeof(struct _REQ_DEVICE_HANDLES) ||
|
|
outputBufferLength < sizeof(struct _REQ_DEVICE_HANDLES)) {
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
|
|
break;
|
|
}
|
|
|
|
device = deviceExtension->DeviceList;
|
|
|
|
// should always have at least one
|
|
if (device != NULL)
|
|
{
|
|
if (reqDeviceHandles->DeviceHandle != NULL)
|
|
{
|
|
//
|
|
// Searching for the next device in the list
|
|
//
|
|
|
|
while (device != NULL && device != reqDeviceHandles->DeviceHandle)
|
|
{
|
|
device = device->Next;
|
|
}
|
|
|
|
//
|
|
// Make device point to the next possible device in our list,
|
|
// if we haven't reached the end of the list
|
|
//
|
|
|
|
if (NULL != device)
|
|
{
|
|
device = device -> Next;
|
|
}
|
|
}
|
|
|
|
//
|
|
// At this point, device is either NULL or points to a usbdiag
|
|
// device. However, the diag device may not yet be started and
|
|
// if so, should not be reported in this query so we must skip
|
|
// over it. We will skip over all such devices in our list.
|
|
// Do that here.
|
|
//
|
|
|
|
while (device != NULL)
|
|
{
|
|
deviceObject = FDO_FROM_DEVICE_HANDLE(device);
|
|
|
|
localDeviceExtension = deviceObject -> DeviceExtension;
|
|
|
|
if (!(localDeviceExtension -> Stopped))
|
|
{
|
|
//
|
|
// Found a legit started device, break out of this loop
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Oops, we've got a device but it hasn't been started yet,
|
|
// don't return it in the query. Try the next one in the list.
|
|
//
|
|
|
|
device = device -> Next;
|
|
}
|
|
|
|
//
|
|
// At this point, device is either NULL or points to a device that
|
|
// can be legitimately returned to the calling app. If a legit
|
|
// device, then create a device string for it.
|
|
//
|
|
|
|
if (NULL != device)
|
|
{
|
|
sprintf(reqDeviceHandles->DeviceString,
|
|
"%2.2d Vid (0x%4.4x) Pid (0x%4.4x)",
|
|
device->DeviceNumber,
|
|
localDeviceExtension->pDeviceDescriptor->idVendor,
|
|
localDeviceExtension->pDeviceDescriptor->idProduct);
|
|
}
|
|
}
|
|
|
|
reqDeviceHandles -> NextDeviceHandle = device;
|
|
Irp->IoStatus.Information = sizeof(struct _REQ_DEVICE_HANDLES);
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IOCTL_USBDIAG_CHAP9_CONTROL:
|
|
|
|
//
|
|
// inputs -
|
|
// outputs -
|
|
//
|
|
//USBDIAG_KdPrint(("USBDIAG.SYS: IOCTL_USBDIAG_CHAP9_CONTROL\n"));
|
|
|
|
ntStatus = USBDIAG_Chap9Control(DeviceObject, Irp);
|
|
//USBDIAG_KdPrint(("USBDIAG.SYS: Done w/ IOCTL_USBDIAG_CHAP9_CONTROL\n"));
|
|
|
|
goto USBDIAG_ProcessIOCTL_Done;
|
|
|
|
break;
|
|
|
|
case IOCTL_USBDIAG_HIDP_GETCOLLECTION:
|
|
|
|
/*
|
|
// calls thru to the HID Parser
|
|
// NOTE: The function called will complete the IRP since it will
|
|
// free the buffers created by the HID parser immediately
|
|
// thereafter, and since BUFFERED method is used, the IOS
|
|
// needs the buffers to be present while it's copying it
|
|
// back to the user space. So, we jump to the end to avoid this.
|
|
*/
|
|
//USBDIAG_KdPrint(("USBDIAG.SYS: IOCTL_USBDIAG_HIDP_GETCOLLECTION\n"));
|
|
|
|
ntStatus = USBDIAG_HIDP_GetCollection (DeviceObject, Irp);
|
|
break;
|
|
|
|
case IOCTL_USBDIAG_CONFIGURE_DEVICE:
|
|
|
|
/*
|
|
// Configures a given device in the given configuration
|
|
// Input: IOCTL block indicating what configuration to put
|
|
// device into
|
|
// Output: Success/error code
|
|
//
|
|
*/
|
|
//USBDIAG_KdPrint(("USBDIAG.SYS: IOCTL_USBDIAG_CONFIGURE_DEVICE\n"));
|
|
|
|
ntStatus = USBDIAG_Configure_Device (DeviceObject, Irp);
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//USBDIAG_KdPrint(("USBDIAG.SYS: Chap9Ctrl Compltng Irp w/ IoStatus.Status=%X | .Inf = %X | ntSt=%X\n",
|
|
//Irp->IoStatus.Status, Irp->IoStatus.Information, ntStatus));
|
|
|
|
ntStatus = Irp->IoStatus.Status;
|
|
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
USBDIAG_ProcessIOCTL_Done:
|
|
|
|
return ntStatus;
|
|
|
|
}
|