You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2515 lines
74 KiB
2515 lines
74 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
urb.c
|
|
|
|
Abstract:
|
|
|
|
main urb "handler"
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
Revision History:
|
|
|
|
6-20-99 : created
|
|
|
|
--*/
|
|
|
|
#include "common.h"
|
|
|
|
// paged functions
|
|
#ifdef ALLOC_PRAGMA
|
|
#endif
|
|
|
|
// non paged functions
|
|
//USBPORT_ProcessURB
|
|
//USBPORT_SelectConfiguration;
|
|
//USBPORT_SelectInterface;
|
|
//USBPORT_AsyncTransfer;
|
|
//USBPORT_IsochTransfer;
|
|
//USBPORT_AbortPipe;
|
|
//USBPORT_ResetPipe;
|
|
//USBPORT_SCT_GetSetDescriptor;
|
|
//USBPORT_SCT_SetClearFeature;
|
|
//USBPORT_SCT_GetStatus;
|
|
//USBPORT_SCT_VendorClassCommand;
|
|
//USBPORT_SCT_GetInterface;
|
|
//USBPORT_SCT_GetConfiguration;
|
|
//USBPORT_TakeFrameLengthControl;
|
|
//USBPORT_ReleaseFrameLengthControl;
|
|
//USBPORT_GetFrameLength;
|
|
//USBPORT_SetFrameLength;
|
|
//USBPORT_BulkTransfer;
|
|
//USBPORT_GetCurrentFrame;
|
|
//USBPORT_InvalidFunction
|
|
//USBPORT_GetMSFeartureDescriptor
|
|
//USBPORT_SyncClearStall
|
|
//USBPORT_GetMSFeartureDescriptor
|
|
|
|
/*
|
|
** URB handler routines
|
|
|
|
Handler --
|
|
This function handles the specific USBDI request, if the request is queued
|
|
by the handler the STATUS_PENDING is returned
|
|
*/
|
|
|
|
|
|
|
|
typedef NTSTATUS URB_HANDLER(PDEVICE_OBJECT FdoDeviceObject, PIRP Irp, PURB Urb);
|
|
|
|
typedef struct _URB_DISPATCH_ENTRY {
|
|
// USB API handler
|
|
URB_HANDLER *UrbHandler;
|
|
// length of the URB expected for this request
|
|
USHORT UrbRequestLength;
|
|
USHORT Pad2;
|
|
// request code for setup packet if standard command
|
|
UCHAR Direction;
|
|
UCHAR Type;
|
|
UCHAR Recipient;
|
|
UCHAR bRequest;
|
|
|
|
// tell the generic urb dispatch routine what to do
|
|
ULONG Flags;
|
|
#if DBG
|
|
ULONG ExpectedFunctionCode;
|
|
#endif
|
|
} URB_DISPATCH_ENTRY;
|
|
|
|
URB_HANDLER USBPORT_SelectConfiguration;
|
|
URB_HANDLER USBPORT_SelectInterface;
|
|
URB_HANDLER USBPORT_AsyncTransfer;
|
|
URB_HANDLER USBPORT_IsochTransfer;
|
|
URB_HANDLER USBPORT_AbortPipe;
|
|
URB_HANDLER USBPORT_SyncResetPipeAndClearStall;
|
|
URB_HANDLER USBPORT_SyncResetPipe;
|
|
URB_HANDLER USBPORT_SyncClearStall;
|
|
URB_HANDLER USBPORT_SCT_GetSetDescriptor;
|
|
URB_HANDLER USBPORT_SCT_SetClearFeature;
|
|
URB_HANDLER USBPORT_SCT_GetStatus;
|
|
URB_HANDLER USBPORT_SCT_VendorClassCommand;
|
|
URB_HANDLER USBPORT_SCT_GetInterface;
|
|
URB_HANDLER USBPORT_SCT_GetConfiguration;
|
|
URB_HANDLER USBPORT_TakeFrameLengthControl;
|
|
URB_HANDLER USBPORT_ReleaseFrameLengthControl;
|
|
URB_HANDLER USBPORT_GetFrameLength;
|
|
URB_HANDLER USBPORT_SetFrameLength;
|
|
URB_HANDLER USBPORT_BulkTransfer;
|
|
URB_HANDLER USBPORT_GetCurrentFrame;
|
|
URB_HANDLER USBPORT_InvalidFunction;
|
|
URB_HANDLER USBPORT_GetMSFeartureDescriptor;
|
|
|
|
// last supported function
|
|
#define URB_FUNCTION_LAST URB_FUNCTION_SYNC_CLEAR_STALL
|
|
|
|
// last valid function
|
|
URB_DISPATCH_ENTRY UrbDispatchTable[URB_FUNCTION_LAST+1] =
|
|
{
|
|
//URB_FUNCTION_SELECT_CONFIGURATION
|
|
USBPORT_SelectConfiguration,
|
|
0, // Length, handler will validate length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SELECT_CONFIGURATION,
|
|
#endif
|
|
//URB_FUNCTION_SELECT_INTERFACE
|
|
USBPORT_SelectInterface, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SELECT_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_ABORT_PIPE
|
|
USBPORT_AbortPipe, // Function
|
|
sizeof(struct _URB_PIPE_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_ABORT_PIPE,
|
|
#endif
|
|
//URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL
|
|
USBPORT_TakeFrameLengthControl, // Function
|
|
sizeof(struct _URB_FRAME_LENGTH_CONTROL), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL,
|
|
#endif
|
|
//URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL
|
|
USBPORT_ReleaseFrameLengthControl, // Function
|
|
sizeof(struct _URB_FRAME_LENGTH_CONTROL), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL,
|
|
#endif
|
|
//URB_FUNCTION_GET_FRAME_LENGTH
|
|
USBPORT_GetFrameLength, // Function
|
|
sizeof(struct _URB_GET_FRAME_LENGTH), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_FRAME_LENGTH,
|
|
#endif
|
|
//URB_FUNCTION_SET_FRAME_LENGTH
|
|
USBPORT_SetFrameLength, // Function
|
|
sizeof(struct _URB_SET_FRAME_LENGTH), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SET_FRAME_LENGTH,
|
|
#endif
|
|
//URB_FUNCTION_GET_CURRENT_FRAME_NUMBER
|
|
USBPORT_GetCurrentFrame, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_CURRENT_FRAME_NUMBER,
|
|
#endif
|
|
//URB_FUNCTION_CONTROL_TRANSFER
|
|
USBPORT_AsyncTransfer, // Function
|
|
sizeof(struct _URB_CONTROL_TRANSFER), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_CONTROL_TRANSFER,
|
|
#endif
|
|
//URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
|
|
USBPORT_AsyncTransfer, // Function
|
|
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER,
|
|
#endif
|
|
//URB_FUNCTION_ISOCH_TRANSFER
|
|
USBPORT_IsochTransfer, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_ISOCH_TRANSFER,
|
|
#endif
|
|
//URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
|
|
USBPORT_SCT_GetSetDescriptor, // Function
|
|
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_DEVICE, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_DESCRIPTOR, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE,
|
|
#endif
|
|
//URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE
|
|
USBPORT_SCT_GetSetDescriptor, // Function
|
|
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_DEVICE, // bmRequestType.Recipient
|
|
USB_REQUEST_SET_DESCRIPTOR, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE,
|
|
#endif
|
|
//URB_FUNCTION_SET_FEATURE_TO_DEVICE
|
|
USBPORT_SCT_SetClearFeature, // Function
|
|
sizeof(struct _URB_CONTROL_FEATURE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_DEVICE, // bmRequestType.Recipient
|
|
USB_REQUEST_SET_FEATURE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | \
|
|
USBPORT_REQUEST_USES_DEFAULT_PIPE | \
|
|
USBPORT_REQUEST_NO_DATA_PHASE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SET_FEATURE_TO_DEVICE,
|
|
#endif
|
|
//URB_FUNCTION_SET_FEATURE_TO_INTERFACE
|
|
USBPORT_SCT_SetClearFeature, // Function
|
|
sizeof(struct _URB_CONTROL_FEATURE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
USB_REQUEST_SET_FEATURE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | \
|
|
USBPORT_REQUEST_USES_DEFAULT_PIPE | \
|
|
USBPORT_REQUEST_NO_DATA_PHASE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SET_FEATURE_TO_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_SET_FEATURE_TO_ENDPOINT
|
|
USBPORT_SCT_SetClearFeature, // Function
|
|
sizeof(struct _URB_CONTROL_FEATURE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_ENDPOINT, // bmRequestType.Recipient
|
|
USB_REQUEST_SET_FEATURE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | \
|
|
USBPORT_REQUEST_USES_DEFAULT_PIPE | \
|
|
USBPORT_REQUEST_NO_DATA_PHASE, // Length
|
|
#if DBG
|
|
URB_FUNCTION_SET_FEATURE_TO_ENDPOINT,
|
|
#endif
|
|
//URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE
|
|
USBPORT_SCT_SetClearFeature, // Function
|
|
sizeof(struct _URB_CONTROL_FEATURE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_DEVICE, // bmRequestType.Recipient
|
|
USB_REQUEST_CLEAR_FEATURE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | \
|
|
USBPORT_REQUEST_USES_DEFAULT_PIPE | \
|
|
USBPORT_REQUEST_NO_DATA_PHASE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE,
|
|
#endif
|
|
//URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE
|
|
USBPORT_SCT_SetClearFeature, // Function
|
|
sizeof(struct _URB_CONTROL_FEATURE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
USB_REQUEST_CLEAR_FEATURE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | \
|
|
USBPORT_REQUEST_USES_DEFAULT_PIPE | \
|
|
USBPORT_REQUEST_NO_DATA_PHASE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT
|
|
USBPORT_SCT_SetClearFeature, // Function
|
|
sizeof(struct _URB_CONTROL_FEATURE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_ENDPOINT, // bmRequestType.Recipient
|
|
USB_REQUEST_CLEAR_FEATURE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | \
|
|
USBPORT_REQUEST_USES_DEFAULT_PIPE | \
|
|
USBPORT_REQUEST_NO_DATA_PHASE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT,
|
|
#endif
|
|
//URB_FUNCTION_GET_STATUS_FROM_DEVICE
|
|
USBPORT_SCT_GetStatus, // Function
|
|
sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_DEVICE, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_STATUS, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_STATUS_FROM_DEVICE,
|
|
#endif
|
|
//URB_FUNCTION_GET_STATUS_FROM_INTERFACE
|
|
USBPORT_SCT_GetStatus, // Function
|
|
sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_STATUS, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_STATUS_FROM_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
|
|
USBPORT_SCT_GetStatus, // Function
|
|
sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_ENDPOINT, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_STATUS, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_STATUS_FROM_ENDPOINT,
|
|
#endif
|
|
//URB_FUNCTION_SYNC_FRAME
|
|
NULL, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
0, //URB_FUNCTION_SYNC_FRAME,
|
|
#endif
|
|
//URB_FUNCTION_VENDOR_DEVICE
|
|
USBPORT_SCT_VendorClassCommand, // Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir, user defined
|
|
BMREQUEST_VENDOR, // bmRequestType.Type
|
|
BMREQUEST_TO_DEVICE, // bmRequestType.Recipient
|
|
0, // bRequest, user defined
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_VENDOR_DEVICE,
|
|
#endif
|
|
//URB_FUNCTION_VENDOR_INTERFACE
|
|
USBPORT_SCT_VendorClassCommand, // Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir, user defined
|
|
BMREQUEST_VENDOR, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
0, // bRequest, user defined
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Length
|
|
#if DBG
|
|
URB_FUNCTION_VENDOR_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_VENDOR_ENDPOINT
|
|
USBPORT_SCT_VendorClassCommand, // Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir, user defined
|
|
BMREQUEST_VENDOR, // bmRequestType.Type
|
|
BMREQUEST_TO_ENDPOINT, // bmRequestType.Recipient
|
|
0, // bRequest, user defined
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_VENDOR_ENDPOINT,
|
|
#endif
|
|
//URB_FUNCTION_CLASS_DEVICE
|
|
USBPORT_SCT_VendorClassCommand, // Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir, user defined
|
|
BMREQUEST_CLASS, // bmRequestType.Type
|
|
BMREQUEST_TO_DEVICE, // bmRequestType.Recipient
|
|
0, // bRequest, user defined
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_CLASS_DEVICE,
|
|
#endif
|
|
//URB_FUNCTION_CLASS_INTERFACE
|
|
USBPORT_SCT_VendorClassCommand, // Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir, user defined
|
|
BMREQUEST_CLASS, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
0, // bRequest, user defined
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_CLASS_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_CLASS_ENDPOINT
|
|
USBPORT_SCT_VendorClassCommand, // Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir, user defined
|
|
BMREQUEST_CLASS, // bmRequestType.Type
|
|
BMREQUEST_TO_ENDPOINT, // bmRequestType.Recipient
|
|
0, // bRequest, user defined
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_CLASS_ENDPOINT,
|
|
#endif
|
|
//URB_FUNCTION_ NOT USED
|
|
NULL, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_RESERVE_0X001D,
|
|
#endif
|
|
//URB_FUNCTION_RESET_PIPE
|
|
USBPORT_SyncResetPipeAndClearStall, // Function
|
|
sizeof(struct _URB_PIPE_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL,
|
|
#endif
|
|
//URB_FUNCTION_CLASS_OTHER
|
|
USBPORT_SCT_VendorClassCommand, // Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir, user defined
|
|
BMREQUEST_CLASS, // bmRequestType.Type
|
|
BMREQUEST_TO_OTHER, // bmRequestType.Recipient
|
|
0, // bRequest, user defined
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Length
|
|
#if DBG
|
|
URB_FUNCTION_CLASS_OTHER,
|
|
#endif
|
|
//URB_FUNCTION_VENDOR_OTHER
|
|
USBPORT_SCT_VendorClassCommand, // Function
|
|
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir, user defined
|
|
BMREQUEST_VENDOR, // bmRequestType.Type
|
|
BMREQUEST_TO_OTHER, // bmRequestType.Recipient
|
|
0, // bRequest, user defined
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_VENDOR_OTHER,
|
|
#endif
|
|
//URB_FUNCTION_GET_STATUS_FROM_OTHER
|
|
USBPORT_SCT_GetStatus, // Function
|
|
sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_OTHER, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_STATUS, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_STATUS_FROM_OTHER,
|
|
#endif
|
|
//URB_FUNCTION_CLEAR_FEATURE_TO_OTHER
|
|
USBPORT_SCT_SetClearFeature, // Function
|
|
sizeof(struct _URB_CONTROL_FEATURE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_OTHER, // bmRequestType.Recipient
|
|
USB_REQUEST_CLEAR_FEATURE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER |
|
|
USBPORT_REQUEST_USES_DEFAULT_PIPE |
|
|
USBPORT_REQUEST_NO_DATA_PHASE,
|
|
#if DBG
|
|
URB_FUNCTION_CLEAR_FEATURE_TO_OTHER,
|
|
#endif
|
|
//URB_FUNCTION_SET_FEATURE_TO_OTHER
|
|
USBPORT_SCT_SetClearFeature, // Function
|
|
sizeof(struct _URB_CONTROL_FEATURE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_OTHER, // bmRequestType.Recipient
|
|
USB_REQUEST_SET_FEATURE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER |
|
|
USBPORT_REQUEST_USES_DEFAULT_PIPE |
|
|
USBPORT_REQUEST_NO_DATA_PHASE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SET_FEATURE_TO_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT
|
|
USBPORT_SCT_GetSetDescriptor, // Function
|
|
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_ENDPOINT, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_DESCRIPTOR, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT,
|
|
#endif
|
|
//URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT
|
|
USBPORT_SCT_GetSetDescriptor, // Function
|
|
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_ENDPOINT, // bmRequestType.Recipient
|
|
USB_REQUEST_SET_DESCRIPTOR, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT,
|
|
#endif
|
|
//URB_FUNCTION_GET_CONFIGURATION
|
|
USBPORT_SCT_GetConfiguration, // Function
|
|
sizeof(struct _URB_CONTROL_GET_CONFIGURATION_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_DEVICE, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_CONFIGURATION, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_CONFIGURATION,
|
|
#endif
|
|
//URB_FUNCTION_GET_INTERFACE
|
|
USBPORT_SCT_GetInterface, // Function
|
|
sizeof(struct _URB_CONTROL_GET_INTERFACE_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_INTERFACE, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE
|
|
USBPORT_SCT_GetSetDescriptor, // Function
|
|
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_DEVICE_TO_HOST, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
USB_REQUEST_GET_DESCRIPTOR, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE
|
|
USBPORT_SCT_GetSetDescriptor, // Function
|
|
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), // Length
|
|
0, // Pad2
|
|
BMREQUEST_HOST_TO_DEVICE, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
USB_REQUEST_SET_DESCRIPTOR, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE,
|
|
#endif
|
|
//URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR
|
|
USBPORT_GetMSFeartureDescriptor, // Function
|
|
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
BMREQUEST_STANDARD, // bmRequestType.Type
|
|
BMREQUEST_TO_INTERFACE, // bmRequestType.Recipient
|
|
USB_REQUEST_SET_DESCRIPTOR, // bRequest
|
|
USBPORT_REQUEST_IS_TRANSFER | USBPORT_REQUEST_USES_DEFAULT_PIPE, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR,
|
|
#endif
|
|
//URB_FUNCTION_2b
|
|
USBPORT_InvalidFunction, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
0x002b,
|
|
#endif
|
|
//URB_FUNCTION_2c
|
|
USBPORT_InvalidFunction, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
0x002c,
|
|
#endif
|
|
//URB_FUNCTION_2d
|
|
USBPORT_InvalidFunction, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
0x002d,
|
|
#endif
|
|
//URB_FUNCTION_2e
|
|
USBPORT_InvalidFunction, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
0x002e,
|
|
#endif
|
|
//URB_FUNCTION_2f
|
|
USBPORT_InvalidFunction, // Function
|
|
0, // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
0x002f,
|
|
#endif
|
|
//URB_FUNCTION_SYNC_RESET_PIPE
|
|
USBPORT_SyncResetPipe, // Function
|
|
sizeof(struct _URB_PIPE_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SYNC_RESET_PIPE,
|
|
#endif
|
|
//URB_FUNCTION_SYNC_CLEAR_STALL
|
|
USBPORT_SyncClearStall, // Function
|
|
sizeof(struct _URB_PIPE_REQUEST), // Length
|
|
0, // Pad2
|
|
0, // bmRequestType.Dir
|
|
0, // bmRequestType.Type
|
|
0, // bmRequestType.Recipient
|
|
0, // bRequest
|
|
0, // Flags
|
|
#if DBG
|
|
URB_FUNCTION_SYNC_CLEAR_STALL,
|
|
#endif
|
|
};
|
|
|
|
|
|
PURB
|
|
USBPORT_UrbFromIrp(
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
PURB urb;
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
urb = irpStack->Parameters.Others.Argument1;
|
|
|
|
USBPORT_ASSERT(urb);
|
|
|
|
return urb;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_ProcessURB(
|
|
PDEVICE_OBJECT PdoDeviceObject,
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Processes a URB from a client IRP.
|
|
|
|
Essentially what we do here is look at the URB and validate some
|
|
of the the parameters for the client.
|
|
|
|
In some cases we translate the urb in to multiple bus transactions.
|
|
|
|
|
|
Arguments:
|
|
|
|
FdoDeviceObject - Device object associated with this IRP request
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
IrpIsPending - FALSE if USBPORT completes the IRP
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
USHORT function;
|
|
PUSBD_PIPE_HANDLE_I pipeHandle;
|
|
PUSBD_DEVICE_HANDLE deviceHandle = NULL;
|
|
PDEVICE_EXTENSION devExt;
|
|
|
|
USBPORT_KdPrint((3, "'enter USBPORT_ProcessURB\n"));
|
|
|
|
GET_DEVICE_EXT(devExt, FdoDeviceObject);
|
|
ASSERT_FDOEXT(devExt);
|
|
|
|
// assume success
|
|
ntStatus = STATUS_SUCCESS;
|
|
|
|
// initialize the error code to success,
|
|
// some drivers do not initailize on entry
|
|
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
|
|
|
|
function = Urb->UrbHeader.Function;
|
|
// don't log to dev handle since it may not be valid
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'pURB', Urb, Irp, function);
|
|
|
|
// Initialize flags field for this request
|
|
Urb->UrbHeader.UsbdFlags = 0;
|
|
|
|
USBPORT_KdPrint((3, "'USBPORT_ProcessURB, function = 0x%x\n", function));
|
|
|
|
if (function > URB_FUNCTION_LAST) {
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_URB_FUNCTION);
|
|
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
#if DBG
|
|
else {
|
|
USBPORT_ASSERT(UrbDispatchTable[function].ExpectedFunctionCode == function);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// do some special transfer specific stuff
|
|
//
|
|
|
|
GET_DEVICE_HANDLE(deviceHandle, Urb);
|
|
|
|
|
|
// check for requests and fail them at low power
|
|
//#if 0
|
|
if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_FAIL_URBS)) {
|
|
|
|
KIRQL irql;
|
|
PUSB_IRP_CONTEXT irpContext;
|
|
|
|
USBPORT_KdPrint((1, "'Error: Bad Request to root hub\n"));
|
|
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, '!URr', Urb, Irp, function);
|
|
|
|
ALLOC_POOL_Z(irpContext, NonPagedPool, sizeof(*irpContext));
|
|
if (irpContext) {
|
|
|
|
irpContext->Sig = SIG_IRPC;
|
|
irpContext->DeviceHandle = deviceHandle;
|
|
irpContext->Irp = Irp;
|
|
|
|
ACQUIRE_BADREQUEST_LOCK(FdoDeviceObject, irql);
|
|
// put it on our list to complete
|
|
//InsertTailList(&devExt->Fdo.BadRequestList,
|
|
// &Irp->Tail.Overlay.ListEntry);
|
|
InsertTailList(&devExt->Fdo.BadRequestList,
|
|
&irpContext->ListEntry);
|
|
|
|
// if handle is invalid assume this device has been removed
|
|
// this will set the USBD status
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_DEVICE_GONE);
|
|
|
|
// overwrite ntStatus,
|
|
// mark pending for the delayed failure
|
|
ntStatus = Irp->IoStatus.Status = STATUS_PENDING;
|
|
IoMarkIrpPending(Irp);
|
|
|
|
RELEASE_BADREQUEST_LOCK(FdoDeviceObject, irql);
|
|
|
|
|
|
} else {
|
|
TEST_TRAP();
|
|
// no memory for link, just complete it now
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_DEVICE_GONE);
|
|
|
|
}
|
|
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
//#endif
|
|
|
|
if (deviceHandle == NULL) {
|
|
PDEVICE_EXTENSION rhDevExt;
|
|
|
|
GET_DEVICE_EXT(rhDevExt, PdoDeviceObject);
|
|
ASSERT_PDOEXT(rhDevExt);
|
|
|
|
// null device handle indicates a urb for
|
|
// the root hub, set the devhandle to the
|
|
// roothub
|
|
deviceHandle = Urb->UrbHeader.UsbdDeviceHandle =
|
|
&rhDevExt->Pdo.RootHubDeviceHandle;
|
|
}
|
|
|
|
// don't log with dev handle since it may not be valid
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'devH', deviceHandle, Urb, 0);
|
|
|
|
// if this is request for the deafult pipe
|
|
|
|
|
|
// validate the state of the device
|
|
if (!USBPORT_ValidateDeviceHandle(FdoDeviceObject,
|
|
deviceHandle,
|
|
TRUE)) {
|
|
KIRQL irql;
|
|
PUSB_IRP_CONTEXT irpContext;
|
|
|
|
USBPORT_DebugClient(("'Invalid Device Handle Passed in\n"));
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, '!URB', Urb, Irp, function);
|
|
|
|
// set to NULL, we can't defrefence it
|
|
deviceHandle = NULL;
|
|
|
|
ALLOC_POOL_Z(irpContext, NonPagedPool, sizeof(*irpContext));
|
|
if (irpContext) {
|
|
|
|
irpContext->Sig = SIG_IRPC;
|
|
irpContext->DeviceHandle = (PUSBD_DEVICE_HANDLE) -1;
|
|
irpContext->Irp = Irp;
|
|
|
|
ACQUIRE_BADREQUEST_LOCK(FdoDeviceObject, irql);
|
|
// put it on our list to complete
|
|
//InsertTailList(&devExt->Fdo.BadRequestList,
|
|
// &Irp->Tail.Overlay.ListEntry);
|
|
InsertTailList(&devExt->Fdo.BadRequestList,
|
|
&irpContext->ListEntry);
|
|
|
|
// if handle is invalid assume this device has been removed
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_DEVICE_GONE);
|
|
|
|
// mark pending for the delayed failure
|
|
ntStatus = Irp->IoStatus.Status = STATUS_PENDING;
|
|
IoMarkIrpPending(Irp);
|
|
|
|
RELEASE_BADREQUEST_LOCK(FdoDeviceObject, irql);
|
|
|
|
|
|
// ntStatus = SET_USBD_ERROR(Urb, USBD_STATUS_DEVICE_GONE);
|
|
} else {
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_DEVICE_GONE);
|
|
|
|
}
|
|
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
|
|
// device handle is valid
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'dURB', Urb, Irp, function);
|
|
/*
|
|
This action is performed by passing TRUE to ValidateDeviceHandle above
|
|
InterlockedIncrement(&deviceHandle->PendingUrbs);
|
|
*/
|
|
// is this a transfer request for the default pipe
|
|
// set the pipe handle in the urb
|
|
if (UrbDispatchTable[function].Flags & USBPORT_REQUEST_USES_DEFAULT_PIPE) {
|
|
|
|
PTRANSFER_URB transferUrb = (PTRANSFER_URB) Urb;
|
|
|
|
transferUrb->UsbdPipeHandle =
|
|
&deviceHandle->DefaultPipe;
|
|
|
|
SET_FLAG(transferUrb->TransferFlags, USBD_DEFAULT_PIPE_TRANSFER);
|
|
}
|
|
|
|
if (UrbDispatchTable[function].Flags & USBPORT_REQUEST_IS_TRANSFER) {
|
|
|
|
PTRANSFER_URB transferUrb = (PTRANSFER_URB) Urb;
|
|
|
|
if (TEST_FLAG(transferUrb->TransferFlags, USBD_DEFAULT_PIPE_TRANSFER) &&
|
|
function == URB_FUNCTION_CONTROL_TRANSFER) {
|
|
|
|
transferUrb->UsbdPipeHandle =
|
|
&deviceHandle->DefaultPipe;
|
|
}
|
|
|
|
// we do not support linked URBs
|
|
if (transferUrb->ReservedMBNull != NULL) {
|
|
ntStatus =
|
|
SET_USBD_ERROR(transferUrb, USBD_STATUS_INVALID_PARAMETER);
|
|
DEBUG_BREAK();
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
|
|
// zero out context field now in case the client
|
|
// is recycling the urb
|
|
transferUrb->pd.HcdTransferContext = NULL;
|
|
|
|
// no data phase therefore no buffer
|
|
if (UrbDispatchTable[function].Flags & USBPORT_REQUEST_NO_DATA_PHASE) {
|
|
transferUrb->TransferBuffer = NULL;
|
|
transferUrb->TransferBufferMDL = NULL;
|
|
transferUrb->TransferBufferLength = 0;
|
|
}
|
|
|
|
if (function == URB_FUNCTION_CONTROL_TRANSFER &&
|
|
transferUrb->UsbdPipeHandle == 0) {
|
|
|
|
TEST_TRAP(); // old diag code baggage?
|
|
}
|
|
|
|
if (TEST_FLAG(transferUrb->TransferFlags, USBD_DEFAULT_PIPE_TRANSFER)) {
|
|
|
|
// usbd never supported control transfers > 4k
|
|
if (transferUrb->TransferBufferLength > 4096) {
|
|
TEST_TRAP();
|
|
ntStatus =
|
|
SET_USBD_ERROR(transferUrb, USBD_STATUS_INVALID_PARAMETER);
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
}
|
|
|
|
// fetch the pipe handle
|
|
pipeHandle = transferUrb->UsbdPipeHandle;
|
|
|
|
// make sure the pipe handle the client s passing is still valid
|
|
|
|
if (!USBPORT_ValidatePipeHandle(deviceHandle, pipeHandle)) {
|
|
|
|
USBPORT_KdPrint((1, "'Error: Invalid Device Handle Passed in\n"));
|
|
DEBUG_BREAK();
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(transferUrb, USBD_STATUS_INVALID_PIPE_HANDLE);
|
|
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
|
|
// If there is a non-zero transfer length then either an MDL or
|
|
// or system buffer address is required.
|
|
//
|
|
if (transferUrb->TransferBuffer == NULL &&
|
|
transferUrb->TransferBufferMDL == NULL &&
|
|
transferUrb->TransferBufferLength != 0) {
|
|
ntStatus =
|
|
SET_USBD_ERROR(transferUrb, USBD_STATUS_INVALID_PARAMETER);
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
|
|
// if only a system buffer address is specified then
|
|
// the caller has passed in a buffer allocated from the
|
|
// non-paged pool.
|
|
|
|
// in this case we allocate an MDL for the request
|
|
|
|
if (transferUrb->TransferBufferMDL == NULL &&
|
|
transferUrb->TransferBufferLength != 0) {
|
|
|
|
if ((transferUrb->TransferBufferMDL =
|
|
IoAllocateMdl(transferUrb->TransferBuffer,
|
|
transferUrb->TransferBufferLength,
|
|
FALSE,
|
|
FALSE,
|
|
NULL)) == NULL) {
|
|
ntStatus =
|
|
SET_USBD_ERROR(transferUrb,
|
|
USBD_STATUS_INSUFFICIENT_RESOURCES);
|
|
goto USBPORT_ProcessURB_Done;
|
|
} else {
|
|
SET_FLAG(transferUrb->Hdr.UsbdFlags,
|
|
USBPORT_REQUEST_MDL_ALLOCATED);
|
|
MmBuildMdlForNonPagedPool(transferUrb->TransferBufferMDL);
|
|
}
|
|
}
|
|
|
|
if (transferUrb->TransferBufferMDL != NULL &&
|
|
transferUrb->TransferBufferLength == 0) {
|
|
ntStatus =
|
|
SET_USBD_ERROR(transferUrb, USBD_STATUS_INVALID_PARAMETER);
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
|
|
// transfer looks valid,
|
|
// set up the per transfer context
|
|
{
|
|
USBD_STATUS usbdStatus;
|
|
|
|
// inialize the transfer
|
|
usbdStatus = USBPORT_AllocTransfer(FdoDeviceObject,
|
|
transferUrb,
|
|
deviceHandle,
|
|
Irp,
|
|
NULL,
|
|
0);
|
|
if (!USBD_SUCCESS(usbdStatus)) {
|
|
ntStatus = SET_USBD_ERROR(transferUrb, usbdStatus);
|
|
DEBUG_BREAK();
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
}
|
|
}
|
|
|
|
// non-transfer functions must validate their own parameters
|
|
|
|
//
|
|
// validate the length field based on the function
|
|
//
|
|
|
|
USBPORT_ASSERT(NT_SUCCESS(ntStatus));
|
|
|
|
if (UrbDispatchTable[function].UrbRequestLength &&
|
|
UrbDispatchTable[function].UrbRequestLength != Urb->UrbHeader.Length) {
|
|
|
|
USBPORT_KdPrint((1, "'Inavlid parameter length length = 0x%x, expected = 0x%x\n",
|
|
Urb->UrbHeader.Length,
|
|
UrbDispatchTable[function].UrbRequestLength));
|
|
DEBUG_BREAK();
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PARAMETER);
|
|
goto USBPORT_ProcessURB_Done;
|
|
}
|
|
|
|
USBPORT_ASSERT(NT_SUCCESS(ntStatus));
|
|
|
|
// call our handler for this specific USBDI function
|
|
|
|
if (UrbDispatchTable[function].UrbHandler) {
|
|
LOGENTRY(NULL, FdoDeviceObject, LOG_URB, 'Urb>', 0, function, Irp);
|
|
|
|
ntStatus =
|
|
(UrbDispatchTable[function].UrbHandler)
|
|
(FdoDeviceObject, Irp, Urb);
|
|
|
|
LOGENTRY(NULL, FdoDeviceObject, LOG_URB, 'Urb<', ntStatus, function, 0);
|
|
// NOTE that the URB and Irp may be gone at this point
|
|
// if STATUS_PENDING is returned
|
|
|
|
} else {
|
|
//
|
|
// really should not get here
|
|
//
|
|
DEBUG_BREAK();
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PARAMETER);
|
|
USBPORT_ASSERT(FALSE);
|
|
}
|
|
|
|
USBPORT_ProcessURB_Done:
|
|
|
|
//
|
|
// if the URB error code is set then we should also be returning
|
|
// an error in ntStatus
|
|
//
|
|
|
|
if (ntStatus != STATUS_PENDING) {
|
|
// request was not queued, complete the irp now
|
|
#if DBG
|
|
// if there is an error code in the URB then
|
|
// we should be returning an error in ntstatus
|
|
// as well
|
|
if (Urb->UrbHeader.Status != USBD_STATUS_SUCCESS &&
|
|
NT_SUCCESS(ntStatus)) {
|
|
|
|
// this is a bug
|
|
USBPORT_ASSERT(FALSE);
|
|
}
|
|
#endif
|
|
// if we allocate a transfer structure we will need to free it
|
|
if (TEST_FLAG(Urb->UrbHeader.UsbdFlags, USBPORT_TRANSFER_ALLOCATED)) {
|
|
PHCD_TRANSFER_CONTEXT t;
|
|
t = USBPORT_UnlinkTransfer(FdoDeviceObject, (PTRANSFER_URB) Urb);
|
|
FREE_POOL(FdoDeviceObject, t);
|
|
}
|
|
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'Uerr', ntStatus, function, Irp);
|
|
|
|
if (deviceHandle != NULL) {
|
|
ASSERT_DEVICE_HANDLE(deviceHandle);
|
|
InterlockedDecrement(&deviceHandle->PendingUrbs);
|
|
}
|
|
|
|
// complete the irp status code returned by the
|
|
// handler
|
|
// NOTE: we complete to the PDO becuse that is the DeviceObject
|
|
// that the client driver passed the URB to
|
|
|
|
USBPORT_CompleteIrp(PdoDeviceObject, Irp, ntStatus, 0);
|
|
|
|
}
|
|
|
|
USBPORT_KdPrint((3, "'exit USBPORT_ProcessURB 0x%x\n", ntStatus));
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SCT_GetSetDescriptor(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Control transfer to get or set a descriptor
|
|
|
|
Arguments:
|
|
|
|
FdoDeviceObject -
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PUSB_DEFAULT_PIPE_SETUP_PACKET setupPacket;
|
|
|
|
USBPORT_KdPrint((3, "' enter USBPORT_SCT_GetSetDescriptor\n"));
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'gsDE', 0, 0, Urb);
|
|
|
|
setupPacket =
|
|
(PUSB_DEFAULT_PIPE_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0];
|
|
|
|
// setup common fields
|
|
setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength;
|
|
|
|
setupPacket->bRequest =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].bRequest;
|
|
setupPacket->bmRequestType.Type =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Type;
|
|
setupPacket->bmRequestType.Dir =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Direction;
|
|
setupPacket->bmRequestType.Recipient =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Recipient;
|
|
setupPacket->bmRequestType.Reserved = 0;
|
|
|
|
Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
|
|
if (setupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST) {
|
|
USBPORT_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags);
|
|
} else {
|
|
USBPORT_SET_TRANSFER_DIRECTION_OUT(Urb->UrbControlTransfer.TransferFlags);
|
|
}
|
|
|
|
USBPORT_QueueTransferUrb((PTRANSFER_URB)Urb);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SCT_SetClearFeature(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
FdoDeviceObject -
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PUSB_DEFAULT_PIPE_SETUP_PACKET setupPacket;
|
|
|
|
USBPORT_KdPrint((2, "'SCT_SetClearFeature\n"));
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'scFE', 0, 0, 0);
|
|
|
|
setupPacket =
|
|
(PUSB_DEFAULT_PIPE_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0];
|
|
|
|
// setup common fields
|
|
setupPacket->wLength = 0;
|
|
|
|
setupPacket->bmRequestType.Type =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Type;
|
|
setupPacket->bmRequestType.Dir =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Direction;
|
|
setupPacket->bmRequestType.Recipient =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Recipient;
|
|
setupPacket->bmRequestType.Reserved = 0;
|
|
//setupPacket->wValue = Urb->UrbControlFeatureRequest.FeatureSelector;
|
|
//setupPacket->wIndex = Urb->UrbControlFeatureRequest.Index;
|
|
|
|
setupPacket->bRequest =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].bRequest;
|
|
|
|
Urb->UrbControlTransfer.TransferBufferLength = 0;
|
|
|
|
Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
|
|
if (setupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST) {
|
|
USBPORT_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags);
|
|
} else {
|
|
USBPORT_SET_TRANSFER_DIRECTION_OUT( Urb->UrbControlTransfer.TransferFlags);
|
|
}
|
|
|
|
USBPORT_QueueTransferUrb((PTRANSFER_URB)Urb);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SCT_GetStatus(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
FdoDeviceObject -
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PUSB_DEFAULT_PIPE_SETUP_PACKET setupPacket;
|
|
NTSTATUS ntStatus;
|
|
|
|
USBPORT_KdPrint((2, "'SCT_GetStatus\n"));
|
|
|
|
setupPacket
|
|
= (PUSB_DEFAULT_PIPE_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0];
|
|
|
|
//
|
|
// setup common fields
|
|
//
|
|
|
|
setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength;
|
|
setupPacket->wValue.W = 0;
|
|
setupPacket->bmRequestType.Type =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Type;
|
|
setupPacket->bmRequestType.Dir =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Direction;
|
|
setupPacket->bmRequestType.Recipient =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Recipient;
|
|
setupPacket->bmRequestType.Reserved = 0;
|
|
setupPacket->bRequest =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].bRequest;
|
|
|
|
|
|
// some parameter validation
|
|
if (setupPacket->wLength != 2) {
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PARAMETER);
|
|
USBPORT_DebugClient(("Bad wLength for GetStatus\n"));
|
|
goto USBD_SCT_GetStatus_Done;
|
|
}
|
|
|
|
ntStatus = STATUS_PENDING;
|
|
|
|
Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
|
|
if (setupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST) {
|
|
USBPORT_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags);
|
|
} else {
|
|
USBPORT_SET_TRANSFER_DIRECTION_OUT(Urb->UrbControlTransfer.TransferFlags);
|
|
}
|
|
|
|
USBPORT_QueueTransferUrb((PTRANSFER_URB)Urb);
|
|
|
|
USBD_SCT_GetStatus_Done:
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SCT_VendorClassCommand(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
FdoDeviceObject -
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PUSB_DEFAULT_PIPE_SETUP_PACKET setupPacket;
|
|
UCHAR direction;
|
|
|
|
USBPORT_KdPrint((2, "'SCT_VendorClassCommand\n"));
|
|
|
|
setupPacket =
|
|
(PUSB_DEFAULT_PIPE_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0];
|
|
|
|
// setup common fields
|
|
setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength;
|
|
|
|
// if a direction was specified in the URB then
|
|
// set direction based on URB transfer flags
|
|
direction = (UCHAR)( (Urb->UrbControlTransfer.TransferFlags &
|
|
USBD_TRANSFER_DIRECTION_IN) ?
|
|
BMREQUEST_DEVICE_TO_HOST : BMREQUEST_HOST_TO_DEVICE);
|
|
|
|
// note that we override only the Recipient,Dir and Type fields
|
|
|
|
setupPacket->bmRequestType.Dir = direction;
|
|
setupPacket->bmRequestType.Type =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Type;
|
|
setupPacket->bmRequestType.Recipient =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Recipient;
|
|
|
|
Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
|
|
|
|
USBPORT_QueueTransferUrb((PTRANSFER_URB)Urb);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_AsyncTransfer(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
pass interrupt or bulk transfer to HCD
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PUSBD_PIPE_HANDLE_I pipeHandle;
|
|
PTRANSFER_URB transferUrb = (PTRANSFER_URB) Urb;
|
|
PHCD_ENDPOINT endpoint;
|
|
|
|
USBPORT_KdPrint((2, "'AsyncTransfer\n"));
|
|
|
|
// extract the pipe handle
|
|
pipeHandle = transferUrb->UsbdPipeHandle;
|
|
// pipe handle should have been validated
|
|
// before we got here
|
|
ASSERT_PIPE_HANDLE(pipeHandle);
|
|
|
|
endpoint = pipeHandle->Endpoint;
|
|
ASSERT_ENDPOINT(endpoint);
|
|
|
|
// set the proper direction based on the direction bit stored with the
|
|
// endpoint address. if this is a control transfer then leave the direction
|
|
// bit alone.
|
|
|
|
if (endpoint->Parameters.TransferType != Control) {
|
|
if (endpoint->Parameters.TransferDirection == In) {
|
|
USBPORT_SET_TRANSFER_DIRECTION_IN(transferUrb->TransferFlags);
|
|
} else {
|
|
USBPORT_SET_TRANSFER_DIRECTION_OUT(transferUrb->TransferFlags);
|
|
}
|
|
}
|
|
|
|
USBPORT_QueueTransferUrb(transferUrb);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
#define UHCD_ASAP_LATENCY 5
|
|
|
|
NTSTATUS
|
|
USBPORT_IsochTransfer(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
pass interrupt transfer to HCD
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PTRANSFER_URB transferUrb = (PTRANSFER_URB) Urb;
|
|
ULONG startFrame, frameCount, p , i, cf, packetCount, maxPacketCount;
|
|
PUSBD_PIPE_HANDLE_I pipeHandle;
|
|
PHCD_ENDPOINT endpoint;
|
|
PDEVICE_EXTENSION devExt;
|
|
KIRQL oldIrql;
|
|
BOOLEAN highSpeed = FALSE;
|
|
|
|
#define ABS(x) ( (0 < (x)) ? (x) : (0 - (x)))
|
|
|
|
GET_DEVICE_EXT(devExt, FdoDeviceObject);
|
|
ASSERT_FDOEXT(devExt);
|
|
|
|
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
|
|
|
USBPORT_KdPrint((2, "'IsochTransfer\n"));
|
|
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'sISO', Urb, 0, 0);
|
|
|
|
// extract the pipe handle
|
|
pipeHandle = transferUrb->UsbdPipeHandle;
|
|
// pipe handle should have been validated
|
|
// before we got here
|
|
ASSERT_PIPE_HANDLE(pipeHandle);
|
|
|
|
if (TEST_FLAG(pipeHandle->PipeStateFlags, USBPORT_PIPE_ZERO_BW)) {
|
|
// bugbug better error code please
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PARAMETER);
|
|
goto USBPORT_IsochTransfer_Done;
|
|
}
|
|
|
|
endpoint = pipeHandle->Endpoint;
|
|
ASSERT_ENDPOINT(endpoint);
|
|
|
|
if (endpoint->Parameters.DeviceSpeed == HighSpeed) {
|
|
highSpeed = TRUE;
|
|
}
|
|
|
|
MP_Get32BitFrameNumber(devExt, cf);
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, '>ISO', Urb, 0, cf);
|
|
|
|
// process an iso transfer request
|
|
|
|
// validate the number of packets per urb, USBD validated
|
|
// the the count was less than 256 and some tests rely on this.
|
|
// NOTE that usbport is capable of handling
|
|
// larger requests so we allow larger requests thru an
|
|
// enhanced URB or if the device is high speed.
|
|
maxPacketCount = 255;
|
|
if (highSpeed) {
|
|
// size of schedule
|
|
maxPacketCount = 1024;
|
|
}
|
|
|
|
// more validation or 'security'
|
|
// we will just fail this case with error since it doesn't make sense
|
|
//
|
|
if (transferUrb->TransferBufferLength == 0 &&
|
|
transferUrb->TransferBufferMDL == NULL &&
|
|
transferUrb->TransferBuffer == NULL) {
|
|
|
|
// this is invalid
|
|
USBPORT_DebugClient((
|
|
"Isoch, no buffer\n"));
|
|
TEST_TRAP();
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'badP', transferUrb, 0, 0);
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PARAMETER);
|
|
|
|
goto USBPORT_IsochTransfer_Done;
|
|
}
|
|
|
|
|
|
if (transferUrb->u.Isoch.NumberOfPackets == 0 ||
|
|
transferUrb->u.Isoch.NumberOfPackets > maxPacketCount) {
|
|
|
|
// this is invalid
|
|
USBPORT_DebugClient((
|
|
"Isoch, numberOfPackets = 0\n"));
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'badF', transferUrb, 0, 0);
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PARAMETER);
|
|
|
|
goto USBPORT_IsochTransfer_Done;
|
|
}
|
|
|
|
// first get the current USB frame number
|
|
MP_Get32BitFrameNumber(devExt, cf);
|
|
|
|
packetCount = transferUrb->u.Isoch.NumberOfPackets;
|
|
if (highSpeed) {
|
|
frameCount = packetCount / 8;
|
|
} else {
|
|
frameCount = transferUrb->u.Isoch.NumberOfPackets;
|
|
}
|
|
|
|
// initailize all packet status codes to 'not_set'
|
|
for (p = 0;
|
|
p < packetCount;
|
|
p++) {
|
|
|
|
transferUrb->u.Isoch.IsoPacket[p].Status = USBD_STATUS_NOT_SET;
|
|
}
|
|
|
|
// see if ASAP flag is set
|
|
if (TEST_FLAG(transferUrb->TransferFlags,
|
|
USBD_START_ISO_TRANSFER_ASAP)) {
|
|
// Yes,
|
|
// if this is the first transfer on the endpoint
|
|
// AKA virgin then set the current frame
|
|
if (TEST_FLAG(endpoint->Flags, EPFLAG_VIRGIN)) {
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'aspV', Urb, 0, cf);
|
|
|
|
// use the same asap latency as the UHCD driver for
|
|
// compatibility
|
|
startFrame =
|
|
endpoint->NextTransferStartFrame = cf+UHCD_ASAP_LATENCY;
|
|
} else {
|
|
startFrame = endpoint->NextTransferStartFrame;
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'aspN', Urb, startFrame, cf);
|
|
|
|
if (ABS((LONG)(cf - startFrame)) > 256) {
|
|
// next asap request out of range, treat this like
|
|
// the virgin case instead of erroring out
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'resV', Urb, 0, cf);
|
|
|
|
startFrame =
|
|
endpoint->NextTransferStartFrame = cf+UHCD_ASAP_LATENCY;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
// No,
|
|
// absolute frame number set
|
|
startFrame =
|
|
endpoint->NextTransferStartFrame =
|
|
transferUrb->u.Isoch.StartFrame;
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'absF', Urb, startFrame, cf);
|
|
|
|
|
|
}
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'ISsf', Urb, startFrame, cf);
|
|
|
|
transferUrb->u.Isoch.StartFrame = startFrame;
|
|
|
|
#if DBG
|
|
if (!highSpeed) {
|
|
USBPORT_ASSERT(frameCount == packetCount);
|
|
}
|
|
#endif
|
|
endpoint->NextTransferStartFrame += frameCount;
|
|
|
|
// now that we have computed a start frame validate it
|
|
|
|
if (ABS((LONG)(startFrame - cf)) > USBD_ISO_START_FRAME_RANGE) {
|
|
|
|
// set all iso packet status codes to not_accessed
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'iLAT', Urb, 0, 0);
|
|
|
|
for (p = 0;
|
|
p < packetCount;
|
|
p++) {
|
|
|
|
USBPORT_ASSERT(transferUrb->u.Isoch.IsoPacket[p].Status ==
|
|
USBD_STATUS_NOT_SET);
|
|
|
|
transferUrb->u.Isoch.IsoPacket[p].Status =
|
|
USBD_STATUS_ISO_NOT_ACCESSED_LATE;
|
|
}
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_BAD_START_FRAME);
|
|
|
|
} else {
|
|
|
|
// we can transmit at least some of the data
|
|
|
|
// set the errors for any packets that got to us too late
|
|
// from the client
|
|
|
|
for (i = startFrame;
|
|
i < startFrame + frameCount;
|
|
i++) {
|
|
|
|
if (i <= cf) {
|
|
|
|
p = i - startFrame;
|
|
|
|
if (highSpeed) {
|
|
ULONG j;
|
|
|
|
p = p*8;
|
|
|
|
for (j=0; j< 8; j++) {
|
|
USBPORT_ASSERT(transferUrb->u.Isoch.IsoPacket[p+j].Status ==
|
|
USBD_STATUS_NOT_SET);
|
|
|
|
transferUrb->u.Isoch.IsoPacket[p+j].Status =
|
|
USBD_STATUS_ISO_NOT_ACCESSED_LATE;
|
|
}
|
|
} else {
|
|
USBPORT_ASSERT(transferUrb->u.Isoch.IsoPacket[p].Status ==
|
|
USBD_STATUS_NOT_SET);
|
|
|
|
transferUrb->u.Isoch.IsoPacket[p].Status =
|
|
USBD_STATUS_ISO_NOT_ACCESSED_LATE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (endpoint->Parameters.TransferDirection == In) {
|
|
USBPORT_SET_TRANSFER_DIRECTION_IN(transferUrb->TransferFlags);
|
|
} else {
|
|
USBPORT_SET_TRANSFER_DIRECTION_OUT(transferUrb->TransferFlags);
|
|
}
|
|
|
|
// now queue the urb for processing by HW
|
|
USBPORT_QueueTransferUrb(transferUrb);
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'ISO<',0, 0, 0);
|
|
|
|
ntStatus = STATUS_PENDING;
|
|
}
|
|
|
|
USBPORT_IsochTransfer_Done:
|
|
|
|
KeLowerIrql(oldIrql);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_GetMSFeartureDescriptor(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
pass interrupt transfer to HCD
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
TEST_TRAP();
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_NOT_SUPPORTED);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_InvalidFunction(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
pass interrupt transfer to HCD
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
TEST_TRAP();
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_URB_FUNCTION);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SyncResetPipe(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This API resets the host side pipe state in response to
|
|
a stall pid.
|
|
|
|
data toggle is reset if the USBDFLAGS feild specifies data
|
|
toggle reset
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PUSBD_PIPE_HANDLE_I pipeHandle;
|
|
PUSBD_DEVICE_HANDLE deviceHandle;
|
|
PHCD_ENDPOINT endpoint;
|
|
PDEVICE_EXTENSION devExt;
|
|
|
|
// this function blocks so it must not be called at DPC level
|
|
|
|
USBPORT_KdPrint((2, "'SyncResetPipe\n"));
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'syrP', Urb, 0, 0);
|
|
|
|
GET_DEVICE_EXT(devExt, FdoDeviceObject);
|
|
ASSERT_FDOEXT(devExt);
|
|
|
|
GET_DEVICE_HANDLE(deviceHandle, Urb);
|
|
pipeHandle = (PUSBD_PIPE_HANDLE_I) Urb->UrbPipeRequest.PipeHandle;
|
|
|
|
if (!USBPORT_ValidatePipeHandle(deviceHandle, pipeHandle)) {
|
|
|
|
USBPORT_KdPrint((1, "'Error: Invalid Device Handle Passed in\n"));
|
|
DEBUG_BREAK();
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PIPE_HANDLE);
|
|
|
|
goto USBPORT_SyncResetPipe_Done;
|
|
}
|
|
|
|
// our bug
|
|
ASSERT_PIPE_HANDLE(pipeHandle);
|
|
endpoint = pipeHandle->Endpoint;
|
|
ASSERT_ENDPOINT(endpoint);
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_URB, 'syrp', Urb, 0, 0);
|
|
|
|
ACQUIRE_ENDPOINT_LOCK(endpoint, FdoDeviceObject, 'LeH0');
|
|
|
|
// see if we have active transfers, if so we cannot
|
|
// reset the pipe.
|
|
// NOTE: this is a synchronization bug in the client.
|
|
if (IsListEmpty(&endpoint->ActiveList)) {
|
|
// clear the pipe state
|
|
|
|
if (TEST_FLAG(Urb->UrbHeader.UsbdFlags, USBPORT_RESET_DATA_TOGGLE)) {
|
|
MP_SetEndpointDataToggle(devExt, endpoint, 0);
|
|
}
|
|
|
|
ntStatus = SET_USBD_ERROR(Urb, USBD_STATUS_SUCCESS);
|
|
|
|
} else {
|
|
|
|
USBPORT_DebugClient((
|
|
"reset pipe with active transfers\n"));
|
|
ntStatus = SET_USBD_ERROR(Urb, USBD_STATUS_ERROR_BUSY);
|
|
}
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'virg', Urb, 0, 0);
|
|
SET_FLAG(endpoint->Flags, EPFLAG_VIRGIN);
|
|
// set the endpoint state to Active
|
|
MP_SetEndpointStatus(devExt, endpoint, ENDPOINT_STATUS_RUN);
|
|
|
|
RELEASE_ENDPOINT_LOCK(endpoint, FdoDeviceObject, 'UeH0');
|
|
|
|
USBPORT_SyncResetPipe_Done:
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SyncClearStall(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Clear stall on an endpoint note: data toggle is unaffected
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PUSBD_PIPE_HANDLE_I pipeHandle;
|
|
PUSBD_DEVICE_HANDLE deviceHandle;
|
|
PHCD_ENDPOINT endpoint;
|
|
USB_DEFAULT_PIPE_SETUP_PACKET setupPacket;
|
|
USBD_STATUS usbdStatus;
|
|
|
|
// this function blocks so it must not be called at DPC level
|
|
|
|
PAGED_CODE();
|
|
|
|
USBPORT_KdPrint((2, "'SyncClearStall\n"));
|
|
|
|
GET_DEVICE_HANDLE(deviceHandle, Urb);
|
|
pipeHandle = (PUSBD_PIPE_HANDLE_I) Urb->UrbPipeRequest.PipeHandle;
|
|
|
|
if (!USBPORT_ValidatePipeHandle(deviceHandle, pipeHandle)) {
|
|
|
|
USBPORT_KdPrint((1, "'Error: Invalid Device Handle Passed in\n"));
|
|
DEBUG_BREAK();
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PIPE_HANDLE);
|
|
|
|
goto USBPORT_SyncClearStall_Done;
|
|
}
|
|
|
|
// our bug
|
|
ASSERT_PIPE_HANDLE(pipeHandle);
|
|
endpoint = pipeHandle->Endpoint;
|
|
ASSERT_ENDPOINT(endpoint);
|
|
|
|
// setup packet for clear endpoint stall
|
|
USBPORT_INIT_SETUP_PACKET(setupPacket,
|
|
USB_REQUEST_CLEAR_FEATURE, // bRequest
|
|
BMREQUEST_HOST_TO_DEVICE, // Dir
|
|
BMREQUEST_TO_ENDPOINT, // Recipient
|
|
BMREQUEST_STANDARD, // Type
|
|
USB_FEATURE_ENDPOINT_STALL, // wValue
|
|
endpoint->Parameters.EndpointAddress, // wIndex
|
|
0); // wLength
|
|
|
|
ntStatus =
|
|
USBPORT_SendCommand(deviceHandle,
|
|
FdoDeviceObject,
|
|
&setupPacket,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&usbdStatus);
|
|
|
|
ntStatus = SET_USBD_ERROR(Urb, usbdStatus);
|
|
|
|
USBPORT_SyncClearStall_Done:
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SyncResetPipeAndClearStall(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process a reset pipe request from the client driver
|
|
synchronously
|
|
|
|
legacy function from usb 1.1 stack sends the clear endpoint
|
|
stall command and resets ths host side state including data
|
|
toggle for the endpoint.
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PUSBD_PIPE_HANDLE_I pipeHandle;
|
|
PUSBD_DEVICE_HANDLE deviceHandle;
|
|
PHCD_ENDPOINT endpoint;
|
|
USBD_STATUS usbdStatus;
|
|
|
|
GET_DEVICE_HANDLE(deviceHandle, Urb);
|
|
pipeHandle = (PUSBD_PIPE_HANDLE_I) Urb->UrbPipeRequest.PipeHandle;
|
|
|
|
if (!USBPORT_ValidatePipeHandle(deviceHandle, pipeHandle)) {
|
|
|
|
USBPORT_KdPrint((1, "'Error: Invalid Pipe Handle Passed in\n"));
|
|
DEBUG_BREAK();
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PIPE_HANDLE);
|
|
|
|
} else {
|
|
|
|
// our bug
|
|
ASSERT_PIPE_HANDLE(pipeHandle);
|
|
|
|
// check for a zero load (BW) endpoint, if so there is
|
|
// nothing to do -- just complete the request with success
|
|
|
|
if (TEST_FLAG(pipeHandle->PipeStateFlags, USBPORT_PIPE_ZERO_BW)) {
|
|
ntStatus = SET_USBD_ERROR(Urb, USBD_STATUS_SUCCESS);
|
|
} else {
|
|
endpoint = pipeHandle->Endpoint;
|
|
ASSERT_ENDPOINT(endpoint);
|
|
|
|
InterlockedIncrement(&deviceHandle->PendingUrbs);
|
|
|
|
// clear the stall first on the device
|
|
// then reset the pipe
|
|
|
|
if (endpoint->Parameters.TransferType == Isochronous) {
|
|
|
|
// This is a nop for iso endpoints
|
|
//
|
|
// the orginal win9x/2k stack did not send this request
|
|
// for iso endpoints so we don't either. Some devices
|
|
// are confused by this. A client driver may override
|
|
// this behavior by call ing clear_stall and reset_pipe
|
|
// directly
|
|
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'iRES', endpoint, 0, 0);
|
|
|
|
|
|
ntStatus = SET_USBD_ERROR(Urb, USBD_STATUS_SUCCESS);
|
|
|
|
} else {
|
|
// only need to reset data toggle if we cleared stall
|
|
// ie only for non-iso endpoints
|
|
SET_FLAG(Urb->UrbHeader.UsbdFlags, USBPORT_RESET_DATA_TOGGLE);
|
|
ntStatus = USBPORT_SyncClearStall(FdoDeviceObject,
|
|
Irp,
|
|
Urb);
|
|
}
|
|
|
|
if (NT_SUCCESS(ntStatus)) {
|
|
ntStatus = USBPORT_SyncResetPipe(FdoDeviceObject,
|
|
Irp,
|
|
Urb);
|
|
|
|
if (endpoint->Parameters.TransferType == Isochronous) {
|
|
|
|
MP_ENDPOINT_STATE currentState;
|
|
|
|
do {
|
|
|
|
ACQUIRE_ENDPOINT_LOCK(endpoint, FdoDeviceObject, 'LeH0');
|
|
|
|
currentState = USBPORT_GetEndpointState(endpoint);
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'iWAT', endpoint,
|
|
currentState, 0);
|
|
|
|
if (currentState == ENDPOINT_PAUSE &&
|
|
IsListEmpty(&endpoint->ActiveList)) {
|
|
LOGENTRY(endpoint,
|
|
FdoDeviceObject, LOG_ISO, 'frcA', endpoint,
|
|
0, 0);
|
|
|
|
USBPORT_SetEndpointState(endpoint, ENDPOINT_ACTIVE);
|
|
}
|
|
|
|
RELEASE_ENDPOINT_LOCK(endpoint, FdoDeviceObject, 'UeH0');
|
|
|
|
if (currentState == ENDPOINT_ACTIVE) {
|
|
// quick release
|
|
break;
|
|
}
|
|
|
|
ASSERT_PASSIVE();
|
|
USBPORT_Wait(FdoDeviceObject, 1);
|
|
|
|
} while (currentState != ENDPOINT_ACTIVE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
InterlockedDecrement(&deviceHandle->PendingUrbs);
|
|
}
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_AbortPipe(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process abort pipe request from the client driver
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PUSBD_PIPE_HANDLE_I pipeHandle;
|
|
PHCD_ENDPOINT endpoint;
|
|
PUSBD_DEVICE_HANDLE deviceHandle;
|
|
|
|
USBPORT_KdPrint((2, "'AbortPipe\n"));
|
|
LOGENTRY(Endpoint,
|
|
FdoDeviceObject, LOG_URB, 'ARP>', 0, Irp, Urb);
|
|
|
|
// extract the pipe handle
|
|
GET_DEVICE_HANDLE(deviceHandle, Urb);
|
|
pipeHandle = Urb->UrbPipeRequest.PipeHandle;
|
|
|
|
// processurb only validate transfer pipe handles so
|
|
// we need to do it here
|
|
if (!USBPORT_ValidatePipeHandle(deviceHandle, pipeHandle)) {
|
|
|
|
USBPORT_KdPrint((1, "'Error: Invalid Pipe Handle Passed in\n"));
|
|
DEBUG_BREAK();
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_INVALID_PIPE_HANDLE);
|
|
} else {
|
|
|
|
if (TEST_FLAG(pipeHandle->PipeStateFlags, USBPORT_PIPE_ZERO_BW)) {
|
|
// just succeed the request if its a no bw pipe
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_SUCCESS);
|
|
} else {
|
|
endpoint = pipeHandle->Endpoint;
|
|
ASSERT_ENDPOINT(endpoint);
|
|
|
|
// the USBD/UHCD driver always pended this request when it passed
|
|
// it thru startio so we are safe to pend it here as well.
|
|
|
|
// We will pend this request until all outstanding transfers
|
|
// (at the time of the abort) have been completed
|
|
|
|
ntStatus = Irp->IoStatus.Status = STATUS_PENDING;
|
|
IoMarkIrpPending(Irp);
|
|
|
|
// now do the abort
|
|
USBPORT_AbortEndpoint(FdoDeviceObject,
|
|
endpoint,
|
|
Irp);
|
|
}
|
|
}
|
|
|
|
LOGENTRY(Endpoint,
|
|
FdoDeviceObject, LOG_URB, 'ARP<', 0, Irp, ntStatus);
|
|
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SCT_GetInterface(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
FdoDeviceObject -
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
TEST_TRAP();
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_NOT_SUPPORTED);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SCT_GetConfiguration(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
FdoDeviceObject -
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PUSB_DEFAULT_PIPE_SETUP_PACKET setupPacket;
|
|
UCHAR direction;
|
|
|
|
USBPORT_KdPrint((2, "'SCT_GetConfiguration\n"));
|
|
|
|
setupPacket =
|
|
(PUSB_DEFAULT_PIPE_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0];
|
|
|
|
setupPacket->bRequest =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].bRequest;
|
|
setupPacket->bmRequestType.Type =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Type;
|
|
setupPacket->bmRequestType.Dir =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Direction;
|
|
setupPacket->bmRequestType.Recipient =
|
|
UrbDispatchTable[Urb->UrbHeader.Function].Recipient;
|
|
setupPacket->bmRequestType.Reserved = 0;
|
|
setupPacket->wValue.W = 0;
|
|
setupPacket->wIndex.W = 0;
|
|
setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength;
|
|
|
|
if (setupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST) {
|
|
USBPORT_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags);
|
|
} else {
|
|
USBPORT_SET_TRANSFER_DIRECTION_OUT(Urb->UrbControlTransfer.TransferFlags);
|
|
}
|
|
Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
|
|
|
|
USBPORT_QueueTransferUrb((PTRANSFER_URB)Urb);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_TakeFrameLengthControl(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process abort pipe request from the client driver
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
TEST_TRAP();
|
|
|
|
// This function is no longer supported
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_NOT_SUPPORTED);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_ReleaseFrameLengthControl(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process abort pipe request from the client driver
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
TEST_TRAP();
|
|
|
|
// This function is no longer supported
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_NOT_SUPPORTED);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_GetFrameLength(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process abort pipe request from the client driver
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
TEST_TRAP();
|
|
|
|
// This function is no longer supported
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_NOT_SUPPORTED);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_SetFrameLength(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process abort pipe request from the client driver
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
TEST_TRAP();
|
|
// This function is no longer supported
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_NOT_SUPPORTED);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPORT_GetCurrentFrame(
|
|
PDEVICE_OBJECT FdoDeviceObject,
|
|
PIRP Irp,
|
|
PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
get the 32 bit frame number from the miniport
|
|
|
|
Arguments:
|
|
|
|
Irp - IO request block
|
|
|
|
Urb - ptr to USB request block
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PDEVICE_EXTENSION devExt;
|
|
ULONG cf;
|
|
|
|
GET_DEVICE_EXT(devExt, FdoDeviceObject);
|
|
ASSERT_FDOEXT(devExt);
|
|
|
|
MP_Get32BitFrameNumber(devExt, cf);
|
|
|
|
LOGENTRY(NULL,
|
|
FdoDeviceObject, LOG_URB, 'Ugcf', Urb, cf, 0);
|
|
|
|
Urb->UrbGetCurrentFrameNumber.FrameNumber = cf;
|
|
|
|
ntStatus =
|
|
SET_USBD_ERROR(Urb, USBD_STATUS_SUCCESS);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
|
|
|