266 lines
12 KiB
C
266 lines
12 KiB
C
/*
|
|
*************************************************************************
|
|
* File: USBCCGP.H
|
|
*
|
|
* Module: USBCCGP.SYS
|
|
* USB Common Class Generic Parent driver.
|
|
*
|
|
* Copyright (c) 1998 Microsoft Corporation
|
|
*
|
|
*
|
|
* Author: ervinp
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
#include <msosdesc.h> // Internal definitions for MS OS Desc.
|
|
|
|
/*
|
|
* USBCCGP signature tag for memory allocations
|
|
*/
|
|
#define USBCCGP_TAG (ULONG)'CbsU'
|
|
|
|
#define GUARD_WORD 'draG'
|
|
|
|
|
|
extern PWCHAR GenericCompositeUSBDeviceString;
|
|
|
|
|
|
enum deviceState {
|
|
STATE_INITIALIZED,
|
|
STATE_STARTING,
|
|
STATE_STARTED,
|
|
STATE_START_FAILED,
|
|
STATE_STOPPING,
|
|
STATE_STOPPED, // implies device was previously started successfully
|
|
STATE_SUSPENDED,
|
|
STATE_REMOVING,
|
|
STATE_REMOVED
|
|
};
|
|
|
|
|
|
typedef struct PARENT_FDO_EXTENSION {
|
|
|
|
enum deviceState state;
|
|
|
|
PDRIVER_OBJECT driverObj;
|
|
PDEVICE_OBJECT pdo;
|
|
PDEVICE_OBJECT fdo;
|
|
PDEVICE_OBJECT topDevObj;
|
|
|
|
/*
|
|
* Counter to keep driver from getting unloaded before all IO completes to us.
|
|
*/
|
|
LONG pendingActionCount;
|
|
KEVENT removeEvent;
|
|
|
|
/*
|
|
* This buffer will hold a USB_CONFIGURATION_DESCRIPTOR plus
|
|
* the following interface descriptors.
|
|
*/
|
|
PUSB_CONFIGURATION_DESCRIPTOR configDesc;
|
|
PUSB_CONFIGURATION_DESCRIPTOR selectedConfigDesc;
|
|
USBD_CONFIGURATION_HANDLE selectedConfigHandle;
|
|
|
|
PUSBD_INTERFACE_LIST_ENTRY interfaceList;
|
|
|
|
USB_DEVICE_DESCRIPTOR deviceDesc;
|
|
|
|
/*
|
|
* The parent device has some number of functions.
|
|
* For each function, we create a PDO and store
|
|
* it in the deviceRelations array.
|
|
*/
|
|
ULONG numFunctions;
|
|
PDEVICE_RELATIONS deviceRelations;
|
|
|
|
/*
|
|
* deviceCapabilities includes a
|
|
* table mapping system power states to device power states.
|
|
*/
|
|
DEVICE_CAPABILITIES deviceCapabilities;
|
|
|
|
PURB dynamicNotifyUrb;
|
|
|
|
PIRP parentWaitWakeIrp;
|
|
PIRP currentSetPowerIrp;
|
|
BOOLEAN isWaitWakePending;
|
|
LIST_ENTRY functionWaitWakeIrpQueue; // WW irps from function client drivers
|
|
|
|
KSPIN_LOCK parentFdoExtSpinLock;
|
|
|
|
BOOLEAN haveCSInterface;
|
|
ULONG CSInterfaceNumber;
|
|
ULONG CSChannelId;
|
|
|
|
BOOLEAN resetPortInProgress;
|
|
LIST_ENTRY pendingResetPortIrpQueue;
|
|
|
|
BOOLEAN cyclePortInProgress;
|
|
LIST_ENTRY pendingCyclePortIrpQueue;
|
|
|
|
PIRP pendingIdleIrp;
|
|
USB_IDLE_CALLBACK_INFO idleCallbackInfo;
|
|
|
|
PMS_EXT_CONFIG_DESC msExtConfigDesc;
|
|
|
|
} PARENT_FDO_EXT, *PPARENT_FDO_EXT;
|
|
|
|
|
|
typedef struct FUNCTION_PDO_EXTENSION {
|
|
|
|
ULONG functionIndex;
|
|
ULONG baseInterfaceNumber;
|
|
ULONG numInterfaces;
|
|
enum deviceState state;
|
|
|
|
PDEVICE_OBJECT pdo;
|
|
PPARENT_FDO_EXT parentFdoExt;
|
|
|
|
/*
|
|
* functionInterfaceList is a pointer into the parent's interfaceList array.
|
|
*/
|
|
PUSBD_INTERFACE_LIST_ENTRY functionInterfaceList;
|
|
|
|
PUSB_CONFIGURATION_DESCRIPTOR dynamicFunctionConfigDesc;
|
|
|
|
USB_DEVICE_DESCRIPTOR functionDeviceDesc;
|
|
|
|
KSPIN_LOCK functionPdoExtSpinLock;
|
|
|
|
PIRP idleNotificationIrp;
|
|
|
|
} FUNCTION_PDO_EXT, *PFUNCTION_PDO_EXT;
|
|
|
|
|
|
typedef struct DEVICE_EXTENSION {
|
|
|
|
ULONG signature;
|
|
|
|
/*
|
|
* Does the associated device object represent
|
|
* the parent FDO that we attached to the device object
|
|
* we got from USBHUB
|
|
* (as opposed to the function PDO we created
|
|
* to represent a single function on that device) ?
|
|
*/
|
|
BOOLEAN isParentFdo;
|
|
|
|
union {
|
|
PARENT_FDO_EXT parentFdoExt;
|
|
FUNCTION_PDO_EXT functionPdoExt;
|
|
};
|
|
|
|
} DEVEXT, *PDEVEXT;
|
|
|
|
|
|
typedef struct _USB_REQUEST_TIMEOUT_CONTEXT {
|
|
|
|
PKEVENT event;
|
|
PLONG lock;
|
|
|
|
} USB_REQUEST_TIMEOUT_CONTEXT, *PUSB_REQUEST_TIMEOUT_CONTEXT;
|
|
|
|
|
|
#define ALLOCPOOL(pooltype, size) ExAllocatePoolWithTag(pooltype, size, USBCCGP_TAG)
|
|
#define FREEPOOL(ptr) ExFreePool(ptr)
|
|
|
|
#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
|
|
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
|
|
|
|
#define POINTER_DISTANCE(ptr1, ptr2) (ULONG)(((PUCHAR)(ptr1))-((PUCHAR)(ptr2)))
|
|
|
|
// Counting the byte count of an ascii string or wide char string
|
|
//
|
|
#define STRLEN( Length, p )\
|
|
{\
|
|
int i;\
|
|
for ( i=0; (p)[i]; i++ );\
|
|
Length = i*sizeof(*p);\
|
|
}
|
|
|
|
/*
|
|
* We use this value, which is guaranteed to never be defined as a status by the kernel,
|
|
* as a default status code to indicate "do nothing and pass the irp down".
|
|
*/
|
|
#define NO_STATUS 0x80000000
|
|
|
|
|
|
|
|
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING UniRegistryPath);
|
|
NTSTATUS USBC_AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
|
|
VOID USBC_DriverUnload(IN PDRIVER_OBJECT DriverObject);
|
|
NTSTATUS USBC_Dispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
|
|
NTSTATUS USBC_Create(PDEVEXT devExt, PIRP irp);
|
|
NTSTATUS USBC_Close(PDEVEXT devExt, PIRP irp);
|
|
NTSTATUS USBC_DeviceControl(PDEVEXT devExt, PIRP irp);
|
|
NTSTATUS USBC_SystemControl(PDEVEXT devExt, PIRP irp);
|
|
NTSTATUS USBC_InternalDeviceControl(PDEVEXT devExt, PIRP irp);
|
|
NTSTATUS USBC_PnP(PDEVEXT devExt, PIRP irp);
|
|
NTSTATUS USBC_PnpComplete(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
|
|
NTSTATUS USBC_Power(PDEVEXT devExt, PIRP irp);
|
|
NTSTATUS CreateStaticFunctionPDOs(PPARENT_FDO_EXT fdoExt);
|
|
NTSTATUS TryGetConfigDescriptor(PPARENT_FDO_EXT parentFdoExt);
|
|
NTSTATUS GetConfigDescriptor(PPARENT_FDO_EXT fdoExt);
|
|
VOID PrepareParentFDOForRemove(PPARENT_FDO_EXT parentFdoExt);
|
|
VOID FreeParentFDOResources(PPARENT_FDO_EXT fdoExt);
|
|
PWCHAR BuildCompatibleIDs(IN PUCHAR CompatibleID, IN PUCHAR SubCompatibleID, IN UCHAR Class, IN UCHAR SubClass, IN UCHAR Protocol);
|
|
NTSTATUS QueryFunctionPdoID(PFUNCTION_PDO_EXT functionPdoExt, PIRP irp);
|
|
NTSTATUS QueryParentDeviceRelations(PPARENT_FDO_EXT parentFdoExt, PIRP irp);
|
|
NTSTATUS QueryFunctionDeviceRelations(PFUNCTION_PDO_EXT functionPdoExt, PIRP irp);
|
|
NTSTATUS QueryFunctionCapabilities(PFUNCTION_PDO_EXT functionPdoExt, PIRP irp);
|
|
NTSTATUS HandleParentFdoPower(PPARENT_FDO_EXT parentFdoExt, PIRP irp);
|
|
NTSTATUS HandleFunctionPdoPower(PFUNCTION_PDO_EXT functionPdoExt, PIRP irp);
|
|
VOID ParentPowerRequestCompletion(IN PDEVICE_OBJECT devObj, IN UCHAR minorFunction, IN POWER_STATE powerState, IN PVOID context, IN PIO_STATUS_BLOCK ioStatus);
|
|
NTSTATUS StartParentFdo(PPARENT_FDO_EXT parentFdoExt, PIRP irp);
|
|
NTSTATUS QueryFunctionCapabilities(PFUNCTION_PDO_EXT functionPdoExt, PIRP irp);
|
|
NTSTATUS ParentPdoPowerCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context);
|
|
NTSTATUS FunctionInternalDeviceControl(PFUNCTION_PDO_EXT functionPdoExt, PIRP irp);
|
|
NTSTATUS ParentInternalDeviceControl(PPARENT_FDO_EXT parentFdoExt, PIRP irp);
|
|
NTSTATUS ParentResetOrCyclePort(PPARENT_FDO_EXT parentFdoExt, PIRP irp, ULONG ioControlCode);
|
|
NTSTATUS BuildFunctionConfigurationDescriptor(PFUNCTION_PDO_EXT functionPdoExt, PUCHAR buffer, ULONG bufferLength, PULONG bytesReturned);
|
|
VOID FreeFunctionPDOResources(PFUNCTION_PDO_EXT functionPdoExt);
|
|
NTSTATUS GetParentFdoCapabilities(PPARENT_FDO_EXT parentFdoExt);
|
|
NTSTATUS CallDriverSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
|
|
NTSTATUS CallDriverSync(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
|
|
NTSTATUS CallNextDriverSync(PPARENT_FDO_EXT parentFdoExt, PIRP irp);
|
|
VOID IncrementPendingActionCount(PPARENT_FDO_EXT parentFdoExt);
|
|
VOID DecrementPendingActionCount(PPARENT_FDO_EXT parentFdoExt);
|
|
PWCHAR AppendInterfaceNumber(PWCHAR oldIDs, ULONG interfaceNum);
|
|
PVOID MemDup(PVOID dataPtr, ULONG length);
|
|
ULONG WStrLen(PWCHAR str);
|
|
ULONG WStrCpy(PWCHAR dest, PWCHAR src);
|
|
BOOLEAN WStrCompareN(PWCHAR str1, PWCHAR str2, ULONG maxChars);
|
|
NTSTATUS GetDeviceDescriptor(PPARENT_FDO_EXT parentFdoExt);
|
|
NTSTATUS SubmitUrb(PPARENT_FDO_EXT parentFdoExt, PURB urb, BOOLEAN synchronous, PVOID completionRoutine, PVOID completionContext);
|
|
NTSTATUS UrbFunctionSelectConfiguration(PFUNCTION_PDO_EXT functionPdoExt, PURB urb);
|
|
NTSTATUS UrbFunctionGetDescriptorFromDevice(PFUNCTION_PDO_EXT functionPdoExt, PURB urb);
|
|
PFUNCTION_PDO_EXT FindFunctionByIndex(PPARENT_FDO_EXT parentFdoExt, ULONG functionIndex);
|
|
PUSBD_INTERFACE_LIST_ENTRY GetFunctionInterfaceListBase(PPARENT_FDO_EXT parentFdoExt, ULONG functionIndex, PULONG numFunctionInterfaces);
|
|
PDEVICE_RELATIONS CopyDeviceRelations(PDEVICE_RELATIONS deviceRelations);
|
|
PUSBD_INTERFACE_LIST_ENTRY GetInterfaceList(PPARENT_FDO_EXT parentFdoExt, PUSB_CONFIGURATION_DESCRIPTOR configDesc);
|
|
VOID FreeInterfaceList(PPARENT_FDO_EXT parentFdoExt, BOOLEAN freeListItself);
|
|
NTSTATUS ParentSelectConfiguration(PPARENT_FDO_EXT parentFdoExt, PUSB_CONFIGURATION_DESCRIPTOR configDesc, PUSBD_INTERFACE_LIST_ENTRY interfaceList);
|
|
VOID ParentCloseConfiguration(PPARENT_FDO_EXT parentFdoExt);
|
|
NTSTATUS GetStringDescriptor(PPARENT_FDO_EXT parentFdoExt, UCHAR stringIndex, LANGID langId, PUSB_STRING_DESCRIPTOR stringDesc, ULONG bufferLen);
|
|
NTSTATUS SetPdoRegistryParameter(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PWCHAR KeyName, IN PVOID Data, IN ULONG DataLength, IN ULONG KeyType, IN ULONG DevInstKeyType);
|
|
NTSTATUS GetPdoRegistryParameter(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PWCHAR ValueName, OUT PVOID Data, IN ULONG DataLength, OUT PULONG Type, OUT PULONG ActualDataLength);
|
|
NTSTATUS GetMsOsFeatureDescriptor(PPARENT_FDO_EXT ParentFdoExt, UCHAR Recipient, UCHAR InterfaceNumber, USHORT Index, PVOID DataBuffer, ULONG DataBufferLength, PULONG BytesReturned);
|
|
NTSTATUS GetMsExtendedConfigDescriptor(IN PPARENT_FDO_EXT ParentFdoExt);
|
|
BOOLEAN ValidateMsExtendedConfigDescriptor(IN PMS_EXT_CONFIG_DESC MsExtConfigDesc, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
|
|
NTSTATUS GetDeviceText(PFUNCTION_PDO_EXT functionPdoExt, PIRP irp);
|
|
NTSTATUS EnqueueFunctionWaitWakeIrp(PFUNCTION_PDO_EXT functionPdoExt, PIRP irp);
|
|
VOID FunctionWaitWakeIrpCancelRoutine(IN PDEVICE_OBJECT deviceObject, IN PIRP irp);
|
|
NTSTATUS SubmitParentWaitWakeIrp(PPARENT_FDO_EXT parentFdoExt);
|
|
NTSTATUS ParentWaitWakeComplete(IN PDEVICE_OBJECT deviceObject, IN UCHAR minorFunction, IN POWER_STATE powerState, IN PVOID context, IN PIO_STATUS_BLOCK ioStatus);
|
|
VOID CompleteAllFunctionWaitWakeIrps(PPARENT_FDO_EXT parentFdoExt, NTSTATUS status);
|
|
VOID CompleteAllFunctionIdleIrps(PPARENT_FDO_EXT parentFdoExt, NTSTATUS status);
|
|
VOID InstallExtPropDesc(IN PFUNCTION_PDO_EXT FunctionPdoExt);
|
|
VOID InstallExtPropDescSections(PDEVICE_OBJECT DeviceObject, PMS_EXT_PROP_DESC pMsExtPropDesc);
|
|
NTSTATUS ParentDeviceControl(PPARENT_FDO_EXT parentFdoExt, PIRP irp);
|
|
VOID CompleteFunctionIdleNotification(PFUNCTION_PDO_EXT functionPdoExt);
|
|
VOID CheckParentIdle(PPARENT_FDO_EXT parentFdoExt);
|
|
NTSTATUS ParentSetD0(IN PPARENT_FDO_EXT parentFdoExt);
|
|
NTSTATUS USBC_SetContentId(IN PIRP irp, IN PVOID pKsProperty, IN PVOID pvData);
|
|
NTSTATUS RegQueryGenericCompositeUSBDeviceString(PWCHAR *GenericCompositeUSBDeviceString);
|