From 3d2f8edda5aa10ac06ae2671eaecbb8950d461b4 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Thu, 14 Jan 2010 01:28:23 +0000 Subject: [PATCH] svn r50: - MSVC6 compatibility (Michael Plante): new driver backend implementation and other compatibility fixes --- libusb/os/windows_usb.c | 188 ++++++++++++++++++++++++++-------------- libusb/os/windows_usb.h | 56 +++++++----- 2 files changed, 157 insertions(+), 87 deletions(-) diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 7c67aed..34570ab 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -298,6 +298,9 @@ static int windows_init(struct libusb_context *ctx) LARGE_INTEGER li_frequency; OSVERSIONINFO os_version; + // We maintain a chained list of the Host Controllers found + struct windows_hcd_priv** _hcd_cur = &hcd_root; + // If our HCD list is populated, we don't need to re-init if (hcd_root != NULL) { usbi_dbg("init already occured."); @@ -348,9 +351,6 @@ static int windows_init(struct libusb_context *ctx) usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); } - // We maintain a chained list of the Host Controllers found - struct windows_hcd_priv** _hcd_cur = &hcd_root; - guid = GUID_DEVINTERFACE_USB_HOST_CONTROLLER; for (bus = 0; ; bus++) @@ -1068,16 +1068,16 @@ static int set_device_paths(struct libusb_context *ctx, struct discovered_devs * found = true; if (safe_strcmp(priv->driver, "WinUSB") == 0) { - priv->api = API_WINUSB; + priv->apib = &windows_winusb_backend; // For non composite, the first interface is the same as the device priv->interface[0].path = safe_strdup(priv->path); // needs strdup } else if (safe_strcmp(reg_key, "usbccgp") == 0) { // Composite (multi-interface) devices are identified by their use of // the USB Common Class Generic Parent driver if (set_composite_device(ctx, dev_info_data.DevInst, priv) == LIBUSB_SUCCESS) { - priv->api = API_WINUSB; + priv->apib = &windows_winusb_backend; } else { - priv->api = API_NONE; + priv->apib = &windows_template_backend; } } else { // All other USB access drivers (HID, Mass Storage) are ignored for now @@ -1200,24 +1200,19 @@ static int windows_get_active_config_descriptor(struct libusb_device *dev, unsig static int windows_open(struct libusb_device_handle *dev_handle) { - int r = LIBUSB_SUCCESS; struct windows_device_priv *priv = __device_priv(dev_handle->dev); - API_CALL(priv->api, open, dev_handle); - - return r; + return priv->apib->open(dev_handle); } static void windows_close(struct libusb_device_handle *dev_handle) { struct windows_device_priv *priv = __device_priv(dev_handle->dev); - switch(priv->api) { - case API_WINUSB: + // Incidentally, we could just add a "close" member and have it not + // warn. + if(&windows_winusb_backend == priv->apib) { winusb_close(dev_handle); - break; - default: - break; } } @@ -1261,7 +1256,7 @@ static int windows_claim_interface(struct libusb_device_handle *dev_handle, int safe_free(priv->interface[iface].endpoint); priv->interface[iface].nb_endpoints= 0; - API_CALL(priv->api, claim_interface, dev_handle, iface); + r = priv->apib->claim_interface(dev_handle, iface); if (r == LIBUSB_SUCCESS) { windows_assign_endpoints(dev_handle->dev, iface, 0); @@ -1278,7 +1273,7 @@ static int windows_set_interface_altsetting(struct libusb_device_handle *dev_han safe_free(priv->interface[iface].endpoint); priv->interface[iface].nb_endpoints= 0; - API_CALL(priv->api, set_interface_altsetting, dev_handle, iface, altsetting); + r = priv->apib->set_interface_altsetting(dev_handle, iface, altsetting); if (r == LIBUSB_SUCCESS) { windows_assign_endpoints(dev_handle->dev, iface, altsetting); @@ -1289,31 +1284,22 @@ static int windows_set_interface_altsetting(struct libusb_device_handle *dev_han static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface) { - int r = LIBUSB_SUCCESS; struct windows_device_priv *priv = __device_priv(dev_handle->dev); windows_set_interface_altsetting(dev_handle, iface, 0); - API_CALL(priv->api, release_interface, dev_handle, iface); - - return r; + return priv->apib->release_interface(dev_handle, iface); } static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { struct windows_device_priv *priv = __device_priv(dev_handle->dev); - int r; - - API_CALL(priv->api, clear_halt, dev_handle, endpoint); - return r; + return priv->apib->clear_halt(dev_handle, endpoint); } static int windows_reset_device(struct libusb_device_handle *dev_handle) { struct windows_device_priv *priv = __device_priv(dev_handle->dev); - int r; - - API_CALL(priv->api, reset_device, dev_handle); - return r; + return priv->apib->reset_device(dev_handle); } // The 3 functions below are unlikely to ever get supported on Windows @@ -1352,7 +1338,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) struct windows_device_priv *priv = __device_priv(transfer->dev_handle->dev); int r; - API_CALL(priv->api, submit_bulk_transfer, itransfer); + r = priv->apib->submit_bulk_transfer(itransfer); if (r != LIBUSB_SUCCESS) { return r; } @@ -1371,7 +1357,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) struct windows_device_priv *priv = __device_priv(transfer->dev_handle->dev); int r; - API_CALL(priv->api, submit_iso_transfer, itransfer); + r = priv->apib->submit_iso_transfer(itransfer); if (r != LIBUSB_SUCCESS) { return r; } @@ -1390,7 +1376,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) struct windows_device_priv *priv = __device_priv(transfer->dev_handle->dev); int r; - API_CALL(priv->api, submit_control_transfer, itransfer); + r = priv->apib->submit_control_transfer(itransfer); if (r != LIBUSB_SUCCESS) { return r; } @@ -1423,20 +1409,16 @@ static int windows_abort_control(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct windows_device_priv *priv = __device_priv(transfer->dev_handle->dev); - int r; - API_CALL(priv->api, abort_control, itransfer); - return r; + return priv->apib->abort_control(itransfer); } static int windows_abort_transfers(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct windows_device_priv *priv = __device_priv(transfer->dev_handle->dev); - int r; - API_CALL(priv->api, abort_transfers, itransfer); - return r; + return priv->apib->abort_transfers(itransfer); } static int windows_cancel_transfer(struct usbi_transfer *itransfer) @@ -1584,46 +1566,118 @@ static int windows_clock_gettime(int clk_id, struct timespec *tp) return LIBUSB_ERROR_OTHER; } + +// NB: MSVC6 does not support named initializers. const struct usbi_os_backend windows_backend = { - .name = "Windows", - .init = windows_init, - .exit = windows_exit, - .get_device_list = windows_get_device_list, - .get_device_descriptor = windows_get_device_descriptor, - .get_active_config_descriptor = windows_get_active_config_descriptor, - .get_config_descriptor = windows_get_config_descriptor, + "Windows", + windows_init, + windows_exit, - .open = windows_open, - .close = windows_close, - .get_configuration = windows_get_configuration, - .set_configuration = windows_set_configuration, - .claim_interface = windows_claim_interface, - .release_interface = windows_release_interface, + windows_get_device_list, + windows_open, + windows_close, - .set_interface_altsetting = windows_set_interface_altsetting, - .clear_halt = windows_clear_halt, - .reset_device = windows_reset_device, + windows_get_device_descriptor, + windows_get_active_config_descriptor, + windows_get_config_descriptor, - .kernel_driver_active = windows_kernel_driver_active, - .detach_kernel_driver = windows_detach_kernel_driver, - .attach_kernel_driver = windows_attach_kernel_driver, + windows_get_configuration, + windows_set_configuration, + windows_claim_interface, + windows_release_interface, - .destroy_device = windows_destroy_device, + windows_set_interface_altsetting, + windows_clear_halt, + windows_reset_device, - .submit_transfer = windows_submit_transfer, - .cancel_transfer = windows_cancel_transfer, - .clear_transfer_priv = windows_clear_transfer_priv, + windows_kernel_driver_active, + windows_detach_kernel_driver, + windows_attach_kernel_driver, - .handle_events = windows_handle_events, + windows_destroy_device, - .clock_gettime = windows_clock_gettime, + windows_submit_transfer, + windows_cancel_transfer, + windows_clear_transfer_priv, - .device_priv_size = sizeof(struct windows_device_priv), - .device_handle_priv_size = sizeof(struct windows_device_handle_priv), - .transfer_priv_size = sizeof(struct windows_transfer_priv), - .add_iso_packet_size = 0, + windows_handle_events, + + windows_clock_gettime, +#ifdef USBI_TIMERFD_AVAILABLE + NULL, +#endif + sizeof(struct windows_device_priv), + sizeof(struct windows_device_handle_priv), + sizeof(struct windows_transfer_priv), + 0, }; + +const struct windows_driver_backend windows_winusb_backend = { + "WinUSB", + winusb_open, + winusb_claim_interface, + winusb_set_interface_altsetting, + winusb_release_interface, + winusb_clear_halt, + winusb_reset_device, + winusb_submit_bulk_transfer, + winusb_submit_iso_transfer, + winusb_submit_control_transfer, + winusb_abort_control, + winusb_abort_transfers, +}; + +static int unsupported_open(struct libusb_device_handle *dev_handle) { + PRINT_UNSUPPORTED_API(unsupported_open); +} +static int unsupported_claim_interface(struct libusb_device_handle *dev_handle, int iface) { + PRINT_UNSUPPORTED_API(unsupported_claim_interface); +} +static int unsupported_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { + PRINT_UNSUPPORTED_API(unsupported_set_interface_altsetting); +} +static int unsupported_release_interface(struct libusb_device_handle *dev_handle, int iface) { + PRINT_UNSUPPORTED_API(unsupported_release_interface); +} +static int unsupported_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { + PRINT_UNSUPPORTED_API(unsupported_clear_halt); +} +static int unsupported_reset_device(struct libusb_device_handle *dev_handle) { + PRINT_UNSUPPORTED_API(unsupported_reset_device); +} +static int unsupported_submit_bulk_transfer(struct usbi_transfer *itransfer) { + PRINT_UNSUPPORTED_API(unsupported_submit_bulk_transfer); +} +static int unsupported_submit_iso_transfer(struct usbi_transfer *itransfer) { + PRINT_UNSUPPORTED_API(unsupported_submit_iso_transfer); +} +static int unsupported_submit_control_transfer(struct usbi_transfer *itransfer) { + PRINT_UNSUPPORTED_API(unsupported_submit_control_transfer); +} +static int unsupported_abort_control(struct usbi_transfer *itransfer) { + PRINT_UNSUPPORTED_API(unsupported_abort_control); +} +static int unsupported_abort_transfers(struct usbi_transfer *itransfer) { + PRINT_UNSUPPORTED_API(unsupported_abort_transfers); +} + +const struct windows_driver_backend windows_template_backend = { + "Dummy", + unsupported_open, + unsupported_claim_interface, + unsupported_set_interface_altsetting, + unsupported_release_interface, + unsupported_clear_halt, + unsupported_reset_device, + unsupported_submit_bulk_transfer, + unsupported_submit_iso_transfer, + unsupported_submit_control_transfer, + unsupported_abort_control, + unsupported_abort_transfers, +}; + + /* * WinUSB API functions */ diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h index 3ecdd68..55c8bdc 100644 --- a/libusb/os/windows_usb.h +++ b/libusb/os/windows_usb.h @@ -69,23 +69,28 @@ void inline upperize(char* str) { #define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL) #define ERRNO GetLastError() -// Supported APIs -enum api_type { - API_NONE, - API_WINUSB, +// This is used to support multiple kernel drivers in Windows. +struct windows_driver_backend { + const char *name; // A human-readable name for your backend, e.g. "WinUSB" + int (*open)(struct libusb_device_handle *dev_handle); + int (*claim_interface)(struct libusb_device_handle *dev_handle, int iface); + int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, int iface, int altsetting); + int (*release_interface)(struct libusb_device_handle *dev_handle, int iface); + int (*clear_halt)(struct libusb_device_handle *dev_handle, unsigned char endpoint); + int (*reset_device)(struct libusb_device_handle *dev_handle); + int (*submit_bulk_transfer)(struct usbi_transfer *itransfer); + int (*submit_iso_transfer)(struct usbi_transfer *itransfer); + int (*submit_control_transfer)(struct usbi_transfer *itransfer); + int (*abort_control)(struct usbi_transfer *itransfer); + int (*abort_transfers)(struct usbi_transfer *itransfer); }; +extern const struct windows_driver_backend windows_template_backend; +extern const struct windows_driver_backend windows_winusb_backend; -#define API_CALL(api, fname, ...) \ - switch(api) { \ - case API_WINUSB: \ - r = winusb_##fname(__VA_ARGS__); \ - break; \ - default: \ - r = LIBUSB_ERROR_NOT_SUPPORTED; \ - usbi_dbg("unsupported API call for '" \ - #fname "' (api=%d)", api); \ - break; \ - } +#define PRINT_UNSUPPORTED_API(fname) \ + usbi_dbg("unsupported API call for '" \ + #fname "'"); \ + return LIBUSB_ERROR_NOT_SUPPORTED; enum windows_version { WINDOWS_UNSUPPORTED, @@ -125,7 +130,7 @@ struct windows_device_priv { uint8_t *endpoint; } interface[USB_MAXINTERFACES]; char *driver; // driver name (eg WinUSB, USBSTOR, HidUsb, etc) - enum api_type api; + struct windows_driver_backend const *apib; uint8_t active_config; USB_DEVICE_DESCRIPTOR dev_descriptor; unsigned char **config_descriptor; // list of pointers to the cached config descriptors @@ -137,7 +142,7 @@ static inline void windows_device_priv_init(struct windows_device_priv* p) { p->connection_index = 0; p->path = NULL; p->driver = NULL; - p->api = API_NONE; + p->apib = &windows_template_backend; p->active_config = 0; p->config_descriptor = NULL; memset(&(p->dev_descriptor), 0, sizeof(USB_DEVICE_DESCRIPTOR)); @@ -213,12 +218,23 @@ typedef struct _USB_HUB_NAME_FIXED { } USB_HUB_NAME_FIXED; // The following structure needs to be packed -#pragma pack(1) +// NB: can't reuse structs containing a zero element arrays +// (eg. struct with a 'Data[0]'), as MSVC6 can't handle it. +#pragma pack(push, 1) typedef struct _USB_CONFIGURATION_DESCRIPTOR_SHORT { - USB_DESCRIPTOR_REQUEST req; + struct { + ULONG ConnectionIndex; + struct { + UCHAR bmRequest; + UCHAR bRequest; + USHORT wValue; + USHORT wIndex; + USHORT wLength; + } SetupPacket; + } req; USB_CONFIGURATION_DESCRIPTOR data; } USB_CONFIGURATION_DESCRIPTOR_SHORT; -#pragma pack() +#pragma pack(pop) #ifndef USB_HUB_CAP_FLAGS typedef union _USB_HUB_CAP_FLAGS {