/* * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver * LICENSE: GPL - See COPYING in the top level directory * FILE: drivers/usb/usbstor/misc.c * PURPOSE: USB block storage device driver. * PROGRAMMERS: * James Tabor * Michael Martin (michael.martin@reactos.org) * Johannes Anderwald (johannes.anderwald@reactos.org) */ #include "usbstor.h" // // driver verifier // IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine; NTSTATUS NTAPI USBSTOR_SyncForwardIrpCompletionRoutine( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) { if (Irp->PendingReturned) { KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); } return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS NTAPI USBSTOR_SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { KEVENT Event; NTSTATUS Status; // // initialize event // KeInitializeEvent(&Event, NotificationEvent, FALSE); // // copy irp stack location // IoCopyCurrentIrpStackLocationToNext(Irp); // // set completion routine // IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE); // // call driver // Status = IoCallDriver(DeviceObject, Irp); // // check if pending // if (Status == STATUS_PENDING) { // // wait for the request to finish // KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); // // copy status code // Status = Irp->IoStatus.Status; } // // done // return Status; } NTSTATUS NTAPI USBSTOR_GetBusInterface( IN PDEVICE_OBJECT DeviceObject, OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface) { KEVENT Event; NTSTATUS Status; PIRP Irp; IO_STATUS_BLOCK IoStatus; PIO_STACK_LOCATION Stack; // // sanity checks // ASSERT(DeviceObject); ASSERT(BusInterface); // // initialize event // KeInitializeEvent(&Event, NotificationEvent, FALSE); // // create irp // Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, DeviceObject, NULL, 0, NULL, &Event, &IoStatus); // // was irp built // if (Irp == NULL) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; } // // initialize request // Stack=IoGetNextIrpStackLocation(Irp); Stack->MajorFunction = IRP_MJ_PNP; Stack->MinorFunction = IRP_MN_QUERY_INTERFACE; Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD); Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&USB_BUS_INTERFACE_USBDI_GUID; Stack->Parameters.QueryInterface.Version = 2; Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface; Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL; Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; // // call driver // Status= IoCallDriver(DeviceObject, Irp); // // did operation complete // if (Status == STATUS_PENDING) { // // wait for completion // KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); // // collect status // Status=IoStatus.Status; } return Status; } NTSTATUS USBSTOR_SyncUrbRequest( IN PDEVICE_OBJECT DeviceObject, OUT PURB UrbRequest) { PIRP Irp; PIO_STACK_LOCATION IoStack; KEVENT Event; NTSTATUS Status; // // allocate irp // Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (!Irp) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; } // // initialize event // KeInitializeEvent(&Event, NotificationEvent, FALSE); // // get next stack location // IoStack = IoGetNextIrpStackLocation(Irp); // // initialize stack location // IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; IoStack->Parameters.Others.Argument1 = (PVOID)UrbRequest; IoStack->Parameters.DeviceIoControl.InputBufferLength = UrbRequest->UrbHeader.Length; Irp->IoStatus.Status = STATUS_SUCCESS; // // setup completion routine // IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE); // // call driver // Status = IoCallDriver(DeviceObject, Irp); // // check if request is pending // if (Status == STATUS_PENDING) { // // wait for completion // KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); // // update status // Status = Irp->IoStatus.Status; } // // free irp // IoFreeIrp(Irp); // // done // return Status; } PVOID AllocateItem( IN POOL_TYPE PoolType, IN ULONG ItemSize) { // // allocate item // PVOID Item = ExAllocatePoolWithTag(PoolType, ItemSize, USB_STOR_TAG); if (Item) { // // zero item // RtlZeroMemory(Item, ItemSize); } // // return element // return Item; } VOID FreeItem( IN PVOID Item) { // // free item // ExFreePoolWithTag(Item, USB_STOR_TAG); } NTSTATUS USBSTOR_GetMaxLUN( IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension) { PURB Urb; PUCHAR Buffer; NTSTATUS Status; // // first allocate urb // Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST)); if (!Urb) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; } // // allocate 1-byte buffer // Buffer = (PUCHAR)AllocateItem(NonPagedPool, sizeof(UCHAR)); if (!Buffer) { // // no memory // FreeItem(Buffer); return STATUS_INSUFFICIENT_RESOURCES; } // // initialize vendor request // Urb->UrbControlVendorClassRequest.Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); Urb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_CLASS_INTERFACE; Urb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN; Urb->UrbControlVendorClassRequest.TransferBufferLength = 1; Urb->UrbControlVendorClassRequest.TransferBuffer = Buffer; Urb->UrbControlVendorClassRequest.Request = USB_BULK_GET_MAX_LUN; // // submit request // Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb); // // free urb // FreeItem(Urb); DPRINT1("MaxLUN: %x\n", *Buffer); if (*Buffer > 0xF) { // // invalid response documented in usb mass storage specification // Status = STATUS_DEVICE_DATA_ERROR; } else { // // store maxlun // DeviceExtension->MaxLUN = *Buffer; } // // free buffer // FreeItem(Buffer); // // done // return Status; }