[Wine-patches] [eterhack 10/23] usbhub.sys: Create devices for root hubs.

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Пт Июн 5 13:00:10 MSD 2009


---
 dlls/usbhub.sys/usbhub.c |  109 ++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 91 insertions(+), 18 deletions(-)

diff --git a/dlls/usbhub.sys/usbhub.c b/dlls/usbhub.sys/usbhub.c
index 8321077..94d8b33 100644
--- a/dlls/usbhub.sys/usbhub.c
+++ b/dlls/usbhub.sys/usbhub.c
@@ -19,7 +19,7 @@
 #include "config.h"
 #include "wine/port.h"
 
-#include <stdarg.h>
+#include <stdio.h>
 #include <stdlib.h>
 
 #ifdef HAVE_LIBUSB_H
@@ -99,6 +99,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
     TRACE( "%p, %p\n", device, irp );
 
     inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
+    if (!inst->service) goto done;
     irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
     urb = irpsp->Parameters.Others.Argument1;
 
@@ -425,6 +426,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
                 irpsp->Parameters.DeviceIoControl.IoControlCode );
     }
 
+done:
     irp->IoStatus.u.Status = status;
     irp->IoStatus.Information = 0;
     IoCompleteRequest( irp, IO_NO_INCREMENT );
@@ -444,6 +446,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
     TRACE( "%p, %p\n", device, irp );
 
     inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
+    if (!inst->service) goto done;
     irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
     urb = irpsp->Parameters.Others.Argument1;
 
@@ -779,6 +782,7 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
                 irpsp->Parameters.DeviceIoControl.IoControlCode );
     }
 
+done:
     irp->IoStatus.u.Status = status;
     irp->IoStatus.Information = 0;
     IoCompleteRequest( irp, IO_NO_INCREMENT );
@@ -793,42 +797,57 @@ static NTSTATUS WINAPI usbhub_dispatch_pnp( DEVICE_OBJECT *device, IRP *irp )
     static const WCHAR device_idW[] = {'U','S','B','\\',
                                        'V','i','d','_','%','0','4','x','&',
                                        'P','i','d','_','%','0','4','x',0};
+    static const WCHAR root_hub_idW[] = {'U','S','B','\\',
+                                         'R','O','O','T','_','H','U','B',0};
 
+    struct PdoExtension *dx;
     IO_STACK_LOCATION *irpsp;
     NTSTATUS status;
     ULONG_PTR info = 0;
 
     TRACE( "%p, %p\n", device, irp );
 
