/*++ 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 );