#include "usbccgp.h"
+#include <ntddk.h>
+
+#define NDEBUG
+#include <debug.h>
+
NTSTATUS
USBCCGP_PdoHandleQueryDeviceText(
IN PDEVICE_OBJECT DeviceObject,
//
// FIXME use GenericCompositeUSBDeviceString
//
- UNIMPLEMENTED
+ UNIMPLEMENTED;
Buffer = AllocateItem(PagedPool, (wcslen(GenericString) + 1) * sizeof(WCHAR));
if (!Buffer)
{
PDEVICE_RELATIONS DeviceRelations;
PIO_STACK_LOCATION IoStack;
- DPRINT1("USBCCGP_PdoHandleDeviceRelations\n");
+ DPRINT("USBCCGP_PdoHandleDeviceRelations\n");
//
// get current irp stack location
// count length of string
//
String = DeviceId;
- while(*String)
+ while (*String)
{
StringLength = wcslen(String) + 1;
Length += StringLength;
//
*OutString = String;
- while(*DeviceId)
+ while (*DeviceId)
{
- StringLength = swprintf(String, L"%s&MI_%02x", DeviceId) + 1;
+ StringLength = swprintf(String, L"%s&MI_%02x", DeviceId, InterfaceNumber) + 1;
Length = wcslen(DeviceId) + 1;
- DPRINT1("String %p\n", String);
+ DPRINT("String %p\n", String);
//
// next string
//
ASSERT(Irp->IoStatus.Information);
swprintf(Buffer, L"%s&MI_%02x", (LPWSTR)Irp->IoStatus.Information, PDODeviceExtension->FunctionDescriptor->FunctionNumber);
- DPRINT1("BusQueryDeviceID %S\n", Buffer);
+ DPRINT("BusQueryDeviceID %S\n", Buffer);
ExFreePool((PVOID)Irp->IoStatus.Information);
- Irp->IoStatus .Information = (ULONG_PTR)Buffer;
+ Irp->IoStatus.Information = (ULONG_PTR)Buffer;
}
else
{
//
DeviceString = &PDODeviceExtension->FunctionDescriptor->CompatibleId;
}
+ else
+ {
+ //
+ // unsupported query
+ //
+ return Irp->IoStatus.Status;
+ }
//
// sanity check
// copy buffer
//
RtlCopyMemory(Buffer, DeviceString->Buffer, DeviceString->Length);
+ Buffer[DeviceString->Length / sizeof(WCHAR)] = UNICODE_NULL;
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
return STATUS_SUCCESS;
PIO_STACK_LOCATION IoStack;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
NTSTATUS Status;
- ULONG Index;
+ ULONG Index, bFound;
//
// get current stack location
switch(IoStack->MinorFunction)
{
- case IRP_MN_QUERY_DEVICE_RELATIONS:
- {
- //
- // handle device relations
- //
- Status = USBCCGP_PdoHandleDeviceRelations(DeviceObject, Irp);
- break;
- }
- case IRP_MN_QUERY_DEVICE_TEXT:
- {
- //
- // handle query device text
- //
- Status = USBCCGP_PdoHandleQueryDeviceText(DeviceObject, Irp);
- break;
- }
- case IRP_MN_QUERY_ID:
- {
- //
- // handle request
- //
- Status = USBCCGP_PdoHandleQueryId(DeviceObject, Irp);
- break;
- }
- case IRP_MN_REMOVE_DEVICE:
- {
- //
- // remove us from the fdo's pdo list
- //
- for(Index = 0; Index < PDODeviceExtension->FDODeviceExtension->FunctionDescriptorCount; Index++)
- {
- if (PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] == DeviceObject)
- {
- //
- // remove us
- //
- PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] = NULL;
- break;
- }
- }
-
- //
- // Complete the IRP
- //
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- //
- // Delete the device object
- //
- IoDeleteDevice(DeviceObject);
- return STATUS_SUCCESS;
- }
- case IRP_MN_QUERY_CAPABILITIES:
- {
- //
- // copy device capabilities
- //
- RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &PDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
-
- /* Complete the IRP */
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
+ case IRP_MN_QUERY_DEVICE_RELATIONS:
+ {
+ //
+ // handle device relations
+ //
+ Status = USBCCGP_PdoHandleDeviceRelations(DeviceObject, Irp);
+ break;
+ }
+ case IRP_MN_QUERY_DEVICE_TEXT:
+ {
+ //
+ // handle query device text
+ //
+ Status = USBCCGP_PdoHandleQueryDeviceText(DeviceObject, Irp);
+ break;
+ }
+ case IRP_MN_QUERY_ID:
+ {
+ //
+ // handle request
+ //
+ Status = USBCCGP_PdoHandleQueryId(DeviceObject, Irp);
+ break;
+ }
+ case IRP_MN_REMOVE_DEVICE:
+ {
+ //
+ // remove us from the fdo's pdo list
+ //
+ bFound = FALSE;
+ for(Index = 0; Index < PDODeviceExtension->FDODeviceExtension->FunctionDescriptorCount; Index++)
+ {
+ if (PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] == DeviceObject)
+ {
+ //
+ // remove us
+ //
+ PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] = NULL;
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ //
+ // Complete the IRP
+ //
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ if (bFound)
+ {
+ //
+ // Delete the device object
+ //
+ IoDeleteDevice(DeviceObject);
+ }
+ return STATUS_SUCCESS;
+ }
+ case IRP_MN_QUERY_CAPABILITIES:
+ {
+ //
+ // copy device capabilities
+ //
+ RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &PDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
+
+ /* Complete the IRP */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+ }
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
{
Status = STATUS_SUCCESS;
break;
}
- case IRP_MN_START_DEVICE:
- {
- //
- // no-op for PDO
- //
- DPRINT1("[USBCCGP] PDO IRP_MN_START\n");
- Status = STATUS_SUCCESS;
- break;
- }
- default:
+ case IRP_MN_START_DEVICE:
+ {
+ //
+ // no-op for PDO
+ //
+ DPRINT("[USBCCGP] PDO IRP_MN_START\n");
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ case IRP_MN_QUERY_INTERFACE:
+ {
+ //
+ // forward to lower device object
+ //
+ IoSkipCurrentIrpStackLocation(Irp);
+ return IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp);
+ }
+ default:
{
//
// do nothing
NTSTATUS
USBCCGP_BuildConfigurationDescriptor(
- PDEVICE_OBJECT DeviceObject,
+ PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
ULONG TotalSize, Index;
+ ULONG Size;
PURB Urb;
PVOID Buffer;
PUCHAR BufferPtr;
+ UCHAR InterfaceNumber;
//
// get current stack location
//
IoStack = IoGetCurrentIrpStackLocation(Irp);
- DPRINT1("USBCCGP_BuildConfigurationDescriptor\n");
+ DPRINT("USBCCGP_BuildConfigurationDescriptor\n");
//
// get device extension
//
TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
- for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
+ for (Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
{
//
// get current interface descriptor
//
InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
+ InterfaceNumber = InterfaceDescriptor->bInterfaceNumber;
//
// add to size and move to next descriptor
{
if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
{
+ if (InterfaceNumber != InterfaceDescriptor->bInterfaceNumber)
+ {
+ //
+ // reached next descriptor
+ //
+ break;
+ }
+
//
- // reached next descriptor
+ // include alternate descriptor
//
- break;
}
//
// move to next descriptor
//
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
- }while(TRUE);
+ } while(TRUE);
}
//
RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength);
- for(Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
+ for (Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++)
{
//
// get current interface descriptor
//
InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index];
+ InterfaceNumber = InterfaceDescriptor->bInterfaceNumber;
//
// copy descriptor and move to next descriptor
{
if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
{
+ if (InterfaceNumber != InterfaceDescriptor->bInterfaceNumber)
+ {
+ //
+ // reached next descriptor
+ //
+ break;
+ }
+
//
- // reached next descriptor
+ // include alternate descriptor
//
- break;
+ DPRINT("InterfaceDescriptor %p Alternate %x InterfaceNumber %x\n", InterfaceDescriptor, InterfaceDescriptor->bAlternateSetting, InterfaceDescriptor->bInterfaceNumber);
}
//
// move to next descriptor
//
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
- }while(TRUE);
+ } while(TRUE);
}
//
// modify configuration descriptor
//
ConfigurationDescriptor = Buffer;
- ConfigurationDescriptor->wTotalLength = TotalSize;
+ ConfigurationDescriptor->wTotalLength = (USHORT)TotalSize;
ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces;
//
//
// copy descriptor
//
- RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength));
+ Size = min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength);
+ RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, Size);
//
// store final size
//
- Urb->UrbControlDescriptorRequest.TransferBufferLength = TotalSize;
+ Urb->UrbControlDescriptorRequest.TransferBufferLength = Size;
//
// free buffer
NTSTATUS
USBCCGP_PDOSelectConfiguration(
- PDEVICE_OBJECT DeviceObject,
+ PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
PPDO_DEVICE_EXTENSION PDODeviceExtension;
PURB Urb, NewUrb;
PUSBD_INTERFACE_INFORMATION InterfaceInformation;
- ULONG InterfaceInformationCount, Index, InterfaceIndex;
+ ULONG InterfaceIndex, Length;
PUSBD_INTERFACE_LIST_ENTRY Entry;
ULONG NeedSelect, FoundInterface;
NTSTATUS Status;
}
//
- // count interface information
+ // if there is no configuration descriptor, unconfigure the device
//
- InterfaceInformationCount = 0;
- InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
- do
+ if (Urb->UrbSelectConfiguration.ConfigurationDescriptor == NULL)
{
- InterfaceInformationCount++;
- InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
- }while((ULONG_PTR)InterfaceInformation < (ULONG_PTR)Urb + Urb->UrbSelectConfiguration.Hdr.Length);
+ return STATUS_SUCCESS;
+ }
+
+ // sanity checks
+ //C_ASSERT(sizeof(struct _URB_HEADER) == 16);
+ //C_ASSERT(FIELD_OFFSET(struct _URB_SELECT_CONFIGURATION, Interface.Length) == 24);
+ //C_ASSERT(sizeof(USBD_INTERFACE_INFORMATION) == 36);
+ //C_ASSERT(sizeof(struct _URB_SELECT_CONFIGURATION) == 0x3C);
+
+ // available buffer length
+ Length = Urb->UrbSelectConfiguration.Hdr.Length - FIELD_OFFSET(struct _URB_SELECT_CONFIGURATION, Interface.Length);
//
// check all interfaces
//
InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
- Index = 0;
+
Entry = NULL;
- DPRINT1("Count %x\n", InterfaceInformationCount);
do
{
- DPRINT1("[USBCCGP] SelectConfiguration Function %x InterfaceNumber %x Alternative %x\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
-
+ DPRINT1("[USBCCGP] SelectConfiguration Function %x InterfaceNumber %x Alternative %x Length %lu InterfaceInformation->Length %lu\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, Length, InterfaceInformation->Length);
+ ASSERT(InterfaceInformation->Length);
//
// search for the interface in the local interface list
//
FoundInterface = FALSE;
- for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; InterfaceIndex++)
+ for (InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; InterfaceIndex++)
{
if (PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[InterfaceIndex]->bInterfaceNumber == InterfaceInformation->InterfaceNumber)
{
// invalid parameter
//
DPRINT1("InterfaceInformation InterfaceNumber %x Alternative %x NumberOfPipes %x not found\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes);
- ASSERT(FALSE);
return STATUS_INVALID_PARAMETER;
}
// now query the total interface list
//
Entry = NULL;
- for(InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->InterfaceListCount; InterfaceIndex++)
+ for (InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->InterfaceListCount; InterfaceIndex++)
{
if (PDODeviceExtension->InterfaceList[InterfaceIndex].Interface->InterfaceNumber == InterfaceInformation->InterfaceNumber)
{
NeedSelect = FALSE;
if (Entry->InterfaceDescriptor->bAlternateSetting == InterfaceInformation->AlternateSetting)
{
-
for(InterfaceIndex = 0; InterfaceIndex < InterfaceInformation->NumberOfPipes; InterfaceIndex++)
{
if (InterfaceInformation->Pipes[InterfaceIndex].MaximumTransferSize != Entry->Interface->Pipes[InterfaceIndex].MaximumTransferSize)
//
// interface is already selected
//
- RtlCopyMemory(InterfaceInformation, Entry->Interface, min(InterfaceInformation->Length, Entry->Interface->Length));
+ ASSERT(Length >= Entry->Interface->Length);
+ RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
+
+ //
+ // adjust remaining buffer size
+ //
+ ASSERT(Entry->Interface->Length);
+ Length -= Entry->Interface->Length;
+
+ //
+ // move to next output interface information
+ //
+ InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + Entry->Interface->Length);
}
else
{
//
// now prepare interface urb
//
- UsbBuildSelectInterfaceRequest(NewUrb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes), PDODeviceExtension->ConfigurationHandle, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
+ UsbBuildSelectInterfaceRequest(NewUrb, (USHORT)GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes), PDODeviceExtension->ConfigurationHandle, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting);
//
// now select the interface
Status = USBCCGP_SyncUrbRequest(PDODeviceExtension->NextDeviceObject, NewUrb);
DPRINT1("SelectInterface Status %x\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed
+ //
+ break;
+ }
+
//
- // did it succeeed
+ // update configuration info
//
- if (NT_SUCCESS(Status))
- {
- //
- // update configuration info
- //
- ASSERT(Entry->Interface->Length == NewUrb->UrbSelectInterface.Interface.Length);
- ASSERT(InterfaceInformation->Length == NewUrb->UrbSelectInterface.Interface.Length);
- RtlCopyMemory(Entry->Interface, &NewUrb->UrbSelectInterface.Interface, NewUrb->UrbSelectInterface.Interface.Length);
+ ASSERT(Entry->Interface->Length >= NewUrb->UrbSelectInterface.Interface.Length);
+ ASSERT(Length >= NewUrb->UrbSelectInterface.Interface.Length);
+ RtlCopyMemory(Entry->Interface, &NewUrb->UrbSelectInterface.Interface, NewUrb->UrbSelectInterface.Interface.Length);
- //
- // update provided interface information
- //
- RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
- }
+ //
+ // update provided interface information
+ //
+ ASSERT(Length >= Entry->Interface->Length);
+ RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length);
+
+ //
+ // decrement remaining buffer size
+ //
+ ASSERT(Entry->Interface->Length);
+ Length -= Entry->Interface->Length;
+
+ //
+ // adjust output buffer offset
+ //
+ InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + Entry->Interface->Length);
//
// free urb
FreeItem(NewUrb);
}
- //
- // move to next information
- //
- InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
- Index++;
- }while(Index < InterfaceInformationCount);
+ } while(Length);
//
// store configuration handle
NTSTATUS
PDO_HandleInternalDeviceControl(
- PDEVICE_OBJECT DeviceObject,
+ PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
}
else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
{
- if(Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
+ if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
{
//
// is the buffer big enough
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+ else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_STRING_DESCRIPTOR_TYPE)
+ {
+ PUSB_STRING_DESCRIPTOR StringDescriptor;
+
+ //
+ // get the requested string descriptor
+ //
+ ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
+ Status = USBCCGP_GetDescriptor(PDODeviceExtension->FDODeviceExtension->NextDeviceObject,
+ USB_STRING_DESCRIPTOR_TYPE,
+ Urb->UrbControlDescriptorRequest.TransferBufferLength,
+ Urb->UrbControlDescriptorRequest.Index,
+ Urb->UrbControlDescriptorRequest.LanguageId,
+ (PVOID*)&StringDescriptor);
+ if (NT_SUCCESS(Status))
+ {
+ if (StringDescriptor->bLength == 2)
+ {
+ FreeItem(StringDescriptor);
+ Status = STATUS_DEVICE_DATA_ERROR;
+ }
+ else
+ {
+ RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
+ StringDescriptor->bString,
+ StringDescriptor->bLength + sizeof(WCHAR));
+ FreeItem(StringDescriptor);
+ Status = STATUS_SUCCESS;
+ }
+ }
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
}
else
{
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);
NTSTATUS
PDO_Dispatch(
- PDEVICE_OBJECT DeviceObject,
+ PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
return PDO_HandlePnp(DeviceObject, Irp);
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
return PDO_HandleInternalDeviceControl(DeviceObject, Irp);
+ case IRP_MJ_POWER:
+ PoStartNextPowerIrp(Irp);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
default:
DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
- ASSERT(FALSE);
Status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
-
}