#include <libusb.h>
#elif defined(HAVE_USB_H)
#include <usb.h>
+#undef USB_ENDPOINT_TYPE_MASK
+#undef USB_ENDPOINT_TYPE_CONTROL
+#undef USB_ENDPOINT_TYPE_ISOCHRONOUS
+#undef USB_ENDPOINT_TYPE_BULK
+#undef USB_ENDPOINT_TYPE_INTERRUPT
#endif
#define NONAMELESSUNION
WINE_DEFAULT_DEBUG_CHANNEL(usbhub);
+#ifdef HAVE_LIBUSB
+
extern NTSTATUS CDECL __wine_add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *dev );
extern DRIVER_OBJECT * CDECL __wine_get_driver_object( const WCHAR *service );
extern NTSTATUS CDECL __wine_start_device( DEVICE_OBJECT *device );
USHORT pid;
char *instance_id;
WCHAR *service;
+ DEVICE_OBJECT *pdo;
#ifdef HAVE_LIBUSB_H
libusb_device *dev;
#else
struct DeviceInstance *instance;
};
-#ifdef HAVE_LIBUSB
+static DRIVER_OBJECT *usbhub_driver;
+
+static CRITICAL_SECTION usbhub_cs;
+static CRITICAL_SECTION_DEBUG usbhub_cs_debug =
+{
+ 0, 0, &usbhub_cs,
+ { &usbhub_cs_debug.ProcessLocksList, &usbhub_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": usbhub_cs") }
+};
+static CRITICAL_SECTION usbhub_cs = { &usbhub_cs_debug, -1, 0, 0, 0, 0 };
+
+static BOOL libusb_initialized;
static void add_data( unsigned char **dst, ULONG *dst_size, const void *src, ULONG src_size )
{
TRACE( "%p, %p\n", device, irp );
+ EnterCriticalSection( &usbhub_cs );
inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
if (inst->service) goto done;
irpsp = irp->Tail.Overlay.s.u2.CurrentStackLocation;
}
done:
+ LeaveCriticalSection( &usbhub_cs );
irp->IoStatus.u.Status = status;
irp->IoStatus.Information = info;
IoCompleteRequest( irp, IO_NO_INCREMENT );
TRACE( "%p, %p\n", device, irp );
+ EnterCriticalSection( &usbhub_cs );
inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
if (!inst->service) goto done;
irpsp = irp->Tail.Overlay.s.u2.CurrentStackLocation;
}
done:
+ LeaveCriticalSection( &usbhub_cs );
irp->IoStatus.u.Status = status;
irp->IoStatus.Information = 0;
IoCompleteRequest( irp, IO_NO_INCREMENT );
TRACE( "%p, %p\n", device, irp );
+ EnterCriticalSection( &usbhub_cs );
inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
if (!inst->service) goto done;
irpsp = irp->Tail.Overlay.s.u2.CurrentStackLocation;
}
done:
+ LeaveCriticalSection( &usbhub_cs );
irp->IoStatus.u.Status = status;
irp->IoStatus.Information = 0;
IoCompleteRequest( irp, IO_NO_INCREMENT );
TRACE( "%p, %p\n", device, irp );
+ EnterCriticalSection( &usbhub_cs );
dx = device->DeviceExtension;
irpsp = irp->Tail.Overlay.s.u2.CurrentStackLocation;
switch (irpsp->MinorFunction)
status = STATUS_SUCCESS;
}
+ LeaveCriticalSection( &usbhub_cs );
irp->IoStatus.u.Status = status;
irp->IoStatus.Information = info;
IoCompleteRequest( irp, IO_NO_INCREMENT );
{
static unsigned int instance_id;
struct DeviceInstance *instance = NULL;
- DEVICE_OBJECT *hubdev;
instance = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance) );
if (instance == NULL) return;
instance->service = NULL;
instance->dev = dev;
- hubdev = create_pdo( instance, hubdrv, DO_POWER_PAGABLE );
- if (hubdev == NULL) goto fail;
+ instance->pdo = create_pdo( instance, hubdrv, DO_POWER_PAGABLE );
+ if (instance->pdo == NULL) goto fail;
list_add_tail( &Devices, &instance->entry );
- register_root_hub_device( hubdev, instance_id );
+ register_root_hub_device( instance->pdo, instance_id );
++instance_id;
return;
fail:
instance->pid = pid;
instance->instance_id = instance_id;
instance->service = (WCHAR *)buf;
+ instance->pdo = NULL;
instance->dev = NULL;
list_add_tail( &Devices, &instance->entry );
instance_id = NULL;
instance->pid = pid;
instance->instance_id = instance_id;
instance->service = NULL;
+ instance->pdo = NULL;
instance->dev = dev;
list_add_tail( &Devices, &instance->entry );
{
struct DeviceInstance *instance;
DRIVER_OBJECT *driver;
- DEVICE_OBJECT *pdo;
+ DEVICE_OBJECT *dev;
NTSTATUS status;
LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
{
- if (instance->service == NULL || instance->dev == NULL) continue;
+ if (instance->service == NULL || instance->dev == NULL ||
+ instance->pdo != NULL) continue;
if (start_service( instance->service ))
{
- pdo = create_pdo( instance, hubdrv,
+ instance->pdo = create_pdo( instance, hubdrv,
DO_BUS_ENUMERATED_DEVICE | DO_POWER_PAGABLE );
- if (pdo == NULL) continue;
- while (!(driver = __wine_get_driver_object(
- instance->service )))
+ if (instance->pdo == NULL) continue;
+ while (!(driver = __wine_get_driver_object( instance->service )))
Sleep( 100 );
- status = __wine_add_device( driver, pdo );
- if (status == STATUS_SUCCESS && pdo->AttachedDevice != NULL)
- __wine_start_device( pdo->AttachedDevice );
+ status = __wine_add_device( driver, instance->pdo );
+ dev = instance->pdo->AttachedDevice;
+ if (status == STATUS_SUCCESS && dev != NULL)
+ __wine_start_device( dev );
}
}
}
-static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
+static BOOL is_new( void *dev )
{
- static const WCHAR usbhub_started_eventW[] = {'_','_','w','i','n','e',
- '_','U','s','b','h','u','b',
- 'S','t','a','r','t','e','d',0};
+ struct DeviceInstance *instance;
+
+ LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
+ if (instance->dev == dev)
+ return FALSE;
+ return TRUE;
+}
#ifdef HAVE_LIBUSB_H
+
+static int initialize_libusb(void)
+{
+ return libusb_init( NULL );
+}
+
+void enum_usb_devices(void)
+{
libusb_device **devs, *dev;
struct libusb_device_descriptor desc;
unsigned int i = 0;
-#else
- struct usb_device *dev;
- struct usb_bus *bus;
- struct usb_device_descriptor *desc;
-#endif
struct DeviceInstance *instance;
- HANDLE event;
BOOL new_device;
- if (!enum_reg_usb_devices())
- {
- ERR( "failed to enumerate USB devices\n" );
+ EnterCriticalSection( &usbhub_cs );
+ if (!libusb_initialized || libusb_get_device_list( NULL, &devs ) < 0)
goto end;
- }
-
-#ifdef HAVE_LIBUSB_H
- if (libusb_init( NULL ))
- {
- ERR( "failed to initialize libusb\n" );
- goto end;
- }
- if (libusb_get_device_list( NULL, &devs ) < 0)
- {
- libusb_exit( NULL );
- goto end;
- }
while ((dev = devs[i++]))
{
+ if (!is_new( dev ))
+ continue;
if (libusb_get_device_descriptor( dev, &desc ))
{
ERR( "failed to get USB device descriptor\n" );
continue;
}
+ TRACE( "add %04x:%04x\n", desc.idVendor, desc.idProduct );
libusb_ref_device( dev );
if (libusb_get_device_address( dev ) == 1)
{
- create_root_hub_device( desc.idVendor, desc.idProduct, dev, usbhubdrv );
+ create_root_hub_device( desc.idVendor, desc.idProduct, dev, usbhub_driver );
continue;
}
new_device = TRUE;
register_usb_device( desc.idVendor, desc.idProduct, dev );
}
libusb_free_device_list( devs, 1 );
+ start_device_drivers( usbhub_driver );
+end:
+ LeaveCriticalSection( &usbhub_cs );
+}
+
#else
+
+static int initialize_libusb(void)
+{
usb_init();
+ return 0;
+}
+
+void enum_usb_devices(void)
+{
+ struct usb_device *dev;
+ struct usb_bus *bus;
+ struct usb_device_descriptor *desc;
+ struct DeviceInstance *instance;
+ BOOL new_device;
+
+ EnterCriticalSection( &usbhub_cs );
+ if (!libusb_initialized)
+ goto end;
usb_find_busses();
usb_find_devices();
-
for (bus = usb_busses; bus; bus = bus->next)
for (dev = bus->devices; dev; dev = dev->next)
{
- if (dev->devnum > 1) continue;
+ if (dev->devnum > 1 || !is_new( dev )) continue;
desc = &dev->descriptor;
+ TRACE( "add %04x:%04x\n", desc->idVendor, desc->idProduct );
create_root_hub_device( desc->idVendor, desc->idProduct, dev,
- usbhubdrv );
+ usbhub_driver );
}
for (bus = usb_busses; bus; bus = bus->next)
for (dev = bus->devices; dev; dev = dev->next)
{
- if (dev->devnum <= 1) continue;
+ if (dev->devnum <= 1 || !is_new( dev )) continue;
desc = &dev->descriptor;
+ TRACE( "add %04x:%04x\n", desc->idVendor, desc->idProduct );
new_device = TRUE;
LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
{
if (new_device)
register_usb_device( desc->idVendor, desc->idProduct, dev );
}
-#endif
- start_root_devices( usbhubdrv );
- start_device_drivers( usbhubdrv );
+ start_device_drivers( usbhub_driver );
end:
+ LeaveCriticalSection( &usbhub_cs );
+}
+
+#endif
+
+#else
+
+void enum_usb_devices(void)
+{
+}
+
+#endif
+
+#ifdef HAVE_LIBUSB
+
+static DWORD CALLBACK initialize_usbhub( void *arg )
+{
+ static const WCHAR usbhub_started_eventW[] = {'_','_','w','i','n','e',
+ '_','U','s','b','h','u','b',
+ 'S','t','a','r','t','e','d',0};
+
+ HANDLE event;
+
+ start_root_devices( usbhub_driver );
+ EnterCriticalSection( &usbhub_cs );
+ if (!enum_reg_usb_devices())
+ ERR( "failed to enumerate USB devices\n" );
+ else if (initialize_libusb())
+ ERR( "failed to initialize libusb\n" );
+ else
+ libusb_initialized = TRUE;
+ LeaveCriticalSection( &usbhub_cs );
+ enum_usb_devices();
event = CreateEventW( NULL, TRUE, FALSE, usbhub_started_eventW );
SetEvent( event );
CloseHandle( event );
#ifdef HAVE_LIBUSB
HANDLE thread;
+ usbhub_driver = driver;
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = usbhub_ioctl;
driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = usbhub_internal_ioctl;
driver->MajorFunction[IRP_MJ_PNP] = usbhub_dispatch_pnp;
- thread = CreateThread( NULL, 0, enum_usb_devices, driver, 0, NULL );
+ thread = CreateThread( NULL, 0, initialize_usbhub, NULL, 0, NULL );
if (!thread) return STATUS_UNSUCCESSFUL;
CloseHandle( thread );
#else