[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:
Johannes Anderwald 2012-01-27 20:58:58 +00:00
parent 43220d11a5
commit a960e537aa
5 changed files with 360 additions and 11 deletions

View file

@ -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(

View file

@ -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

View file

@ -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
//

View file

@ -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);

View file

@ -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