Apply .gitattributes normalization to convert all CRLF line endings inherited from Windows-origin source files to Unix LF. 175 files, zero content changes.
2101 lines
75 KiB
C++
2101 lines
75 KiB
C++
/*****************************************************************************
|
|
Company : Shree Ganesha Inc.
|
|
File Name : SkyWalker1Usb.cpp
|
|
Author :
|
|
Date :
|
|
Purpose : This File Holds all the USB Device access related declarations
|
|
|
|
Revision History:
|
|
===============================================================================
|
|
DATE VERSION AUTHOR REMARK
|
|
===============================================================================
|
|
|
|
XXth April,2009 01 Initial Version
|
|
|
|
*****************************************************************************/
|
|
/* Include the Library and Other header file */
|
|
//#include <ntddk.h>
|
|
#include "SkyWalker1Main.h" //Header for the Tuner related definitions
|
|
|
|
/* End of Inclusion the Library and Other header file */
|
|
|
|
/* Macro Definitions */
|
|
#define USB_MEMORY_TAG 'MBSU'
|
|
/* End of Global & Static variables Declaration */
|
|
|
|
/* External Variable Declaration */
|
|
/* End of External Variable Declaration */
|
|
|
|
/* Declare Enumerations here */
|
|
/* End of Enumeration declaration */
|
|
|
|
/* Function Prototypes */
|
|
NTSTATUS ReadandSelectDescriptors( IN PKSDEVICE pKSDeviceObject );
|
|
NTSTATUS ConfigureDevice(IN PKSDEVICE pKSDeviceObject);
|
|
NTSTATUS SelectInterfaces( IN PKSDEVICE pKSDeviceObject,
|
|
IN PUSB_CONFIGURATION_DESCRIPTOR pConfigurationDescriptor);
|
|
|
|
NTSTATUS UsbReadWriteCompletion(
|
|
IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket,
|
|
IN PVOID pContext
|
|
);
|
|
NTSTATUS ResetUsbPipe( IN PKSDEVICE pKSDeviceObject,
|
|
IN PUSBD_PIPE_INFORMATION pPipeInformation);
|
|
NTSTATUS ResetUsbDevice(IN PKSDEVICE pKSDeviceObject);
|
|
NTSTATUS GetUsbPortStatus( IN PKSDEVICE pKSDeviceObject,
|
|
IN OUT PULONG pulPortStatus);
|
|
NTSTATUS ResetUsbParentPort( IN PKSDEVICE pKSDeviceObject );
|
|
NTSTATUS SendURBToBusDriver(IN PKSDEVICE pKSDeviceObject,
|
|
IN PURB pUSBRequestBlock );
|
|
NTSTATUS AbortUsbPipes(IN PKSDEVICE pKSDeviceObject);
|
|
LONG IncrementPendingIoCount(IN OUT CSkyWalker1Device * pDevice);
|
|
LONG DecrementPendingIoCount(IN OUT CSkyWalker1Device * pDevice);
|
|
|
|
//Debugging related Functions
|
|
VOID PrintDeviceDescriptor( PUSB_DEVICE_DESCRIPTOR pDeviceDescriptor);
|
|
VOID PrintConfigurationDescriptor(IN PUSB_CONFIGURATION_DESCRIPTOR pConfigurationDescriptor);
|
|
VOID PrintInterfaceDescriptor(IN PUSB_INTERFACE_DESCRIPTOR pInterfaceDescriptor);
|
|
VOID PrintPipeInformation(PUSBD_PIPE_INFORMATION pPipeInformation);
|
|
/* End of Function prototype definitions */
|
|
|
|
/*****************************************************************************
|
|
Function : InitializeUsbDevice
|
|
Description : Function to used to Initialize the USB Interface of the Tuner
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object which needs to be Initialized
|
|
<PIRP> Irp to start the device IRP_MN_START
|
|
OUT PARAM : <NTSTATUS> Status of the Device Initialization
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Device initialized
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS InitializeUsbDevice(IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket)
|
|
{
|
|
NTSTATUS ntInitStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = NULL;
|
|
KIRQL kOldIrql;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context);
|
|
|
|
//We cannot touch the device (send it any non pnp irps) until a
|
|
//start device has been passed down to the lower drivers.
|
|
//first pass the Irp down
|
|
|
|
ntInitStatus = PassDownIRPAndWaitForCompletion( pKSDeviceObject->NextDeviceObject,
|
|
pIoRequestPacket,
|
|
TRUE);
|
|
if(!NT_SUCCESS(ntInitStatus))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Lower Driver did not start !!!,Stopping Device Start\n"));
|
|
goto FinishStartDevice;
|
|
}
|
|
|
|
//Lower Device Initialized , Start the Device Now
|
|
//
|
|
//Read the device descriptor, configuration descriptor
|
|
//and select the interface descriptors
|
|
//
|
|
|
|
ntInitStatus = ReadandSelectDescriptors(pKSDeviceObject);
|
|
|
|
if(!NT_SUCCESS(ntInitStatus))
|
|
{
|
|
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("ReadandSelectDescriptors failed\n"));
|
|
goto FinishStartDevice;
|
|
}
|
|
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
SET_NEW_PNP_STATE(pDevice, Working);
|
|
pDevice->QueueState = AllowRequests;
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
/*
|
|
//initialize wait wake outstanding flag to false.
|
|
//and issue a wait wake.
|
|
|
|
deviceExtension->FlagWWOutstanding = 0;
|
|
deviceExtension->FlagWWCancel = 0;
|
|
deviceExtension->WaitWakeIrp = NULL;
|
|
|
|
if(deviceExtension->WaitWakeEnable)
|
|
{
|
|
|
|
IssueWaitWake(deviceExtension);
|
|
}
|
|
|
|
ProcessQueuedRequests(deviceExtension);
|
|
|
|
*/
|
|
FinishStartDevice:
|
|
PrintFunctionExit(__FUNCTION__,ntInitStatus);
|
|
|
|
return ntInitStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : ReadandSelectDescriptors
|
|
Description : Function to used to Read Device Descriptor
|
|
IN PARAM : <PKSDEVICE> Pointer to KS Device Object
|
|
OUT PARAM : <NTSTATUS> Status of the Device Descriptor Read
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error
|
|
PreCondition : NONE
|
|
PostCondtion : Device Descriptor Read
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS ReadandSelectDescriptors( IN PKSDEVICE pKSDeviceObject )
|
|
{
|
|
URB USBRequestBlock;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//1. Read the device descriptor
|
|
|
|
UsbBuildGetDescriptorRequest(
|
|
&USBRequestBlock,
|
|
(USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
|
|
USB_DEVICE_DESCRIPTOR_TYPE,
|
|
0,
|
|
0,
|
|
&pDevice->USBDeviceDescriptor,
|
|
NULL,
|
|
sizeof(pDevice->USBDeviceDescriptor),
|
|
NULL);
|
|
|
|
ntStatus = SendURBToBusDriver( pKSDeviceObject,
|
|
&USBRequestBlock);
|
|
if (!NT_SUCCESS(ntStatus))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Error Trying to Read Device Descriptor\n"));
|
|
goto CompleteReadAndSetup;
|
|
}
|
|
|
|
PrintDeviceDescriptor(&pDevice->USBDeviceDescriptor);
|
|
|
|
//Device Descriptor read successfully thus, Read and select configuration
|
|
ntStatus = ConfigureDevice(pKSDeviceObject);
|
|
|
|
CompleteReadAndSetup:
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntStatus);
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : ConfigureDevice
|
|
Description : This helper routine reads the configuration descriptor
|
|
for the device in couple of steps.
|
|
IN PARAM : <PKSDEVICE> Pointer to KS Device Object
|
|
OUT PARAM : <NTSTATUS> Status of the Configuration Descriptor Read
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error
|
|
PreCondition : NONE
|
|
PostCondtion : Configuration Descriptor Read
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS ConfigureDevice(IN PKSDEVICE pKSDeviceObject)
|
|
{
|
|
URB USBRequestBlock;
|
|
NTSTATUS ntConfigureStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
USB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
|
PUSB_CONFIGURATION_DESCRIPTOR pConfigurationDescriptor = NULL;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Total Number of Configurations = %d\n", pDevice->USBDeviceDescriptor.bNumConfigurations));
|
|
|
|
//Read the first configuration descriptor
|
|
//This requires two steps:
|
|
//1. Read the fixed sized configuration desciptor (CD)
|
|
//2. Read the CD with all embedded interface and endpoint descriptors
|
|
|
|
UsbBuildGetDescriptorRequest( &USBRequestBlock,
|
|
sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST),
|
|
USB_CONFIGURATION_DESCRIPTOR_TYPE,
|
|
0,
|
|
0,
|
|
&ConfigurationDescriptor,
|
|
NULL,
|
|
sizeof(ConfigurationDescriptor),
|
|
NULL);
|
|
|
|
ntConfigureStatus = SendURBToBusDriver( pKSDeviceObject,
|
|
&USBRequestBlock);
|
|
if (!NT_SUCCESS(ntConfigureStatus))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Error Trying to Read Fixed Size Configuration Descriptor\n"));
|
|
goto CompleteDeviceConfigure;
|
|
}
|
|
|
|
ULONG ulConfigurationDesciptorSize = ConfigurationDescriptor.wTotalLength;
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("Configuration Descriptor Size = %lu \n",ulConfigurationDesciptorSize));
|
|
|
|
pConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePoolWithTag( NonPagedPool,
|
|
ulConfigurationDesciptorSize,
|
|
USB_MEMORY_TAG);
|
|
if (!pConfigurationDescriptor)
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Unable to allocate %lu bytes for Configuration Descriptor\n", ulConfigurationDesciptorSize));
|
|
ntConfigureStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto CompleteDeviceConfigure;
|
|
}
|
|
|
|
UsbBuildGetDescriptorRequest( &USBRequestBlock,
|
|
sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST),
|
|
USB_CONFIGURATION_DESCRIPTOR_TYPE,
|
|
0,
|
|
0,
|
|
pConfigurationDescriptor,
|
|
NULL,
|
|
ulConfigurationDesciptorSize,
|
|
NULL);
|
|
|
|
ntConfigureStatus = SendURBToBusDriver( pKSDeviceObject,
|
|
&USBRequestBlock);
|
|
if (!NT_SUCCESS(ntConfigureStatus))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Error Trying to Read Actual Configuration Descriptor\n"));
|
|
goto CompleteDeviceConfigure;
|
|
}
|
|
|
|
PrintConfigurationDescriptor(&ConfigurationDescriptor);
|
|
|
|
ntConfigureStatus = SelectInterfaces(pKSDeviceObject, pConfigurationDescriptor);
|
|
|
|
CompleteDeviceConfigure:
|
|
if(pConfigurationDescriptor)
|
|
{
|
|
ExFreePoolWithTag(pConfigurationDescriptor,USB_MEMORY_TAG);
|
|
}
|
|
PrintFunctionExit(__FUNCTION__,ntConfigureStatus);
|
|
return ntConfigureStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : SelectInterfaces
|
|
Description : This helper routine selects the configuration
|
|
IN PARAM : <PKSDEVICE> Pointer to KS Device Object
|
|
<PUSB_CONFIGURATION_DESCRIPTOR> Configuration Descriptor
|
|
OUT PARAM : <NTSTATUS> Status of the Configuration Descriptor Selection
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error
|
|
PreCondition : NONE
|
|
PostCondtion : Configuration Descriptor Selection
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS SelectInterfaces( IN PKSDEVICE pKSDeviceObject,
|
|
IN PUSB_CONFIGURATION_DESCRIPTOR pConfigurationDescriptor)
|
|
{
|
|
NTSTATUS ntSelectStatus = STATUS_SUCCESS;
|
|
URB USBRequestBlock;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
PUSB_INTERFACE_DESCRIPTOR pInterfaceDescriptor = NULL;
|
|
PUSBD_INTERFACE_INFORMATION pInterfaceInformation = NULL;
|
|
LONG lNumberOfInterfaces = pConfigurationDescriptor->bNumInterfaces;
|
|
LONG lInterfaceNumber = 0L;
|
|
LONG lInterfaceIndex = 0L;
|
|
ULONG ulPipeIndex = 0L;
|
|
|
|
//The Device needs to be configured by sending a URB that specifies the configuration to use
|
|
//if device driver fails to configure the device then the I/O manager subsequently unloads
|
|
//the Driver from memory
|
|
//Search for the Configuration descriptor in the list of all configuration and obtain a pointer
|
|
//to the interface
|
|
pInterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
|
|
pConfigurationDescriptor, //Address of the Configuration Descriptor Structure
|
|
pConfigurationDescriptor, //Adress within the First Structure from where search should begin
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1);
|
|
if (!pInterfaceDescriptor)
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("No Interface available for the Device\n"));
|
|
ntSelectStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
goto FinishSelectInterface;
|
|
}
|
|
|
|
//Create a URB that can be sent to the host controller driver (HCD) to set the Device
|
|
//in the configured state
|
|
USBD_INTERFACE_LIST_ENTRY Interfaces[2] =
|
|
{
|
|
{pInterfaceDescriptor, NULL},
|
|
{NULL, NULL},
|
|
};
|
|
|
|
PURB pConfigSelectURB = USBD_CreateConfigurationRequestEx(pConfigurationDescriptor, Interfaces);
|
|
if (!pConfigSelectURB)
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Unable to Create Configuration Request\n"));
|
|
ntSelectStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto FinishSelectInterface;
|
|
}
|
|
|
|
//Get the Interface supported by selected configuration
|
|
|
|
pInterfaceInformation = &pConfigSelectURB->UrbSelectConfiguration.Interface;
|
|
|
|
for(ulPipeIndex=0; ulPipeIndex<pInterfaceInformation->NumberOfPipes; ulPipeIndex++)
|
|
{
|
|
//Perform pipe initialization here set the transfer size and any pipe flags we use
|
|
//USBD sets the rest of the Interface struct members
|
|
|
|
//pInterfaceInformation->Pipes[ulPipeIndex].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
|
|
}
|
|
|
|
ntSelectStatus = SendURBToBusDriver(pKSDeviceObject,pConfigSelectURB);
|
|
|
|
if (!NT_SUCCESS(ntSelectStatus))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Error Trying to Select Configuration\n"));
|
|
goto FinishSelectInterface;
|
|
}
|
|
|
|
PrintInterfaceDescriptor(pInterfaceDescriptor);
|
|
|
|
for(ulPipeIndex=0; ulPipeIndex<pInterfaceInformation->NumberOfPipes; ulPipeIndex++)
|
|
{
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("--------------------------\n"));
|
|
PrintPipeInformation(&pInterfaceInformation->Pipes[ulPipeIndex]);
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("--------------------------\n"));
|
|
|
|
//Setting the Pipes
|
|
if(pInterfaceInformation->Pipes[ulPipeIndex].EndpointAddress == 0x82)
|
|
{
|
|
RtlCopyMemory( &pDevice->ReadPipe,
|
|
&pInterfaceInformation->Pipes[ulPipeIndex],
|
|
sizeof(pDevice->ReadPipe));
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory( &pDevice->WritePipe,
|
|
&pInterfaceInformation->Pipes[ulPipeIndex],
|
|
sizeof(pDevice->WritePipe));
|
|
}
|
|
|
|
}
|
|
FinishSelectInterface:
|
|
|
|
if(pConfigSelectURB)
|
|
{
|
|
ExFreePool(pConfigSelectURB);
|
|
}
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntSelectStatus);
|
|
return ntSelectStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : QueryStopUsbDevice
|
|
Description : Function to used to Service PnP IRPs of Minor Type
|
|
IRP_MN_QUERY_STOP_DEVICE
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object whose stop query has come
|
|
<PIRP> Device Stop Query Irp with Minor Code IRP_MN_QUERY_STOP_DEVICE
|
|
OUT PARAM : <NTSTATUS> Status of the Stop Query Processing
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Device can be stopped or not is returned
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS QueryStopUsbDevice(IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket)
|
|
{
|
|
KIRQL kOldIrql;
|
|
NTSTATUS ntQueryStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *) pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//If we can stop the device, we need to set the QueueState to
|
|
//HoldRequests so further requests will be queued.
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
SET_NEW_PNP_STATE(pDevice, PendingStop);
|
|
pDevice->QueueState = HoldRequests;
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
//wait for the existing ones to be finished.
|
|
//first, decrement this operation
|
|
DecrementPendingIoCount(pDevice);
|
|
|
|
KeWaitForSingleObject(&pDevice->EvDeviceStopOk,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntQueryStatus);
|
|
|
|
return ntQueryStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : DecrementPendingIoCount
|
|
Description : This routine decrements the outstanding I/O count
|
|
This is typically invoked after the dispatch routine
|
|
has finished processing the irp.
|
|
IN PARAM : <CSkyWalker1Device* > Device Pointer
|
|
OUT PARAM : <LONG> Io Pending Count
|
|
PreCondition : NONE
|
|
PostCondtion : Pending IO Count is Decremented and same is returned to
|
|
the caller
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
LONG DecrementPendingIoCount(IN OUT CSkyWalker1Device * pDevice)
|
|
{
|
|
LONG ulResult = 0;
|
|
KIRQL kOldIrql;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
KeAcquireSpinLock(&pDevice->kIoCountLock, &kOldIrql);
|
|
|
|
ulResult = InterlockedDecrement((PLONG)&pDevice->ulOutStandingIoCount);
|
|
|
|
if(ulResult == 1)
|
|
{
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Device can be Stopped\n"));
|
|
KeSetEvent(&pDevice->EvDeviceStopOk, IO_NO_INCREMENT, FALSE);
|
|
}
|
|
|
|
if(ulResult == 0)
|
|
{
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Device can be Removed\n"));
|
|
KeSetEvent(&pDevice->EvDeviceRemoveOk,IO_NO_INCREMENT, FALSE);
|
|
}
|
|
|
|
KeReleaseSpinLock(&pDevice->kIoCountLock, kOldIrql);
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("%s::%d\n",__FUNCTION__,ulResult));
|
|
|
|
PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS);
|
|
|
|
return ulResult;
|
|
}
|
|
/*****************************************************************************
|
|
Function : IncrementPendingIoCount
|
|
Description : This routine increments the outstanding I/O count
|
|
This is typically invoked before the dispatch routine
|
|
to process new Irp is called
|
|
IN PARAM : <CSkyWalker1Device* > Device Pointer
|
|
OUT PARAM : <LONG> Io Pending Count
|
|
PreCondition : NONE
|
|
PostCondtion : Pending IO Count is Incremented and same is returned to
|
|
the caller
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
LONG IncrementPendingIoCount(IN OUT CSkyWalker1Device * pDevice)
|
|
{
|
|
LONG ulResult = 0;
|
|
KIRQL kOldIrql;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
KeAcquireSpinLock(&pDevice->kIoCountLock, &kOldIrql);
|
|
|
|
ulResult = InterlockedIncrement((PLONG)&pDevice->ulOutStandingIoCount);
|
|
|
|
//when OutStandingIO bumps from 1 to 2, clear the StopEvent
|
|
if(ulResult == 2)
|
|
{
|
|
|
|
KeClearEvent(&pDevice->EvDeviceStopOk);
|
|
}
|
|
|
|
KeReleaseSpinLock(&pDevice->kIoCountLock, kOldIrql);
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("%s::%d\n",__FUNCTION__,ulResult));
|
|
|
|
PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS);
|
|
|
|
return ulResult;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : CancelStopUsbDevice
|
|
Description : Function to used to Service PnP IRPs of Minor Type
|
|
IRP_MN_CANCEL_STOP_DEVICE
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object whose Cancel stop request has come
|
|
<PIRP> Device Stop Cancel Irp with Minor Code IRP_MN_CANCEL_STOP_DEVICE
|
|
OUT PARAM : <NTSTATUS> Status of the Device Stop Cancel Processing
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Device Stop is cancelled
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS CancelStopUsbDevice(IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket)
|
|
{
|
|
KIRQL kOldIrql;
|
|
KEVENT Evevent;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//First check to see whether you have received cancel-stop
|
|
//without first receiving a query-stop. This could happen if someone
|
|
//above us fails a query-stop and passes down the subsequent
|
|
//cancel-stop.
|
|
if(pDevice->UsbDeviceState == PendingStop )
|
|
{
|
|
if(NT_SUCCESS(ntStatus))
|
|
{
|
|
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
RESTORE_PREVIOUS_PNP_STATE(pDevice);
|
|
pDevice->QueueState = AllowRequests;
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
//ProcessQueuedRequests(deviceExtension);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
//spurious Irp
|
|
//
|
|
//If the device is already in an active state when the driver
|
|
//receives this IRP, a function driver simply sets status to
|
|
//success and passes the IRP to the next driver. For such a
|
|
//cancel-stop IRP, a function driver need not set a completion
|
|
//routine.
|
|
|
|
}
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntStatus);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : DeconfigureUsbDevice
|
|
Description : This routine is invoked when the device is removed or stopped.
|
|
This routine de-configures the usb device.
|
|
IN PARAM : <PKSDEVICE> Pointer to KS Device Object
|
|
OUT PARAM : <NTSTATUS> Status of the Device Deinitialization
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error
|
|
PreCondition : NONE
|
|
PostCondtion : USB Device Uninitialized
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS DeconfigureUsbDevice(IN PKSDEVICE pKSDeviceObject)
|
|
{
|
|
NTSTATUS ntUnInitStatus = STATUS_SUCCESS;
|
|
URB USBRequestBlock;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
UsbBuildSelectConfigurationRequest(&USBRequestBlock, sizeof(_URB_SELECT_CONFIGURATION), NULL);
|
|
|
|
ntUnInitStatus = SendURBToBusDriver(pKSDeviceObject,&USBRequestBlock);
|
|
|
|
if (!NT_SUCCESS(ntUnInitStatus))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Error Trying to Deconfigure the Device\n"));
|
|
}
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntUnInitStatus);
|
|
return ntUnInitStatus;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : StopUsbDevice
|
|
Description : This routine is invoked when the device is stopped.
|
|
This routine services Irp of minor type IRP_MN_STOP_DEVICE
|
|
IN PARAM : <PKSDEVICE> Pointer to KS Device Object
|
|
<PIRP> STOP DEVICE Irp
|
|
OUT PARAM : <NTSTATUS> Status of the Device Stop
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error
|
|
PreCondition : NONE
|
|
PostCondtion : USB Device Stopped
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS StopUsbDevice(IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket)
|
|
{
|
|
KIRQL kOldIrql;
|
|
NTSTATUS ntDeviceStopStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = NULL;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//initialize variables
|
|
pDevice = (CSkyWalker1Device *) pKSDeviceObject->Context;
|
|
|
|
|
|
//if(WinXpOrBetter == deviceExtension->WdmVersion) {
|
|
|
|
// if(deviceExtension->SSEnable) {
|
|
|
|
// //
|
|
// //Cancel the timer so that the DPCs are no longer fired.
|
|
// //Thus, we are making judicious usage of our resources.
|
|
// //we do not need DPCs because the device is stopping.
|
|
// //The timers are re-initialized while handling the start
|
|
// //device irp.
|
|
// //
|
|
|
|
// KeCancelTimer(&deviceExtension->Timer);
|
|
|
|
// //
|
|
// //after the device is stopped, it can be surprise removed.
|
|
// //we set this to 0, so that we do not attempt to cancel
|
|
// //the timer while handling surprise remove or remove irps.
|
|
// //when we get the start device request, this flag will be
|
|
// //reinitialized.
|
|
// //
|
|
// deviceExtension->SSEnable = 0;
|
|
|
|
// //
|
|
// //make sure that if a DPC was fired before we called cancel timer,
|
|
// //then the DPC and work-time have run to their completion
|
|
// //
|
|
// KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent,
|
|
// Executive,
|
|
// KernelMode,
|
|
// FALSE,
|
|
// NULL);
|
|
|
|
// //
|
|
// //make sure that the selective suspend request has been completed.
|
|
// //
|
|
// KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
|
|
// Executive,
|
|
// KernelMode,
|
|
// FALSE,
|
|
// NULL);
|
|
// }
|
|
//}
|
|
|
|
//
|
|
//after the stop Irp is sent to the lower driver object,
|
|
//the driver must not send any more Irps down that touch
|
|
//the device until another Start has occurred.
|
|
//
|
|
|
|
/* if(deviceExtension->WaitWakeEnable) {
|
|
|
|
CancelWaitWake(deviceExtension);
|
|
}*/
|
|
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
SET_NEW_PNP_STATE(pDevice, Stopped);
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
ntDeviceStopStatus = DeconfigureUsbDevice(pKSDeviceObject);
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntDeviceStopStatus);
|
|
|
|
return ntDeviceStopStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : ReadWriteUsbDevice
|
|
Description : Dispatch routine for read and write.
|
|
This routine creates a BULKUSB_RW_CONTEXT for a read/write.
|
|
This read/write is performed in stages of MAX_BULK_PACKET_SIZE.
|
|
once a stage of transfer is complete, then the irp is circulated again,
|
|
until the requested length of tranfer is performed.
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object
|
|
<UCHAR> Device Register to/From which Write/ Read is to be performed
|
|
<PUCHAR> Transfer Buffer
|
|
<ULONG> Length of the Transfer Buffer
|
|
<BOOLEAN> True if Read from else False for Write to device
|
|
OUT PARAM : <NTSTATUS> Status of Read / Write request sending to Device
|
|
STATUS_PENDING on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Read/ Write Request submitted to Device
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS ReadWriteUsbDevice(IN PKSDEVICE pKSDeviceObject,
|
|
IN ULONG ulStreamIndex,
|
|
IN ULONG ulPacketIndex,
|
|
IN PUCHAR pucTransferBuffer,
|
|
IN ULONG ulTransferLength,
|
|
IN BOOLEAN bRead)
|
|
{
|
|
NTSTATUS ntReadWriteStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *) pKSDeviceObject->Context;
|
|
ULONG ulURBFlags = 0;
|
|
ULONG ulStageTransferLength = 0;
|
|
PURB pUSBRequestBlock = NULL;
|
|
PUSBD_PIPE_INFORMATION pPipeInformation = NULL;
|
|
PIO_STACK_LOCATION pNextStackLocation = NULL;
|
|
PBULKUSB_RW_CONTEXT pReadWriteContext = NULL;
|
|
PIRP pUsbIoRequestPacket = NULL;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//Acquire device Remove lock here
|
|
if(pDevice->UsbDeviceState != Working)
|
|
{
|
|
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Invalid device state\n"));
|
|
ntReadWriteStatus = STATUS_INVALID_DEVICE_STATE;
|
|
goto FinishDeviceReadWrite;
|
|
}
|
|
|
|
if(!IS_VALID(pucTransferBuffer))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Invalid Transfer Buffer Passed\n"));
|
|
ntReadWriteStatus = STATUS_INVALID_PARAMETER;
|
|
goto FinishDeviceReadWrite;
|
|
}
|
|
|
|
if(ulTransferLength > MAX_BULK_TRANSFER_SIZE)
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,
|
|
("Tansfer Length (%lu) > MAX_BULK_TRANSFER_SIZE (%lu)\n",
|
|
ulTransferLength,
|
|
MAX_BULK_TRANSFER_SIZE));
|
|
ntReadWriteStatus = STATUS_INVALID_PARAMETER;
|
|
goto FinishDeviceReadWrite;
|
|
}
|
|
|
|
if(ulTransferLength == 0)
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Transfer data length = 0\n"));
|
|
ntReadWriteStatus = STATUS_SUCCESS;
|
|
goto FinishDeviceReadWrite;
|
|
}
|
|
|
|
ulURBFlags = USBD_SHORT_TRANSFER_OK;
|
|
if(bRead)
|
|
{
|
|
ulURBFlags |= USBD_TRANSFER_DIRECTION_IN;
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Read Operation\n"));
|
|
pPipeInformation = &pDevice->ReadPipe;
|
|
}
|
|
else
|
|
{
|
|
|
|
ulURBFlags |= USBD_TRANSFER_DIRECTION_OUT;
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Write Operation\n"));
|
|
pPipeInformation = &pDevice->WritePipe;
|
|
}
|
|
|
|
DbgPrint("Pipe Information = %p\n",pPipeInformation);
|
|
|
|
//the transfer request is for TransferLength.
|
|
//we can perform a max of Packet Size
|
|
//in each stage.
|
|
if(ulTransferLength > MAX_BULK_PACKET_SIZE)
|
|
{
|
|
ulStageTransferLength = MAX_BULK_PACKET_SIZE;
|
|
}
|
|
else
|
|
{
|
|
ulStageTransferLength = ulTransferLength;
|
|
}
|
|
|
|
//Allocate IRP for the USB Transfer
|
|
pUsbIoRequestPacket = IoAllocateIrp(pKSDeviceObject->NextDeviceObject->StackSize,
|
|
FALSE);
|
|
if(!IS_VALID(pUsbIoRequestPacket))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Failed to Allocate Memory for the USB Irp\n"));
|
|
ntReadWriteStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto FinishDeviceReadWrite;
|
|
}
|
|
|
|
ULONG ulStreamOffset = PACKET_PER_FRAME * ulStreamIndex;
|
|
pDevice->pUsbStreamIrp[ulPacketIndex + ulStreamOffset] = pUsbIoRequestPacket;
|
|
|
|
|
|
pUSBRequestBlock = (PURB)ExAllocatePoolWithTag( NonPagedPool,
|
|
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
|
|
USB_MEMORY_TAG);
|
|
|
|
if(!IS_VALID(pUSBRequestBlock))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Failed to Allocate Memory for the Bulk / Interrupt URB\n"));
|
|
ntReadWriteStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto FinishDeviceReadWrite;
|
|
}
|
|
|
|
RtlZeroMemory(pUSBRequestBlock, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
|
|
|
|
UsbBuildInterruptOrBulkTransferRequest(
|
|
pUSBRequestBlock,
|
|
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
|
|
pPipeInformation->PipeHandle,
|
|
pucTransferBuffer,
|
|
NULL,
|
|
ulStageTransferLength,
|
|
ulURBFlags,
|
|
NULL);
|
|
|
|
pReadWriteContext = (PBULKUSB_RW_CONTEXT)ExAllocatePoolWithTag( NonPagedPool,
|
|
sizeof(BULKUSB_RW_CONTEXT),
|
|
USB_MEMORY_TAG);
|
|
|
|
if(!IS_VALID(pReadWriteContext))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Failed to Allocate Memory for the Read Write Context\n"));
|
|
ntReadWriteStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto FinishDeviceReadWrite;
|
|
}
|
|
|
|
//set BULKUSB_RW_CONTEXT parameters.
|
|
pReadWriteContext->pUSBRequestBlock = pUSBRequestBlock;
|
|
pReadWriteContext->pTransferBuffer = pucTransferBuffer + ulStageTransferLength;
|
|
pReadWriteContext->ulRemainingByteTransfer = ulTransferLength - ulStageTransferLength ;
|
|
pReadWriteContext->ulCompletedByteTransfer = 0L;
|
|
pReadWriteContext->pDevice = pDevice;
|
|
pReadWriteContext->ulStreamIndex = ulStreamIndex;
|
|
|
|
//use the original read/write irp as an internal device control irp
|
|
pNextStackLocation = IoGetNextIrpStackLocation(pUsbIoRequestPacket);
|
|
pNextStackLocation->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
|
pNextStackLocation->Parameters.Others.Argument1 = (PVOID)pUSBRequestBlock ;
|
|
pNextStackLocation->Parameters.DeviceIoControl.IoControlCode =
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB;
|
|
|
|
IoSetCompletionRoutine(pUsbIoRequestPacket,
|
|
(PIO_COMPLETION_ROUTINE)UsbReadWriteCompletion,
|
|
pReadWriteContext,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("USB Transfer Details for Stream %lu Packet %lu\n",
|
|
ulStreamIndex,
|
|
ulPacketIndex));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("ulStageTransferLength = %lu\n",ulStageTransferLength));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pReadWriteContext->ulCompletedByteTransfer = %lu\n",pReadWriteContext->ulCompletedByteTransfer));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pReadWriteContext->ulRemainingByteTransfer = %lu\n",pReadWriteContext->ulRemainingByteTransfer));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("bRead = %02d\n",bRead));
|
|
|
|
//since we return STATUS_PENDING call IoMarkIrpPending.
|
|
//This is the boiler plate code.
|
|
//This may cause extra overhead of an APC for the Irp completion
|
|
//but this is the correct thing to do.
|
|
|
|
IoMarkIrpPending(pUsbIoRequestPacket);
|
|
IncrementPendingIoCount(pDevice);
|
|
|
|
ntReadWriteStatus = IoCallDriver( pKSDeviceObject->NextDeviceObject,
|
|
pUsbIoRequestPacket);
|
|
|
|
if(!NT_SUCCESS(ntReadWriteStatus))
|
|
{
|
|
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("IoCallDriver Failed with status %X\n", ntReadWriteStatus));
|
|
|
|
//if the device was yanked out, then the pipeInformation
|
|
//field is invalid.
|
|
//similarly if the request was cancelled, then we need not
|
|
//invoked reset pipe/device.
|
|
KIRQL CurrentIrql = KeGetCurrentIrql();
|
|
|
|
if((ntReadWriteStatus != STATUS_CANCELLED) &&
|
|
(ntReadWriteStatus != STATUS_DEVICE_NOT_CONNECTED))
|
|
{
|
|
|
|
if(CurrentIrql < DISPATCH_LEVEL)
|
|
{
|
|
ntReadWriteStatus = ResetUsbPipe(pKSDeviceObject,pPipeInformation);
|
|
if(!NT_SUCCESS(ntReadWriteStatus))
|
|
{
|
|
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Reset USB Pipe Failed\n"));
|
|
|
|
ntReadWriteStatus = ResetUsbDevice(pKSDeviceObject);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("ntReadWriteStatus is STATUS_CANCELLED or "
|
|
"STATUS_DEVICE_NOT_CONNECTED\n"));
|
|
}
|
|
//Freeing up the resources allocated in this routine
|
|
goto FinishDeviceReadWrite;
|
|
}
|
|
|
|
PrintFunctionExit(__FUNCTION__,STATUS_PENDING);
|
|
|
|
return STATUS_PENDING;
|
|
|
|
FinishDeviceReadWrite:
|
|
|
|
if(IS_VALID(pUSBRequestBlock))
|
|
{
|
|
ExFreePoolWithTag(pUSBRequestBlock,USB_MEMORY_TAG);
|
|
pUSBRequestBlock = NULL;
|
|
}
|
|
if(IS_VALID(pReadWriteContext))
|
|
{
|
|
ExFreePoolWithTag(pReadWriteContext,USB_MEMORY_TAG);
|
|
pReadWriteContext = NULL;
|
|
}
|
|
if(IS_VALID(pUsbIoRequestPacket))
|
|
{
|
|
IoFreeIrp(pUsbIoRequestPacket);
|
|
pUsbIoRequestPacket = NULL;
|
|
}
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntReadWriteStatus);
|
|
|
|
return ntReadWriteStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : UsbReadWriteCompletion
|
|
Description : This is the completion routine for reads/writes
|
|
If the irp completes with success, we check if we
|
|
need to recirculate this irp for another stage of
|
|
transfer. In this case return STATUS_MORE_PROCESSING_REQUIRED.
|
|
if the irp completes in error, free all memory allocs and
|
|
return the status.
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object
|
|
<PIRP> Io Request Packet
|
|
<PVOID> Context
|
|
OUT PARAM : <NTSTATUS> Status of Read / Write request Completion
|
|
STATUS_MORE_PROCESSING_REQUIRED always
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Read/ Write Request Completed
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS UsbReadWriteCompletion(
|
|
IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket,
|
|
IN PVOID pContext
|
|
)
|
|
{
|
|
ULONG ulStageTransferLength = 0;
|
|
NTSTATUS ntReadWriteCompleteStatus = pIoRequestPacket->IoStatus.Status;
|
|
PIO_STACK_LOCATION pNextStackLocation;
|
|
PBULKUSB_RW_CONTEXT pReadWriteContext = (PBULKUSB_RW_CONTEXT)pContext;
|
|
CSkyWalker1Device * pDevice = pReadWriteContext->pDevice;
|
|
ULONG ulStreamIndex = 0L;
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//successfully performed a stageLength of transfer.
|
|
//check if we need to recirculate the irp.
|
|
if(NT_SUCCESS(ntReadWriteCompleteStatus))
|
|
{
|
|
if(pReadWriteContext)
|
|
{
|
|
pReadWriteContext->ulCompletedByteTransfer +=
|
|
pReadWriteContext->pUSBRequestBlock->UrbBulkOrInterruptTransfer.TransferBufferLength;
|
|
|
|
if((pReadWriteContext->ulRemainingByteTransfer)&& (!pIoRequestPacket->Cancel))
|
|
{
|
|
//another stage transfer
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("Another stage transfer...\n"));
|
|
|
|
//the transfer request is for TransferLength.
|
|
//we can perform a max of MAX_BULK_PACKET_SIZE
|
|
//in each stage.
|
|
if(pReadWriteContext->ulRemainingByteTransfer > MAX_BULK_PACKET_SIZE)
|
|
{
|
|
ulStageTransferLength = MAX_BULK_PACKET_SIZE;
|
|
}
|
|
else
|
|
{
|
|
ulStageTransferLength = pReadWriteContext->ulRemainingByteTransfer;
|
|
}
|
|
|
|
//Reinitialize the urb
|
|
pReadWriteContext->pUSBRequestBlock->UrbBulkOrInterruptTransfer.TransferBufferLength
|
|
= ulStageTransferLength;
|
|
|
|
pReadWriteContext->pUSBRequestBlock->UrbBulkOrInterruptTransfer.TransferBuffer
|
|
= pReadWriteContext->pTransferBuffer;
|
|
|
|
pReadWriteContext->pTransferBuffer += ulStageTransferLength;
|
|
pReadWriteContext->ulRemainingByteTransfer -= ulStageTransferLength ;
|
|
|
|
//use the original read/write irp as an internal device control irp
|
|
pNextStackLocation = IoGetNextIrpStackLocation(pIoRequestPacket);
|
|
pNextStackLocation->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
|
pNextStackLocation->Parameters.Others.Argument1 = (PVOID)pReadWriteContext->pUSBRequestBlock ;
|
|
pNextStackLocation->Parameters.DeviceIoControl.IoControlCode =
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB;
|
|
|
|
IoSetCompletionRoutine(pIoRequestPacket,
|
|
(PIO_COMPLETION_ROUTINE)UsbReadWriteCompletion,
|
|
pReadWriteContext,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("USB Transfer Details for Stream %lu\n",
|
|
pReadWriteContext->ulStreamIndex));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("ulStageTransferLength = %lu\n",ulStageTransferLength));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pReadWriteContext->ulCompletedByteTransfer = %lu\n",pReadWriteContext->ulCompletedByteTransfer));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pReadWriteContext->ulRemainingByteTransfer = %lu\n",pReadWriteContext->ulRemainingByteTransfer));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pIoRequestPacket = 0x%p\n",pIoRequestPacket));
|
|
ntReadWriteCompleteStatus = IoCallDriver( pDevice->m_pKSDevice->NextDeviceObject,
|
|
pIoRequestPacket);
|
|
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
else
|
|
{
|
|
|
|
InterlockedExchangeAdd((LONG*)&pDevice->m_NumberOfBytesRead[pReadWriteContext->ulStreamIndex],
|
|
pReadWriteContext->ulCompletedByteTransfer);
|
|
|
|
ulStreamIndex = pReadWriteContext->ulStreamIndex;
|
|
|
|
//This is the last transfer
|
|
//SkyWalkerDebugPrint(ENTRY_LEVEL,("Valid Synthesis Buffer\n"));
|
|
// //This is not needed as anyways the IRP is going to Free soon
|
|
//pIoRequestPacket->IoStatus.Information = pReadWriteContext->ulCompletedByteTransfer;
|
|
////Set the Frame Read Event here
|
|
//
|
|
//if(pReadWriteContext->ulCompletedByteTransfer == pDevice->m_SampleSize)
|
|
//{
|
|
// pDevice->m_SynthesisDataValid = 1;
|
|
//}
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("ReadWriteCompletion Failed \n"));
|
|
}
|
|
|
|
if(pReadWriteContext)
|
|
{
|
|
//Dump pReadWriteContext
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Completed Stream = %lu",pReadWriteContext->ulStreamIndex));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pReadWriteContext->pUSBRequestBlock = 0x%p\n",
|
|
pReadWriteContext->pUSBRequestBlock));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pReadWriteContext->ulRemainingByteTransfer = %lu\n",
|
|
pReadWriteContext->ulRemainingByteTransfer));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pReadWriteContext->ulCompletedByteTransfer = %lu\n",
|
|
pReadWriteContext->ulCompletedByteTransfer));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pReadWriteContext->pDevice = 0x%p\n",
|
|
pReadWriteContext->pDevice));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Actual Byte Transfer = %lu",
|
|
pReadWriteContext->pUSBRequestBlock->
|
|
UrbBulkOrInterruptTransfer.TransferBufferLength));
|
|
|
|
|
|
DecrementPendingIoCount(pDevice);
|
|
|
|
if(IS_VALID(pReadWriteContext->pUSBRequestBlock))
|
|
{
|
|
ExFreePoolWithTag(pReadWriteContext->pUSBRequestBlock,USB_MEMORY_TAG);
|
|
pReadWriteContext->pUSBRequestBlock = NULL;
|
|
}
|
|
|
|
if(IS_VALID(pReadWriteContext))
|
|
{
|
|
ExFreePoolWithTag(pReadWriteContext,USB_MEMORY_TAG);
|
|
pReadWriteContext = NULL;
|
|
}
|
|
|
|
if(IS_VALID(pIoRequestPacket))
|
|
{
|
|
IoFreeIrp(pIoRequestPacket);
|
|
pIoRequestPacket = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Calling ProcessStream \n"));
|
|
//TS is read, Process the stream
|
|
pDevice->ProcessStream(ulStreamIndex);
|
|
|
|
PrintFunctionExit(__FUNCTION__,STATUS_MORE_PROCESSING_REQUIRED);
|
|
|
|
//This is the only status that can be returned from the Asynchronous
|
|
//IRP created by Driver
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
/*****************************************************************************
|
|
Function : ControlUsbDevice
|
|
Description : This Function is used to send the Vendor requests to the Device
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object
|
|
<UCHAR> Vendor Request
|
|
<USHORT> Value corresponding to Request
|
|
<USHORT> Index for the Request (Used with Request)
|
|
<PUCHAR> Transfer Buffer for Read/Write
|
|
<ULONG> size of the Transfer Buffer
|
|
<BOOLEAN> True if Read from else False for Write to device
|
|
OUT PARAM : <NTSTATUS> Status of Vendor Request Execution
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Vendor Request Command Executed
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS ControlUsbDevice( IN PKSDEVICE pKSDeviceObject,
|
|
IN UCHAR ucRequest,
|
|
IN USHORT usValue,
|
|
IN USHORT usIndex,
|
|
IN PUCHAR pucTransferBuffer,
|
|
IN ULONG ulTransferLength,
|
|
IN BOOLEAN bRead)
|
|
{
|
|
NTSTATUS ntControlStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *) pKSDeviceObject->Context;
|
|
PURB pUSBRequestBlock = NULL;
|
|
ULONG ulURBFlags = 0L;
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
if(pDevice->UsbDeviceState != Working)
|
|
{
|
|
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Invalid device state\n"));
|
|
ntControlStatus = STATUS_INVALID_DEVICE_STATE;
|
|
goto ExitControlDevice;
|
|
}
|
|
ulURBFlags = USBD_SHORT_TRANSFER_OK;
|
|
if(bRead)
|
|
{
|
|
ulURBFlags |= USBD_TRANSFER_DIRECTION_IN; //Requst data from Device
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Read Operation\n"));
|
|
}
|
|
else
|
|
{
|
|
ulURBFlags |= USBD_TRANSFER_DIRECTION_OUT;
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Write Operation\n"));
|
|
}
|
|
|
|
pUSBRequestBlock = (PURB)ExAllocatePoolWithTag( NonPagedPool,
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
|
|
USB_MEMORY_TAG);
|
|
|
|
if(!IS_VALID(pUSBRequestBlock))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Failed to Allocate Memory for the Vendor URB\n"));
|
|
ntControlStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto ExitControlDevice;
|
|
}
|
|
|
|
UsbBuildVendorRequest(
|
|
pUSBRequestBlock,//Pointer to an URB that
|
|
//is to be formatted as a vendor or class
|
|
//request.
|
|
URB_FUNCTION_VENDOR_DEVICE, //Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), //Length of URB in Bytes
|
|
ulURBFlags, //Zero, One or Combination of
|
|
//USBD_TRANSFER_DIRECTION_IN & USBD_SHORT_TRANSFER_OK
|
|
0, //Reserved
|
|
ucRequest, //USB/Vendor Specific Request Code
|
|
usValue, //Value Specific to Request
|
|
usIndex, //Device Defined identifier else Zero
|
|
pucTransferBuffer,//Pointer to Resident Buffer for Transfer or NULL
|
|
NULL, //Pointer to MDL for Transfer or NULL
|
|
ulTransferLength,//Length in Bytes of Buffer specified
|
|
NULL //NULL Always
|
|
);
|
|
|
|
|
|
ntControlStatus = SendURBToBusDriver(pKSDeviceObject,pUSBRequestBlock);
|
|
|
|
if(!NT_SUCCESS(ntControlStatus))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Sending Vendor Request Failed\n"));
|
|
}
|
|
|
|
ExFreePool(pUSBRequestBlock);
|
|
|
|
ExitControlDevice:
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntControlStatus);
|
|
return ntControlStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : SendURBToBusDriver
|
|
Description : Function to used to Send the URB to the USB Bus Driver (USBD.sys)
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object to which URB is to be sent
|
|
<PURB> Pointer to the URB to be sent
|
|
OUT PARAM : <NTSTATUS> Status of the URB Send operation
|
|
STATUS_SUCCESS on Successful execution
|
|
STATUS_INVALID_PARAMETER in case of Error
|
|
STATUS_INSUFFICIENT_RESOURCES in case IRP could not be created
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success URB sent to the Bus Driver
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS SendURBToBusDriver(IN PKSDEVICE pKSDeviceObject,
|
|
IN PURB pUSBRequestBlock )
|
|
{
|
|
NTSTATUS ntIrpProcessingStatus = STATUS_SUCCESS;
|
|
USBD_STATUS UsbStatus;
|
|
PIRP pIoRequestPacket = NULL;
|
|
KEVENT kIrpCompleted;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
PIO_STACK_LOCATION pNextIoStackLocation = NULL;
|
|
PDEVICE_OBJECT pRootDeviceObject = pKSDeviceObject->NextDeviceObject;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *) pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
if((!IS_VALID(pRootDeviceObject)) || (!(IS_VALID(pUSBRequestBlock))))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("pRootDeviceObject = 0x%p, pUSBRequestBlock = 0x%p\n",pRootDeviceObject,pUSBRequestBlock));
|
|
ntIrpProcessingStatus = STATUS_INVALID_PARAMETER;
|
|
goto CompleteURBSend;
|
|
}
|
|
//Initialize Kernel Event which should be trigerred after completion
|
|
//of the Device IO Control request
|
|
KeInitializeEvent(&kIrpCompleted, //PKEVENT
|
|
NotificationEvent, //Type
|
|
FALSE); //State
|
|
|
|
//Create Internal Device Io Control Request
|
|
pIoRequestPacket = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_USB_SUBMIT_URB ,
|
|
pRootDeviceObject, //Device to which the request to be sent
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
TRUE, //TRUE for IRM_MJ_INTERNAL_DEVICE_CONTROL, IRP_MJ_SCSI
|
|
&kIrpCompleted, //Event should be trigerred when the IRP completes
|
|
&IoStatusBlock); //The Status Block should be set when the Io request Completes
|
|
|
|
|
|
//If could not create the IRP return with the INSUFFICIENT RESOURCES
|
|
if(pIoRequestPacket == NULL)
|
|
{
|
|
ntIrpProcessingStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto CompleteURBSend;
|
|
}
|
|
|
|
pNextIoStackLocation = IoGetNextIrpStackLocation(pIoRequestPacket);
|
|
pNextIoStackLocation->Parameters.Others.Argument1 = pUSBRequestBlock;
|
|
|
|
IncrementPendingIoCount(pDevice);
|
|
|
|
//Call the Next Driver
|
|
ntIrpProcessingStatus = IoCallDriver(pRootDeviceObject,pIoRequestPacket);
|
|
if(ntIrpProcessingStatus == STATUS_PENDING)
|
|
{
|
|
LARGE_INTEGER Timeout;
|
|
Timeout.QuadPart = (LONGLONG) 2 /*sec*/* 1000 /*msec*/ * 1000 /*usec*/ * (-10)/*Conv. Factor*/;
|
|
//for(int nRetry = 0; ((nRetry < 3) && (ntIrpProcessingStatus != STATUS_SUCCESS)) ; nRetry++)
|
|
{
|
|
//IRP is yet to be processed thus STATUS_PENDING is returned from the Lower Device Driver (USBD.sys)
|
|
ntIrpProcessingStatus = KeWaitForSingleObject(&kIrpCompleted, //PKEVENT
|
|
Executive, //Wait Reason has to be Executive
|
|
KernelMode, //Must be kernel mode so
|
|
//that Stack will not Paged out
|
|
FALSE, //No Alert
|
|
NULL//&Timeout //Wait for 2 sec max
|
|
);
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("KeWaitForSingleObject returned with status = %s(0x%X)\n",
|
|
NTStatusToString(ntIrpProcessingStatus),ntIrpProcessingStatus));
|
|
//SkyWalkerDebugPrint(EXTREME_LEVEL,("nRetry = %d\n",nRetry));
|
|
}
|
|
|
|
ntIrpProcessingStatus = IoStatusBlock.Status;
|
|
UsbStatus = URB_STATUS(pUSBRequestBlock);
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("URB STATUS = 0x%X\n",UsbStatus));
|
|
}
|
|
|
|
DecrementPendingIoCount(pDevice);
|
|
|
|
CompleteURBSend:
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntIrpProcessingStatus);
|
|
|
|
return ntIrpProcessingStatus;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : QueryRemoveUsbDevice
|
|
Description : Function to used to Service PnP IRPs of Minor Type
|
|
IRP_MN_QUERY_REMOVE_DEVICE
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object whose Remove Query has come
|
|
<PIRP> Device Remove Query Irp with Minor Code IRP_MN_QUERY_REMOVE_DEVICE
|
|
OUT PARAM : <NTSTATUS> Status of the Device Remove Query Processing
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Device can be removed is conveyed to the caller
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS QueryRemoveUsbDevice( IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket)
|
|
{
|
|
KIRQL kOldIrql;
|
|
NTSTATUS ntQueryStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *) pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//
|
|
//If we can allow removal of the device, we should set the QueueState
|
|
//to HoldRequests so further requests will be queued. This is required
|
|
//so that we can process queued up requests in cancel-remove just in
|
|
//case somebody else in the stack fails the query-remove.
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
SET_NEW_PNP_STATE(pDevice, PendingRemove);
|
|
pDevice->QueueState = HoldRequests;
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
//wait for the existing ones to be finished.
|
|
//first, decrement this operation
|
|
DecrementPendingIoCount(pDevice);
|
|
|
|
KeWaitForSingleObject(&pDevice->EvDeviceStopOk,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntQueryStatus);
|
|
|
|
return ntQueryStatus;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : CancelRemoveUsbDevice
|
|
Description : Function to used to Service PnP IRPs of Minor Type
|
|
IRP_MN_CANCEL_REMOVE_DEVICE
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object whose Remove request has
|
|
been cancelled
|
|
<PIRP> Device Remove Cancel Irp with Minor Code
|
|
IRP_MN_CANCEL_REMOVE_DEVICE
|
|
OUT PARAM : <NTSTATUS> Status of the Device Remove Cancel Irp Processing
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Device Remove cancel request is processed
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS CancelRemoveUsbDevice(IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket)
|
|
{
|
|
KIRQL kOldIrql;
|
|
KEVENT Evevent;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//We need to reset the QueueState flag to ProcessRequest,
|
|
//since the device resume its normal activities.
|
|
//
|
|
//First check to see whether you have received cancel-stop
|
|
//without first receiving a query-stop. This could happen if someone
|
|
//above us fails a query-stop and passes down the subsequent
|
|
//cancel-stop.
|
|
if(pDevice->UsbDeviceState == PendingRemove )
|
|
{
|
|
ntStatus = PassDownIRPAndWaitForCompletion(pKSDeviceObject->NextDeviceObject,
|
|
pIoRequestPacket,
|
|
true);
|
|
if(NT_SUCCESS(ntStatus))
|
|
{
|
|
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
RESTORE_PREVIOUS_PNP_STATE(pDevice);
|
|
pDevice->QueueState = AllowRequests;
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
//ProcessQueuedRequests(deviceExtension);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
/* spurious cancel Remove
|
|
|
|
If the device is already started when the driver receives
|
|
this IRP, the driver simply sets status to success and passes
|
|
the IRP to the next driver. For such a cancel-remove IRP, a
|
|
function driver need not set a completion routine. The device
|
|
may not be in the remove-pending state, because, for example,
|
|
the driver failed the previous IRP_MN_QUERY_REMOVE_DEVICE.*/
|
|
|
|
}
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntStatus);
|
|
|
|
return ntStatus;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : SurpriseUsbDeviceRemoval
|
|
Description : Function to used to Service PnP IRPs of Minor Type
|
|
IRP_MN_SURPRISE_REMOVAL
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object which is removed
|
|
surprisingly
|
|
<PIRP> Device Remove Cancel Irp with Minor Code
|
|
IRP_MN_SURPRISE_REMOVAL
|
|
OUT PARAM : <NTSTATUS> Status of the Spurious Device Removal Processing
|
|
STATUS_SUCCESS Always
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Surprised Device Remove is processed
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS SurpriseUsbDeviceRemoval(IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket)
|
|
{
|
|
KIRQL kOldIrql;
|
|
KEVENT Evevent;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//
|
|
//1. fail pending requests
|
|
//2. return device and memory resources
|
|
//3. disable interfaces
|
|
//
|
|
|
|
//if(deviceExtension->WaitWakeEnable) {
|
|
//
|
|
// CancelWaitWake(deviceExtension);
|
|
//}
|
|
|
|
|
|
//if(WinXpOrBetter == deviceExtension->WdmVersion) {
|
|
|
|
// if(deviceExtension->SSEnable) {
|
|
|
|
// //
|
|
// //Cancel the timer so that the DPCs are no longer fired.
|
|
// //we do not need DPCs because the device has been surprise
|
|
// //removed
|
|
// //
|
|
//
|
|
// KeCancelTimer(&deviceExtension->Timer);
|
|
|
|
// deviceExtension->SSEnable = 0;
|
|
|
|
// //
|
|
// //make sure that if a DPC was fired before we called cancel timer,
|
|
// //then the DPC and work-time have run to their completion
|
|
// //
|
|
// KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent,
|
|
// Executive,
|
|
// KernelMode,
|
|
// FALSE,
|
|
// NULL);
|
|
|
|
// //
|
|
// //make sure that the selective suspend request has been completed.
|
|
// //
|
|
// KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
|
|
// Executive,
|
|
// KernelMode,
|
|
// FALSE,
|
|
// NULL);
|
|
// }
|
|
//}
|
|
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
SET_NEW_PNP_STATE(pDevice, SurpriseRemoved);
|
|
pDevice->QueueState = FailRequests;
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
//ProcessQueuedRequests(deviceExtension);
|
|
|
|
AbortUsbPipes(pKSDeviceObject);
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntStatus);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : AbortUsbPipes
|
|
Description : This function sends an abort pipe request for pipes.
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object
|
|
OUT PARAM : <NTSTATUS> Status of the Pipe Abort
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Pipe are aborted
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS AbortUsbPipes(IN PKSDEVICE pKSDeviceObject)
|
|
{
|
|
PURB pUsbRequestBlock = NULL;
|
|
ULONG ulPipeIndex = 0;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
PUSBD_PIPE_INFORMATION pPipeInformation = &pDevice->ReadPipe;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
for(ulPipeIndex = 0; ulPipeIndex < 2; ulPipeIndex++)
|
|
{
|
|
//if(pPipeInformation->PipeOpen)
|
|
{
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("Aborting Pipe 0x%X\n",pPipeInformation->EndpointAddress));
|
|
|
|
pUsbRequestBlock = (PURB) ExAllocatePoolWithTag( NonPagedPool,
|
|
sizeof(struct _URB_PIPE_REQUEST),
|
|
USB_MEMORY_TAG);
|
|
|
|
if(pUsbRequestBlock)
|
|
{
|
|
|
|
pUsbRequestBlock->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
|
|
pUsbRequestBlock->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
|
|
pUsbRequestBlock->UrbPipeRequest.PipeHandle = pPipeInformation->PipeHandle;
|
|
|
|
ntStatus = SendURBToBusDriver(pKSDeviceObject,pUsbRequestBlock);
|
|
|
|
ExFreePool(pUsbRequestBlock);
|
|
}
|
|
else
|
|
{
|
|
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Failed to Allocate memory for URB during Pipe Abort\n"));
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto FinishAbortPipe;
|
|
}
|
|
|
|
if(NT_SUCCESS(ntStatus))
|
|
{
|
|
//pPipeInformation->PipeOpen = FALSE;
|
|
}
|
|
pPipeInformation = &pDevice->WritePipe;
|
|
}
|
|
}
|
|
|
|
FinishAbortPipe:
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntStatus);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : RemoveUsbDevice
|
|
Description : Function to used to Service PnP IRPs of Minor Type
|
|
IRP_MN_REMOVE_DEVICE
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object whose remove
|
|
request has come
|
|
<PIRP> Device Remove Cancel Irp with Minor Code
|
|
IRP_MN_REMOVE_DEVICE
|
|
OUT PARAM : <NTSTATUS> Status of the Device Removal
|
|
STATUS_SUCCESS Always
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Device Remove request is processed
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS RemoveUsbDevice( IN PKSDEVICE pKSDeviceObject,
|
|
IN PIRP pIoRequestPacket)
|
|
{
|
|
KIRQL kOldIrql;
|
|
KEVENT Evevent;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
ULONG ulRequestCount = 0L;
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//
|
|
//The Plug & Play system has dictated the removal of this device. We
|
|
//have no choice but to detach and delete the device object.
|
|
//(If we wanted to express an interest in preventing this removal,
|
|
//we should have failed the query remove IRP).
|
|
//
|
|
|
|
if(pDevice->UsbDeviceState != SurpriseRemoved )
|
|
{
|
|
|
|
//
|
|
//we are here after QUERY_REMOVE
|
|
//
|
|
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
pDevice->QueueState = FailRequests;
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
//if(deviceExtension->WaitWakeEnable) {
|
|
//
|
|
// CancelWaitWake(deviceExtension);
|
|
//}
|
|
|
|
//if(WinXpOrBetter == deviceExtension->WdmVersion) {
|
|
|
|
// if(deviceExtension->SSEnable) {
|
|
|
|
// //
|
|
// //Cancel the timer so that the DPCs are no longer fired.
|
|
// //we do not need DPCs because the device has been removed
|
|
// //
|
|
// KeCancelTimer(&deviceExtension->Timer);
|
|
|
|
// deviceExtension->SSEnable = 0;
|
|
|
|
// //
|
|
// //make sure that if a DPC was fired before we called cancel timer,
|
|
// //then the DPC and work-time have run to their completion
|
|
// //
|
|
// KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent,
|
|
// Executive,
|
|
// KernelMode,
|
|
// FALSE,
|
|
// NULL);
|
|
|
|
// //
|
|
// //make sure that the selective suspend request has been completed.
|
|
// //
|
|
// KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
|
|
// Executive,
|
|
// KernelMode,
|
|
// FALSE,
|
|
// NULL);
|
|
// }
|
|
//}
|
|
|
|
//ProcessQueuedRequests(deviceExtension);
|
|
|
|
AbortUsbPipes(pKSDeviceObject);
|
|
}
|
|
|
|
KeAcquireSpinLock(&pDevice->DeviceStateLock, &kOldIrql);
|
|
|
|
SET_NEW_PNP_STATE(pDevice, Removed);
|
|
|
|
KeReleaseSpinLock(&pDevice->DeviceStateLock, kOldIrql);
|
|
|
|
//
|
|
//need 2 decrements
|
|
//
|
|
|
|
ulRequestCount = DecrementPendingIoCount(pDevice);
|
|
ulRequestCount = DecrementPendingIoCount(pDevice);
|
|
|
|
KeWaitForSingleObject(&pDevice->EvDeviceRemoveOk,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntStatus);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : ResetUsbPipe
|
|
Description : This routine synchronously submits a URB_FUNCTION_RESET_PIPE
|
|
request down the stack.
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object
|
|
<PUSBD_PIPE_INFORMATION> Pipe to be reseted
|
|
OUT PARAM : <NTSTATUS> Status of the Reset Usb Pipe Request
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Usb Pipe is reseted
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS ResetUsbPipe( IN PKSDEVICE pKSDeviceObject,
|
|
IN PUSBD_PIPE_INFORMATION pPipeInformation)
|
|
{
|
|
PURB pUsbRequestBlock = NULL;
|
|
NTSTATUS ntResetStatus = STATUS_SUCCESS;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *)pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Pipe to Reset = 0x%X",pPipeInformation->EndpointAddress));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Pipe Handle = 0x%p",pPipeInformation->PipeHandle));
|
|
|
|
pUsbRequestBlock = (PURB) ExAllocatePoolWithTag( NonPagedPool,
|
|
sizeof(struct _URB_PIPE_REQUEST),
|
|
USB_MEMORY_TAG);
|
|
|
|
if(pUsbRequestBlock)
|
|
{
|
|
|
|
pUsbRequestBlock->UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
|
|
pUsbRequestBlock->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
|
|
pUsbRequestBlock->UrbPipeRequest.PipeHandle = pPipeInformation->PipeHandle;
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Sending the Pipe Reset Command\n"));
|
|
ntResetStatus = SendURBToBusDriver(pKSDeviceObject, pUsbRequestBlock);
|
|
|
|
ExFreePool(pUsbRequestBlock);
|
|
}
|
|
else
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Failed to allocate URB Memory during Pipe Reset\n"));
|
|
ntResetStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if(NT_SUCCESS(ntResetStatus))
|
|
{
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("Successfully Reseted the Usb Pipe\n"));
|
|
ntResetStatus = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Failed to reset the Usb Pipe\n"));
|
|
}
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntResetStatus);
|
|
|
|
return ntResetStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : ResetUsbDevice
|
|
Description : This routine checks the current status of the Usb Port
|
|
If Device is connected but not enabled then it resets
|
|
the Usb Port
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object
|
|
OUT PARAM : <NTSTATUS> Status of the Reset Usb Device Request
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Usb Device is reseted
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS ResetUsbDevice(IN PKSDEVICE pKSDeviceObject)
|
|
{
|
|
NTSTATUS ntResetStatus = STATUS_SUCCESS;
|
|
ULONG ulPortStatus = 0;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
ntResetStatus = GetUsbPortStatus(pKSDeviceObject, &ulPortStatus);
|
|
|
|
if((NT_SUCCESS(ntResetStatus))
|
|
&& (!(ulPortStatus & USBD_PORT_ENABLED))
|
|
&& (ulPortStatus & USBD_PORT_CONNECTED))
|
|
{
|
|
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Resetting the Parent Port\n"));
|
|
ntResetStatus = ResetUsbParentPort(pKSDeviceObject);
|
|
}
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntResetStatus);
|
|
|
|
return ntResetStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : GetUsbPortStatus
|
|
Description : This routine retrives the Usb Port Status as Enabled / Disabled
|
|
and Connected / Not Connected
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object
|
|
<PULONG> Port Status
|
|
OUT PARAM : <NTSTATUS> Status of the USB Port Status Request
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Usb Port status is retrived
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS GetUsbPortStatus( IN PKSDEVICE pKSDeviceObject,
|
|
IN OUT PULONG pulPortStatus)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
KEVENT EvRequestComplete;
|
|
PIRP pIoRequestPacket = NULL;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
PIO_STACK_LOCATION pNextStackLocation = NULL;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *) pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
*pulPortStatus = 0;
|
|
|
|
//Initialize the Event to be triggerred after completion of Device Io Control request
|
|
KeInitializeEvent(&EvRequestComplete, NotificationEvent, FALSE);
|
|
|
|
pIoRequestPacket = IoBuildDeviceIoControlRequest(
|
|
IOCTL_INTERNAL_USB_GET_PORT_STATUS,
|
|
pKSDeviceObject->NextDeviceObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
TRUE,
|
|
&EvRequestComplete,
|
|
&IoStatus);
|
|
|
|
if(!IS_VALID(pIoRequestPacket))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Memory Allocation during Get Port Status Failed\n"));
|
|
goto FinishGetPortStatus;
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
pNextStackLocation = IoGetNextIrpStackLocation(pIoRequestPacket);
|
|
|
|
pNextStackLocation->Parameters.Others.Argument1 = pulPortStatus;
|
|
|
|
ntStatus = IoCallDriver(pKSDeviceObject->NextDeviceObject, pIoRequestPacket);
|
|
|
|
if(ntStatus == STATUS_PENDING)
|
|
{
|
|
KeWaitForSingleObject(&EvRequestComplete, Executive, KernelMode, FALSE, NULL);
|
|
}
|
|
else
|
|
{
|
|
IoStatus.Status = ntStatus;
|
|
}
|
|
|
|
ntStatus = IoStatus.Status;
|
|
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("Port Status = %lu (",*pulPortStatus));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("%s, ",(((*pulPortStatus) & USBD_PORT_ENABLED)? "Enabled" : "Disabled")));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("%s)\n",(((*pulPortStatus) & USBD_PORT_CONNECTED)? "Connected" : "Not Connected")));
|
|
|
|
FinishGetPortStatus:
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntStatus);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Function : ResetUsbParentPort
|
|
Description : This routine sends an IOCTL_INTERNAL_USB_RESET_PORT
|
|
synchronously down the stack.
|
|
IN PARAM : <PKSDEVICE> Pointer to Device Object
|
|
OUT PARAM : <NTSTATUS> Status of the Reset USB Port Request
|
|
STATUS_SUCCESS on Successful execution
|
|
else Error from the Bus Driver
|
|
PreCondition : NONE
|
|
PostCondtion : On Success Usb Port is reseted
|
|
Logic : NONE
|
|
Assumption : NONE
|
|
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
|
|
*****************************************************************************/
|
|
NTSTATUS ResetUsbParentPort( IN PKSDEVICE pKSDeviceObject )
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
KEVENT EvRequestComplete;
|
|
PIRP pIoRequestPacket = NULL;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
PIO_STACK_LOCATION pNextStackLocation = NULL;
|
|
CSkyWalker1Device * pDevice = (CSkyWalker1Device *) pKSDeviceObject->Context;
|
|
|
|
PrintFunctionEntry(__FUNCTION__);
|
|
|
|
//Initialize the Event to be triggerred after completion of Device Io Control request
|
|
KeInitializeEvent(&EvRequestComplete, NotificationEvent, FALSE);
|
|
|
|
pIoRequestPacket = IoBuildDeviceIoControlRequest(
|
|
IOCTL_INTERNAL_USB_RESET_PORT,
|
|
pKSDeviceObject->NextDeviceObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
TRUE,
|
|
&EvRequestComplete,
|
|
&IoStatus);
|
|
|
|
if(!IS_VALID(pIoRequestPacket))
|
|
{
|
|
SkyWalkerDebugPrint(ENTRY_LEVEL,("Memory Allocation during Reset Parent Device Failed\n"));
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto FinishResetDevice;
|
|
|
|
}
|
|
|
|
pNextStackLocation = IoGetNextIrpStackLocation(pIoRequestPacket);
|
|
|
|
ntStatus = IoCallDriver(pKSDeviceObject->NextDeviceObject, pIoRequestPacket);
|
|
|
|
if(ntStatus == STATUS_PENDING)
|
|
{
|
|
KeWaitForSingleObject(&EvRequestComplete, Executive, KernelMode, FALSE, NULL);
|
|
}
|
|
else
|
|
{
|
|
IoStatus.Status = ntStatus;
|
|
}
|
|
|
|
ntStatus = IoStatus.Status;
|
|
|
|
FinishResetDevice:
|
|
|
|
PrintFunctionExit(__FUNCTION__,ntStatus);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
//Print Device Descriptor
|
|
VOID PrintDeviceDescriptor(IN PUSB_DEVICE_DESCRIPTOR pDeviceDescriptor)
|
|
{
|
|
SkyWalkerDebugPrint(INTERMEDIATE_LEVEL, (__FUNCTION__"\n"));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bLength= %02d\n",
|
|
pDeviceDescriptor->bLength));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bDescriptorType= %02d\n",
|
|
pDeviceDescriptor->bDescriptorType));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bcdUSB= 0x%X\n",
|
|
pDeviceDescriptor->bcdUSB));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bDeviceClass= 0x%02X\n",
|
|
pDeviceDescriptor->bDeviceClass));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bDeviceSubClass= 0x%02X\n",
|
|
pDeviceDescriptor->bDeviceSubClass));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bDeviceProtocol= 0x%02X\n",
|
|
pDeviceDescriptor->bDeviceProtocol));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bMaxPacketSize0= %02d\n",
|
|
pDeviceDescriptor->bMaxPacketSize0));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->idVendor= 0x%X\n",
|
|
pDeviceDescriptor->idVendor));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->idProduct= 0x%X\n",
|
|
pDeviceDescriptor->idProduct));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bcdDevice= 0x%X\n",
|
|
pDeviceDescriptor->bcdDevice));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->iManufacturer= %02d\n",
|
|
pDeviceDescriptor->iManufacturer));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->iProduct= %02d\n",
|
|
pDeviceDescriptor->iProduct));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->iSerialNumber= %02d\n",
|
|
pDeviceDescriptor->iSerialNumber));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pDeviceDescriptor->bNumConfigurations= %02d\n",
|
|
pDeviceDescriptor->bNumConfigurations));
|
|
}
|
|
|
|
//Print Configuration Descriptor
|
|
VOID PrintConfigurationDescriptor(IN PUSB_CONFIGURATION_DESCRIPTOR pConfigurationDescriptor)
|
|
{
|
|
SkyWalkerDebugPrint(INTERMEDIATE_LEVEL, (__FUNCTION__"\n"));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pConfigurationDescriptor->bLength= %02d\n",
|
|
pConfigurationDescriptor->bLength));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pConfigurationDescriptor->bDescriptorType= %02d\n",
|
|
pConfigurationDescriptor->bDescriptorType));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pConfigurationDescriptor->wTotalLength= %d\n",
|
|
pConfigurationDescriptor->wTotalLength));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pConfigurationDescriptor->bNumInterfaces= %02d\n",
|
|
pConfigurationDescriptor->bNumInterfaces));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pConfigurationDescriptor->bConfigurationValue= %02d\n",
|
|
pConfigurationDescriptor->bConfigurationValue));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pConfigurationDescriptor->iConfiguration= %02d\n",
|
|
pConfigurationDescriptor->iConfiguration));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pConfigurationDescriptor->bmAttributes= 0x%02X\n",
|
|
pConfigurationDescriptor->bmAttributes));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pConfigurationDescriptor->MaxPower= %02d\n",
|
|
pConfigurationDescriptor->MaxPower));
|
|
|
|
}
|
|
//Print Interface Descriptor
|
|
VOID PrintInterfaceDescriptor(IN PUSB_INTERFACE_DESCRIPTOR pInterfaceDescriptor)
|
|
{
|
|
SkyWalkerDebugPrint(INTERMEDIATE_LEVEL, (__FUNCTION__"\n"));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->bLength= %02d\n",
|
|
pInterfaceDescriptor->bLength));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->bDescriptorType= %02d\n",
|
|
pInterfaceDescriptor->bDescriptorType));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->bInterfaceNumber= %02d\n",
|
|
pInterfaceDescriptor->bInterfaceNumber));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->bAlternateSetting= %02d\n",
|
|
pInterfaceDescriptor->bAlternateSetting));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->bNumEndpoints= %02d\n",
|
|
pInterfaceDescriptor->bNumEndpoints));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->bInterfaceClass= 0x%02X\n",
|
|
pInterfaceDescriptor->bInterfaceClass));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->bInterfaceSubClass= 0x%02X\n",
|
|
pInterfaceDescriptor->bInterfaceSubClass));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->bInterfaceProtocol= 0x%02X\n",
|
|
pInterfaceDescriptor->bInterfaceProtocol));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pInterfaceDescriptor->iInterface= %02d\n",
|
|
pInterfaceDescriptor->iInterface));
|
|
|
|
}
|
|
|
|
//Print Pipe Information
|
|
VOID PrintPipeInformation(PUSBD_PIPE_INFORMATION pPipeInformation)
|
|
{
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pPipeInformation->PipeType = 0x%X\n",
|
|
pPipeInformation->PipeType));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pPipeInformation->EndpointAddress = 0x%X\n",
|
|
pPipeInformation->EndpointAddress));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pPipeInformation->MaximumPacketSize = 0x%X\n",
|
|
pPipeInformation->MaximumPacketSize));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pPipeInformation->Interval = 0x%X\n",
|
|
pPipeInformation->Interval));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pPipeInformation->PipeHandle = 0x%p\n",
|
|
pPipeInformation->PipeHandle));
|
|
SkyWalkerDebugPrint(EXTREME_LEVEL,("pPipeInformation->MaximumTransferSize = 0x%X\n",
|
|
pPipeInformation->MaximumTransferSize));
|
|
|
|
} |