Ryan Malloy bbdcb243dc Normalize line endings to LF across entire repository
Apply .gitattributes normalization to convert all CRLF line
endings inherited from Windows-origin source files to Unix LF.
175 files, zero content changes.
2026-02-20 10:55:50 -07:00

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));
}