diff --git a/drivers/usb/usbstor/disk.c b/drivers/usb/usbstor/disk.c index 16b40e2f632..b11fa28bc8b 100644 --- a/drivers/usb/usbstor/disk.c +++ b/drivers/usb/usbstor/disk.c @@ -143,6 +143,276 @@ USBSTOR_HandleInternalDeviceControl( return Status; } +ULONG +USBSTOR_GetFieldLength( + IN PUCHAR Name, + IN ULONG MaxLength) +{ + ULONG Index; + ULONG LastCharacterPosition = 0; + + // + // scan the field and return last positon which contains a valid character + // + for(Index = 0; Index < MaxLength; Index++) + { + if (Name[Index] != ' ') + { + // + // trim white spaces from field + // + LastCharacterPosition = Index; + } + } + + // + // convert from zero based index to length + // + return LastCharacterPosition + 1; +} + +NTSTATUS +USBSTOR_HandleQueryProperty( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PSTORAGE_PROPERTY_QUERY PropertyQuery; + PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader; + PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor; + ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength; + PPDO_DEVICE_EXTENSION PDODeviceExtension; + PUFI_INQUIRY_RESPONSE InquiryData; + PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor; + PUCHAR Buffer; + + DPRINT1("USBSTOR_HandleQueryProperty\n"); + + // + // get current stack location + // + IoStack = IoGetCurrentIrpStackLocation(Irp); + + // + // sanity check + // + ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY)); + ASSERT(Irp->AssociatedIrp.SystemBuffer); + + // + // get property query + // + PropertyQuery = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer; + + // + // check property type + // + if (PropertyQuery->PropertyId != StorageDeviceProperty && + PropertyQuery->PropertyId != StorageAdapterProperty) + { + // + // only device property / adapter property are supported + // + return STATUS_INVALID_PARAMETER_1; + } + + // + // check query type + // + if (PropertyQuery->QueryType == PropertyExistsQuery) + { + // + // device property / adapter property is supported + // + return STATUS_SUCCESS; + } + + if (PropertyQuery->QueryType != PropertyStandardQuery) + { + // + // only standard query and exists query are supported + // + return STATUS_INVALID_PARAMETER_2; + } + + // + // check if it is a device property + // + if (PropertyQuery->PropertyId == StorageDeviceProperty) + { + DPRINT1("USBSTOR_HandleQueryProperty StorageDeviceProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength); + + // + // get device extension + // + PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + ASSERT(PDODeviceExtension); + + // + // get inquiry data + // + InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData; + ASSERT(InquiryData); + + // + // compute extra parameters length + // + FieldLengthVendor = USBSTOR_GetFieldLength(InquiryData->Vendor, 8); + FieldLengthProduct = USBSTOR_GetFieldLength(InquiryData->Product, 16); + FieldLengthRevision = USBSTOR_GetFieldLength(InquiryData->Revision, 4); + + // + // FIXME handle serial number + // + + // + // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 3 extra null bytes - 1 + // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data + // + TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 2; + + // + // check if output buffer is long enough + // + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < TotalLength) + { + // + // buffer too small + // + DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer; + ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER)); + + // + // return required size + // + DescriptorHeader->Version = TotalLength; + DescriptorHeader->Size = TotalLength; + + Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER); + return STATUS_SUCCESS; + } + + // + // get device descriptor + // + DeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer; + + // + // initialize device descriptor + // + DeviceDescriptor->Version = TotalLength; + DeviceDescriptor->Size = TotalLength; + DeviceDescriptor->DeviceType = InquiryData->DeviceType; + DeviceDescriptor->DeviceTypeModifier = (InquiryData->RMB & 0x7F); + DeviceDescriptor->RemovableMedia = FALSE; //FIXME check if floppy + DeviceDescriptor->CommandQueueing = FALSE; + DeviceDescriptor->BusType = BusTypeUsb; + DeviceDescriptor->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR); + DeviceDescriptor->ProductIdOffset = DeviceDescriptor->VendorIdOffset + FieldLengthVendor + 1; + DeviceDescriptor->ProductRevisionOffset = DeviceDescriptor->ProductIdOffset + FieldLengthProduct + 1; + DeviceDescriptor->SerialNumberOffset = 0; //FIXME + DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + 3; + + // + // copy descriptors + // + Buffer = (PUCHAR)((ULONG_PTR)DeviceDescriptor + sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR)); + + // + // copy vendor + // + RtlCopyMemory(Buffer, InquiryData->Vendor, FieldLengthVendor); + Buffer[FieldLengthVendor] = '\0'; + Buffer += FieldLengthVendor + 1; + + // + // copy product + // + RtlCopyMemory(Buffer, InquiryData->Product, FieldLengthProduct); + Buffer[FieldLengthProduct] = '\0'; + Buffer += FieldLengthProduct + 1; + + // + // copy revision + // + RtlCopyMemory(Buffer, InquiryData->Revision, FieldLengthRevision); + Buffer[FieldLengthRevision] = '\0'; + Buffer += FieldLengthRevision + 1; + + // + // TODO: copy revision + // + + DPRINT("Vendor %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->VendorIdOffset)); + DPRINT("Product %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductIdOffset)); + DPRINT("Revision %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductRevisionOffset)); + + // + // done + // + Irp->IoStatus.Information = TotalLength; + return STATUS_SUCCESS; + } + else + { + // + // adapter property query request + // + DPRINT1("USBSTOR_HandleQueryProperty StorageAdapterProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength); + + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_ADAPTER_DESCRIPTOR)) + { + // + // buffer too small + // + DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer; + ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER)); + + // + // return required size + // + DescriptorHeader->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR); + DescriptorHeader->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR); + + Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER); + return STATUS_SUCCESS; + } + + // + // get adapter descriptor, information is returned in the same buffer + // + AdapterDescriptor = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer; + + // + // fill out descriptor + // + AdapterDescriptor->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR); + AdapterDescriptor->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR); + AdapterDescriptor->MaximumTransferLength = MAXULONG; //FIXME compute some sane value + AdapterDescriptor->MaximumPhysicalPages = 25; //FIXME compute some sane value + AdapterDescriptor->AlignmentMask = 0; + AdapterDescriptor->AdapterUsesPio = FALSE; + AdapterDescriptor->AdapterScansDown = FALSE; + AdapterDescriptor->CommandQueueing = FALSE; + AdapterDescriptor->AcceleratedTransfer = FALSE; + AdapterDescriptor->BusType = BusTypeUsb; + AdapterDescriptor->BusMajorVersion = 0x2; //FIXME verify + AdapterDescriptor->BusMinorVersion = 0x00; //FIXME + + // + // store returned length + // + Irp->IoStatus.Information = sizeof(STORAGE_ADAPTER_DESCRIPTOR); + + // + // done + // + return STATUS_SUCCESS; + } +} + + + NTSTATUS USBSTOR_HandleDeviceControl( IN PDEVICE_OBJECT DeviceObject, @@ -155,6 +425,14 @@ USBSTOR_HandleDeviceControl( // IoStack = IoGetCurrentIrpStackLocation(Irp); + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY) + { + // + // query property + // + return USBSTOR_HandleQueryProperty(DeviceObject, Irp); + } + DPRINT1("USBSTOR_HandleDeviceControl IoControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); DPRINT1("USBSTOR_HandleDeviceControl InputBufferLength %x\n", IoStack->Parameters.DeviceIoControl.InputBufferLength); DPRINT1("USBSTOR_HandleDeviceControl OutputBufferLength %x\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength); @@ -163,7 +441,6 @@ USBSTOR_HandleDeviceControl( DPRINT1("USBSTOR_HandleDeviceControl UserBuffer %x\n", Irp->UserBuffer); DPRINT1("USBSTOR_HandleDeviceControl MdlAddress %x\n", Irp->MdlAddress); - //IOCTL_STORAGE_QUERY_PROPERTY return STATUS_NOT_SUPPORTED; }