📄 ioctl.c
字号:
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ioctl.c
Abstract:
USB device driver for Philips D12 USB test board
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
--*/
#define DRIVER
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "D12.h"
#include "ioctl.h"
#include "usbdlib.h"
PUSB_CONFIGURATION_DESCRIPTOR
D12_GetConfigDescriptor(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
devcice.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb;
ULONG siz;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
D12_KdPrint (("D12TEST.SYS: enter D12_GetConfigDescriptor\n"));
deviceExtension = DeviceObject->DeviceExtension;
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (urb) {
// BUGBUG 82930 chokes if on the next command if you don't get
// the entire descriptor on the first try
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR)+256;
get_config_descriptor_retry2:
configurationDescriptor = ExAllocatePool(NonPagedPool,
siz);
if (configurationDescriptor) {
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
configurationDescriptor,
NULL,
siz,
NULL);
ntStatus = D12_CallUSBD(DeviceObject, urb);
D12_KdPrint (("D12TEST.SYS: Configuration Descriptor = %x, len %x\n",
configurationDescriptor,
urb->UrbControlDescriptorRequest.TransferBufferLength));
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (NT_SUCCESS(ntStatus) &&
(urb->UrbControlDescriptorRequest.TransferBufferLength >=
sizeof(USB_CONFIGURATION_DESCRIPTOR)) &&
(configurationDescriptor->wTotalLength >=
sizeof(USB_CONFIGURATION_DESCRIPTOR)))
{
//
// The Get Config Descriptor request did not return an error
// AND at least enough data was transferred to fill a Config
// Descriptor AND the Config Descriptor wLength is at least the
// size of a Config Descriptor
//
if (configurationDescriptor->wTotalLength > siz)
{
//
// The request buffer is not big enough to hold the
// entire set of descriptors. Free the current buffer
// and retry with a buffer which should be big enough.
//
siz = configurationDescriptor->wTotalLength;
ExFreePool(configurationDescriptor);
configurationDescriptor = NULL;
goto get_config_descriptor_retry2;
}
else if (configurationDescriptor->wTotalLength >
urb->UrbControlDescriptorRequest.TransferBufferLength)
{
//
// The request buffer is greater than or equal to the
// Config Descriptor wLength, but less data was transferred
// than wLength. Return NULL to indicate a device error.
//
ExFreePool(configurationDescriptor);
configurationDescriptor = NULL;
}
//
// else everything is OK with the Config Descriptor, return it.
//
}
else
{
//
// The Get Config Descriptor request returned an error OR
// not enough data was transferred to fill a Config Descriptor
// OR the Config Descriptor wLength is less than the size of
// a Config Descriptor. Return NULL to indicate a device error.
//
ExFreePool(configurationDescriptor);
configurationDescriptor = NULL;
}
ExFreePool(urb);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
D12_KdPrint (("D12TEST.SYS: exit D12_GetConfigDescriptor\n"));
return configurationDescriptor;
}
NTSTATUS
D12_GetPortStatus(
IN PDEVICE_OBJECT DeviceObject,
IN PULONG PortStatus
)
/*++
Routine Description:
returns the port status for our device
Arguments:
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION deviceExtension;
D12_KdPrint (("D12TEST.SYS: enter D12_GetPortStatus\n"));
deviceExtension = DeviceObject->DeviceExtension;
*PortStatus = 0;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_GET_PORT_STATUS,
deviceExtension->TopOfStackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, /* INTERNAL */
&event,
&ioStatus);
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
nextStack->Parameters.Others.Argument1 = PortStatus;
D12_KdPrint (("D12TEST.SYS: calling USBD port status api\n"));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
D12_KdPrint (("D12TEST.SYS: return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
D12_KdPrint (("D12TEST.SYS: Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
D12_KdPrint (("D12TEST.SYS: Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
D12_KdPrint (("D12TEST.SYS: Port status = %x\n", *PortStatus));
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
D12_KdPrint (("D12TEST.SYS: D12_GetPortStatus (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
D12_ResetParentPort(
IN IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Reset the our parent port
Arguments:
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION deviceExtension;
D12_KdPrint (("D12TEST.SYS: enter D12_ResetPort\n"));
deviceExtension = DeviceObject->DeviceExtension;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_RESET_PORT,
deviceExtension->TopOfStackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, /* INTERNAL */
&event,
&ioStatus);
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
D12_KdPrint (("D12TEST.SYS: calling USBD enable port api\n"));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
D12_KdPrint (("D12TEST.SYS: return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
D12_KdPrint (("D12TEST.SYS: Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
D12_KdPrint (("D12TEST.SYS: Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
D12_KdPrint (("D12TEST.SYS: D12_ResetPort (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
D12_ReadWriteRegister(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -