mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[USBCCGP]
- Implement counting of all interface descriptors - Store device descriptor and configuration descriptor in pdo device extension - Store all interface descriptors for an composite audio device - Implement parsing and constructing a special configuration descriptor for each individual device function - Implement URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE for device descriptor and configuration descriptor - USBGCCGP now receives select configuration request - Tested in XP + Ros USB Stack + USB Audio Device svn path=/branches/usb-bringup-trunk/; revision=55261
This commit is contained in:
parent
43220d11a5
commit
a960e537aa
5 changed files with 360 additions and 11 deletions
|
@ -201,6 +201,66 @@ CountInterfaceDescriptors(
|
|||
return Count;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
AllocateInterfaceDescriptorsArray(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||
OUT PUSB_INTERFACE_DESCRIPTOR **OutArray)
|
||||
{
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
PVOID CurrentPosition;
|
||||
ULONG Count = 0;
|
||||
PUSB_INTERFACE_DESCRIPTOR *Array;
|
||||
|
||||
Count = CountInterfaceDescriptors(ConfigurationDescriptor);
|
||||
ASSERT(Count);
|
||||
|
||||
//
|
||||
// allocate array
|
||||
//
|
||||
Array = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * Count);
|
||||
if (!Array)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
//
|
||||
// enumerate all interfaces
|
||||
//
|
||||
CurrentPosition = ConfigurationDescriptor;
|
||||
Count = 0;
|
||||
do
|
||||
{
|
||||
//
|
||||
// find next descriptor
|
||||
//
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1);
|
||||
if (!InterfaceDescriptor)
|
||||
break;
|
||||
|
||||
//
|
||||
// store descriptor
|
||||
//
|
||||
Array[Count] = InterfaceDescriptor;
|
||||
Count++;
|
||||
|
||||
//
|
||||
// advance to next descriptor
|
||||
//
|
||||
CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
|
||||
}while(TRUE);
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
*OutArray = Array;
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_ScanConfigurationDescriptor(
|
||||
|
|
|
@ -279,7 +279,9 @@ FDO_CreateChildPdo(
|
|||
PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
|
||||
PDODeviceExtension->NextDeviceObject = DeviceObject;
|
||||
PDODeviceExtension->FunctionIndex = Index;
|
||||
PDODeviceExtension->ConfigurationDescriptor = FDODeviceExtension->ConfigurationDescriptor;
|
||||
RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||
RtlCopyMemory(&PDODeviceExtension->DeviceDescriptor, &FDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||
|
||||
//
|
||||
// patch the stack size
|
||||
|
|
|
@ -787,23 +787,18 @@ USBCCGP_EnumWithAudioLegacy(
|
|||
FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0;
|
||||
|
||||
//
|
||||
// FIXME: how many interfaces should be stored?
|
||||
// store interfaces
|
||||
//
|
||||
|
||||
FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1);
|
||||
if (!FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList)
|
||||
Status = AllocateInterfaceDescriptorsArray(FDODeviceExtension->ConfigurationDescriptor, &FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
// failed to allocate descriptor array
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
DPRINT1("[USBCCGP] Failed to allocate descriptor array %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// store interface descriptor
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList[0] = InterfaceDescriptor;
|
||||
|
||||
//
|
||||
// now init the device ids
|
||||
//
|
||||
|
@ -817,6 +812,11 @@ USBCCGP_EnumWithAudioLegacy(
|
|||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// number of interfaces
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor[0].NumberOfInterfaces = CountInterfaceDescriptors(FDODeviceExtension->ConfigurationDescriptor);
|
||||
|
||||
//
|
||||
// store function count
|
||||
//
|
||||
|
|
|
@ -323,6 +323,280 @@ PDO_HandlePnp(
|
|||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_BuildConfigurationDescriptor(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
ULONG TotalSize, Index;
|
||||
PURB Urb;
|
||||
PVOID Buffer;
|
||||
PUCHAR BufferPtr;
|
||||
|
||||
//
|
||||
// get current stack location
|
||||
//
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
DPRINT1("USBCCGP_BuildConfigurationDescriptor\n");
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
//
|
||||
// get configuration descriptor
|
||||
//
|
||||
ConfigurationDescriptor = PDODeviceExtension->ConfigurationDescriptor;
|
||||
|
||||
//
|
||||
// calculate size of configuration descriptor
|
||||
//
|
||||
TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
|
||||
|
||||
for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
|
||||
{
|
||||
//
|
||||
// get current interface descriptor
|
||||
//
|
||||
InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
|
||||
|
||||
//
|
||||
// add to size and move to next descriptor
|
||||
//
|
||||
TotalSize += InterfaceDescriptor->bLength;
|
||||
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
|
||||
do
|
||||
{
|
||||
if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
|
||||
{
|
||||
//
|
||||
// reached end of configuration descriptor
|
||||
//
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// association descriptors are removed
|
||||
//
|
||||
if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
|
||||
{
|
||||
if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
|
||||
{
|
||||
//
|
||||
// reached next descriptor
|
||||
//
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// append size
|
||||
//
|
||||
TotalSize += InterfaceDescriptor->bLength;
|
||||
}
|
||||
|
||||
//
|
||||
// move to next descriptor
|
||||
//
|
||||
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
}while(TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// now allocate temporary buffer for the configuration descriptor
|
||||
//
|
||||
Buffer = AllocateItem(NonPagedPool, TotalSize);
|
||||
if (!Buffer)
|
||||
{
|
||||
//
|
||||
// failed to allocate buffer
|
||||
//
|
||||
DPRINT1("[USBCCGP] Failed to allocate %lu Bytes\n", TotalSize);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// first copy the configuration descriptor
|
||||
//
|
||||
RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
|
||||
BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength);
|
||||
|
||||
for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
|
||||
{
|
||||
//
|
||||
// get current interface descriptor
|
||||
//
|
||||
InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
|
||||
|
||||
//
|
||||
// copy descriptor and move to next descriptor
|
||||
//
|
||||
RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
|
||||
BufferPtr += InterfaceDescriptor->bLength;
|
||||
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
|
||||
do
|
||||
{
|
||||
if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
|
||||
{
|
||||
//
|
||||
// reached end of configuration descriptor
|
||||
//
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// association descriptors are removed
|
||||
//
|
||||
if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
|
||||
{
|
||||
if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
|
||||
{
|
||||
//
|
||||
// reached next descriptor
|
||||
//
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// copy descriptor
|
||||
//
|
||||
RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength);
|
||||
BufferPtr += InterfaceDescriptor->bLength;
|
||||
}
|
||||
|
||||
//
|
||||
// move to next descriptor
|
||||
//
|
||||
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
}while(TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// modify configuration descriptor
|
||||
//
|
||||
ConfigurationDescriptor = Buffer;
|
||||
ConfigurationDescriptor->wTotalLength = TotalSize;
|
||||
ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces;
|
||||
|
||||
//
|
||||
// get urb
|
||||
//
|
||||
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||
ASSERT(Urb);
|
||||
|
||||
//
|
||||
// copy descriptor
|
||||
//
|
||||
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength));
|
||||
|
||||
//
|
||||
// store final size
|
||||
//
|
||||
Urb->UrbControlDescriptorRequest.TransferBufferLength = TotalSize;
|
||||
|
||||
//
|
||||
// free buffer
|
||||
//
|
||||
FreeItem(Buffer);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
PDO_HandleInternalDeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||
NTSTATUS Status;
|
||||
PURB Urb;
|
||||
|
||||
//
|
||||
// get current stack location
|
||||
//
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
|
||||
{
|
||||
//
|
||||
// get urb
|
||||
//
|
||||
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||
ASSERT(Urb);
|
||||
|
||||
if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
|
||||
{
|
||||
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function);
|
||||
|
||||
if(Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
|
||||
{
|
||||
//
|
||||
// is the buffer big enough
|
||||
//
|
||||
if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR))
|
||||
{
|
||||
//
|
||||
// invalid buffer size
|
||||
//
|
||||
DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
|
||||
Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
|
||||
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INVALID_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
//
|
||||
// copy device descriptor
|
||||
//
|
||||
ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE)
|
||||
{
|
||||
//
|
||||
// build configuration descriptor
|
||||
//
|
||||
Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||
DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength);
|
||||
DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
|
||||
DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer);
|
||||
|
||||
ASSERT(FALSE);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
PDO_Dispatch(
|
||||
|
@ -339,6 +613,8 @@ PDO_Dispatch(
|
|||
{
|
||||
case IRP_MJ_PNP:
|
||||
return PDO_HandlePnp(DeviceObject, Irp);
|
||||
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
||||
return PDO_HandleInternalDeviceControl(DeviceObject, Irp);
|
||||
default:
|
||||
DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
|
||||
ASSERT(FALSE);
|
||||
|
|
|
@ -50,6 +50,8 @@ typedef struct
|
|||
PDEVICE_OBJECT NextDeviceObject; // next device object
|
||||
DEVICE_CAPABILITIES Capabilities; // device capabilities
|
||||
ULONG FunctionIndex; // function index
|
||||
USB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor
|
||||
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor
|
||||
}PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
||||
|
||||
/* descriptor.c */
|
||||
|
@ -73,6 +75,15 @@ USBCCGP_GetDescriptor(
|
|||
IN LANGID LanguageId,
|
||||
OUT PVOID *OutDescriptor);
|
||||
|
||||
ULONG
|
||||
CountInterfaceDescriptors(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
|
||||
|
||||
NTSTATUS
|
||||
AllocateInterfaceDescriptorsArray(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||
OUT PUSB_INTERFACE_DESCRIPTOR **OutArray);
|
||||
|
||||
/* misc.c */
|
||||
|
||||
NTSTATUS
|
||||
|
|
Loading…
Reference in a new issue