[Wine-patches] [eterhack 1/4] Add libusb-1.0 support.
Alexander Morozov
=?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Чт Апр 30 16:59:38 MSD 2009
---
configure.ac | 22 +++-
dlls/usbhub.sys/Makefile.in | 1 +
dlls/usbhub.sys/usbhub.c | 271 ++++++++++++++++++++++++++++++++++++++++++-
include/config.h.in | 3 +
4 files changed, 285 insertions(+), 12 deletions(-)
diff --git a/configure.ac b/configure.ac
index 6d4d671..45deb7c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -363,7 +363,6 @@ AC_CHECK_HEADERS(\
syscall.h \
termios.h \
unistd.h \
- usb.h \
utime.h \
valgrind/memcheck.h \
valgrind/valgrind.h
@@ -1055,13 +1054,24 @@ WINE_NOTICE_WITH(ieee1284,[test "x$ac_cv_lib_ieee1284_ieee1284_find_ports" = "x"
dnl **** Check for LIBUSB ****
AC_SUBST(USBLIBS,"")
-if test "$ac_cv_header_usb_h" = "yes" -a "x$with_usb" != "xno"
+AC_SUBST(USBINCL,"")
+if test "x$with_usb" != "xno"
then
- AC_CHECK_LIB(usb, usb_init,
- [AC_DEFINE(HAVE_LIBUSB, 1, [Define if you have the libusb library and header])
- USBLIBS="-lusb"])
+ AC_CHECK_HEADERS([usb.h],
+ AC_CHECK_LIB(usb, usb_init,
+ [AC_DEFINE(HAVE_LIBUSB, 1, [Define if you have the libusb library and header])
+ USBLIBS="-lusb"]))
+ ac_usb_incl=`pkg-config --cflags libusb-1.0`
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$ac_usb_incl $CPPFLAGS"
+ AC_CHECK_HEADERS([libusb.h],
+ AC_CHECK_LIB(usb-1.0, libusb_init,
+ [AC_DEFINE(HAVE_LIBUSB, 1, [Define if you have the libusb library and header])
+ USBLIBS="-lusb-1.0"
+ AC_SUBST(USBINCL,"$ac_usb_incl")]))
+ CPPFLAGS="$ac_save_CPPFLAGS"
fi
-WINE_NOTICE_WITH(usb,[test "$ac_cv_lib_usb_usb_init" != "yes"],
+WINE_NOTICE_WITH(usb,[test "x$ac_cv_lib_usb_usb_init" != "xyes" -a "x$ac_cv_lib_usb_1_0_libusb_init" != "xyes"],
[libusb ${notice_platform}development files not found, USB won't be supported.])
diff --git a/dlls/usbhub.sys/Makefile.in b/dlls/usbhub.sys/Makefile.in
index 548fe4b..a04b8cc 100644
--- a/dlls/usbhub.sys/Makefile.in
+++ b/dlls/usbhub.sys/Makefile.in
@@ -5,6 +5,7 @@ VPATH = @srcdir@
MODULE = usbhub.sys
IMPORTS = ntoskrnl.exe kernel32 advapi32 setupapi ntdll
EXTRADLLFLAGS = -Wb,--subsystem,native
+EXTRAINCL = @USBINCL@
EXTRALIBS = @USBLIBS@
C_SRCS = \
diff --git a/dlls/usbhub.sys/usbhub.c b/dlls/usbhub.sys/usbhub.c
index a6f80b1..5518dff 100644
--- a/dlls/usbhub.sys/usbhub.c
+++ b/dlls/usbhub.sys/usbhub.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Alexander Morozov for Etersoft
+ * Copyright 2008-2009 Alexander Morozov for Etersoft
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,9 @@
#include <stdarg.h>
-#ifdef HAVE_USB_H
+#ifdef HAVE_LIBUSB_H
+#include <libusb.h>
+#elif defined(HAVE_USB_H)
#include <usb.h>
#endif
@@ -62,7 +64,11 @@ struct DeviceInstance
USHORT pid;
char *instance_id;
WCHAR *service;
+#ifdef HAVE_LIBUSB_H
+ libusb_device *dev;
+#else
struct usb_device *dev;
+#endif
};
struct PdoExtension
@@ -70,8 +76,9 @@ struct PdoExtension
struct DeviceInstance *instance;
};
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
-static void add_data( char **dst, int *dst_size, void *src, int src_size )
+#ifdef HAVE_LIBUSB
+
+static void add_data( char **dst, int *dst_size, const void *src, int src_size )
{
int copy;
@@ -81,6 +88,193 @@ static void add_data( char **dst, int *dst_size, void *src, int src_size )
*dst_size -= copy;
}
+#ifdef HAVE_LIBUSB_H
+
+static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
+{
+ IO_STACK_LOCATION *irpsp;
+ URB *urb;
+ NTSTATUS status = STATUS_UNSUCCESSFUL;
+ struct DeviceInstance *inst;
+
+ TRACE( "%p, %p\n", device, irp );
+
+ inst = ((struct PdoExtension *)device->DeviceExtension)->instance;
+ irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
+ urb = irpsp->Parameters.Others.Argument1;
+
+ switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case IOCTL_INTERNAL_USB_SUBMIT_URB:
+ switch (urb->u.UrbHeader.Function)
+ {
+ case URB_FUNCTION_SELECT_CONFIGURATION:
+ {
+ USB_CONFIGURATION_DESCRIPTOR *conf_desc =
+ urb->u.UrbSelectConfiguration.ConfigurationDescriptor;
+ libusb_device_handle *husb;
+
+ TRACE( "URB_FUNCTION_SELECT_CONFIGURATION\n" );
+
+ if (!libusb_open( inst->dev, &husb ))
+ {
+ int ret;
+
+ ret = libusb_set_configuration( husb,
+ conf_desc->bConfigurationValue );
+ if (ret < 0)
+ ERR( "libusb_set_configuration: %d\n", ret );
+ else
+ status = STATUS_SUCCESS;
+ libusb_close( husb );
+ }
+ }
+ break;
+ case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+ {
+ struct _URB_CONTROL_DESCRIPTOR_REQUEST *request =
+ &urb->u.UrbControlDescriptorRequest;
+
+ TRACE( "URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n" );
+
+ switch (request->DescriptorType)
+ {
+ case USB_DEVICE_DESCRIPTOR_TYPE:
+ TRACE( "USB_DEVICE_DESCRIPTOR_TYPE\n" );
+ {
+ struct libusb_device_descriptor desc;
+
+ if (request->TransferBuffer == NULL)
+ break;
+ if (sizeof(USB_DEVICE_DESCRIPTOR) <= request->TransferBufferLength)
+ {
+ if (libusb_get_device_descriptor( inst->dev, &desc ))
+ break;
+ memcpy( request->TransferBuffer, &desc,
+ sizeof(USB_DEVICE_DESCRIPTOR) );
+ status = STATUS_SUCCESS;
+ }
+ }
+ break;
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ TRACE( "USB_CONFIGURATION_DESCRIPTOR_TYPE\n" );
+ {
+ unsigned int i, k;
+ char *buf = request->TransferBuffer;
+ struct libusb_config_descriptor *conf;
+ const struct libusb_interface_descriptor *intf;
+ const struct libusb_endpoint_descriptor *endp;
+ int size = request->TransferBufferLength;
+
+ /* FIXME: case of num_altsetting > 1 */
+
+ if (buf == NULL)
+ break;
+ if (libusb_get_active_config_descriptor( inst->dev, &conf ))
+ break;
+ add_data( &buf, &size, conf,
+ sizeof(USB_CONFIGURATION_DESCRIPTOR) );
+ if (size > 0 && conf->extra)
+ add_data( &buf, &size, conf->extra, conf->extra_length );
+ for (i = 0; i < conf->bNumInterfaces; ++i)
+ {
+ intf = &conf->interface[i].altsetting[0];
+ if (size > 0)
+ add_data( &buf, &size, intf,
+ sizeof(USB_INTERFACE_DESCRIPTOR) );
+ if (size > 0 && intf->extra)
+ add_data( &buf, &size, intf->extra, intf->extra_length );
+ for (k = 0; k < intf->bNumEndpoints; ++k)
+ {
+ endp = &intf->endpoint[k];
+ if (size > 0)
+ add_data( &buf, &size, endp,
+ sizeof(USB_ENDPOINT_DESCRIPTOR) );
+ if (size > 0 && endp->extra)
+ add_data( &buf, &size, endp->extra,
+ endp->extra_length );
+ }
+ }
+ libusb_free_config_descriptor( conf );
+ status = STATUS_SUCCESS;
+ }
+ break;
+ default:
+ FIXME( "unsupported descriptor type %x\n",
+ request->DescriptorType );
+ }
+ }
+ break;
+ case URB_FUNCTION_VENDOR_DEVICE:
+ case URB_FUNCTION_VENDOR_INTERFACE:
+ case URB_FUNCTION_VENDOR_ENDPOINT:
+ {
+ libusb_device_handle *husb;
+ struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *request =
+ &urb->u.UrbControlVendorClassRequest;
+
+ TRACE( "URB_FUNCTION_VENDOR_*\n" );
+
+ if (!libusb_open( inst->dev, &husb ))
+ {
+ UCHAR req_type = request->RequestTypeReservedBits | (2 << 5);
+ unsigned char *buf;
+ int ret;
+
+ if (urb->u.UrbHeader.Function == URB_FUNCTION_VENDOR_INTERFACE)
+ req_type |= 1;
+ else if (urb->u.UrbHeader.Function == URB_FUNCTION_VENDOR_ENDPOINT)
+ req_type |= 2;
+ buf = HeapAlloc( GetProcessHeap(), 0,
+ request->TransferBufferLength );
+ if (buf != NULL)
+ {
+ memcpy( buf, request->TransferBuffer,
+ request->TransferBufferLength );
+ if (request->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+ req_type |= (1 << 7);
+ ret = libusb_control_transfer( husb, req_type,
+ request->Request, request->Value, request->Index,
+ buf, request->TransferBufferLength, 1000 );
+ if (ret < 0)
+ ERR( "libusb_control_transfer: %d\n", ret );
+ else
+ {
+ if (request->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+ {
+ request->TransferBufferLength =
+ (ret <= request->TransferBufferLength) ?
+ ret : request->TransferBufferLength;
+ memcpy( request->TransferBuffer, buf,
+ request->TransferBufferLength );
+ }
+ status = STATUS_SUCCESS;
+ }
+ HeapFree( GetProcessHeap(), 0, buf );
+ }
+ libusb_close( husb );
+ }
+ }
+ break;
+ default:
+ FIXME( "unsupported URB function %x\n", urb->u.UrbHeader.Function );
+ }
+ urb->u.UrbHeader.Status = status;
+ break;
+ default:
+ FIXME( "IOCTL %08x is not implemented\n",
+ irpsp->Parameters.DeviceIoControl.IoControlCode );
+ }
+
+ irp->IoStatus.u.Status = status;
+ irp->IoStatus.Information = 0;
+ IoCompleteRequest( irp, IO_NO_INCREMENT );
+
+ return status;
+}
+
+#else
+
static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
{
IO_STACK_LOCATION *irpsp;
@@ -257,6 +451,8 @@ static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
return status;
}
+#endif
+
static NTSTATUS WINAPI usbhub_dispatch_pnp( DEVICE_OBJECT *device, IRP *irp )
{
static const WCHAR device_idW[] = {'U','S','B','\\',
@@ -500,9 +696,15 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
'_','U','s','b','h','u','b',
'S','t','a','r','t','e','d',0};
- struct DeviceInstance *instance;
+#ifdef HAVE_LIBUSB_H
+ libusb_device **devs, *dev;
+ struct libusb_device_descriptor desc;
+ unsigned int i = 0;
+#else
struct usb_device *dev;
struct usb_bus *bus;
+#endif
+ struct DeviceInstance *instance;
DEVICE_OBJECT *pdo;
DRIVER_OBJECT *driver;
DRIVER_OBJECT *hubdrv = usbhubdrv;
@@ -515,6 +717,61 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
return 1;
}
+#ifdef HAVE_LIBUSB_H
+ if (libusb_init( NULL ))
+ {
+ ERR( "failed to initialize libusb\n" );
+ return 1;
+ }
+ if (libusb_get_device_list( NULL, &devs ) < 0)
+ {
+ libusb_exit( NULL );
+ return 1;
+ }
+ while ((dev = devs[i++]))
+ {
+ if (libusb_get_device_descriptor( dev, &desc ))
+ {
+ ERR( "failed to get USB device descriptor\n" );
+ continue;
+ }
+ LIST_FOR_EACH_ENTRY( instance, &Devices, struct DeviceInstance, entry )
+ {
+ if (instance->dev == NULL && desc.idVendor == instance->vid &&
+ desc.idProduct == instance->pid)
+ {
+ /* HACK for grdkey.sys */
+ if (instance->vid == 0xa89 && start_service( grdkeyW ))
+ {
+ status = IoCreateDevice( hubdrv, 0, NULL, 0, 0, FALSE, &pdo );
+ if (status != STATUS_SUCCESS) break;
+ while (!(driver = __wine_get_driver_object( grdkeyW )))
+ Sleep( 100 );
+ status = __wine_add_device( driver, pdo );
+ if (status != STATUS_SUCCESS) break;
+ if (pdo->AttachedDevice)
+ __wine_start_device( pdo->AttachedDevice );
+ }
+ if (start_service( instance->service ))
+ {
+ pdo = create_pdo( instance, hubdrv );
+ if (pdo == NULL) break;
+ instance->dev = dev;
+ libusb_ref_device( dev );
+ while (!(driver = __wine_get_driver_object(
+ instance->service )))
+ Sleep( 100 );
+ status = __wine_add_device( driver, pdo );
+ if (status != STATUS_SUCCESS) break;
+ if (pdo->AttachedDevice)
+ __wine_start_device( pdo->AttachedDevice );
+ }
+ break;
+ }
+ }
+ }
+ libusb_free_device_list( devs, 1 );
+#else
usb_init();
usb_find_busses();
usb_find_devices();
@@ -555,17 +812,19 @@ static DWORD CALLBACK enum_usb_devices( void *usbhubdrv )
break;
}
}
+#endif
event = CreateEventW( NULL, TRUE, FALSE, usbhub_started_eventW );
SetEvent( event );
CloseHandle( event );
return 0;
}
+
#endif
NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
{
-#if defined(HAVE_LIBUSB) && defined(HAVE_USB_H)
+#ifdef HAVE_LIBUSB
HANDLE thread;
driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = usbhub_internal_ioctl;
diff --git a/include/config.h.in b/include/config.h.in
index 43bc531..0e32157 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -351,6 +351,9 @@
/* Define if you have the libusb library and header */
#undef HAVE_LIBUSB
+/* Define to 1 if you have the <libusb.h> header file. */
+#undef HAVE_LIBUSB_H
+
/* Define if you have the libxml2 library */
#undef HAVE_LIBXML2
--
1.6.1.3.GIT
Подробная информация о списке рассылки Wine-patches