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