[USBCCGP]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 26 Jan 2012 19:11:44 +0000 (19:11 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 26 Jan 2012 19:11:44 +0000 (19:11 +0000)
- Implement querying device relations for FDO
- Implement creating device objects for each discovered function
- Invalidate device relations after the child pdo have been created
- Implement PDO device relations, most of query id, query device capabilities, start device
- USBCCGP should now initialize and create the child pdos
- Next is device control handling
- WIP, untested

svn path=/branches/usb-bringup-trunk/; revision=55219

drivers/usb/usbccgp/fdo.c
drivers/usb/usbccgp/pdo.c
drivers/usb/usbccgp/usbccgp.h

index 7026276..49a7deb 100644 (file)
@@ -127,9 +127,181 @@ FDO_DeviceRelations(
     PDEVICE_OBJECT DeviceObject, 
     PIRP Irp)
 {
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    ULONG DeviceCount = 0;
+    ULONG Index;
+    PDEVICE_RELATIONS DeviceRelations;
+    PIO_STACK_LOCATION IoStack;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+
+    //
+    // get device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+
+    //
+    // get current irp stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // check if relation type is BusRelations
+    //
+    if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
+    {
+        //
+        // FDO always only handles bus relations
+        //
+        return USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
+    }
+
+    //
+    // go through array and count device objects
+    //
+    for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
+    {
+        if (FDODeviceExtension->ChildPDO[Index])
+        {
+            //
+            // child pdo
+            //
+            DeviceCount++;
+        }
+    }
+
+    //
+    // allocate device relations
+    //
+    DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
+    if (!DeviceRelations)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // add device objects
+    //
+    for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
+    {
+        if (FDODeviceExtension->ChildPDO[Index])
+        {
+            //
+            // store child pdo
+            //
+            DeviceRelations->Objects[DeviceRelations->Count] = FDODeviceExtension->ChildPDO[Index];
+
+            //
+            // add reference
+            //
+            ObReferenceObject(FDODeviceExtension->ChildPDO[Index]);
+
+            //
+            // increment count
+            //
+            DeviceRelations->Count++;
+        }
+    }
+
+    //
+    // store result
+    //
+    Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+    //
+    // request completed successfully
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FDO_CreateChildPdo(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    NTSTATUS Status;
+    PDEVICE_OBJECT PDODeviceObject;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+    ULONG Index;
+
+    //
+    // get device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    ASSERT(FDODeviceExtension->Common.IsFDO);
+
+    //
+    // lets create array for the child PDO
+    //
+    FDODeviceExtension->ChildPDO = AllocateItem(NonPagedPool, sizeof(PDEVICE_OBJECT) * FDODeviceExtension->FunctionDescriptorCount);
+    if (!FDODeviceExtension->ChildPDO)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // create pdo for each function
+    //
+    for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
+    {
+        //
+        // create the PDO
+        //
+        Status = IoCreateDevice(FDODeviceExtension->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_USB, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &PDODeviceObject);
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // failed to create device object
+            //
+            DPRINT1("IoCreateDevice failed with %x\n", Status);
+            return Status;
+        }
+
+        //
+        // store in array
+        //
+        FDODeviceExtension->ChildPDO[Index] = PDODeviceObject;
+
+        //
+        // get device extension
+        //
+        PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+        RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
+
+        //
+        // init device extension
+        //
+        PDODeviceExtension->Common.IsFDO = FALSE;
+        PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
+        PDODeviceExtension->NextDeviceObject = DeviceObject;
+        PDODeviceExtension->FunctionIndex = Index;
+        RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
+
+        //
+        // patch the stack size
+        //
+        PDODeviceObject->StackSize = DeviceObject->StackSize + 1;
+
+        //
+        // set device flags
+        //
+        PDODeviceObject->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
+
+        //
+        // device is initialized
+        //
+        PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+    }
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -206,13 +378,30 @@ FDO_StartDevice(
     ASSERT(FDODeviceExtension->FunctionDescriptor);
 
     //
-    // FIXME:create PDO for each function
+    // now create the pdo
     //
-    ASSERT(FALSE);
+    Status = FDO_CreateChildPdo(DeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed
+        //
+        DPRINT1("FDO_CreateChildPdo failed with %x\n", Status);
+        return Status;
+    }
+
+    //
+    // inform pnp manager of new device objects
+    //
+    IoInvalidateDeviceRelations(FDODeviceExtension->PhysicalDeviceObject, BusRelations);
+
+    //
+    // done
+    //
+    DPRINT1("[USBCCGP] FDO initialized successfully\n");
     return Status;
 }
 
-
 NTSTATUS
 FDO_HandlePnp(
     PDEVICE_OBJECT DeviceObject,
@@ -234,11 +423,17 @@ FDO_HandlePnp(
     {
         case IRP_MN_START_DEVICE:
         {
+            //
+            // start the device
+            //
             Status = FDO_StartDevice(DeviceObject, Irp);
             break;
         }
         case IRP_MN_QUERY_DEVICE_RELATIONS:
         {
+            //
+            // handle device relations
+            //
             Status = FDO_DeviceRelations(DeviceObject, Irp);
             break;
         }
@@ -301,6 +496,7 @@ FDO_Dispatch(
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
             return Status;
     }
+
 }
 
 
index 192cfa5..f1d011a 100644 (file)
 
 #include "usbccgp.h"
 
+NTSTATUS
+USBCCGP_PdoHandleQueryDeviceText(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp)
+{
+    LPWSTR Buffer;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+
+    //
+    // get device extension
+    //
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // is there a device description
+    //
+    if (PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length)
+    {
+        //
+        // allocate buffer
+        //
+        Buffer = AllocateItem(NonPagedPool, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length + sizeof(WCHAR));
+        if (!Buffer)
+        {
+            //
+            // no memory
+            //
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        //
+        // copy buffer
+        //
+        Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+        RtlCopyMemory(Buffer, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Buffer, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length);
+        return STATUS_SUCCESS;
+    }
+
+    //
+    // FIXME use GenericCompositeUSBDeviceString
+    //
+    UNIMPLEMENTED
+    return Irp->IoStatus.Status;
+}
+
+NTSTATUS
+USBCCGP_PdoHandleDeviceRelations(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp)
+{
+    PDEVICE_RELATIONS DeviceRelations;
+    PIO_STACK_LOCATION IoStack;
+
+    DPRINT1("USBCCGP_PdoHandleDeviceRelations\n");
+
+    //
+    // get current irp stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // check if relation type is BusRelations
+    //
+    if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
+    {
+        //
+        // PDO handles only target device relation
+        //
+        return Irp->IoStatus.Status;
+    }
+
+    //
+    // allocate device relations
+    //
+    DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
+    if (!DeviceRelations)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // initialize device relations
+    //
+    DeviceRelations->Count = 1;
+    DeviceRelations->Objects[0] = DeviceObject;
+    ObReferenceObject(DeviceObject);
+
+    //
+    // store result
+    //
+    Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+    //
+    // completed successfully
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+USBCCGP_PdoHandleQueryId(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PUNICODE_STRING DeviceString = NULL;
+    UNICODE_STRING TempString;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    NTSTATUS Status;
+    LPWSTR Buffer;
+
+    //
+    // get current irp stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // get device extension
+    //
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+
+    if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
+    {
+        //
+        // handle query device id
+        //
+        Status = USBCCGP_SyncForwardIrp(PDODeviceExtension->NextDeviceObject, Irp);
+
+        //
+        // FIXME append interface id
+        //
+        ASSERT(FALSE);
+        return Status;
+    }
+    else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
+    {
+        //
+        // handle instance id
+        //
+        DeviceString = &PDODeviceExtension->FunctionDescriptor->HardwareId;
+    }
+    else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
+    {
+        //
+        // handle instance id
+        //
+        RtlInitUnicodeString(&TempString, L"0000");
+        DeviceString = &TempString;
+    }
+    else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
+    {
+        //
+        // handle instance id
+        //
+        DeviceString = &PDODeviceExtension->FunctionDescriptor->CompatibleId;
+    }
+
+    //
+    // sanity check
+    //
+    ASSERT(DeviceString != NULL);
+
+    //
+    // allocate buffer
+    //
+    Buffer = AllocateItem(NonPagedPool, DeviceString->Length + sizeof(WCHAR));
+    if (!Buffer)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // copy buffer
+    //
+    Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+    RtlCopyMemory(Buffer, DeviceString->Buffer, DeviceString->Length);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PDO_HandlePnp(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    NTSTATUS Status;
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // get device extension
+    //
+    PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    //
+    // sanity check
+    //
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+    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:
+       {
+           DPRINT1("IRP_MN_REMOVE_DEVICE\n");
+
+           /* 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_START_DEVICE:
+       {
+           //
+           // no-op for PDO
+           //
+           DPRINT1("[USBCCGP] PDO IRP_MN_START\n");
+           Status = STATUS_SUCCESS;
+           break;
+       }
+       default:
+        {
+            //
+            // do nothing
+            //
+            Status = Irp->IoStatus.Status;
+        }
+    }
+
+    //
+    // complete request
+    //
+    if (Status != STATUS_PENDING)
+    {
+        //
+        // store result
+        //
+        Irp->IoStatus.Status = Status;
+
+        //
+        // complete request
+        //
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+
+    //
+    // done processing
+    //
+    return Status;
+
+}
 
 
 NTSTATUS
@@ -18,7 +318,22 @@ PDO_Dispatch(
     PDEVICE_OBJECT DeviceObject, 
     PIRP Irp)
 {
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+
+    /* get stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    switch(IoStack->MajorFunction)
+    {
+        case IRP_MJ_PNP:
+            return PDO_HandlePnp(DeviceObject, Irp);
+        default:
+            DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
+            ASSERT(FALSE);
+            Status = Irp->IoStatus.Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
+    }
+
 }
index 36f01bc..9764735 100644 (file)
@@ -38,6 +38,7 @@ typedef struct
     USBC_DEVICE_CONFIGURATION_INTERFACE_V1 BusInterface;     // bus custom enumeration interface
     PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor;            // usb function descriptor
     ULONG FunctionDescriptorCount;                           // number of function descriptor
+    PDEVICE_OBJECT * ChildPDO;                               // child pdos
 }FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 #define USBCCPG_TAG 'cbsu'
@@ -45,7 +46,10 @@ typedef struct
 typedef struct
 {
     COMMON_DEVICE_EXTENSION Common;                          // shared with FDO
-
+    PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor;            // function descriptor
+    PDEVICE_OBJECT NextDeviceObject;                         // next device object
+    DEVICE_CAPABILITIES Capabilities;                        // device capabilities
+    ULONG FunctionIndex;                                     // function index
 }PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
 
 /* descriptor.c */