+    dx = device->DeviceExtension;
     irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
     switch (irpsp->MinorFunction)
     {
     case IRP_MN_QUERY_DEVICE_RELATIONS:
-        status = irp->IoStatus.u.Status;
-        info = irp->IoStatus.Information;
+        /* dx->instance->service is NULL for root hubs */
+        if (dx->instance->service)
+        {
+            status = irp->IoStatus.u.Status;
+            info = irp->IoStatus.Information;
+        }
+        else
+        {
+            FIXME( "IRP_MN_QUERY_DEVICE_RELATIONS is not implemented for root hubs\n" );
+            status = STATUS_NOT_IMPLEMENTED;
+        }
         break;
     case IRP_MN_QUERY_ID:
         switch (irpsp->Parameters.QueryId.IdType)
         {
         case BusQueryDeviceID:
         {
-            struct PdoExtension *dx = device->DeviceExtension;
-            WCHAR *device_id = ExAllocatePool( PagedPool, sizeof(device_idW) );
+            WCHAR *device_id = ExAllocatePool( PagedPool, dx->instance->service ?
+                    sizeof(device_idW) : sizeof(root_hub_idW) );
 
             if (device_id == NULL)
             {
                 status = STATUS_INSUFFICIENT_RESOURCES;
                 break;
             }
-            snprintfW( device_id, strlenW(device_idW) + 1, device_idW,
-                    dx->instance->vid, dx->instance->pid );
+            if (dx->instance->service)
+                snprintfW( device_id, strlenW(device_idW) + 1, device_idW,
+                        dx->instance->vid, dx->instance->pid );
+            else
+                strcpyW( device_id, root_hub_idW );
             status = STATUS_SUCCESS;
             info = (ULONG_PTR)device_id;
             break;
         }
         case BusQueryInstanceID:
         {
-            struct PdoExtension *dx = device->DeviceExtension;
             char *instance_id;
             ULONG len;
             ULONG size;
@@ -901,21 +920,26 @@ static BOOL start_service( const WCHAR *name )
     return ret;
 }
 
-static DEVICE_OBJECT *create_pdo( struct DeviceInstance *inst, DRIVER_OBJECT *hubdrv )
+static BOOL create_pdo_name( UNICODE_STRING *pdo_name )
 {
     static const WCHAR usbpdoW[] = {'\\','D','e','v','i','c','e','\\',
-                                    'U','S','B','P','D','O','-','%','u',0};
+                                     'U','S','B','P','D','O','-','%','u',0};
 
     static unsigned int last_pdo_num;
-    UNICODE_STRING pdo_name;
-    DEVICE_OBJECT *usbdev = NULL;
-    WCHAR *buf;
+    WCHAR *buf = RtlAllocateHeap( GetProcessHeap(), 0, 30 * sizeof(WCHAR) );
 
-    buf = HeapAlloc( GetProcessHeap(), 0, 30 * sizeof(WCHAR) );
-    if (buf == NULL) return NULL;
+    if (buf == NULL) return FALSE;
     snprintfW( buf, 30, usbpdoW, last_pdo_num++ );
-    RtlInitUnicodeString( &pdo_name, buf );
+    RtlInitUnicodeString( pdo_name, buf );
+    return TRUE;
+}
+
+static DEVICE_OBJECT *create_pdo( struct DeviceInstance *inst, DRIVER_OBJECT *hubdrv )
+{
+    UNICODE_STRING pdo_name;
+    DEVICE_OBJECT *usbdev = NULL;
 
+    if (!create_pdo_name( &pdo_name )) return NULL;
     if (IoCreateDevice( hubdrv, sizeof(struct PdoExtension), &pdo_name,
         0, 0, FALSE, &usbdev ) == STATUS_SUCCESS)
     {
@@ -923,10 +947,46 @@ static DEVICE_OBJECT *create_pdo( struct DeviceInstance *inst, DRIVER_OBJECT *hu
         usbdev->Flags |= DO_BUS_ENUMERATED_DEVICE | DO_POWER_PAGABLE;
         usbdev->Flags &= ~DO_DEVICE_INITIALIZING;
     }
-    HeapFree( GetProcessHeap(), 0, buf );
+    RtlFreeUnicodeString( &pdo_name );
     return usbdev;
 }
 
+static void create_root_hub_device( USHORT vid, USHORT pid, void *dev,
+        DRIVER_OBJECT *hubdrv )
+{
+    static unsigned int instance_id;
+    struct DeviceInstance *instance = NULL;
+    DEVICE_OBJECT *hubdev;
+    UNICODE_STRING pdo_name = {0, 0, NULL};
+
+    instance = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance) );
+    if (instance == NULL) return;
+    instance->instance_id = HeapAlloc( GetProcessHeap(), 0, 16 );
+    if (instance->instance_id == NULL) goto fail;
+    instance->vid = vid;
+    instance->pid = pid;
+    snprintf( instance->instance_id, 16, "%u", instance_id );
+    instance->service = NULL;
+    instance->dev = dev;
+
+    if (!create_pdo_name( &pdo_name )) goto fail;
+    if (IoCreateDevice( hubdrv, sizeof(struct PdoExtension), &pdo_name,
+        0, 0, FALSE, &hubdev ) != STATUS_SUCCESS) goto fail;
+
+    ++instance_id;
+    list_add_tail( &Devices, &instance->entry );
+    ((struct PdoExtension *)hubdev->DeviceExtension)->instance = instance;
+    hubdev->Flags |= DO_POWER_PAGABLE;
+    hubdev->Flags &= ~DO_DEVICE_INITIALIZING;
+    return;
+fail:
+    if (instance->instance_id)
+        HeapFree( GetProcessHeap(), 0, instance->instance_id );
+    HeapFree( GetProcessHeap(), 0, instance );
+    RtlFreeUnicodeString( &pdo_name );
+    return;
+}
+
 static BOOL enum_reg_usb_devices(void)
 {
     static const WCHAR usb[] = {'U','S','B',0};
@@ -1040,6 +1100,7 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
 #else
     struct usb_device *dev;
     struct usb_bus *bus;
+    struct usb_device_descriptor *desc;
 #endif
     struct DeviceInstance *instance;
     DEVICE_OBJECT *pdo;
@@ -1072,6 +1133,12 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
             ERR( "failed to get USB device descriptor\n" );
             continue;
         }
+        if (libusb_get_device_address( dev ) == 1)
+        {
+            libusb_ref_device( dev );
+            create_root_hub_device( desc.idVendor, desc.idProduct, dev, hubdrv );
+            continue;
+        }
         LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
         {
             if (instance->dev == NULL && desc.idVendor == instance->vid &&
@@ -1114,7 +1181,13 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
     usb_find_devices();
 
     for (bus = usb_busses; bus; bus = bus->next)
-        for (dev = bus->devices; dev; dev = dev->next)
+    {
+        desc = &bus->devices->descriptor;
+        create_root_hub_device( desc->idVendor, desc->idProduct,
+                bus->devices, hubdrv );
+    }
+    for (bus = usb_busses; bus; bus = bus->next)
+        for (dev = bus->devices->next; dev; dev = dev->next)
             LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
             {
                 if (instance->dev == NULL &&
-- 
1.6.3.1



Подробная информация о списке рассылки Wine-patches