diff --git a/drivers/usb/usbehci_new/hub_controller.cpp b/drivers/usb/usbehci_new/hub_controller.cpp index cb6530d9030..3a57dd76f0f 100644 --- a/drivers/usb/usbehci_new/hub_controller.cpp +++ b/drivers/usb/usbehci_new/hub_controller.cpp @@ -1080,6 +1080,8 @@ CHubController::HandleGetDescriptor( NTSTATUS Status = STATUS_NOT_IMPLEMENTED; PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; PUCHAR Buffer; + PUSBDEVICE UsbDevice; + ULONG Length; // // check descriptor type @@ -1092,6 +1094,7 @@ CHubController::HandleGetDescriptor( // sanity check // PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR)); + PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); if (Urb->UrbHeader.UsbdDeviceHandle == NULL) { @@ -1100,7 +1103,24 @@ CHubController::HandleGetDescriptor( // RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); Status = STATUS_SUCCESS; - break; + } + else + { + // + // check if this is a valid usb device handle + // + PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))); + + // + // get device + // + UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); + + // + // retrieve device descriptor from device + // + UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer); + Status = STATUS_SUCCESS; } break; } @@ -1112,52 +1132,95 @@ CHubController::HandleGetDescriptor( PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR)); - // - // FIXME: support devices - // - PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL); - - // - // copy configuration descriptor template - // - C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR) == sizeof(USB_CONFIGURATION_DESCRIPTOR)); - RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR)); - - // - // get configuration descriptor, very retarded! - // - ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer; - - // - // check if buffer can hold interface and endpoint descriptor - // - if (ConfigurationDescriptor->wTotalLength > Urb->UrbControlDescriptorRequest.TransferBufferLength) + if (Urb->UrbHeader.UsbdDeviceHandle == NULL) { // - // buffer too small + // request is for the root bus controller + // + C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR) == sizeof(USB_CONFIGURATION_DESCRIPTOR)); + RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR)); + + // + // get configuration descriptor, very retarded! + // + ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer; + + // + // check if buffer can hold interface and endpoint descriptor + // + if (ConfigurationDescriptor->wTotalLength > Urb->UrbControlDescriptorRequest.TransferBufferLength) + { + // + // buffer too small + // + Status = STATUS_SUCCESS; + break; + } + + // + // copy interface descriptor template + // + Buffer = (PUCHAR)(ConfigurationDescriptor + 1); + C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR) == sizeof(USB_INTERFACE_DESCRIPTOR)); + RtlCopyMemory(Buffer, ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR)); + + // + // copy end point descriptor template + // + Buffer += sizeof(USB_INTERFACE_DESCRIPTOR); + C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR) == sizeof(USB_ENDPOINT_DESCRIPTOR)); + RtlCopyMemory(Buffer, ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR)); + + // + // done // Status = STATUS_SUCCESS; - break; + } + else + { + DPRINT1("Length %u\n", Urb->UrbControlDescriptorRequest.TransferBufferLength); - // - // copy interface descriptor template - // - Buffer = (PUCHAR)(ConfigurationDescriptor + 1); - C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR) == sizeof(USB_INTERFACE_DESCRIPTOR)); - RtlCopyMemory(Buffer, ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR)); + // + // check if this is a valid usb device handle + // + PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))); - // - // copy end point descriptor template - // - Buffer += sizeof(USB_INTERFACE_DESCRIPTOR); - C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR) == sizeof(USB_ENDPOINT_DESCRIPTOR)); - RtlCopyMemory(Buffer, ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR)); + // + // get device + // + UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - // - // done - // - Status = STATUS_SUCCESS; + if (UsbDevice->GetConfigurationDescriptorsLength() > Urb->UrbControlDescriptorRequest.TransferBufferLength) + { + // + // buffer too small + // + Urb->UrbControlDescriptorRequest.TransferBufferLength = UsbDevice->GetConfigurationDescriptorsLength(); + + // + // bail out + // + Status = STATUS_SUCCESS; + break; + } + + // + // perform work in IUSBDevice + // + UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength, &Length); + + // + // sanity check + // + PC_ASSERT(UsbDevice->GetConfigurationDescriptorsLength() == Length); + + // + // store result size + // + Urb->UrbControlDescriptorRequest.TransferBufferLength = Length; + Status = STATUS_SUCCESS; + } break; } default: diff --git a/drivers/usb/usbehci_new/interfaces.h b/drivers/usb/usbehci_new/interfaces.h index 9075b9acd40..3f8171f9a49 100644 --- a/drivers/usb/usbehci_new/interfaces.h +++ b/drivers/usb/usbehci_new/interfaces.h @@ -795,6 +795,13 @@ DECLARE_INTERFACE_(IUSBDevice, IUnknown) virtual VOID GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer, IN ULONG BufferLength, OUT PULONG OutBufferLength) = 0; + +//---------------------------------------------------------------------------------------- +// +// Description: returns length of configuration descriptors +// + virtual ULONG GetConfigurationDescriptorsLength() = 0; + }; typedef IUSBDevice *PUSBDEVICE; diff --git a/drivers/usb/usbehci_new/usb_device.cpp b/drivers/usb/usbehci_new/usb_device.cpp index 2e0d703ab44..f3981118869 100644 --- a/drivers/usb/usbehci_new/usb_device.cpp +++ b/drivers/usb/usbehci_new/usb_device.cpp @@ -66,7 +66,7 @@ public: virtual UCHAR GetConfigurationValue(); virtual NTSTATUS SubmitIrp(PIRP Irp); virtual VOID GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer, IN ULONG BufferLength, OUT PULONG OutBufferLength); - + virtual ULONG GetConfigurationDescriptorsLength(); // local function virtual NTSTATUS CommitIrp(PIRP Irp); @@ -74,6 +74,7 @@ public: virtual NTSTATUS CreateConfigurationDescriptor(ULONG ConfigurationIndex); virtual NTSTATUS CreateDeviceDescriptor(); virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor); + virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor); // constructor / destructor CUSBDevice(IUnknown *OuterUnknown){} @@ -752,6 +753,11 @@ CUSBDevice::CreateConfigurationDescriptor( // ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Buffer; + // + // informal debug print + // + DumpConfigurationDescriptor(ConfigurationDescriptor); + // // sanity check // @@ -867,6 +873,9 @@ CUSBDevice::GetConfigurationDescriptors( IN ULONG BufferLength, OUT PULONG OutBufferLength) { + PVOID Buffer; + ULONG InterfaceIndex, EndpointIndex; + // // sanity check // @@ -874,6 +883,11 @@ CUSBDevice::GetConfigurationDescriptors( PC_ASSERT(ConfigDescriptorBuffer); PC_ASSERT(OutBufferLength); + // + // reset copied length + // + *OutBufferLength = 0; + // // FIXME: support multiple configurations // @@ -885,12 +899,87 @@ CUSBDevice::GetConfigurationDescriptors( RtlCopyMemory(ConfigDescriptorBuffer, &m_ConfigurationDescriptors[0].ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR)); // - // store length + // subtract length // - *OutBufferLength = sizeof(USB_CONFIGURATION_DESCRIPTOR); + BufferLength -= sizeof(USB_CONFIGURATION_DESCRIPTOR); + *OutBufferLength += sizeof(USB_CONFIGURATION_DESCRIPTOR); + + // + // increment offset + // + Buffer = (PVOID)(ConfigDescriptorBuffer + 1); + + for(InterfaceIndex = 0; InterfaceIndex < m_ConfigurationDescriptors[0].ConfigurationDescriptor.bNumInterfaces; InterfaceIndex++) + { + if (BufferLength < sizeof(USB_INTERFACE_DESCRIPTOR)) + { + // + // no more room in buffer + // + return; + } + + // + // copy interface descriptor + // + RtlCopyMemory(Buffer, &m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor, sizeof(USB_INTERFACE_DESCRIPTOR)); + + // + // increment offset + // + Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(USB_INTERFACE_DESCRIPTOR)); + BufferLength -= sizeof(USB_INTERFACE_DESCRIPTOR); + *OutBufferLength += sizeof(USB_INTERFACE_DESCRIPTOR); + + // + // does the interface have endpoints + // + if (m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints) + { + // + // is enough space available + // + if (BufferLength < sizeof(USB_ENDPOINT_DESCRIPTOR) * m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints) + { + // + // no buffer + // + return; + } + + // + // copy end points + // + for(EndpointIndex = 0; EndpointIndex < m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints; EndpointIndex++) + { + // + // copy endpoint + // + RtlCopyMemory(Buffer, &m_ConfigurationDescriptors[0].Interfaces[InterfaceIndex].EndPoints[EndpointIndex].EndPointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR)); + + // + // increment buffer offset + // + Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof(USB_ENDPOINT_DESCRIPTOR)); + BufferLength -= sizeof(USB_ENDPOINT_DESCRIPTOR); + *OutBufferLength += sizeof(USB_ENDPOINT_DESCRIPTOR); + } + } + } } +//---------------------------------------------------------------------------------------- +ULONG +CUSBDevice::GetConfigurationDescriptorsLength() +{ + // + // FIXME: support multiple configurations + // + PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1); + return m_ConfigurationDescriptors[0].ConfigurationDescriptor.wTotalLength; +} +//---------------------------------------------------------------------------------------- VOID CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) { @@ -911,6 +1000,20 @@ CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations); } +//---------------------------------------------------------------------------------------- +VOID +CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) +{ + DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor); + DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength); + DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType); + DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength); + DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces); + DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue); + DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration); + DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes); + DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower); +} //---------------------------------------------------------------------------------------- NTSTATUS CreateUSBDevice(