/*++ Copyright (c) 1995 Microsoft Corporation Module Name: URB.C Abstract: This module contains the code to process URBs passed in by client drivers. Environment: kernel mode only Notes: ** URB handler routines Handler -- This function handles the specific USBD request, if the function passes the urb on to the port driver then it must return STATUS_PENDING. If any parameters are invalid then it returns the appropriate NT status code, and the IRP will completed by the deviceControl function. PostHandler -- This function is called when the Irp/Urb completes through the iocompletion routine. This routine is responsible for performing any cleanup and completing the request. Revision History: 09-29-95 : created 07-19-96 : removed device object --*/ #include "wdm.h" #include "stdarg.h" #include "stdio.h" #include "usbdi.h" //public data structures #include "hcdi.h" #include "usbd.h" //private data strutures #ifdef USBD_DRIVER // USBPORT supercedes most of USBD, so we will remove // the obsolete code by compiling it only if // USBD_DRIVER is set. typedef NTSTATUS URB_HANDLER(PDEVICE_OBJECT DeviceObject, PIRP Irp, PURB Urb, BOOLEAN *IrpIsPending); typedef NTSTATUS URB_POSTHANDLER(PDEVICE_OBJECT DeviceObject, PIRP Irp, PURB Urb, PVOID Context); typedef struct _URB_DISPATCH_ENTRY { URB_HANDLER *UrbHandler; // API handler USHORT UrbRequestLength; // Length of the URB expected for this request USHORT RequestCode; // Request code for setup packet if standard command ULONG Flags; #if DBG ULONG ExpectedFunctionCode; #endif } URB_DISPATCH_ENTRY; URB_HANDLER USBD_SelectConfiguration; URB_HANDLER USBD_SelectInterface; URB_HANDLER USBD_AsyncTransfer; URB_HANDLER USBD_IsochTransfer; URB_HANDLER USBD_PassThru; URB_HANDLER USBD_AbortPipe; URB_HANDLER USBD_ResetPipe; URB_HANDLER USBD_SCT_GetSetDescriptor; URB_HANDLER USBD_SCT_SetClearFeature; URB_HANDLER USBD_SCT_GetStatus; URB_HANDLER USBD_SCT_VendorClassCommand; URB_HANDLER USBD_SCT_GetInterface; URB_HANDLER USBD_SCT_GetConfiguration; URB_HANDLER USBD_TakeFrameLengthControl; URB_HANDLER USBD_ReleaseFrameLengthControl; URB_HANDLER USBD_GetFrameLength; URB_HANDLER USBD_SetFrameLength; URB_HANDLER USBD_BulkTransfer; URB_DISPATCH_ENTRY UrbDispatchTable[URB_FUNCTION_LAST+1] = { //URB_FUNCTION_SELECT_CONFIGURATION USBD_SelectConfiguration, 0, // handler will validate length 0, 0, #if DBG URB_FUNCTION_SELECT_CONFIGURATION, #endif //URB_FUNCTION_SELECT_INTERFACE USBD_SelectInterface, 0, 0, 0, #if DBG URB_FUNCTION_SELECT_INTERFACE, #endif //URB_FUNCTION_ABORT_PIPE USBD_AbortPipe, sizeof(struct _URB_PIPE_REQUEST), 0, 0, #if DBG URB_FUNCTION_ABORT_PIPE, #endif //URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL USBD_TakeFrameLengthControl, sizeof(struct _URB_FRAME_LENGTH_CONTROL), 0, 0, #if DBG URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL, #endif //URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL USBD_ReleaseFrameLengthControl, sizeof(struct _URB_FRAME_LENGTH_CONTROL), 0, 0, #if DBG URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL, #endif //URB_FUNCTION_GET_FRAME_LENGTH USBD_GetFrameLength, sizeof(struct _URB_GET_FRAME_LENGTH), 0, 0, #if DBG URB_FUNCTION_GET_FRAME_LENGTH, #endif //URB_FUNCTION_SET_FRAME_LENGTH USBD_SetFrameLength, sizeof(struct _URB_SET_FRAME_LENGTH), 0, 0, #if DBG URB_FUNCTION_SET_FRAME_LENGTH, #endif //URB_FUNCTION_GET_CURRENT_FRAME_NUMBER USBD_PassThru, 0, 0, 0, #if DBG URB_FUNCTION_GET_CURRENT_FRAME_NUMBER, #endif //URB_FUNCTION_CONTROL_TRANSFER USBD_AsyncTransfer, sizeof(struct _URB_CONTROL_TRANSFER), 0, USBD_REQUEST_IS_TRANSFER, #if DBG URB_FUNCTION_CONTROL_TRANSFER, #endif //URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER USBD_AsyncTransfer, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), 0, USBD_REQUEST_IS_TRANSFER, #if DBG URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER, #endif //URB_FUNCTION_ISOCH_TRANSFER USBD_IsochTransfer, 0, 0, USBD_REQUEST_IS_TRANSFER, #if DBG URB_FUNCTION_ISOCH_TRANSFER, #endif //URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE USBD_SCT_GetSetDescriptor, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), STANDARD_COMMAND_GET_DESCRIPTOR, USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, #endif //URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE USBD_SCT_GetSetDescriptor, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), STANDARD_COMMAND_SET_DESCRIPTOR, USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE, #endif //URB_FUNCTION_SET_FEATURE_TO_DEVICE USBD_SCT_SetClearFeature, sizeof(struct _URB_CONTROL_FEATURE_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_DEVICE) | (USB_REQUEST_SET_FEATURE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE | USBD_REQUEST_NO_DATA_PHASE, #if DBG URB_FUNCTION_SET_FEATURE_TO_DEVICE, #endif //URB_FUNCTION_SET_FEATURE_TO_INTERFACE USBD_SCT_SetClearFeature, sizeof(struct _URB_CONTROL_FEATURE_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_INTERFACE) | (USB_REQUEST_SET_FEATURE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE | USBD_REQUEST_NO_DATA_PHASE, #if DBG URB_FUNCTION_SET_FEATURE_TO_INTERFACE, #endif //URB_FUNCTION_SET_FEATURE_TO_ENDPOINT USBD_SCT_SetClearFeature, sizeof(struct _URB_CONTROL_FEATURE_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_ENDPOINT) | (USB_REQUEST_SET_FEATURE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE | USBD_REQUEST_NO_DATA_PHASE, #if DBG URB_FUNCTION_SET_FEATURE_TO_ENDPOINT, #endif //URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE USBD_SCT_SetClearFeature, sizeof(struct _URB_CONTROL_FEATURE_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_DEVICE) | (USB_REQUEST_CLEAR_FEATURE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE | USBD_REQUEST_NO_DATA_PHASE, #if DBG URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE, #endif //URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE USBD_SCT_SetClearFeature, sizeof(struct _URB_CONTROL_FEATURE_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_INTERFACE) | (USB_REQUEST_CLEAR_FEATURE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE | USBD_REQUEST_NO_DATA_PHASE, #if DBG URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE, #endif //URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT USBD_SCT_SetClearFeature, sizeof(struct _URB_CONTROL_FEATURE_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_ENDPOINT) | (USB_REQUEST_CLEAR_FEATURE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE | USBD_REQUEST_NO_DATA_PHASE, #if DBG URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT, #endif //URB_FUNCTION_GET_STATUS_FROMDEVICE USBD_SCT_GetStatus, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), ((USB_DEVICE_TO_HOST | USB_COMMAND_TO_DEVICE) | (USB_REQUEST_GET_STATUS<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_STATUS_FROM_DEVICE, #endif //URB_FUNCTION_GET_STATUS_FROM_INTERFACE USBD_SCT_GetStatus, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), ((USB_DEVICE_TO_HOST | USB_COMMAND_TO_INTERFACE) | (USB_REQUEST_GET_STATUS<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_STATUS_FROM_INTERFACE, #endif //URB_FUNCTION_GET_STATUS_FROMENDPOINT USBD_SCT_GetStatus, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), ((USB_DEVICE_TO_HOST | USB_COMMAND_TO_ENDPOINT) | (USB_REQUEST_GET_STATUS<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_STATUS_FROM_ENDPOINT, #endif //URB_FUNCTION_SYNC_FRAME NULL, 0, 0, USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG 0, //URB_FUNCTION_SYNC_FRAME, #endif //URB_FUNCTION_VENDOR_DEVICE USBD_SCT_VendorClassCommand, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), (USB_COMMAND_TO_DEVICE | USB_VENDOR_COMMAND), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_VENDOR_DEVICE, #endif //URB_FUNCTION_VENDOR_INTERFACE USBD_SCT_VendorClassCommand, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), (USB_COMMAND_TO_INTERFACE | USB_VENDOR_COMMAND), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_VENDOR_INTERFACE, #endif //URB_FUNCTION_VENDOR_ENDPOINT USBD_SCT_VendorClassCommand, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), (USB_COMMAND_TO_ENDPOINT | USB_VENDOR_COMMAND), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_VENDOR_ENDPOINT, #endif //URB_FUNCTION_CLASS_DEVICE USBD_SCT_VendorClassCommand, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), (USB_COMMAND_TO_DEVICE | USB_CLASS_COMMAND), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_CLASS_DEVICE, #endif //URB_FUNCTION_CLASS_INTERFACE USBD_SCT_VendorClassCommand, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), (USB_COMMAND_TO_INTERFACE | USB_CLASS_COMMAND), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_CLASS_INTERFACE, #endif //URB_FUNCTION_CLASS_ENDPOINT USBD_SCT_VendorClassCommand, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), (USB_COMMAND_TO_ENDPOINT | USB_CLASS_COMMAND), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_CLASS_ENDPOINT, #endif //URB_FUNCTION_ NOT USED NULL, 0, 0, 0, #if DBG URB_FUNCTION_RESERVED, #endif //URB_FUNCTION_RESET_PIPE USBD_ResetPipe, sizeof(struct _URB_PIPE_REQUEST), (USB_COMMAND_TO_DEVICE), 0, #if DBG URB_FUNCTION_RESET_PIPE, #endif //URB_FUNCTION_CLASS_OTHER USBD_SCT_VendorClassCommand, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), (USB_COMMAND_TO_OTHER | USB_CLASS_COMMAND), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_CLASS_OTHER, #endif //URB_FUNCTION_VENDOR_OTHER USBD_SCT_VendorClassCommand, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), (USB_COMMAND_TO_OTHER | USB_VENDOR_COMMAND), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_VENDOR_OTHER, #endif //URB_FUNCTION_GET_STATUS_FROMOTHER USBD_SCT_GetStatus, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), ((USB_DEVICE_TO_HOST | USB_COMMAND_TO_OTHER) | (USB_REQUEST_GET_STATUS<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_STATUS_FROM_OTHER, #endif //URB_FUNCTION_CLEAR_FEATURE_TO_OTHER USBD_SCT_SetClearFeature, sizeof(struct _URB_CONTROL_FEATURE_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_OTHER) | (USB_REQUEST_CLEAR_FEATURE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE | USBD_REQUEST_NO_DATA_PHASE, #if DBG URB_FUNCTION_CLEAR_FEATURE_TO_OTHER, #endif //URB_FUNCTION_SET_FEATURE_TO_OTHER USBD_SCT_SetClearFeature, sizeof(struct _URB_CONTROL_FEATURE_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_OTHER) | (USB_REQUEST_SET_FEATURE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE | USBD_REQUEST_NO_DATA_PHASE, #if DBG URB_FUNCTION_SET_FEATURE_TO_INTERFACE, #endif //URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT USBD_SCT_GetSetDescriptor, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), ((USB_DEVICE_TO_HOST | USB_COMMAND_TO_ENDPOINT) | (USB_REQUEST_GET_DESCRIPTOR<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT, #endif //URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT USBD_SCT_GetSetDescriptor, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_ENDPOINT) | (USB_REQUEST_SET_DESCRIPTOR<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT, #endif //URB_FUNCTION_GET_CONFIGURATION USBD_SCT_GetConfiguration, sizeof(struct _URB_CONTROL_GET_CONFIGURATION_REQUEST), ((USB_DEVICE_TO_HOST | USB_COMMAND_TO_DEVICE) | (USB_REQUEST_GET_CONFIGURATION<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_CONFIGURATION, #endif //URB_FUNCTION_GET_INTERFACE USBD_SCT_GetInterface, sizeof(struct _URB_CONTROL_GET_INTERFACE_REQUEST), ((USB_DEVICE_TO_HOST | USB_COMMAND_TO_INTERFACE) | (USB_REQUEST_GET_INTERFACE<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_INTERFACE, #endif //URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE USBD_SCT_GetSetDescriptor, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), ((USB_DEVICE_TO_HOST | USB_COMMAND_TO_INTERFACE) | (USB_REQUEST_GET_DESCRIPTOR<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE, #endif //URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE USBD_SCT_GetSetDescriptor, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), ((USB_HOST_TO_DEVICE | USB_COMMAND_TO_INTERFACE) | (USB_REQUEST_SET_DESCRIPTOR<<8)), USBD_REQUEST_IS_TRANSFER | USBD_REQUEST_USES_DEFAULT_PIPE, #if DBG URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE, #endif }; BOOLEAN USBD_ValidatePipe( PUSBD_PIPE PipeHandle ) /*++ Routine Description: Validates the pipe flags and anything else that we deem appropriate. Arguments: PipeHandle - PipeHandle associated with the URB in this IRP request Return Value: Boolean value indicating whether PipeHandle should be considered valid or not --*/ { if (!PipeHandle || (PipeHandle->Sig != SIG_PIPE) || (PipeHandle->UsbdPipeFlags & ~(USBD_PF_VALID_MASK))) { return FALSE; } return TRUE; } NTSTATUS USBD_ProcessURB( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: Processes a URB from a client IRP, this does the guts of the processing. Two way to tell the caller not to pass the URB on 1) set IrpIsPending to FALSE or 2) return an error in Arguments: DeviceObject - Device object associated with this IRP request Irp - IO request block Urb - ptr to USB request block IrpIsPending - FALSE if USBD completes the IRP Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; USHORT function; PHCD_URB hcdUrb = (PHCD_URB) Urb; PUSBD_PIPE pipeHandle; PUSBD_DEVICE_DATA device; USBD_KdPrint(3, ("'enter USBD_ProcessURB\n")); if (Urb == NULL) { return STATUS_INVALID_PARAMETER; } // initialize the error code to zero, // some drivers do not initailize on entry hcdUrb->HcdUrbCommonTransfer.Status = 0; if (Urb->UrbHeader.UsbdDeviceHandle == NULL) { PUSBD_EXTENSION deviceExtension; deviceExtension = GET_DEVICE_EXTENSION(DeviceObject); USBD_KdPrint(3, ("'USBD_ProcessURB -- URB for root hub\n")); Urb->UrbHeader.UsbdDeviceHandle = deviceExtension->RootHubDeviceData; } function = Urb->UrbHeader.Function; // Initialize flags field for this request hcdUrb->UrbHeader.UsbdFlags = 0; USBD_KdPrint(3, ("'USBD_ProcessURB, function = 0x%x\n", function)); if (function > URB_FUNCTION_LAST) { ntStatus = STATUS_INVALID_PARAMETER; } #if DBG else { USBD_ASSERT(UrbDispatchTable[function].ExpectedFunctionCode == function); } #endif // // do some special transfer specific stuff // device = DEVICE_FROM_DEVICEHANDLEROBJECT(Urb->UrbHeader.UsbdDeviceHandle); if (!device) { hcdUrb->HcdUrbCommonTransfer.Status = SET_USBD_ERROR(USBD_STATUS_INVALID_PARAMETER); goto USBD_ProcessURB_Done; } ASSERT_DEVICE(device); if (UrbDispatchTable[function].Flags & USBD_REQUEST_IS_TRANSFER) { if (!device->AcceptingRequests) { // // Driver is attempting to transfer data when the device // is not in a state to accept requets or is not configured // USBD_Warning(device, "Failing driver transfer requests\n", FALSE); hcdUrb->HcdUrbCommonTransfer.Status = SET_USBD_ERROR(USBD_STATUS_INVALID_PARAMETER); goto USBD_ProcessURB_Done; } while (hcdUrb) { hcdUrb->UrbHeader.UsbdFlags |= USBD_REQUEST_IS_TRANSFER; if (UrbDispatchTable[function].Flags & USBD_REQUEST_NO_DATA_PHASE) { hcdUrb->HcdUrbCommonTransfer.TransferBuffer = NULL; hcdUrb->HcdUrbCommonTransfer.TransferBufferMDL = NULL; hcdUrb->HcdUrbCommonTransfer.TransferBufferLength = 0; } if (UrbDispatchTable[function].Flags & USBD_REQUEST_USES_DEFAULT_PIPE) { ASSERT_PIPE(&device->DefaultPipe); hcdUrb->HcdUrbCommonTransfer.UsbdPipeHandle = &device->DefaultPipe; } else if (function == URB_FUNCTION_CONTROL_TRANSFER && hcdUrb->HcdUrbCommonTransfer.UsbdPipeHandle == 0) { PUSBD_EXTENSION deviceExtension; deviceExtension = GET_DEVICE_EXTENSION(DeviceObject); if ((deviceExtension->DiagnosticMode) && !( (deviceExtension->DiagIgnoreHubs) && (device->DeviceDescriptor.bDeviceClass == 0x09) ) ) { // allow 0 to indicate default pipe in diag mode device = DEVICE_FROM_DEVICEHANDLEROBJECT(Urb->UrbHeader.UsbdDeviceHandle); ASSERT_PIPE(&device->DefaultPipe); hcdUrb->HcdUrbCommonTransfer.UsbdPipeHandle = &device->DefaultPipe; } else { hcdUrb->HcdUrbCommonTransfer.Status = SET_USBD_ERROR(USBD_STATUS_INVALID_PIPE_HANDLE); goto USBD_ProcessURB_Done; } } pipeHandle = hcdUrb->HcdUrbCommonTransfer.UsbdPipeHandle; ASSERT_PIPE(pipeHandle); // Validate the pipe flags. // BUGBUG: Need to use USBD_STATUS_INVALID_PIPE_FLAGS (usb.h). if (!USBD_ValidatePipe(pipeHandle)) { USBD_Warning(device, "Invalid PipeFlags passed to USBD_ProcessURB, fail!\n", TRUE); hcdUrb->HcdUrbCommonTransfer.Status = SET_USBD_ERROR(USBD_STATUS_INVALID_PIPE_HANDLE); goto USBD_ProcessURB_Done; } // make sure the pipe handle is still valid if (PIPE_CLOSED(pipeHandle)) { USBD_Warning(device, "PipeHandle closed in USBD_ProcessURB\n", FALSE); hcdUrb->HcdUrbCommonTransfer.Status = SET_USBD_ERROR(USBD_STATUS_INVALID_PIPE_HANDLE); goto USBD_ProcessURB_Done; } hcdUrb->HcdUrbCommonTransfer.hca.HcdIrp = Irp; hcdUrb->HcdUrbCommonTransfer.hca.HcdExtension = NULL; // if only a system buffer address is specified then // the caller has passed in a buffer allocated from the // non-paged pool -- we allocate an MDL for the request in // this case. if (hcdUrb->HcdUrbCommonTransfer.TransferBufferMDL == NULL && hcdUrb->HcdUrbCommonTransfer.TransferBufferLength != 0) { if ((hcdUrb->HcdUrbCommonTransfer.TransferBufferMDL = IoAllocateMdl(hcdUrb->HcdUrbCommonTransfer.TransferBuffer, hcdUrb->HcdUrbCommonTransfer.TransferBufferLength, FALSE, FALSE, NULL)) == NULL) ntStatus = STATUS_INSUFFICIENT_RESOURCES; else { hcdUrb->UrbHeader.UsbdFlags |= USBD_REQUEST_MDL_ALLOCATED; MmBuildMdlForNonPagedPool(hcdUrb->HcdUrbCommonTransfer.TransferBufferMDL); } } if (hcdUrb->HcdUrbCommonTransfer.TransferBufferMDL != NULL && hcdUrb->HcdUrbCommonTransfer.TransferBufferLength == 0) { ntStatus = STATUS_INVALID_PARAMETER; } // get next urb in the chain hcdUrb = hcdUrb->HcdUrbCommonTransfer.UrbLink; } /* end while hcd urb */ } else { /* request is not a transfer, we will still attempt some validation */ switch(function) { case URB_FUNCTION_ABORT_PIPE: case URB_FUNCTION_RESET_PIPE: /* not valid to attempt these after a remove */ // // NOTE there is no gurantee that device will be valid // at this point but we will at least attempt to catch it // // in the case whwee the driver is attempting a reset of its // port this will prevent calls to the HCD with bogus endpoint // handles. // if (!device->AcceptingRequests) { USBD_Warning(NULL, "Failing ABORT/RESET request\n", FALSE); hcdUrb->HcdUrbCommonTransfer.Status = SET_USBD_ERROR(USBD_STATUS_INVALID_PARAMETER); goto USBD_ProcessURB_Done; } break; } } // // validate the length field based on the function // if (NT_SUCCESS(ntStatus) && UrbDispatchTable[function].UrbRequestLength && UrbDispatchTable[function].UrbRequestLength != Urb->UrbHeader.Length) { ntStatus = STATUS_INVALID_PARAMETER; USBD_KdPrint(3, ("' Inavlid parameter length length = 0x%x, expected = 0x%x\n", Urb->UrbHeader.Length, UrbDispatchTable[function].UrbRequestLength)); } if (NT_SUCCESS(ntStatus)) { if (UrbDispatchTable[function].UrbHandler) ntStatus = (UrbDispatchTable[function].UrbHandler)(DeviceObject, Irp, Urb, IrpIsPending); else { // //Complete the Irp now with an error. // ntStatus = STATUS_NOT_IMPLEMENTED; } } USBD_ProcessURB_Done: // // if the URB error code is set then this will map to // the appropriate nt status code to that the irp will // be completed. // ntStatus = USBD_MapError_UrbToNT(Urb, ntStatus); USBD_KdPrint(3, ("'exit USBD_ProcessURB 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_MapError_UrbToNT( IN PURB Urb, IN NTSTATUS NtStatus ) /*++ Routine Description: Map a USBD specific error code in a URB to a NTSTATUS code. Arguments: Urb - ptr to USB request block Return Value: --*/ { // // if we have an NT status code then just return // that. // if (!NT_SUCCESS(NtStatus)) { return NtStatus; } // otherwise... // // if the irp completed with no error code but the URB has an // error, map the error in the urb to an nt error code. // if (USBD_SUCCESS(Urb->UrbHeader.Status)) { NtStatus = STATUS_SUCCESS; } else { // // map the USBD status code to // an NT status code. // switch (Urb->UrbHeader.Status) { case USBD_STATUS_NO_MEMORY: NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; case USBD_STATUS_INVALID_URB_FUNCTION: case USBD_STATUS_INVALID_PARAMETER: NtStatus = STATUS_INVALID_PARAMETER; break; default: NtStatus = STATUS_DEVICE_DATA_ERROR; } } return NtStatus; } NTSTATUS USBD_SCT_GetSetDescriptor( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: Arguments: DeviceObject - Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PUSB_STANDARD_SETUP_PACKET setupPacket; USBD_KdPrint(3, ("' enter USBD_SCT_GetSetDescriptor\n")); setupPacket = (PUSB_STANDARD_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0]; // setup common fields setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength; setupPacket->RequestCode = UrbDispatchTable[Urb->UrbHeader.Function].RequestCode; Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; if (USB_DEVICE_TO_HOST & setupPacket->RequestCode) { USBD_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags); } else { USBD_SET_TRANSFER_DIRECTION_OUT(Urb->UrbControlTransfer.TransferFlags); } #if DBG // // some parameter validation // { UCHAR bRequest = (UCHAR) (setupPacket->RequestCode >> 8); UCHAR dType, dIndex, *pch; dType = (UCHAR) (setupPacket->wValue >> 8); dIndex = (UCHAR) setupPacket->wValue; pch = (PUCHAR) setupPacket; USBD_KdPrint(3, ("'USB REQUEST %02.2x %02.2x %02.2x %02.2x ", *pch, *(pch+1), *(pch+2), *(pch+3))); USBD_KdPrint(3, ("'USB REQUEST %02.2x %02.2x %02.2x %02.2x\n", *(pch+4), *(pch+5), *(pch+6), *(pch+7))); USBD_KdPrint(3, ("'USB REQUEST bRequest = %x dType = %x dIndex = %x wLength = %x\n", bRequest, dType, dIndex, setupPacket->wLength)); switch (bRequest) { // get descriptor command case USB_REQUEST_GET_DESCRIPTOR: case USB_REQUEST_SET_DESCRIPTOR: if (dType == 4 || dType == 5) { USBD_Warning(NULL, "USBD detects a bogus Get/Set Descriptor Request from driver\n", TRUE); } break; default: USBD_KdBreak(("Invalid Get/Set Descriptor request\n")); } } #endif if (NT_SUCCESS(ntStatus)) { ((PHCD_URB) Urb)->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER; ((PHCD_URB) Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint = ((PUSBD_PIPE)((PHCD_URB)Urb)->HcdUrbCommonTransfer.UsbdPipeHandle)->HcdEndpoint; *IrpIsPending = TRUE; } USBD_KdPrint(3, ("' exit USBD_SCT_GetSetDescriptor 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_SCT_SetClearFeature( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: Arguments: DeviceObject - Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PUSB_STANDARD_SETUP_PACKET setupPacket; USBD_KdPrint(3, ("' enter USBD_SCT_SetClearFeature\n")); setupPacket = (PUSB_STANDARD_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0]; // setup common fields setupPacket->wLength = 0; //setupPacket->wValue = Urb->UrbControlFeatureRequest.FeatureSelector; //setupPacket->wIndex = Urb->UrbControlFeatureRequest.Index; setupPacket->RequestCode = UrbDispatchTable[Urb->UrbHeader.Function].RequestCode; Urb->UrbControlTransfer.TransferBufferLength = 0; Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; if (USB_DEVICE_TO_HOST & setupPacket->RequestCode) { USBD_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags); } else { USBD_SET_TRANSFER_DIRECTION_OUT( Urb->UrbControlTransfer.TransferFlags); } if (NT_SUCCESS(ntStatus)) { ((PHCD_URB) Urb)->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER; ((PHCD_URB) Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint = ((PUSBD_PIPE)((PHCD_URB)Urb)->HcdUrbCommonTransfer.UsbdPipeHandle)->HcdEndpoint; *IrpIsPending = TRUE; } USBD_KdPrint(3, ("' exit USBD_SCT_SetClearFeature 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_SCT_GetStatus( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: Arguments: DeviceObject - Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PUSB_STANDARD_SETUP_PACKET setupPacket; USBD_KdPrint(3, ("' enter USBD_SCT_GetStatus\n")); setupPacket = (PUSB_STANDARD_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0]; // // setup common fields // setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength; if (setupPacket->wLength != 2) { ntStatus = STATUS_INVALID_PARAMETER; Urb->UrbHeader.Status = SET_USBD_ERROR(USBD_STATUS_INVALID_PARAMETER); goto USBD_SCT_GetStatus_Done; } setupPacket->wValue = 0; setupPacket->RequestCode = UrbDispatchTable[Urb->UrbHeader.Function].RequestCode; Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; if (USB_DEVICE_TO_HOST & setupPacket->RequestCode) { USBD_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags); } else { USBD_SET_TRANSFER_DIRECTION_OUT( Urb->UrbControlTransfer.TransferFlags); } if (NT_SUCCESS(ntStatus)) { ((PHCD_URB) Urb)->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER; ((PHCD_URB) Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint = ((PUSBD_PIPE)((PHCD_URB)Urb)->HcdUrbCommonTransfer.UsbdPipeHandle)->HcdEndpoint; *IrpIsPending = TRUE; } USBD_SCT_GetStatus_Done: USBD_KdPrint(3, ("' exit USBD_SCT_GetStatus 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_SCT_VendorClassCommand( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: Arguments: DeviceObject - Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PUSB_STANDARD_SETUP_PACKET setupPacket; UCHAR direction; USBD_KdPrint(3, ("' enter USBD_SCT_VendorClassCommand\n")); setupPacket = (PUSB_STANDARD_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0]; // setup common fields setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength; direction = (UCHAR)( (Urb->UrbControlTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN) ? USB_DEVICE_TO_HOST : USB_HOST_TO_DEVICE); USBD_KdPrint(3, ("' direction = 0x%x\n", direction)); // allow only reserved bits to be set by caller setupPacket->RequestCode &= ~0x00e3; setupPacket->RequestCode |= (direction | UrbDispatchTable[Urb->UrbHeader.Function].RequestCode); Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; if (USB_DEVICE_TO_HOST & setupPacket->RequestCode) { USBD_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags); } else { USBD_SET_TRANSFER_DIRECTION_OUT( Urb->UrbControlTransfer.TransferFlags); } if (NT_SUCCESS(ntStatus)) { ((PHCD_URB) Urb)->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER; ((PHCD_URB) Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint = ((PUSBD_PIPE)((PHCD_URB)Urb)->HcdUrbCommonTransfer.UsbdPipeHandle)->HcdEndpoint; *IrpIsPending = TRUE; } USBD_KdPrint(3, ("' exit USBD_SCT_VendorClassCommand 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_AsyncTransfer( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: pass interrupt or bulk transfer to HCD Arguments: Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PUSBD_DEVICE_DATA deviceData; PUSBD_PIPE pipeHandle; USBD_KdPrint(3, ("' enter USBD_AsyncTransfer\n")); deviceData = Urb->UrbHeader.UsbdDeviceHandle; // pass the irp to HCD // extract the pipe handle pipeHandle = (PUSBD_PIPE)((PHCD_URB)Urb)->HcdUrbCommonTransfer.UsbdPipeHandle; ASSERT_PIPE(pipeHandle); ((PHCD_URB)Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint = pipeHandle->HcdEndpoint; // 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 ((USB_ENDPOINT_TYPE_MASK & pipeHandle->EndpointDescriptor.bmAttributes) != USB_ENDPOINT_TYPE_CONTROL) { if (pipeHandle->EndpointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) { USBD_SET_TRANSFER_DIRECTION_IN(((PHCD_URB)Urb)->HcdUrbCommonTransfer.TransferFlags); } else { USBD_SET_TRANSFER_DIRECTION_OUT(((PHCD_URB)Urb)->HcdUrbCommonTransfer.TransferFlags); } } *IrpIsPending = TRUE; USBD_KdPrint(3, ("' exit USBD_AsyncTransfer 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_IsochTransfer( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: pass interrupt transfer to HCD Arguments: Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PUSBD_DEVICE_DATA deviceData; PUSBD_PIPE pipeHandle; ULONG transferFlags; struct _URB_ISOCH_TRANSFER *iso; USBD_KdPrint(3, ("' enter USBD_IsochTransfer\n")); deviceData = Urb->UrbHeader.UsbdDeviceHandle; // pass the irp to HCD // extract the pipe handle pipeHandle = (PUSBD_PIPE)Urb->UrbIsochronousTransfer.PipeHandle; transferFlags = Urb->UrbIsochronousTransfer.TransferFlags; iso = (struct _URB_ISOCH_TRANSFER *)Urb; ASSERT_PIPE(pipeHandle); // // limit iso transfers to 255 packets per URB // if (iso->NumberOfPackets == 0 || iso->NumberOfPackets > 255) { ntStatus = STATUS_INVALID_PARAMETER; Urb->UrbHeader.Status = SET_USBD_ERROR(USBD_STATUS_INVALID_PARAMETER); *IrpIsPending = FALSE; goto USBD_IsochTransfer_Done; } ((PHCD_URB)Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint = pipeHandle->HcdEndpoint; // set the proper direction based on the direction bit stored with the // endpoint address. if (pipeHandle->EndpointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) { USBD_SET_TRANSFER_DIRECTION_IN(((PHCD_URB)Urb)->HcdUrbCommonTransfer.TransferFlags); } else { USBD_SET_TRANSFER_DIRECTION_OUT(((PHCD_URB)Urb)->HcdUrbCommonTransfer.TransferFlags); } *IrpIsPending = TRUE; USBD_IsochTransfer_Done: USBD_KdPrint(3, ("' exit USBD_IsochTransfer 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_PassThru( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: pass urb thru unmodified Arguments: Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; USBD_KdPrint(3, ("' enter USBD_PassThru\n")); //deviceData = Urb->UrbHeader.UsbdDeviceHandle; *IrpIsPending = TRUE; USBD_KdPrint(3, ("' exit USBD_PassThru 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_ResetPipe( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ 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 = STATUS_SUCCESS; PHCD_URB hcdUrb = (PHCD_URB)Urb; PUSBD_PIPE pipeHandle; // this function blocks so it must not be called at DPC level PAGED_CODE(); USBD_KdPrint(3, ("' enter USBD_ResetPipe\n")); pipeHandle = (PUSBD_PIPE) Urb->UrbPipeRequest.PipeHandle; ASSERT_PIPE(pipeHandle); // // first clear the stall on the device if this is a // bulk or interrupt pipe. // // The reason we do this is to ensure that the data toggle // on both the host and the device is reset. // if (((USB_ENDPOINT_TYPE_MASK & pipeHandle->EndpointDescriptor.bmAttributes) == USB_ENDPOINT_TYPE_BULK) || ((USB_ENDPOINT_TYPE_MASK & pipeHandle->EndpointDescriptor.bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT)) { ntStatus = USBD_SendCommand(Urb->UrbHeader.UsbdDeviceHandle, DeviceObject, STANDARD_COMMAND_CLEAR_FEATURE_ENDPOINT, USB_FEATURE_ENDPOINT_STALL, pipeHandle->EndpointDescriptor.bEndpointAddress, 0, NULL, 0, NULL, NULL); } if (NT_SUCCESS(ntStatus)) { // // Change the Urb command to set endpoint state // note: we rely on these two structures being // identical so that we can reuse the URB // ASSERT(sizeof(struct _URB_HCD_ENDPOINT_STATE) == sizeof(struct _URB_PIPE_REQUEST)); ASSERT_PIPE((PUSBD_PIPE) Urb->UrbPipeRequest.PipeHandle); hcdUrb->HcdUrbEndpointState.Function = URB_FUNCTION_HCD_SET_ENDPOINT_STATE; hcdUrb->HcdUrbEndpointState.HcdEndpoint = ((PUSBD_PIPE) (Urb->UrbPipeRequest.PipeHandle))->HcdEndpoint; // request to clear halt and reset toggle hcdUrb->HcdUrbEndpointState.HcdEndpointState = HCD_ENDPOINT_RESET_DATA_TOGGLE; *IrpIsPending = TRUE; } USBD_KdPrint(3, ("' exit USBD_ResetPipe 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_AbortPipe( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ 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 = STATUS_SUCCESS; PHCD_URB hcdUrb = (PHCD_URB)Urb; USBD_KdPrint(3, ("' enter USBD_AbortPipe\n")); // // Change the Urb command to abort endpoint // ASSERT_PIPE((PUSBD_PIPE) Urb->UrbPipeRequest.PipeHandle); hcdUrb->HcdUrbAbortEndpoint.Function = URB_FUNCTION_HCD_ABORT_ENDPOINT; hcdUrb->HcdUrbAbortEndpoint.HcdEndpoint = ((PUSBD_PIPE) (Urb->UrbPipeRequest.PipeHandle))->HcdEndpoint; *IrpIsPending = TRUE; USBD_KdPrint(3, ("' exit USBD_AbortPipe 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_SCT_GetInterface( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: Arguments: DeviceObject - Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PUSB_STANDARD_SETUP_PACKET setupPacket; USBD_KdPrint(3, ("' enter USBD_SCT_GetStatus\n")); setupPacket = (PUSB_STANDARD_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0]; // setup common fields setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength; if (setupPacket->wLength != 1) { ntStatus = STATUS_INVALID_PARAMETER; goto USBD_SCT_GetInterface_Done; } setupPacket->wValue = 0; setupPacket->wIndex = Urb->UrbControlGetInterfaceRequest.Interface; setupPacket->RequestCode = UrbDispatchTable[Urb->UrbHeader.Function].RequestCode; Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; if (USB_DEVICE_TO_HOST & setupPacket->RequestCode) { USBD_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags); } else { USBD_SET_TRANSFER_DIRECTION_OUT( Urb->UrbControlTransfer.TransferFlags); } if (NT_SUCCESS(ntStatus)) { ((PHCD_URB) Urb)->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER; ((PHCD_URB) Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint = ((PUSBD_PIPE)((PHCD_URB)Urb)->HcdUrbCommonTransfer.UsbdPipeHandle)->HcdEndpoint; *IrpIsPending = TRUE; } USBD_SCT_GetInterface_Done: USBD_KdPrint(3, ("' exit USBD_SCT_GetInterface 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_SCT_GetConfiguration( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ Routine Description: Arguments: DeviceObject - Irp - IO request block Urb - ptr to USB request block Return Value: --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PUSB_STANDARD_SETUP_PACKET setupPacket; USBD_KdPrint(3, ("' enter USBD_SCT_GetStatus\n")); setupPacket = (PUSB_STANDARD_SETUP_PACKET) &Urb->UrbControlTransfer.SetupPacket[0]; // setup common fields setupPacket->wLength = (USHORT) Urb->UrbControlTransfer.TransferBufferLength; USBD_ASSERT(setupPacket->wLength == 1); setupPacket->wValue = 0; setupPacket->wIndex = 0; setupPacket->RequestCode = UrbDispatchTable[Urb->UrbHeader.Function].RequestCode; Urb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; if (USB_DEVICE_TO_HOST & setupPacket->RequestCode) { USBD_SET_TRANSFER_DIRECTION_IN(Urb->UrbControlTransfer.TransferFlags); } else { USBD_SET_TRANSFER_DIRECTION_OUT( Urb->UrbControlTransfer.TransferFlags); } if (NT_SUCCESS(ntStatus)) { ((PHCD_URB) Urb)->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER; ((PHCD_URB) Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint = ((PUSBD_PIPE)((PHCD_URB)Urb)->HcdUrbCommonTransfer.UsbdPipeHandle)->HcdEndpoint; *IrpIsPending = TRUE; } USBD_KdPrint(3, ("' exit USBD_SCT_GetConfiguration 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_TakeFrameLengthControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ 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 = STATUS_SUCCESS; PUSBD_DEVICE_DATA deviceData; PUSBD_EXTENSION deviceExtension; PAGED_CODE(); USBD_KdPrint(3, ("' enter USBD_TakeFrameLengthControl\n")); deviceExtension = GET_DEVICE_EXTENSION(DeviceObject); deviceData = Urb->UrbHeader.UsbdDeviceHandle; *IrpIsPending = FALSE; if (deviceExtension->FrameLengthControlOwner != NULL) { Urb->UrbHeader.Status = SET_USBD_ERROR(USBD_STATUS_FRAME_CONTROL_OWNED); } else { Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; deviceExtension->FrameLengthControlOwner = deviceData; } USBD_KdPrint(3, ("' exit USBD_TakeFrameLengthControl 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_ReleaseFrameLengthControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ 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 = STATUS_SUCCESS; PUSBD_DEVICE_DATA deviceData; PUSBD_EXTENSION deviceExtension; USBD_KdPrint(3, ("' enter USBD_ReleaseFrameLengthControl\n")); deviceExtension = GET_DEVICE_EXTENSION(DeviceObject); deviceData = Urb->UrbHeader.UsbdDeviceHandle; *IrpIsPending = FALSE; if (deviceExtension->FrameLengthControlOwner == NULL || deviceExtension->FrameLengthControlOwner != deviceData) { Urb->UrbHeader.Status = SET_USBD_ERROR(USBD_STATUS_FRAME_CONTROL_NOT_OWNED); } else { Urb->UrbHeader.Status = STATUS_SUCCESS; deviceExtension->FrameLengthControlOwner = NULL; } USBD_KdPrint(3, ("' exit USBD_ReleaseFrameLengthControl 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_GetFrameLength( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ 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 = STATUS_SUCCESS; PUSBD_DEVICE_DATA deviceData; PUSBD_EXTENSION deviceExtension; PAGED_CODE(); USBD_KdPrint(3, ("' enter USBD_GetFrameLength\n")); deviceExtension = GET_DEVICE_EXTENSION(DeviceObject); deviceData = Urb->UrbHeader.UsbdDeviceHandle; if (NT_SUCCESS(ntStatus)) { // pass on to HC *IrpIsPending = TRUE; } USBD_KdPrint(3, ("' exit USBD_GetFrameLength 0x%x\n", ntStatus)); return ntStatus; } NTSTATUS USBD_SetFrameLength( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PURB Urb, OUT PBOOLEAN IrpIsPending ) /*++ 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 = STATUS_SUCCESS; PUSBD_DEVICE_DATA deviceData; PUSBD_EXTENSION deviceExtension; PAGED_CODE(); USBD_KdPrint(3, ("' enter USBD_SetFrameLength\n")); deviceExtension = GET_DEVICE_EXTENSION(DeviceObject); deviceData = Urb->UrbHeader.UsbdDeviceHandle; if (deviceExtension->FrameLengthControlOwner != deviceData) { Urb->UrbHeader.Status = SET_USBD_ERROR(USBD_STATUS_FRAME_CONTROL_NOT_OWNED); ntStatus = STATUS_INVALID_PARAMETER; } if (Urb->UrbSetFrameLength.FrameLengthDelta < -1 || Urb->UrbSetFrameLength.FrameLengthDelta > 1) { SET_USBD_ERROR(USBD_STATUS_INVALID_PARAMETER); ntStatus = STATUS_INVALID_PARAMETER; } if (NT_SUCCESS(ntStatus)) { // pass on to HC *IrpIsPending = TRUE; } USBD_KdPrint(3, ("' exit USBD_SetFrameLength 0x%x\n", ntStatus)); return ntStatus; } #endif // USBD_DRIVER