📄 windows.c
字号:
/* LIBUSB-WIN32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
* Copyright (c) 2000-2005 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <windows.h>
#include <winioctl.h>
#include <setupapi.h>
#include "usb.h"
#include "error.h"
#include "usbi.h"
#include "driver_api.h"
#include "registry.h"
#define LIBUSB_DEFAULT_TIMEOUT 5000
#define LIBUSB_DEVICE_NAME "\\\\.\\libusb0-"
#define LIBUSB_BUS_NAME "bus-0"
#define LIBUSB_MAX_DEVICES 256
extern int __usb_debug;
typedef struct {
usb_dev_handle *dev;
libusb_request req;
char *bytes;
int size;
DWORD control_code;
OVERLAPPED ol;
} usb_context_t;
static struct usb_version _usb_version = {
{ VERSION_MAJOR,
VERSION_MINOR,
VERSION_MICRO,
VERSION_NANO },
{ -1, -1, -1, -1 }
};
static int _usb_setup_async(usb_dev_handle *dev, void **context,
DWORD control_code,
unsigned char ep, int pktsize);
static int _usb_transfer_sync(usb_dev_handle *dev, int control_code,
int ep, int pktsize, char *bytes, int size,
int timeout);
/* static int usb_get_configuration(usb_dev_handle *dev); */
static int _usb_cancel_io(usb_context_t *context);
static int _usb_abort_ep(usb_dev_handle *dev, unsigned int ep);
static int _usb_io_sync(HANDLE dev, unsigned int code, void *in, int in_size,
void *out, int out_size, int *ret);
static int _usb_reap_async(void *context, int timeout, int cancel);
static int _usb_add_virtual_hub(struct usb_bus *bus);
static void _usb_free_bus_list(struct usb_bus *bus);
static void _usb_free_dev_list(struct usb_device *dev);
static void _usb_deinit(void);
/* DLL main entry point */
BOOL WINAPI DllMain(HANDLE module, DWORD reason, LPVOID reserved)
{
switch(reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
_usb_deinit();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
default:
break;
}
return TRUE;
}
/* static int usb_get_configuration(usb_dev_handle *dev) */
/* { */
/* int ret; */
/* char config; */
/* ret = usb_control_msg(dev, USB_RECIP_DEVICE | USB_ENDPOINT_IN, */
/* USB_REQ_GET_CONFIGURATION, 0, 0, &config, 1, */
/* LIBUSB_DEFAULT_TIMEOUT); */
/* if(ret >= 0) */
/* { */
/* return config; */
/* } */
/* return ret; */
/* } */
int usb_os_open(usb_dev_handle *dev)
{
char dev_name[LIBUSB_PATH_MAX];
char *p;
/* int config; */
if(!dev)
{
usb_error("usb_os_open: invalid device handle %p", dev);
return -EINVAL;
}
dev->impl_info = INVALID_HANDLE_VALUE;
dev->config = 0;
dev->interface = -1;
dev->altsetting = -1;
if(!dev->device->filename)
{
usb_error("usb_os_open: invalid file name");
return -ENOENT;
}
/* build the Windows file name from the unique device name */
strcpy(dev_name, dev->device->filename);
p = strstr(dev_name, "--");
if(!p)
{
usb_error("usb_os_open: invalid file name %s", dev->device->filename);
return -ENOENT;
}
*p = 0;
dev->impl_info = CreateFile(dev_name, 0, 0, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if(dev->impl_info == INVALID_HANDLE_VALUE)
{
usb_error("usb_os_open: failed to open %s: win error: %s",
dev->device->filename, usb_win_error_to_string());
return -ENOENT;
}
/* now, retrieve the device's current configuration, except from hubs */
/* if(dev->device->config && dev->device->config->interface */
/* && dev->device->config->interface[0].altsetting */
/* && dev->device->config->interface[0].altsetting[0].bInterfaceClass */
/* != USB_CLASS_HUB) */
/* { */
/* config = usb_get_configuration(dev); */
/* if(config > 0) */
/* { */
/* dev->config = config; */
/* } */
/* } */
return 0;
}
int usb_os_close(usb_dev_handle *dev)
{
if(dev->impl_info != INVALID_HANDLE_VALUE)
{
if(dev->interface >= 0)
{
usb_release_interface(dev, dev->interface);
}
CloseHandle(dev->impl_info);
dev->impl_info = INVALID_HANDLE_VALUE;
dev->interface = -1;
dev->altsetting = -1;
}
return 0;
}
int usb_set_configuration(usb_dev_handle *dev, int configuration)
{
libusb_request req;
if(dev->impl_info == INVALID_HANDLE_VALUE)
{
usb_error("usb_set_configuration: error: device not open");
return -EINVAL;
}
if(dev->config == configuration)
{
return 0;
}
if(dev->interface >= 0)
{
usb_error("usb_set_configuration: can't change configuration, "
"an interface is still in use (claimed)");
return -EINVAL;
}
req.configuration.configuration = configuration;
req.timeout = LIBUSB_DEFAULT_TIMEOUT;
if(!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_SET_CONFIGURATION,
&req, sizeof(libusb_request), NULL, 0, NULL))
{
usb_error("usb_set_configuration: could not set config %d: "
"win error: %s", configuration, usb_win_error_to_string());
return -usb_win_error_to_errno();
}
dev->config = configuration;
dev->interface = -1;
dev->altsetting = -1;
return 0;
}
int usb_claim_interface(usb_dev_handle *dev, int interface)
{
libusb_request req;
if(dev->impl_info == INVALID_HANDLE_VALUE)
{
usb_error("usb_claim_interface: device not open");
return -EINVAL;
}
if(!dev->config)
{
usb_error("usb_claim_interface: could not claim interface %d, invalid "
"configuration %d", interface, dev->config);
return -EINVAL;
}
if(dev->interface == interface)
{
return 0;
}
req.interface.interface = interface;
if(!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_CLAIM_INTERFACE,
&req, sizeof(libusb_request), NULL, 0, NULL))
{
usb_error("usb_claim_interface: could not claim interface %d, "
"win error: %s", interface, usb_win_error_to_string());
return -usb_win_error_to_errno();
}
else
{
dev->interface = interface;
dev->altsetting = 0;
return 0;
}
}
int usb_release_interface(usb_dev_handle *dev, int interface)
{
libusb_request req;
if(dev->impl_info == INVALID_HANDLE_VALUE)
{
usb_error("usb_release_interface: device not open");
return -EINVAL;
}
if(!dev->config)
{
usb_error("usb_release_interface: could not release interface %d, "
"invalid configuration %d", interface, dev->config);
return -EINVAL;
}
req.interface.interface = interface;
if(!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_RELEASE_INTERFACE,
&req, sizeof(libusb_request), NULL, 0, NULL))
{
usb_error("usb_release_interface: could not release interface %d, "
"win error: %s", interface, usb_win_error_to_string());
return -usb_win_error_to_errno();
}
else
{
dev->interface = -1;
dev->altsetting = -1;
return 0;
}
}
int usb_set_altinterface(usb_dev_handle *dev, int alternate)
{
libusb_request req;
if(dev->impl_info == INVALID_HANDLE_VALUE)
{
usb_error("usb_set_altinterface: device not open");
return -EINVAL;
}
if(dev->config <= 0)
{
usb_error("usb_set_altinterface: could not set alt interface %d: "
"invalid configuration %d", alternate, dev->config);
return -EINVAL;
}
if(dev->interface < 0)
{
usb_error("usb_set_altinterface: could not set alt interface %d: "
"no interface claimed", alternate);
return -EINVAL;
}
req.interface.interface = dev->interface;
req.interface.altsetting = alternate;
req.timeout = LIBUSB_DEFAULT_TIMEOUT;
if(!_usb_io_sync(dev->impl_info, LIBUSB_IOCTL_SET_INTERFACE,
&req, sizeof(libusb_request),
NULL, 0, NULL))
{
usb_error("usb_set_altinterface: could not set alt interface "
"%d/%d: win error: %s",
dev->interface, alternate, usb_win_error_to_string());
return -usb_win_error_to_errno();
}
dev->altsetting = alternate;
return 0;
}
static int _usb_setup_async(usb_dev_handle *dev, void **context,
DWORD control_code,
unsigned char ep, int pktsize)
{
usb_context_t **c = (usb_context_t **)context;
if(((control_code == LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE)
|| (control_code == LIBUSB_IOCTL_ISOCHRONOUS_WRITE))
&& (ep & USB_ENDPOINT_IN))
{
usb_error("_usb_setup_async: invalid endpoint 0x%02x", ep);
return -EINVAL;
}
if(((control_code == LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ)
|| (control_code == LIBUSB_IOCTL_ISOCHRONOUS_READ))
&& !(ep & USB_ENDPOINT_IN))
{
usb_error("_usb_setup_async: invalid endpoint 0x%02x", ep);
return -EINVAL;
}
*c = malloc(sizeof(usb_context_t));
if(!*c)
{
usb_error("_usb_setup_async: memory allocation error");
return -ENOMEM;
}
memset(*c, 0, sizeof(usb_context_t));
(*c)->dev = dev;
(*c)->req.endpoint.endpoint = ep;
(*c)->req.endpoint.packet_size = pktsize;
(*c)->control_code = control_code;
(*c)->ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!(*c)->ol.hEvent)
{
free(*c);
*c = NULL;
usb_error("_usb_setup_async: creating event failed: win error: %s",
usb_win_error_to_string());
return -usb_win_error_to_errno();
}
return 0;
}
int usb_submit_async(void *context, char *bytes, int size)
{
usb_context_t *c = (usb_context_t *)context;
if(!c)
{
usb_error("usb_submit_async: invalid context");
return -EINVAL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -