Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

657 lines
17 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
USBD.H
Abstract:
This module contains the PRIVATE (driver-only) definitions for the
code that implements the usbd driver.
Environment:
Kernel & user mode
Revision History:
09-29-95 : created
--*/
#ifndef USBKDEXTS
#include "dbg.h"
#endif
#define NAME_MAX 64
#define USBD_TAG 0x44425355 /* "USBD" */
#if DBG
#define DEBUG_LOG
#endif
//enable pageable code
#ifndef PAGE_CODE
#define PAGE_CODE
#endif
#define _USBD_
//
// Constents used to format USB setup packets
// for the default pipe
//
//
// Values for the bmRequest field
//
#define USB_HOST_TO_DEVICE 0x00
#define USB_DEVICE_TO_HOST 0x80
#define USB_STANDARD_COMMAND 0x00
#define USB_CLASS_COMMAND 0x20
#define USB_VENDOR_COMMAND 0x40
#define USB_COMMAND_TO_DEVICE 0x00
#define USB_COMMAND_TO_INTERFACE 0x01
#define USB_COMMAND_TO_ENDPOINT 0x02
#define USB_COMMAND_TO_OTHER 0x03
#define USBD_TAG 0x44425355 //"USBD"
/* Registry Keys */
// **
// The following keys are specific to the instance of the
// host controller -- the keys are read from the software
// branch of the registry for the given PDO:
//
/* DWORD keys */
// This key enables a set of global hacks for early or broken USB
// devices -- the default value is OFF
#define SUPPORT_NON_COMP_KEY L"SupportNonComp"
// this key forces the stack in to daignotic mode
#define DAIGNOSTIC_MODE_KEY L"DiagnosticMode"
// enables specif USB device specific hacks to work around
// certain busted devices.
// see #define USBD_DEVHACK_
#define DEVICE_HACK_KEY L"DeviceHackFlags"
//**
// The following keys are global to the USB stack
// ie effect all HC controllers in the system:
//
// they are found in HKLM\System\CCS\Services\USB
// BINARY keys (1 byte)
// turns on hacks for the Toshiba Pseudo Hid device
#define LEGACY_TOSHIBA_USB_KEY L"LegacyToshibaUSB"
// forces 'fast-iso' on all ISO-out endpoints, this key
// is for test purposes only
#define FORCE_FAST_ISO_KEY L"ForceFastIso"
// forces double buffering for all bulk-in endpoints
// this key is for testing purposes only
#define FORCE_DOUBLE_BUFFER_KEY L"ForceDoubleBuffer"
/****/
//
// USB standard command values
// combines bmRequest and bRequest fields
// in the setup packet for standard control
// transfers
//
#define STANDARD_COMMAND_REQUEST_MASK 0xff00
#define STANDARD_COMMAND_GET_DESCRIPTOR ((USB_DEVICE_TO_HOST | \
USB_COMMAND_TO_DEVICE) | \
(USB_REQUEST_GET_DESCRIPTOR<<8))
#define STANDARD_COMMAND_SET_DESCRIPTOR ((USB_HOST_TO_DEVICE | \
USB_COMMAND_TO_DEVICE) | \
(USB_REQUEST_SET_DESCRIPTOR<<8))
#define STANDARD_COMMAND_GET_STATUS_ENDPOINT ((USB_DEVICE_TO_HOST | \
USB_COMMAND_TO_ENDPOINT) | \
(USB_REQUEST_GET_STATUS<<8))
#define STANDARD_COMMAND_GET_STATUS_INTERFACE ((USB_DEVICE_TO_HOST | \
USB_COMMAND_TO_INTERFACE) | \
(USB_REQUEST_GET_STATUS<<8))
#define STANDARD_COMMAND_GET_STATUS_DEVICE ((USB_DEVICE_TO_HOST | \
USB_COMMAND_TO_DEVICE) | \
(USB_REQUEST_GET_STATUS<<8))
#define STANDARD_COMMAND_SET_CONFIGURATION ((USB_HOST_TO_DEVICE | \
USB_COMMAND_TO_DEVICE) | \
(USB_REQUEST_SET_CONFIGURATION<<8))
#define STANDARD_COMMAND_SET_INTERFACE ((USB_HOST_TO_DEVICE | \
USB_COMMAND_TO_INTERFACE) | \
(USB_REQUEST_SET_INTERFACE<<8))
#define STANDARD_COMMAND_SET_ADDRESS ((USB_HOST_TO_DEVICE | \
USB_COMMAND_TO_DEVICE) | \
(USB_REQUEST_SET_ADDRESS<<8))
#define STANDARD_COMMAND_CLEAR_FEATURE_ENDPOINT ((USB_HOST_TO_DEVICE | \
USB_COMMAND_TO_ENDPOINT) | \
(USB_REQUEST_CLEAR_FEATURE<<8))
//
// USB class command macros
//
#define CLASS_COMMAND_GET_DESCRIPTOR ((USB_CLASS_COMMAND | \
USB_DEVICE_TO_HOST | \
USB_COMMAND_TO_DEVICE) | \
(USB_REQUEST_GET_DESCRIPTOR<<8))
#define CLASS_COMMAND_GET_STATUS_OTHER ((USB_CLASS_COMMAND | \
USB_DEVICE_TO_HOST | \
USB_COMMAND_TO_OTHER) | \
(USB_REQUEST_GET_STATUS<<8))
#define CLASS_COMMAND_SET_FEATURE_TO_OTHER ((USB_CLASS_COMMAND | \
USB_HOST_TO_DEVICE | \
USB_COMMAND_TO_OTHER) | \
(USB_REQUEST_SET_FEATURE<<8))
//
// Macros to set transfer direction flag
//
#define USBD_SET_TRANSFER_DIRECTION_IN(tf) ((tf) |= USBD_TRANSFER_DIRECTION_IN)
#define USBD_SET_TRANSFER_DIRECTION_OUT(tf) ((tf) &= ~USBD_TRANSFER_DIRECTION_IN)
//
// Flags for the URB header flags field used
// by USBD
//
#define USBD_REQUEST_IS_TRANSFER 0x00000001
#define USBD_REQUEST_MDL_ALLOCATED 0x00000002
#define USBD_REQUEST_USES_DEFAULT_PIPE 0x00000004
#define USBD_REQUEST_NO_DATA_PHASE 0x00000008
typedef struct _USB_STANDARD_SETUP_PACKET {
USHORT RequestCode;
USHORT wValue;
USHORT wIndex;
USHORT wLength;
} USB_STANDARD_SETUP_PACKET, *PUSB_STANDARD_SETUP_PACKET;
//
// information for each active pipe on a device
//
typedef struct _USBD_PIPE {
ULONG Sig;
USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
PVOID HcdEndpoint;
ULONG MaxTransferSize;
ULONG ScheduleOffset;
ULONG UsbdPipeFlags;
} USBD_PIPE, *PUSBD_PIPE;
//
// information for each active interface
// for a device
//
typedef struct _USBD_INTERFACE {
ULONG Sig;
BOOLEAN HasAlternateSettings;
UCHAR Pad[3];
USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; // copy of interface descriptor
// copy of interfaceInformation structure, stores user parameters
// for interface in case of failure during alt-interface selection
PUSBD_INTERFACE_INFORMATION InterfaceInformation;
USBD_PIPE PipeHandle[0]; // array of pipe handle structures
} USBD_INTERFACE, *PUSBD_INTERFACE;
//
// informnation for the active configuration
// on a device
//
typedef struct _USBD_CONFIG {
ULONG Sig;
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
PUSBD_INTERFACE InterfaceHandle[1]; // array of pointers to interface
} USBD_CONFIG, *PUSBD_CONFIG;
//
// instance information for a device
//
typedef struct _USBD_DEVICE_DATA {
ULONG Sig;
USHORT DeviceAddress; // address assigned to the device
UCHAR Pad[2];
PUSBD_CONFIG ConfigurationHandle;
// KTIMER TimeoutTimer;
// KDPC TimeoutDpc;
USBD_PIPE DefaultPipe;
USB_DEVICE_DESCRIPTOR DeviceDescriptor; // a copy of the USB device descriptor
USB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
BOOLEAN LowSpeed; // TRUE if the device is low speed
BOOLEAN AcceptingRequests;
} USBD_DEVICE_DATA, *PUSBD_DEVICE_DATA;
typedef struct _USBD_RH_DELAYED_SET_POWER_D0_WORK_ITEM {
WORK_QUEUE_ITEM WorkQueueItem;
struct _USBD_EXTENSION *DeviceExtension;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
} USBD_RH_DELAYED_SET_POWER_D0_WORK_ITEM, *PUSBD_RH_DELAYED_SET_POWER_D0_WORK_ITEM;
#define PIPE_CLOSED(ph) ((ph)->HcdEndpoint == NULL)
#define GET_DEVICE_EXTENSION(DeviceObject) (((PUSBD_EXTENSION)(DeviceObject->DeviceExtension))->TrueDeviceExtension)
//#define GET_DEVICE_EXTENSION(DeviceObject) ((PUSBD_EXTENSION)(DeviceObject->DeviceExtension))
#define HCD_DEVICE_OBJECT(DeviceObject) (DeviceObject)
#define DEVICE_FROM_DEVICEHANDLEROBJECT(UsbdDeviceHandle) (PUSBD_DEVICE_DATA) (UsbdDeviceHandle)
#define SET_USBD_ERROR(err) ((err) | USBD_STATUS_ERROR)
#define HC_URB(urb) ((PHCD_URB)(urb))
//
// we use a semaphore to serialize access to the configuration functions
// in USBD
//
#define InitializeUsbDeviceMutex(de) KeInitializeSemaphore(&(de)->UsbDeviceMutex, 1, 1);
#define USBD_WaitForUsbDeviceMutex(de) { USBD_KdPrint(3, ("'***WAIT dev mutex %x\n", &(de)->UsbDeviceMutex)); \
KeWaitForSingleObject(&(de)->UsbDeviceMutex, \
Executive,\
KernelMode, \
FALSE, \
NULL); \
}
#define USBD_ReleaseUsbDeviceMutex(de) { USBD_KdPrint(3, ("'***RELEASE dev mutex %x\n", &(de)->UsbDeviceMutex));\
KeReleaseSemaphore(&(de)->UsbDeviceMutex,\
LOW_REALTIME_PRIORITY,\
1,\
FALSE);\
}
//#if DBG
//VOID
//USBD_IoCompleteRequest(
// IN PIRP Irp,
// IN CCHAR PriorityBoost
// );
//#else
#define USBD_IoCompleteRequest(a, b) IoCompleteRequest(a, b)
//#endif
//
//Function Prototypes
//
#if DBG
VOID
USBD_Warning(
PUSBD_DEVICE_DATA DeviceData,
PUCHAR Message,
BOOLEAN DebugBreak
);
#else
#define USBD_Warning(x, y, z)
#endif
NTSTATUS
USBD_Internal_Device_Control(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PUSBD_EXTENSION DeviceExtension,
IN PBOOLEAN IrpIsPending
);
NTSTATUS
USBD_SendCommand(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN USHORT RequestCode,
IN USHORT WValue,
IN USHORT WIndex,
IN USHORT WLength,
IN PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG BytesReturned,
OUT USBD_STATUS *UsbStatus
);
NTSTATUS
USBD_CreateDevice(
IN OUT PUSBD_DEVICE_DATA *DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN DeviceIsLowSpeed,
IN ULONG MaxPacketSize_Endpoint0,
IN OUT PULONG NonCompliantDevice
);
NTSTATUS
USBD_InitializeDevice(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN OUT PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
IN ULONG DeviceDescriptorLength,
IN OUT PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
IN ULONG ConfigDescriptorLength
);
NTSTATUS
USBD_ProcessURB(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PURB Urb,
OUT PBOOLEAN IrpIsPending
);
NTSTATUS
USBD_MapError_UrbToNT(
IN PURB Urb,
IN NTSTATUS NtStatus
);
NTSTATUS
USBD_Irp_Complete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
USHORT
USBD_AllocateUsbAddress(
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
USBD_OpenEndpoint(
IN PUSBD_DEVICE_DATA Device,
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_PIPE PipeHandle,
OUT USBD_STATUS *UsbStatus,
BOOLEAN IsDefaultPipe
);
NTSTATUS
USBD_GetDescriptor(
IN PUSBD_DEVICE_DATA Device,
IN PDEVICE_OBJECT DeviceObject,
OUT PUCHAR DescriptorBuffer,
IN USHORT DescriptorBufferLength,
IN USHORT DescriptorTypeAndIndex
);
NTSTATUS
USBD_CloseEndpoint(
IN PUSBD_DEVICE_DATA Device,
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_PIPE PipeHandle,
OUT USBD_STATUS *UsbStatus
);
NTSTATUS
USBD_PnP(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
USBD_LogInit(
);
NTSTATUS
USBD_SubmitSynchronousURB(
IN PURB Urb,
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_DEVICE_DATA DeviceData
);
NTSTATUS
USBD_EnumerateBUS(
IN PDEVICE_OBJECT DeviceObject,
IN PUCHAR DeviceEnumBuffer,
IN ULONG DeviceEnumBufferLength
);
NTSTATUS
USBD_InternalCloseConfiguration(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN OUT USBD_STATUS *UsbdStatus,
IN BOOLEAN AbortTransfers,
IN BOOLEAN KeepConfig
);
PUSB_INTERFACE_DESCRIPTOR
USBD_InternalParseConfigurationDescriptor(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN UCHAR InterfaceNumber,
IN UCHAR AlternateSetting,
PBOOLEAN HasAlternateSettings
);
NTSTATUS
USBD_GetPdoRegistryParameters (
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN OUT PULONG ComplienceFlags,
IN OUT PULONG DiagnosticFlags,
IN OUT PULONG DeviceHackFlags
);
NTSTATUS
USBD_GetGlobalRegistryParameters (
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN OUT PULONG ComplienceFlags,
IN OUT PULONG DiagnosticFlags,
IN OUT PULONG DeviceHackFlags
);
NTSTATUS
USBD_GetEndpointState(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_PIPE PipeHandle,
OUT USBD_STATUS *UsbStatus,
OUT PULONG EndpointState
);
VOID
USBD_SyncUrbTimeoutDPC(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
VOID
USBD_FreeUsbAddress(
IN PDEVICE_OBJECT DeviceObject,
IN USHORT DeviceAddress
);
ULONG
USBD_InternalGetInterfaceLength(
IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
IN PUCHAR End
);
NTSTATUS
USBD_InitializeConfigurationHandle(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN ULONG NumberOfInterfaces,
IN OUT PUSBD_CONFIG *ConfigHandle
);
BOOLEAN
USBD_InternalInterfaceBusy(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_INTERFACE InterfaceHandle
);
NTSTATUS
USBD_InternalOpenInterface(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_CONFIG ConfigHandle,
IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInformation,
IN OUT PUSBD_INTERFACE *InterfaceHandle,
IN BOOLEAN SendSetInterfaceCommand,
IN PBOOLEAN NoBandwidth
);
NTSTATUS
USBD_SelectConfiguration(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PURB Urb,
OUT PBOOLEAN IrpIsPending
);
NTSTATUS
USBD_SelectInterface(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PURB Urb,
OUT PBOOLEAN IrpIsPending
);
NTSTATUS
USBD_GetRegistryKeyValue(
IN HANDLE Handle,
IN PWCHAR KeyNameString,
IN ULONG KeyNameStringLength,
IN PVOID Data,
IN ULONG DataLength
);
NTSTATUS
USBD_InternalMakePdoName(
IN OUT PUNICODE_STRING PdoNameUnicodeString,
IN ULONG Index
);
NTSTATUS
USBD_SymbolicLink(
BOOLEAN CreateFlag,
PUSBD_EXTENSION DeviceExtension
);
NTSTATUS
USBD_PdoDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PUSBD_EXTENSION DeviceExtension,
PBOOLEAN IrpNeedsCompletion
);
NTSTATUS
USBD_FdoDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PUSBD_EXTENSION DeviceExtension,
PBOOLEAN IrpNeedsCompletion
);
NTSTATUS
USBD_DeferPoRequestCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE DeviceState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
);
NTSTATUS
USBD_InternalRestoreConfiguration(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_CONFIG ConfigHandle
);
NTSTATUS
USBD_InternalCloseDefaultPipe(
IN PUSBD_DEVICE_DATA DeviceData,
IN PDEVICE_OBJECT DeviceObject,
IN OUT USBD_STATUS *UsbdStatus,
IN BOOLEAN AbortTransfers
);
NTSTATUS
USBD_GetHubName(
PUSBD_EXTENSION DeviceExtension,
PIRP Irp
);
NTSTATUS
USBD_SetRegistryKeyValue (
IN HANDLE Handle,
IN PUNICODE_STRING KeyNameUnicodeString,
IN PVOID Data,
IN ULONG DataLength,
IN ULONG KeyType
);
NTSTATUS
USBD_SetPdoRegistryParameter (
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PWCHAR KeyName,
IN ULONG KeyNameLength,
IN PVOID Data,
IN ULONG DataLength,
IN ULONG KeyType,
IN ULONG DevInstKeyType
);
NTSTATUS
USBD_SubmitWaitWakeIrpToHC(
IN PUSBD_EXTENSION DeviceExtension
);
BOOLEAN
USBD_ValidatePipe(
PUSBD_PIPE PipeHandle
);
VOID
USBD_CompleteIdleNotification(
IN PUSBD_EXTENSION DeviceExtension
);
NTSTATUS
USBD_FdoSetContentId(
IN PIRP irp,
IN PVOID pKsProperty,
IN PVOID pvData
);