Machine Interface Utility:VER1.0

This commit is contained in:
TAO Cheng
2013-05-09 20:29:54 +08:00
commit 036cdcb228
743 changed files with 104786 additions and 0 deletions
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level='requireAdministrator' uiAccess='false' />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
@@ -0,0 +1,572 @@
/*
* Parses descriptors
*
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is covered by the LGPL, read LICENSE for details.
*/
#include <stdio.h>
#include <string.h>
#include "usbi.h"
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
unsigned char type, unsigned char index, void *buf, int size)
{
memset(buf, 0, size);
return usb_control_msg(udev, ep | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(type << 8) + index, 0, buf, size, 1000);
}
int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, int size)
{
memset(buf, 0, size);
return usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(type << 8) + index, 0, buf, size, 1000);
}
int usb_parse_descriptor(unsigned char *source, char *description, void *dest)
{
unsigned char *sp = source, *dp = dest;
uint16_t w;
uint32_t d;
char *cp;
for (cp = description; *cp; cp++)
{
switch (*cp)
{
case 'b': /* 8-bit byte */
*dp++ = *sp++;
break;
case 'w': /* 16-bit word, convert from little endian to CPU */
w = (sp[1] << 8) | sp[0];
sp += 2;
//dp += ((unsigned long)dp & 1); /* Align to word boundary */
*((uint16_t *)dp) = w;
dp += 2;
break;
case 'd': /* 32-bit dword, convert from little endian to CPU */
d = (sp[3] << 24) | (sp[2] << 16) | (sp[1] << 8) | sp[0];
sp += 4;
//dp += ((unsigned long)dp & 2); /* Align to dword boundary */
*((uint32_t *)dp) = d;
dp += 4;
break;
/* These two characters are undocumented and just a hack for Linux */
case 'W': /* 16-bit word, keep CPU endianess */
//dp += ((unsigned long)dp & 1); /* Align to word boundary */
memcpy(dp, sp, 2);
sp += 2;
dp += 2;
break;
case 'D': /* 32-bit dword, keep CPU endianess */
//dp += ((unsigned long)dp & 2); /* Align to dword boundary */
memcpy(dp, sp, 4);
sp += 4;
dp += 4;
break;
}
}
return (int)(sp - source);
}
/*
* This code looks surprisingly similar to the code I wrote for the Linux
* kernel. It's not a coincidence :)
*/
static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
{
struct usb_descriptor_header header;
unsigned char *begin;
int parsed = 0, len, numskipped;
usb_parse_descriptor(buffer, "bb", &header);
/* Everything should be fine being passed into here, but we sanity */
/* check JIC */
if (header.bLength > size)
{
if (usb_debug >= 1)
fprintf(stderr, "ran out of descriptors parsing\n");
return -1;
}
if (header.bDescriptorType != USB_DT_ENDPOINT)
{
if (usb_debug >= 2)
fprintf(stderr, "unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X\n",
header.bDescriptorType, USB_DT_ENDPOINT);
return parsed;
}
if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)
usb_parse_descriptor(buffer, "bbbbwbbb", endpoint);
else if (header.bLength >= ENDPOINT_DESC_LENGTH)
usb_parse_descriptor(buffer, "bbbbwb", endpoint);
buffer += header.bLength;
size -= header.bLength;
parsed += header.bLength;
/* Skip over the rest of the Class Specific or Vendor Specific */
/* descriptors */
begin = buffer;
numskipped = 0;
while (size >= DESC_HEADER_LENGTH)
{
usb_parse_descriptor(buffer, "bb", &header);
if (header.bLength < 2)
{
if (usb_debug >= 1)
fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
return -1;
}
/* If we find another "proper" descriptor then we're done */
if ((header.bDescriptorType == USB_DT_ENDPOINT) ||
(header.bDescriptorType == USB_DT_INTERFACE) ||
(header.bDescriptorType == USB_DT_CONFIG) ||
(header.bDescriptorType == USB_DT_DEVICE))
break;
if (usb_debug >= 1)
fprintf(stderr, "skipping descriptor 0x%X\n", header.bDescriptorType);
numskipped++;
buffer += header.bLength;
size -= header.bLength;
parsed += header.bLength;
}
if (numskipped && usb_debug >= 2)
fprintf(stderr, "skipped %d class/vendor specific endpoint descriptors\n", numskipped);
/* Copy any unknown descriptors into a storage area for drivers */
/* to later parse */
len = (int)(buffer - begin);
if (!len)
{
endpoint->extra = NULL;
endpoint->extralen = 0;
return parsed;
}
endpoint->extra = malloc(len);
if (!endpoint->extra)
{
if (usb_debug >= 1)
fprintf(stderr, "couldn't allocate memory for endpoint extra descriptors\n");
endpoint->extralen = 0;
return parsed;
}
memcpy(endpoint->extra, begin, len);
endpoint->extralen = len;
return parsed;
}
static int usb_parse_interface(struct usb_interface *interface,
unsigned char *buffer, int size)
{
int i, len, numskipped, retval, parsed = 0;
struct usb_descriptor_header header;
struct usb_interface_descriptor *ifp;
unsigned char *begin;
interface->num_altsetting = 0;
while (size >= INTERFACE_DESC_LENGTH)
{
interface->altsetting = realloc(interface->altsetting, sizeof(struct usb_interface_descriptor) * (interface->num_altsetting + 1));
if (!interface->altsetting)
{
if (usb_debug >= 1)
fprintf(stderr, "couldn't malloc interface->altsetting\n");
return -1;
}
ifp = interface->altsetting + interface->num_altsetting;
interface->num_altsetting++;
usb_parse_descriptor(buffer, "bbbbbbbbb", ifp);
/* Skip over the interface */
buffer += ifp->bLength;
parsed += ifp->bLength;
size -= ifp->bLength;
begin = buffer;
numskipped = 0;
/* Skip over any interface, class or vendor descriptors */
while (size >= DESC_HEADER_LENGTH)
{
usb_parse_descriptor(buffer, "bb", &header);
if (header.bLength < 2)
{
if (usb_debug >= 1)
fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
return -1;
}
/* If we find another "proper" descriptor then we're done */
if ((header.bDescriptorType == USB_DT_INTERFACE) ||
(header.bDescriptorType == USB_DT_ENDPOINT) ||
(header.bDescriptorType == USB_DT_CONFIG) ||
(header.bDescriptorType == USB_DT_DEVICE))
break;
numskipped++;
buffer += header.bLength;
parsed += header.bLength;
size -= header.bLength;
}
if (numskipped && usb_debug >= 2)
fprintf(stderr, "skipped %d class/vendor specific interface descriptors\n", numskipped);
/* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */
len = (int)(buffer - begin);
if (!len)
{
ifp->extra = NULL;
ifp->extralen = 0;
}
else
{
ifp->extra = malloc(len);
if (!ifp->extra)
{
if (usb_debug >= 1)
fprintf(stderr, "couldn't allocate memory for interface extra descriptors\n");
ifp->extralen = 0;
return -1;
}
memcpy(ifp->extra, begin, len);
ifp->extralen = len;
}
/* Did we hit an unexpected descriptor? */
usb_parse_descriptor(buffer, "bb", &header);
if ((size >= DESC_HEADER_LENGTH) &&
((header.bDescriptorType == USB_DT_CONFIG) ||
(header.bDescriptorType == USB_DT_DEVICE)))
return parsed;
if (ifp->bNumEndpoints > USB_MAXENDPOINTS)
{
if (usb_debug >= 1)
fprintf(stderr, "too many endpoints\n");
return -1;
}
if (ifp->bNumEndpoints > 0)
{
ifp->endpoint = (struct usb_endpoint_descriptor *)
malloc(ifp->bNumEndpoints *
sizeof(struct usb_endpoint_descriptor));
if (!ifp->endpoint)
{
if (usb_debug >= 1)
fprintf(stderr, "couldn't allocate memory for ifp->endpoint\n");
return -1;
}
memset(ifp->endpoint, 0, ifp->bNumEndpoints *
sizeof(struct usb_endpoint_descriptor));
for (i = 0; i < ifp->bNumEndpoints; i++)
{
usb_parse_descriptor(buffer, "bb", &header);
if (header.bLength > size)
{
if (usb_debug >= 1)
fprintf(stderr, "ran out of descriptors parsing\n");
return -1;
}
retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
if (retval < 0)
return retval;
buffer += retval;
parsed += retval;
size -= retval;
}
}
else
ifp->endpoint = NULL;
/* We check to see if it's an alternate to this one */
ifp = (struct usb_interface_descriptor *)buffer;
if (size < USB_DT_INTERFACE_SIZE ||
ifp->bDescriptorType != USB_DT_INTERFACE ||
!ifp->bAlternateSetting)
return parsed;
}
return parsed;
}
int usb_parse_configuration(struct usb_config_descriptor *config,
unsigned char *buffer)
{
int i, retval, size;
struct usb_descriptor_header header;
usb_parse_descriptor(buffer, "bbwbbbbb", config);
size = config->wTotalLength;
if (config->bNumInterfaces > USB_MAXINTERFACES)
{
if (usb_debug >= 1)
fprintf(stderr, "too many interfaces\n");
return -1;
}
config->interface = (struct usb_interface *)
malloc(config->bNumInterfaces *
sizeof(struct usb_interface));
if (!config->interface)
{
if (usb_debug >= 1)
fprintf(stderr, "out of memory\n");
return -1;
}
memset(config->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface));
buffer += config->bLength;
size -= config->bLength;
config->extra = NULL;
config->extralen = 0;
for (i = 0; i < config->bNumInterfaces; i++)
{
int numskipped, len;
unsigned char *begin;
/* Skip over the rest of the Class Specific or Vendor */
/* Specific descriptors */
begin = buffer;
numskipped = 0;
while (size >= DESC_HEADER_LENGTH)
{
usb_parse_descriptor(buffer, "bb", &header);
if ((header.bLength > size) || (header.bLength < DESC_HEADER_LENGTH))
{
if (usb_debug >= 1)
fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
return -1;
}
/* If we find another "proper" descriptor then we're done */
if ((header.bDescriptorType == USB_DT_ENDPOINT) ||
(header.bDescriptorType == USB_DT_INTERFACE) ||
(header.bDescriptorType == USB_DT_CONFIG) ||
(header.bDescriptorType == USB_DT_DEVICE))
break;
if (usb_debug >= 2)
fprintf(stderr, "skipping descriptor 0x%X\n", header.bDescriptorType);
numskipped++;
buffer += header.bLength;
size -= header.bLength;
}
if (numskipped && usb_debug >= 2)
fprintf(stderr, "skipped %d class/vendor specific endpoint descriptors\n", numskipped);
/* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */
len = (int)(buffer - begin);
if (len)
{
/* FIXME: We should realloc and append here */
if (!config->extralen)
{
config->extra = malloc(len);
if (!config->extra)
{
if (usb_debug >= 1)
fprintf(stderr, "couldn't allocate memory for config extra descriptors\n");
config->extralen = 0;
return -1;
}
memcpy(config->extra, begin, len);
config->extralen = len;
}
}
retval = usb_parse_interface(config->interface + i, buffer, size);
if (retval < 0)
return retval;
buffer += retval;
size -= retval;
}
return size;
}
void usb_destroy_configuration(struct usb_device *dev)
{
int c, i, j, k;
if (!dev->config)
return;
for (c = 0; c < dev->descriptor.bNumConfigurations; c++)
{
struct usb_config_descriptor *cf = &dev->config[c];
if (!cf->interface)
continue;
for (i = 0; i < cf->bNumInterfaces; i++)
{
struct usb_interface *ifp = &cf->interface[i];
if (!ifp->altsetting)
continue;
for (j = 0; j < ifp->num_altsetting; j++)
{
struct usb_interface_descriptor *as = &ifp->altsetting[j];
if (as->extra)
free(as->extra);
if (!as->endpoint)
continue;
for (k = 0; k < as->bNumEndpoints; k++)
{
if (as->endpoint[k].extra)
free(as->endpoint[k].extra);
}
free(as->endpoint);
}
free(ifp->altsetting);
}
free(cf->interface);
}
free(dev->config);
}
void usb_fetch_and_parse_descriptors(usb_dev_handle *udev)
{
struct usb_device *dev = udev->device;
int i;
if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG)
{
if (usb_debug >= 1)
fprintf(stderr, "Too many configurations (%d > %d)\n", dev->descriptor.bNumConfigurations, USB_MAXCONFIG);
return;
}
if (dev->descriptor.bNumConfigurations < 1)
{
if (usb_debug >= 1)
fprintf(stderr, "Not enough configurations (%d < %d)\n", dev->descriptor.bNumConfigurations, 1);
return;
}
dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor));
if (!dev->config)
{
if (usb_debug >= 1)
fprintf(stderr, "Unable to allocate memory for config descriptor\n");
return;
}
memset(dev->config, 0, dev->descriptor.bNumConfigurations *
sizeof(struct usb_config_descriptor));
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
{
unsigned char buffer[USB_DT_CONFIG_SIZE], *bigbuffer;
struct usb_config_descriptor config;
int res;
/* Get the first 8 bytes so we can figure out what the total length is */
res = usb_get_descriptor(udev, USB_DT_CONFIG, (unsigned char)i, buffer, USB_DT_CONFIG_SIZE);
if (res < USB_DT_CONFIG_SIZE)
{
if (usb_debug >= 1)
{
if (res < 0)
fprintf(stderr, "Unable to get descriptor (%d)\n", res);
else
fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", USB_DT_CONFIG_SIZE, res);
}
goto err;
}
usb_parse_descriptor(buffer, "bbw", &config);
bigbuffer = malloc(config.wTotalLength);
if (!bigbuffer)
{
if (usb_debug >= 1)
fprintf(stderr, "Unable to allocate memory for descriptors\n");
goto err;
}
res = usb_get_descriptor(udev, USB_DT_CONFIG, (unsigned char)i, bigbuffer,
config.wTotalLength);
if (res < config.wTotalLength)
{
if (usb_debug >= 1)
{
if (res < 0)
fprintf(stderr, "Unable to get descriptor (%d)\n", res);
else
fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, res);
}
free(bigbuffer);
goto err;
}
res = usb_parse_configuration(&dev->config[i], bigbuffer);
if (usb_debug >= 2)
{
if (res > 0)
fprintf(stderr, "Descriptor data still left\n");
else if (res < 0)
fprintf(stderr, "Unable to parse descriptors\n");
}
free(bigbuffer);
}
return;
err:
free(dev->config);
dev->config = NULL;
}
@@ -0,0 +1,56 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS abort_endpoint(libusb_device_t *dev, int endpoint, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
USBMSG("endpoint: 0x%02x timeout: %d\n", endpoint, timeout);
memset(&urb, 0, sizeof(struct _URB_PIPE_REQUEST));
if (!dev->config.value)
{
USBERR0("invalid configuration 0\n");
return STATUS_INVALID_DEVICE_STATE;
}
if (!get_pipe_handle(dev, endpoint, &urb.UrbPipeRequest.PipeHandle))
{
USBERR0("getting endpoint pipe failed\n");
return STATUS_INVALID_PARAMETER;
}
urb.UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
urb.UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("request failed: status: 0x%x, urb-status: 0x%x\n", status, urb.UrbHeader.Status);
}
return status;
}
@@ -0,0 +1,63 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS claim_interface(libusb_device_t *dev, FILE_OBJECT *file_object,
int interface)
{
USBMSG("interface %d\n", interface);
if (!dev->config.value)
{
USBERR0("device is not configured\n");
return STATUS_INVALID_DEVICE_STATE;
}
if (interface >= LIBUSB_MAX_NUMBER_OF_INTERFACES)
{
USBERR("interface number %d too high\n",
interface);
return STATUS_INVALID_PARAMETER;
}
if (!dev->config.interfaces[interface].valid)
{
USBERR("interface %d does not exist\n", interface);
return STATUS_INVALID_PARAMETER;
}
if (dev->config.interfaces[interface].file_object == file_object)
{
return STATUS_SUCCESS;
}
if (dev->config.interfaces[interface].file_object)
{
USBERR("could not claim interface %d, interface is already claimed\n", interface);
return STATUS_DEVICE_BUSY;
}
dev->config.interfaces[interface].file_object = file_object;
return STATUS_SUCCESS;
}
@@ -0,0 +1,64 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS clear_feature(libusb_device_t *dev,
int recipient, int index, int feature, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
USBMSG("recipient: %02d index: %04d feature: %04d timeout: %d\n",
recipient,index,feature,timeout);
memset(&urb, 0, sizeof(struct _URB_CONTROL_FEATURE_REQUEST));
switch (recipient)
{
case USB_RECIP_DEVICE:
urb.UrbHeader.Function = URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE;
break;
case USB_RECIP_INTERFACE:
urb.UrbHeader.Function = URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE;
break;
case USB_RECIP_ENDPOINT:
urb.UrbHeader.Function = URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT;
break;
case USB_RECIP_OTHER:
urb.UrbHeader.Function = URB_FUNCTION_CLEAR_FEATURE_TO_OTHER;
break;
default:
USBERR0("invalid recipient\n");
return STATUS_INVALID_PARAMETER;
}
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_FEATURE_REQUEST);
urb.UrbControlFeatureRequest.FeatureSelector = (USHORT)feature;
urb.UrbControlFeatureRequest.Index = (USHORT)index;
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("clearing feature failed: status: 0x%x, urb-status: 0x%x\n", status, urb.UrbHeader.Status);
}
return status;
}
@@ -0,0 +1,99 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS DDKAPI dispatch(DEVICE_OBJECT *device_object, IRP *irp)
{
libusb_device_t *dev = device_object->DeviceExtension;
IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
switch (stack_location->MajorFunction)
{
case IRP_MJ_PNP:
return dispatch_pnp(dev, irp);
case IRP_MJ_POWER:
// ID: 2960644 (farthen)
// You can't set the power state if the device is not handled at all
if(!dev->next_stack_device)
{
return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0);
}
return dispatch_power(dev, irp);
}
/* since this driver may run as an upper filter we have to check whether */
/* the IRP is sent to this device object or to the lower one */
if (accept_irp(dev, irp))
{
switch (stack_location->MajorFunction)
{
case IRP_MJ_DEVICE_CONTROL:
if (dev->is_started)
{
return dispatch_ioctl(dev, irp);
}
else /* not started yet */
{
return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0);
}
case IRP_MJ_CREATE:
if (dev->is_started)
{
// only one driver can act as power policy owner and
// power_set_device_state() can only be issued by the PPO.
// disallow_power_control is set to true for drivers which
// we know cause a BSOD on any attempt to request power irps.
if (dev->power_state.DeviceState != PowerDeviceD0 && !dev->disallow_power_control)
{
/* power up the device, block until the call */
/* completes */
power_set_device_state(dev, PowerDeviceD0, TRUE);
}
return complete_irp(irp, STATUS_SUCCESS, 0);
}
else /* not started yet */
{
return complete_irp(irp, STATUS_INVALID_DEVICE_STATE, 0);
}
case IRP_MJ_CLOSE:
/* release all interfaces bound to this file object */
release_all_interfaces(dev, stack_location->FileObject);
return complete_irp(irp, STATUS_SUCCESS, 0);
case IRP_MJ_CLEANUP:
return complete_irp(irp, STATUS_SUCCESS, 0);
default:
return complete_irp(irp, STATUS_NOT_SUPPORTED, 0);
}
}
else /* the IRP is for the lower device object */
{
return pass_irp_down(dev, irp, NULL, NULL);
}
}
@@ -0,0 +1,227 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __DRIVER_API_H__
#define __DRIVER_API_H__
enum
{
LIBUSB_DEBUG_OFF,
LIBUSB_DEBUG_ERR,
LIBUSB_DEBUG_WRN,
LIBUSB_DEBUG_MSG,
LIBUSB_DEBUG_MAX = 0xff,
};
/* 64k */
#define LIBUSB_MAX_READ_WRITE 0x10000
#define LIBUSB_MAX_NUMBER_OF_DEVICES 256
#define LIBUSB_MAX_NUMBER_OF_CHILDREN 32
#define LIBUSB_IOCTL_SET_CONFIGURATION CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_GET_CONFIGURATION CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_SET_INTERFACE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_GET_INTERFACE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_SET_FEATURE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_CLEAR_FEATURE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x806, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_GET_STATUS CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x807, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_SET_DESCRIPTOR CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x808, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_GET_DESCRIPTOR CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x809, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x80A, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x80B, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_VENDOR_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x80C, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_VENDOR_READ CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x80D, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_RESET_ENDPOINT CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x80E, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_ABORT_ENDPOINT CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x80F, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_RESET_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x810, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_SET_DEBUG_LEVEL CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x811, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_GET_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x812, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_ISOCHRONOUS_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x813, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_ISOCHRONOUS_READ CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x814, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_CLAIM_INTERFACE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x815, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_RELEASE_INTERFACE CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x816, METHOD_BUFFERED, FILE_ANY_ACCESS)
/////////////////////////////////////////////////////////////////////////////
// supported after 0.1.12.2
/////////////////////////////////////////////////////////////////////////////
// [trobinso] adds support for querying device properties
#define LIBUSB_IOCTL_GET_DEVICE_PROPERTY CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define LIBUSB_IOCTL_GET_CUSTOM_REG_PROPERTY CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// supported after 1.2.0.0
/////////////////////////////////////////////////////////////////////////////
#define LIBUSB_IOCTL_GET_CACHED_CONFIGURATION CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x902, METHOD_BUFFERED, FILE_ANY_ACCESS)
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// supported after 1.2.2.0
/////////////////////////////////////////////////////////////////////////////
#define LIBUSB_IOCTL_GET_OBJECT_NAME CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x8FF, METHOD_BUFFERED, FILE_ANY_ACCESS)
/////////////////////////////////////////////////////////////////////////////
#include <pshpack1.h>
enum LIBUSB0_TRANSFER_FLAGS
{
TRANSFER_FLAGS_SHORT_NOT_OK = 1 << 0,
TRANSFER_FLAGS_ISO_SET_START_FRAME = 1 << 30,
TRANSFER_FLAGS_ISO_ADD_LATENCY = 1 << 31,
};
typedef struct
{
unsigned int timeout;
union
{
struct
{
unsigned int configuration;
} configuration;
struct
{
unsigned int interface;
unsigned int altsetting;
} interface;
struct
{
unsigned int endpoint;
unsigned int packet_size;
// TODO: max_transfer_size, short transfer not ok, use iso_start_frame
unsigned int max_transfer_size;
unsigned int transfer_flags;
unsigned int iso_start_frame_latency;
} endpoint;
struct
{
unsigned int type;
unsigned int recipient;
unsigned int request;
unsigned int value;
unsigned int index;
} vendor;
struct
{
unsigned int recipient;
unsigned int feature;
unsigned int index;
} feature;
struct
{
unsigned int recipient;
unsigned int index;
unsigned int status;
} status;
struct
{
unsigned int type;
unsigned int index;
unsigned int language_id;
unsigned int recipient;
} descriptor;
struct
{
unsigned int level;
} debug;
struct
{
unsigned int major;
unsigned int minor;
unsigned int micro;
unsigned int nano;
unsigned int mod_value;
} version;
struct
{
unsigned int property;
} device_property;
struct
{
unsigned int key_type;
unsigned int name_offset;
unsigned int value_offset;
unsigned int value_length;
} device_registry_key;
struct
{
// 0 - device plug and play registry key pathname
unsigned int objname_index;
} objname;
};
} libusb_request;
#include <poppack.h>
#endif
@@ -0,0 +1,75 @@
/* LIBUSB-WIN32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
#include <stdio.h>
#include <stdarg.h>
int debug_level = LIBUSB_DEBUG_MSG;
void DEBUG_PRINT_NL()
{
#ifdef DBG
if (debug_level >= LIBUSB_DEBUG_MSG)
DbgPrint(("\n"));
#endif
}
void DEBUG_SET_LEVEL(int level)
{
#ifdef DBG
debug_level = level;
#endif
}
void DEBUG_MESSAGE(const char *format, ...)
{
#ifdef DBG
char tmp[256];
if (debug_level >= LIBUSB_DEBUG_MSG)
{
va_list args;
va_start(args, format);
_vsnprintf(tmp, sizeof(tmp) - 1, format, args);
va_end(args);
DbgPrint("LIBUSB-DRIVER - %s", tmp);
}
#endif
}
void DEBUG_ERROR(const char *format, ...)
{
#ifdef DBG
char tmp[256];
if (debug_level >= LIBUSB_DEBUG_ERR)
{
va_list args;
va_start(args, format);
_vsnprintf(tmp, sizeof(tmp) - 1, format, args);
va_end(args);
DbgPrint("LIBUSB-DRIVER - %s", tmp);
}
#endif
}
@@ -0,0 +1,30 @@
/* LIBUSB-WIN32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LIBUSB_DEBUG_H__
#define __LIBUSB_DEBUG_H__
void DEBUG_PRINT_NL();
void DEBUG_SET_LEVEL(int level);
void DEBUG_MESSAGE(const char *format, ...);
void DEBUG_ERROR(const char *format, ...);
#endif
@@ -0,0 +1,275 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
/* missing in mingw's ddk headers */
#ifndef PLUGPLAY_REGKEY_DEVICE
#define PLUGPLAY_REGKEY_DEVICE 1
#endif
#define LIBUSB_REG_SURPRISE_REMOVAL_OK L"SurpriseRemovalOK"
#define LIBUSB_REG_INITIAL_CONFIG_VALUE L"InitialConfigValue"
static bool_t reg_get_property(DEVICE_OBJECT *physical_device_object,
int property, char *data, int size);
static bool_t reg_get_property(DEVICE_OBJECT *physical_device_object,
int property, char *data, int size)
{
WCHAR tmp[512];
ULONG ret;
ULONG i;
if (!physical_device_object || !data || !size)
{
return FALSE;
}
memset(data, 0, size);
memset(tmp, 0, sizeof(tmp));
if (NT_SUCCESS(IoGetDeviceProperty(physical_device_object,
property,
sizeof(tmp) - 2,
tmp,
&ret)) && ret)
{
/* convert unicode string to normal character string */
for (i = 0; (i < ret/2) && (i < ((ULONG)size - 1)); i++)
{
data[i] = (char)tmp[i];
}
_strlwr(data);
return TRUE;
}
return FALSE;
}
bool_t reg_get_properties(libusb_device_t *dev)
{
HANDLE key = NULL;
PVOID keyObject = NULL;
NTSTATUS status;
UNICODE_STRING surprise_removal_ok_name;
UNICODE_STRING initial_config_value_name;
KEY_VALUE_FULL_INFORMATION *info;
ULONG pool_length;
ULONG length;
ULONG val;
if (!dev->physical_device_object)
{
return FALSE;
}
/* default settings */
dev->surprise_removal_ok = FALSE;
dev->is_filter = TRUE;
dev->initial_config_value = SET_CONFIG_ACTIVE_CONFIG;
status = IoOpenDeviceRegistryKey(dev->physical_device_object,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_ALL,
&key);
if (NT_SUCCESS(status))
{
RtlInitUnicodeString(&surprise_removal_ok_name,
LIBUSB_REG_SURPRISE_REMOVAL_OK);
RtlInitUnicodeString(&initial_config_value_name,
LIBUSB_REG_INITIAL_CONFIG_VALUE);
pool_length = sizeof(KEY_VALUE_FULL_INFORMATION) + 512;
info = ExAllocatePool(NonPagedPool, pool_length);
if (!info)
{
ZwClose(key);
USBERR("ExAllocatePool failed allocating %d bytes\n", pool_length);
return FALSE;
}
// get surprise_removal_ok
// get is_filter
length = pool_length;
memset(info, 0, length);
status = ZwQueryValueKey(key, &surprise_removal_ok_name,
KeyValueFullInformation, info, length, &length);
if (NT_SUCCESS(status) && (info->Type == REG_DWORD))
{
val = *((ULONG *)(((char *)info) + info->DataOffset));
dev->surprise_removal_ok = val ? TRUE : FALSE;
dev->is_filter = FALSE;
}
// get initial_config_value
length = pool_length;
memset(info, 0, length);
status = ZwQueryValueKey(key, &initial_config_value_name,
KeyValueFullInformation, info, length, &length);
if (NT_SUCCESS(status) && (info->Type == REG_DWORD))
{
val = *((ULONG *)(((char *)info) + info->DataOffset));
dev->initial_config_value = (int)val;
}
status = ObReferenceObjectByHandle(key, KEY_READ, NULL, KernelMode, &keyObject, NULL);
if (NT_SUCCESS(status))
{
length = pool_length;
memset(info, 0, length);
status = ObQueryNameString(keyObject, (POBJECT_NAME_INFORMATION)info, length, &length);
if (NT_SUCCESS(status))
{
PWSTR nameW =((POBJECT_NAME_INFORMATION)info)->Name.Buffer;
PSTR nameA = dev->objname_plugplay_registry_key;
val=0;
while (nameW[val] && val < (length/2))
{
*nameA=(char)nameW[val];
nameA++;
val++;
}
*nameA='\0';
USBDBG("reg-key-name=%s\n",dev->objname_plugplay_registry_key);
}
else
{
USBERR("ObQueryNameString failed. status=%Xh\n",status);
}
ObDereferenceObject(keyObject);
}
else
{
USBERR("ObReferenceObjectByHandle failed. status=%Xh\n",status);
}
ExFreePool(info);
ZwClose(key);
}
return TRUE;
}
bool_t reg_get_hardware_id(DEVICE_OBJECT *physical_device_object,
char *data, int size)
{
if (!physical_device_object || !data || !size)
{
return FALSE;
}
return reg_get_property(physical_device_object, DevicePropertyHardwareID,
data, size);
}
bool_t reg_get_compatible_id(DEVICE_OBJECT *physical_device_object,
char *data, int size)
{
if (!physical_device_object || !data || !size)
{
return FALSE;
}
return reg_get_property(physical_device_object, DevicePropertyCompatibleIDs,
data, size);
}
/*
Gets a device property for the device_object.
Returns: NTSTATUS code from IoGetDeviceProperty
STATUS_INVALID_PARAMETER
*/
NTSTATUS reg_get_device_property(PDEVICE_OBJECT device_object,
int property,
char* data_buffer,
int data_length,
int* actual_length)
{
NTSTATUS status = STATUS_INVALID_PARAMETER;
if (!device_object || !data_buffer || !data_length || !actual_length)
return status;
// clear data
memset(data_buffer, 0, data_length);
*actual_length=0;
// get device property
status = IoGetDeviceProperty(
device_object, property, data_length, data_buffer, (PULONG)actual_length);
return status;
}
/*
Gets a property from the device registry key of the device_object.
Returns: NTSTATUS from ZwQueryValueKey
NTSTATUS from IoOpenDeviceRegistryKey if the device registry
key could not be opened.
*/
NTSTATUS reg_get_custom_property(PDEVICE_OBJECT device_object,
char *data_buffer,
unsigned int data_length,
unsigned int name_offset,
int* actual_length)
{
HANDLE key = NULL;
NTSTATUS status;
UNICODE_STRING name;
KEY_VALUE_FULL_INFORMATION *info;
ULONG length;
status = IoOpenDeviceRegistryKey(device_object, PLUGPLAY_REGKEY_DEVICE, KEY_READ, &key);
if (NT_SUCCESS(status))
{
RtlInitUnicodeString(&name, (WCHAR*)(&data_buffer[name_offset]));
length = sizeof(KEY_VALUE_FULL_INFORMATION) + name.MaximumLength + data_length;
info = ExAllocatePool(NonPagedPool, length);
if (info)
{
memset(info, 0, length);
status = ZwQueryValueKey(key, &name, KeyValueFullInformation, info, length, &length);
if (NT_SUCCESS(status))
{
data_length = (info->DataLength > data_length) ? data_length : info->DataLength;
memcpy(data_buffer, (((char *)info) + info->DataOffset),data_length);
*actual_length=data_length;
}
ExFreePool(info);
}
ZwClose(key);
}
return status;
}
@@ -0,0 +1,56 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS get_configuration(libusb_device_t *dev,
unsigned char *configuration, int *ret,
int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
USBMSG("timeout: %d\n", timeout);
memset(&urb, 0, sizeof(URB));
urb.UrbHeader.Function = URB_FUNCTION_GET_CONFIGURATION;
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_GET_CONFIGURATION_REQUEST);
urb.UrbControlGetConfigurationRequest.TransferBufferLength = 1;
urb.UrbControlGetConfigurationRequest.TransferBuffer = configuration;
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("getting configuration failed: status: 0x%x, urb-status: 0x%x\n",
status, urb.UrbHeader.Status);
*ret = 0;
}
else
{
USBMSG("current configuration is: %d\n",
*configuration);
*ret = urb.UrbControlGetConfigurationRequest.TransferBufferLength;
}
return status;
}
@@ -0,0 +1,161 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS get_descriptor(libusb_device_t *dev,
void *buffer, int size, int type, int recipient,
int index, int language_id, int *received, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
USBMSG("buffer size: %d type: %04d recipient: %04d index: %04d language id: %04d timeout: %d\n",
size, type, recipient, index, language_id, timeout);
memset(&urb, 0, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
switch (recipient)
{
case USB_RECIP_DEVICE:
urb.UrbHeader.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
break;
case USB_RECIP_INTERFACE:
urb.UrbHeader.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE;
break;
case USB_RECIP_ENDPOINT:
urb.UrbHeader.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT;
break;
default:
USBERR0("invalid recipient\n");
return STATUS_INVALID_PARAMETER;
}
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
urb.UrbControlDescriptorRequest.TransferBufferLength = size;
urb.UrbControlDescriptorRequest.TransferBuffer = buffer;
urb.UrbControlDescriptorRequest.DescriptorType = (UCHAR)type;
urb.UrbControlDescriptorRequest.Index = (UCHAR)index;
urb.UrbControlDescriptorRequest.LanguageId = (USHORT)language_id;
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("getting descriptor failed: status: 0x%x, urb-status: 0x%x\n",
status, urb.UrbHeader.Status);
*received = 0;
}
else
{
*received = urb.UrbControlDescriptorRequest.TransferBufferLength;
}
return status;
}
PUSB_CONFIGURATION_DESCRIPTOR get_config_descriptor(
libusb_device_t *dev,
int value,
int *size,
int* index)
{
NTSTATUS status;
USB_CONFIGURATION_DESCRIPTOR *desc = NULL;
USB_DEVICE_DESCRIPTOR device_descriptor;
int i;
volatile int desc_size;
*index = 0;
status = get_descriptor(dev, &device_descriptor,
sizeof(USB_DEVICE_DESCRIPTOR),
USB_DEVICE_DESCRIPTOR_TYPE,
USB_RECIP_DEVICE,
0, 0, size, LIBUSB_DEFAULT_TIMEOUT);
if (!NT_SUCCESS(status) || *size != sizeof(USB_DEVICE_DESCRIPTOR))
{
USBERR0("getting device descriptor failed\n");
return NULL;
}
if (!(desc = ExAllocatePool(NonPagedPool,
sizeof(USB_CONFIGURATION_DESCRIPTOR))))
{
USBERR0("memory allocation error\n");
return NULL;
}
for (i = 0; i < device_descriptor.bNumConfigurations; i++)
{
if (!NT_SUCCESS(get_descriptor(dev, desc,
sizeof(USB_CONFIGURATION_DESCRIPTOR),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
USB_RECIP_DEVICE,
i, 0, size, LIBUSB_DEFAULT_TIMEOUT)))
{
USBERR0("getting configuration descriptor failed\n");
break;
}
// if value is negative, get the descriptor by index
// if positive, get it by value.
if ((value > 0 && desc->bConfigurationValue == value) ||
(value < 0 && -(i+1) == (value)))
{
desc_size = desc->wTotalLength;
ExFreePool(desc);
if (!(desc = ExAllocatePool(NonPagedPool, desc_size)))
{
USBERR0("memory allocation error\n");
break;
}
if (!NT_SUCCESS(get_descriptor(dev, desc, desc_size,
USB_CONFIGURATION_DESCRIPTOR_TYPE,
USB_RECIP_DEVICE,
i, 0, size, LIBUSB_DEFAULT_TIMEOUT)))
{
USBERR0("getting configuration descriptor failed\n");
break;
}
else
{
*index = i+1;
}
return desc;
}
}
if (desc)
{
ExFreePool(desc);
}
return NULL;
}
@@ -0,0 +1,64 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS get_interface(libusb_device_t *dev,
int interface, unsigned char *altsetting,
int *ret, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
USBMSG("interface: %d timeout: %d\n", interface, timeout);
if (!dev->config.value)
{
USBERR0("invalid configuration 0\n");
return STATUS_INVALID_DEVICE_STATE;
}
memset(&urb, 0, sizeof(URB));
urb.UrbHeader.Function = URB_FUNCTION_GET_INTERFACE;
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_GET_INTERFACE_REQUEST);
urb.UrbControlGetInterfaceRequest.TransferBufferLength = 1;
urb.UrbControlGetInterfaceRequest.TransferBuffer = altsetting;
urb.UrbControlGetInterfaceRequest.Interface = (USHORT)interface;
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("getting interface failed: status: 0x%x, urb-status: 0x%x\n",
status, urb.UrbHeader.Status);
*ret = 0;
}
else
{
*ret = urb.UrbControlGetInterfaceRequest.TransferBufferLength;
USBMSG("current altsetting is %d\n", *altsetting);
}
return status;
}
@@ -0,0 +1,74 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS get_status(libusb_device_t *dev, int recipient,
int index, char *status, int *ret, int timeout)
{
NTSTATUS _status = STATUS_SUCCESS;
URB urb;
USBMSG("recipient: %02d index: %04d timeout: %d\n",
recipient, index, timeout);
memset(&urb, 0, sizeof(URB));
switch (recipient)
{
case USB_RECIP_DEVICE:
urb.UrbHeader.Function = URB_FUNCTION_GET_STATUS_FROM_DEVICE;
break;
case USB_RECIP_INTERFACE:
urb.UrbHeader.Function = URB_FUNCTION_GET_STATUS_FROM_INTERFACE;
break;
case USB_RECIP_ENDPOINT:
urb.UrbHeader.Function = URB_FUNCTION_GET_STATUS_FROM_ENDPOINT;
break;
case USB_RECIP_OTHER:
urb.UrbHeader.Function = URB_FUNCTION_GET_STATUS_FROM_OTHER;
break;
default:
USBERR0("invalid recipient\n");
return STATUS_INVALID_PARAMETER;
}
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST);
urb.UrbControlGetStatusRequest.TransferBufferLength = 2;
urb.UrbControlGetStatusRequest.TransferBuffer = status;
urb.UrbControlGetStatusRequest.Index = (USHORT)index;
_status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(_status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("getting status failed: status: 0x%x, urb-status: 0x%x\n",
_status, urb.UrbHeader.Status);
*ret = 0;
}
else
{
*ret = urb.UrbControlGetStatusRequest.TransferBufferLength;
}
return _status;
}
@@ -0,0 +1,566 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2010 Travis Robinson <libusbdotnet@gmail.com>
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
#include "libusb-win32_version.h"
// used but all transfer functions to get a valid libusb_endpoint_t *
// for the request.
//
#define TRANSFER_IOCTL_GET_PIPEINFO() \
/* check if the pipe exists and get the pipe information */ \
if (!get_pipe_info(dev, request->endpoint.endpoint,&pipe_info)) \
{ \
USBERR("%s: failed getting pipe info for endpoint: %02Xh\n", \
dispCtlCode, request->endpoint.endpoint); \
status = STATUS_INVALID_PARAMETER; \
goto IOCTL_Done; \
}
// warns if receive buffer is not an interval of the maximum packet size.
#define TRANSFER_IOCTL_CHECK_READ_BUFFER() \
/* read buffer lengthd must be equal to or an interval of the max */ \
/* packet size */ \
if (!pipe_info->maximum_packet_size) \
{ \
USBWRN("%s: wMaxPacketSize=0 for endpoint %02Xh.\n", \
dispCtlCode, request->endpoint.endpoint); \
status = STATUS_INVALID_PARAMETER; \
goto IOCTL_Done; \
} \
else if (transfer_buffer_length % pipe_info->maximum_packet_size) \
{ \
USBWRN("%s: buffer length %d is not an interval wMaxPacketSize " \
"for endpoint %02Xh.\n", \
dispCtlCode, transfer_buffer_length, request->endpoint.endpoint); \
}
// validates the urb function and direction against libusb_endpoint_t
#define TRANSFER_IOCTL_CHECK_FUNCTION_AND_DIRECTION() \
if (urbFunction != UrbFunctionFromEndpoint(pipe_info) || \
usbdDirection != UsbdDirectionFromEndpoint(pipe_info)) \
{ \
USBERR("%s: not compatible with endpoint %02Xh\n", \
dispCtlCode, pipe_info->address); \
status = STATUS_INVALID_PARAMETER; \
goto IOCTL_Done; \
}
// calls the transfer function and returns NTSTATUS
#define TRANSFER_IOCTL_EXECUTE() \
if (transfer_buffer_length > (ULONG)(maxTransferSize)) \
/* split large transfers */ \
return large_transfer(dev, irp, \
usbdDirection, \
urbFunction, \
pipe_info, \
request->endpoint.packet_size, \
maxTransferSize, \
request->endpoint.transfer_flags, \
request->endpoint.iso_start_frame_latency, \
transfer_buffer_mdl, \
transfer_buffer_length); \
else \
/* normal transfer */ \
return transfer(dev, irp, \
usbdDirection, \
urbFunction, \
pipe_info, \
request->endpoint.packet_size, \
maxTransferSize, \
request->endpoint.transfer_flags, \
request->endpoint.iso_start_frame_latency, \
transfer_buffer_mdl, \
transfer_buffer_length);
NTSTATUS dispatch_ioctl(libusb_device_t *dev, IRP *irp)
{
int maxTransferSize;
int ret = 0;
NTSTATUS status = STATUS_SUCCESS;
IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
ULONG control_code = stack_location->Parameters.DeviceIoControl.IoControlCode;
ULONG input_buffer_length = stack_location->Parameters.DeviceIoControl.InputBufferLength;
ULONG output_buffer_length = stack_location->Parameters.DeviceIoControl.OutputBufferLength;
ULONG transfer_buffer_length = stack_location->Parameters.DeviceIoControl.OutputBufferLength;
libusb_request *request = (libusb_request *)irp->AssociatedIrp.SystemBuffer;
char *output_buffer = (char *)irp->AssociatedIrp.SystemBuffer;
char *input_buffer = (char *)irp->AssociatedIrp.SystemBuffer;
MDL *transfer_buffer_mdl = irp->MdlAddress;
libusb_endpoint_t* pipe_info = NULL;
const char* dispCtlCode = NULL;
int urbFunction = -1;
int usbdDirection = -1;
status = remove_lock_acquire(dev);
if (!NT_SUCCESS(status))
{
status = complete_irp(irp, status, 0);
remove_lock_release(dev);
return status;
}
///////////////////////////////////
// DIRECT control codes //
///////////////////////////////////
switch(control_code)
{
case LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ:
dispCtlCode = "INTERRUPT_OR_BULK_READ";
// check if the request and buffer is valid
if (!request || !transfer_buffer_mdl || input_buffer_length < sizeof(libusb_request))
{
USBERR("%s: invalid transfer request\n",
dispCtlCode);
status = STATUS_INVALID_PARAMETER;
goto IOCTL_Done;
}
// check if the pipe exists and get the pipe information
TRANSFER_IOCTL_GET_PIPEINFO();
// must be a bulk or interrupt pipe
if (!IS_BULK_PIPE(pipe_info) && !IS_INTR_PIPE(pipe_info))
{
USBERR("%s: incorrect pipe type: %02Xh\n",
dispCtlCode, pipe_info->pipe_type);
status = STATUS_INVALID_PARAMETER;
goto IOCTL_Done;
}
// read buffer length must be equal to or an interval of the max packet size
TRANSFER_IOCTL_CHECK_READ_BUFFER();
urbFunction = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
usbdDirection = USBD_TRANSFER_DIRECTION_IN;
maxTransferSize = GetMaxTransferSize(pipe_info, request->endpoint.max_transfer_size);
// ensure that the urb function and direction we set matches the
// pipe information
//
TRANSFER_IOCTL_CHECK_FUNCTION_AND_DIRECTION();
// calls the transfer function and returns NTSTATUS
TRANSFER_IOCTL_EXECUTE();
case LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE:
dispCtlCode = "INTERRUPT_OR_BULK_WRITE";
/* we don't check 'transfer_buffer_mdl' here because it might be NULL */
/* if the DLL requests to send a zero-length packet */
if (!request || input_buffer_length < sizeof(libusb_request))
{
USBERR("%s: invalid transfer request\n", dispCtlCode);
status = STATUS_INVALID_PARAMETER;
goto IOCTL_Done;
}
// check if the pipe exists and get the pipe information
TRANSFER_IOCTL_GET_PIPEINFO();
// must be a bulk or interrupt pipe
if (!IS_BULK_PIPE(pipe_info) && !IS_INTR_PIPE(pipe_info))
{
USBERR("%s: incorrect pipe type: %02Xh\n",
dispCtlCode, pipe_info->pipe_type);
status = STATUS_INVALID_PARAMETER;
goto IOCTL_Done;
}
urbFunction = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
usbdDirection = USBD_TRANSFER_DIRECTION_OUT;
maxTransferSize = GetMaxTransferSize(pipe_info, request->endpoint.max_transfer_size);
// ensure that the urb function and direction we set matches the
// pipe information
//
TRANSFER_IOCTL_CHECK_FUNCTION_AND_DIRECTION();
// calls the transfer function and returns NTSTATUS
TRANSFER_IOCTL_EXECUTE();
case LIBUSB_IOCTL_ISOCHRONOUS_READ:
dispCtlCode = "ISOCHRONOUS_READ";
// check if the request and buffer is valid
if (!request || !transfer_buffer_mdl || input_buffer_length < sizeof(libusb_request))
{
USBERR("%s: invalid transfer request\n", dispCtlCode);
status = STATUS_INVALID_PARAMETER;
goto IOCTL_Done;
}
// check if the pipe exists and get the pipe information
TRANSFER_IOCTL_GET_PIPEINFO();
// read buffer length must be equal to or an interval of the max packet size
TRANSFER_IOCTL_CHECK_READ_BUFFER();
// must be an isochronous endpoint
if (!IS_ISOC_PIPE(pipe_info))
{
USBERR("%s: incorrect pipe type: %02Xh\n",
dispCtlCode, pipe_info->pipe_type);
status = STATUS_INVALID_PARAMETER;
goto IOCTL_Done;
}
urbFunction = URB_FUNCTION_ISOCH_TRANSFER;
usbdDirection = USBD_TRANSFER_DIRECTION_IN;
maxTransferSize = GetMaxTransferSize(pipe_info, request->endpoint.max_transfer_size);
// ensure that the urb function and direction we set matches the
// pipe information
//
TRANSFER_IOCTL_CHECK_FUNCTION_AND_DIRECTION();
// calls the transfer function and returns NTSTATUS
TRANSFER_IOCTL_EXECUTE();
case LIBUSB_IOCTL_ISOCHRONOUS_WRITE:
dispCtlCode = "ISOCHRONOUS_WRITE";
// check if the request and buffer is valid
if (!transfer_buffer_mdl || !request || input_buffer_length < sizeof(libusb_request))
{
USBERR("%s: invalid transfer request\n", dispCtlCode);
status = STATUS_INVALID_PARAMETER;
goto IOCTL_Done;
}
// check if the pipe exists and get the pipe information
TRANSFER_IOCTL_GET_PIPEINFO();
// must be an isochronous endpoint
if (!IS_ISOC_PIPE(pipe_info))
{
USBERR("%s: incorrect pipe type: %02Xh\n",
dispCtlCode, pipe_info->pipe_type);
status = STATUS_INVALID_PARAMETER;
goto IOCTL_Done;
}
urbFunction = URB_FUNCTION_ISOCH_TRANSFER;
usbdDirection = USBD_TRANSFER_DIRECTION_OUT;
TRANSFER_IOCTL_CHECK_FUNCTION_AND_DIRECTION();
maxTransferSize = GetMaxTransferSize(pipe_info, request->endpoint.max_transfer_size);
// ensure that the urb function and direction we set matches the
// pipe information
//
TRANSFER_IOCTL_CHECK_FUNCTION_AND_DIRECTION();
TRANSFER_IOCTL_EXECUTE();
}
///////////////////////////////////
// METHOD_BUFFERED control codes //
///////////////////////////////////
if (!request || input_buffer_length < sizeof(libusb_request)
|| input_buffer_length > LIBUSB_MAX_READ_WRITE
|| output_buffer_length > LIBUSB_MAX_READ_WRITE
|| transfer_buffer_length > LIBUSB_MAX_READ_WRITE)
{
USBERR0("invalid input or output buffer\n");
status = complete_irp(irp, STATUS_INVALID_PARAMETER, 0);
remove_lock_release(dev);
return status;
}
switch(control_code)
{
case LIBUSB_IOCTL_SET_CONFIGURATION:
status = set_configuration(dev,
request->configuration.configuration,
request->timeout);
break;
case LIBUSB_IOCTL_GET_CACHED_CONFIGURATION:
case LIBUSB_IOCTL_GET_CONFIGURATION:
if (!output_buffer || output_buffer_length < 1)
{
USBERR0("get_configuration: invalid output buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
if (control_code == LIBUSB_IOCTL_GET_CACHED_CONFIGURATION)
{
ret = 0;
if (dev->config.value >= 0)
{
*output_buffer = (char)dev->config.value;
ret = 1;
}
status = STATUS_SUCCESS;
}
else
{
status = get_configuration(dev, output_buffer, &ret, request->timeout);
}
break;
case LIBUSB_IOCTL_SET_INTERFACE:
status = set_interface(dev, request->interface.interface,
request->interface.altsetting, request->timeout);
break;
case LIBUSB_IOCTL_GET_INTERFACE:
if (!output_buffer || output_buffer_length < 1)
{
USBERR0("get_interface: invalid output buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
status = get_interface(dev, request->interface.interface,
output_buffer, &ret, request->timeout);
break;
case LIBUSB_IOCTL_SET_FEATURE:
status = set_feature(dev, request->feature.recipient,
request->feature.index, request->feature.feature,
request->timeout);
break;
case LIBUSB_IOCTL_CLEAR_FEATURE:
status = clear_feature(dev, request->feature.recipient,
request->feature.index, request->feature.feature,
request->timeout);
break;
case LIBUSB_IOCTL_GET_STATUS:
if (!output_buffer || output_buffer_length < 2)
{
USBERR0("get_status: invalid output buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
status = get_status(dev, request->status.recipient,
request->status.index, output_buffer,
&ret, request->timeout);
break;
case LIBUSB_IOCTL_SET_DESCRIPTOR:
if (input_buffer_length <= sizeof(libusb_request))
{
USBERR0("set_descriptor: invalid input buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
status = set_descriptor(dev,
input_buffer + sizeof(libusb_request),
input_buffer_length - sizeof(libusb_request),
request->descriptor.type,
request->descriptor.recipient,
request->descriptor.index,
request->descriptor.language_id,
&ret, request->timeout);
break;
case LIBUSB_IOCTL_GET_DESCRIPTOR:
if (!output_buffer || !output_buffer_length)
{
USBERR0("get_descriptor: invalid output buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
status = get_descriptor(dev, output_buffer,
output_buffer_length,
request->descriptor.type,
request->descriptor.recipient,
request->descriptor.index,
request->descriptor.language_id,
&ret, request->timeout);
break;
case LIBUSB_IOCTL_VENDOR_READ:
if (output_buffer_length && !output_buffer)
{
USBERR0("vendor_read: invalid output buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
status = vendor_class_request(dev,
request->vendor.type,
request->vendor.recipient,
request->vendor.request,
request->vendor.value,
request->vendor.index,
output_buffer,
output_buffer_length,
USBD_TRANSFER_DIRECTION_IN,
&ret, request->timeout);
break;
case LIBUSB_IOCTL_VENDOR_WRITE:
status =
vendor_class_request(dev,
request->vendor.type,
request->vendor.recipient,
request->vendor.request,
request->vendor.value,
request->vendor.index,
input_buffer_length == sizeof(libusb_request) ?
NULL : input_buffer + sizeof(libusb_request),
input_buffer_length - sizeof(libusb_request),
USBD_TRANSFER_DIRECTION_OUT,
&ret, request->timeout);
break;
case LIBUSB_IOCTL_RESET_ENDPOINT:
status = reset_endpoint(dev, request->endpoint.endpoint,
request->timeout);
break;
case LIBUSB_IOCTL_ABORT_ENDPOINT:
status = abort_endpoint(dev, request->endpoint.endpoint,
request->timeout);
break;
case LIBUSB_IOCTL_RESET_DEVICE:
status = reset_device(dev, request->timeout);
break;
case LIBUSB_IOCTL_SET_DEBUG_LEVEL:
usb_log_set_level(request->debug.level);
break;
case LIBUSB_IOCTL_GET_VERSION:
if (!request || output_buffer_length < sizeof(libusb_request))
{
USBERR0("get_version: invalid output buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
request->version.major = VERSION_MAJOR;
request->version.minor = VERSION_MINOR;
request->version.micro = VERSION_MICRO;
request->version.nano = VERSION_NANO;
request->version.mod_value = 1;
ret = sizeof(libusb_request);
break;
case LIBUSB_IOCTL_CLAIM_INTERFACE:
status = claim_interface(dev, stack_location->FileObject,
request->interface.interface);
break;
case LIBUSB_IOCTL_RELEASE_INTERFACE:
status = release_interface(dev, stack_location->FileObject,
request->interface.interface);
break;
case LIBUSB_IOCTL_GET_DEVICE_PROPERTY:
if (!request || output_buffer_length < sizeof(libusb_request))
{
USBERR0("get_device_property: invalid output buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
status = reg_get_device_property(
dev->physical_device_object,
request->device_property.property,
output_buffer,
output_buffer_length, &ret);
break;
case LIBUSB_IOCTL_GET_CUSTOM_REG_PROPERTY:
if (!input_buffer || (input_buffer_length < sizeof(libusb_request)))
{
USBERR0("get_custom_reg_property: invalid buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
status=reg_get_custom_property(
dev->physical_device_object,
input_buffer,
output_buffer_length,
request->device_registry_key.name_offset,
&ret);
break;
case LIBUSB_IOCTL_GET_OBJECT_NAME:
if (!request || output_buffer_length < 2)
{
USBERR0("get_object_name: invalid output buffer\n");
status = STATUS_INVALID_PARAMETER;
break;
}
switch (request->objname.objname_index)
{
case 0:
ret = (int)strlen(dev->objname_plugplay_registry_key)+1;
ret = ret > (int)output_buffer_length ? (int)output_buffer_length : ret;
RtlCopyMemory(output_buffer, dev->objname_plugplay_registry_key,(SIZE_T) (ret-1));
output_buffer[ret-1]='\0';
break;
default:
status = STATUS_INVALID_PARAMETER;
}
break;
default:
status = STATUS_INVALID_PARAMETER;
}
IOCTL_Done:
status = complete_irp(irp, status, ret);
remove_lock_release(dev);
return status;
}
@@ -0,0 +1,748 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define __LIBUSB_DRIVER_C__
#include "libusb_driver.h"
#include "libusb-win32_version.h"
// Device objects with an attached device using the
// driver names listed here skipped in the add_device() routine.
//
const char* attached_driver_skip_list[] =
{
"\\driver\\picopp",
"\\driver\\libusb0",
NULL
};
// Device objects with an attached device using the
// driver names listed here have wdf below them. Special
// restrictions apply to these devices.
//
const char* attached_driver_wdf_list[] =
{
"\\driver\\winusb",
"\\driver\\wudfrd",
NULL
};
static bool_t match_driver(PDEVICE_OBJECT deviceObject, const char* driverString);
#ifdef DBG
static void debug_show_devices(PDEVICE_OBJECT deviceObject, int index, bool_t showNextDevice)
{
ANSI_STRING driverName;
if (index > 16) return;
if (deviceObject)
{
if (deviceObject->DriverObject)
{
if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&driverName, &deviceObject->DriverObject->DriverName, TRUE)))
{
USBDBG("[%s #%d] %s\n",
(showNextDevice ? "NextDevice" : "AttachedDevice"),
index, driverName.Buffer);
RtlFreeAnsiString(&driverName);
}
}
if (deviceObject->AttachedDevice && !showNextDevice)
debug_show_devices(deviceObject->AttachedDevice, index+1, showNextDevice);
if (deviceObject->NextDevice && showNextDevice)
debug_show_devices(deviceObject->NextDevice, index+1, showNextDevice);
}
}
#endif
static bool_t match_driver(PDEVICE_OBJECT deviceObject, const char* driverString)
{
ANSI_STRING driverName;
bool_t ret = FALSE;
if (deviceObject)
{
if (deviceObject->DriverObject)
{
if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&driverName, &deviceObject->DriverObject->DriverName, TRUE)))
{
_strlwr(driverName.Buffer);
if (strstr(driverName.Buffer,driverString))
{
ret = TRUE;
}
RtlFreeAnsiString(&driverName);
}
}
}
return ret;
}
static void DDKAPI unload(DRIVER_OBJECT *driver_object);
static NTSTATUS DDKAPI on_usbd_complete(DEVICE_OBJECT *device_object,
IRP *irp,
void *context);
NTSTATUS DDKAPI DriverEntry(DRIVER_OBJECT *driver_object,
UNICODE_STRING *registry_path)
{
int i;
USBMSG("[loading-driver] v%d.%d.%d.%d\n",
VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO, VERSION_NANO);
/* initialize the driver object's dispatch table */
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
driver_object->MajorFunction[i] = dispatch;
}
driver_object->DriverExtension->AddDevice = add_device;
driver_object->DriverUnload = unload;
return STATUS_SUCCESS;
}
NTSTATUS DDKAPI add_device(DRIVER_OBJECT *driver_object,
DEVICE_OBJECT *physical_device_object)
{
NTSTATUS status;
DEVICE_OBJECT *device_object = NULL;
libusb_device_t *dev;
ULONG device_type;
UNICODE_STRING nt_device_name;
UNICODE_STRING symbolic_link_name;
WCHAR tmp_name_0[128];
WCHAR tmp_name_1[128];
char id[256];
char compat_id[256];
int i;
DEVICE_OBJECT* attached_device;
bool_t has_wdf = FALSE;
/* get the hardware ID from the registry */
if (!reg_get_hardware_id(physical_device_object, id, sizeof(id)))
{
USBERR0("unable to read registry\n");
return STATUS_SUCCESS;
}
/* only attach the (filter) driver to USB devices, skip hubs */
if (!strstr(id, "usb\\") ||
strstr(id, "hub") ||
!strstr(id, "vid_") ||
!strstr(id, "pid_"))
{
USBDBG("skipping non-usb device or hub %s\n",id);
return STATUS_SUCCESS;
}
if (!reg_get_compatible_id(physical_device_object, compat_id, sizeof(compat_id)))
{
USBERR0("unable to read registry\n");
return STATUS_SUCCESS;
}
// Don't attach to usb device hubs
if (strstr(compat_id, "class_09"))
{
USBDBG("skipping usb device hub (%s) %s\n",compat_id, id);
return STATUS_SUCCESS;
}
#ifdef DBG
debug_show_devices(physical_device_object->AttachedDevice, 0, FALSE);
#endif
attached_device = physical_device_object->AttachedDevice;
while (attached_device)
{
// make sure this device isn't already using a driver that is
// incompatible with libusb-win32.
for (i=0; attached_driver_skip_list[i] != NULL; i++)
{
if (match_driver(attached_device, attached_driver_skip_list[i]))
{
USBDBG("skipping device %s\n", id);
return STATUS_SUCCESS;
}
}
// look for wdf
for (i=0; attached_driver_wdf_list[i] != NULL; i++)
{
if (match_driver(attached_device, attached_driver_wdf_list[i]))
{
has_wdf = TRUE;
}
}
attached_device=attached_device->AttachedDevice;
}
device_object = IoGetAttachedDeviceReference(physical_device_object);
if (device_object)
{
device_type = device_object->DeviceType;
ObDereferenceObject(device_object);
}
else
{
device_type = FILE_DEVICE_UNKNOWN;
}
/* try to create a new device object */
for (i = 1; i < LIBUSB_MAX_NUMBER_OF_DEVICES; i++)
{
/* initialize some unicode strings */
_snwprintf(tmp_name_0, sizeof(tmp_name_0)/sizeof(WCHAR), L"%s%04d",
LIBUSB_NT_DEVICE_NAME, i);
_snwprintf(tmp_name_1, sizeof(tmp_name_1)/sizeof(WCHAR), L"%s%04d",
LIBUSB_SYMBOLIC_LINK_NAME, i);
RtlInitUnicodeString(&nt_device_name, tmp_name_0);
RtlInitUnicodeString(&symbolic_link_name, tmp_name_1);
/* create the object */
status = IoCreateDevice(driver_object,
sizeof(libusb_device_t),
&nt_device_name, device_type, 0, FALSE,
&device_object);
if (NT_SUCCESS(status))
{
USBMSG("device #%d created for %s\n", i, id);
break;
}
device_object = NULL;
/* continue until an unused device name is found */
}
if (!device_object)
{
USBERR0("creating device failed\n");
return status;
}
status = IoCreateSymbolicLink(&symbolic_link_name, &nt_device_name);
if (!NT_SUCCESS(status))
{
USBERR0("creating symbolic link failed\n");
IoDeleteDevice(device_object);
return status;
}
/* setup the "device object" */
dev = device_object->DeviceExtension;
memset(dev, 0, sizeof(libusb_device_t));
// [trobinso] See patch: 2873573 (Tim Green)
dev->self = device_object;
dev->physical_device_object = physical_device_object;
dev->id = i;
// store the device id in the device extentions
RtlCopyMemory(dev->device_id, id, sizeof(dev->device_id));
/* set initial power states */
dev->power_state.DeviceState = PowerDeviceD0;
dev->power_state.SystemState = PowerSystemWorking;
dev->disallow_power_control = has_wdf;
/* get device properties from the registry */
if (!reg_get_properties(dev))
{
USBERR0("getting device properties failed\n");
IoDeleteSymbolicLink(&symbolic_link_name);
IoDeleteDevice(device_object);
return STATUS_SUCCESS;
}
if (dev->is_filter && !physical_device_object->AttachedDevice)
{
USBWRN("[FILTER-MODE-MISMATCH] device is reporting itself as filter when there are no attached device(s).\n%s\n", id);
}
else if (!dev->is_filter && physical_device_object->AttachedDevice)
{
USBWRN("[FILTER-MODE-MISMATCH] device is reporting itself as normal when there are already attached device(s).\n%s\n", id);
//dev->is_filter = TRUE;
}
clear_pipe_info(dev);
remove_lock_initialize(dev);
// make sure the the devices can't be removed
// before we are done adding it.
if (!NT_SUCCESS(remove_lock_acquire(dev)))
{
USBERR0("remove_lock_acquire failed\n");
IoDeleteSymbolicLink(&symbolic_link_name);
IoDeleteDevice(device_object);
return STATUS_SUCCESS;
}
/* attach the newly created device object to the stack */
dev->next_stack_device = IoAttachDeviceToDeviceStack(device_object, physical_device_object);
if (!dev->next_stack_device)
{
USBERR("attaching %s to device stack failed\n", id);
IoDeleteSymbolicLink(&symbolic_link_name);
IoDeleteDevice(device_object);
remove_lock_release(dev); // always release acquired locks
return STATUS_NO_SUCH_DEVICE;
}
if (dev->is_filter)
{
USBDBG("[filter-mode] id=#%d %s\n",dev->id, dev->device_id);
/* send all USB requests to the PDO in filter driver mode */
dev->target_device = dev->physical_device_object;
/* use the same flags as the underlying object */
device_object->Flags |= dev->next_stack_device->Flags
& (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);
// use the same DeviceType as the underlying object
device_object->DeviceType = dev->next_stack_device->DeviceType;
// use the same Characteristics as the underlying object
device_object->Characteristics = dev->next_stack_device->Characteristics;
}
else
{
USBDBG("[normal-mode] id=#%d %s\n",dev->id, dev->device_id);
/* send all USB requests to the lower object in device driver mode */
dev->target_device = dev->next_stack_device;
device_object->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
}
device_object->Flags &= ~DO_DEVICE_INITIALIZING;
remove_lock_release(dev);
USBMSG("complete status=%08X\n",status);
return status;
}
VOID DDKAPI unload(DRIVER_OBJECT *driver_object)
{
USBMSG("[unloading-driver] v%d.%d.%d.%d\n",
VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO, VERSION_NANO);
}
NTSTATUS complete_irp(IRP *irp, NTSTATUS status, ULONG info)
{
irp->IoStatus.Status = status;
irp->IoStatus.Information = info;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS call_usbd_ex(libusb_device_t *dev, void *urb, ULONG control_code,
int timeout, int max_timeout)
{
KEVENT event;
NTSTATUS status;
IRP *irp;
IO_STACK_LOCATION *next_irp_stack;
LARGE_INTEGER _timeout;
IO_STATUS_BLOCK io_status;
if (max_timeout > 0 && timeout > max_timeout)
{
timeout = max_timeout;
}
if (timeout <= 0)
timeout = LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(control_code, dev->target_device,
NULL, 0, NULL, 0, TRUE,
NULL, &io_status);
if (!irp)
{
return STATUS_NO_MEMORY;
}
next_irp_stack = IoGetNextIrpStackLocation(irp);
next_irp_stack->Parameters.Others.Argument1 = urb;
next_irp_stack->Parameters.Others.Argument2 = NULL;
IoSetCompletionRoutine(irp, on_usbd_complete, &event, TRUE, TRUE, TRUE);
status = IoCallDriver(dev->target_device, irp);
if(status == STATUS_PENDING)
{
_timeout.QuadPart = -(timeout * 10000);
if(KeWaitForSingleObject(&event, Executive, KernelMode,
FALSE, &_timeout) == STATUS_TIMEOUT)
{
USBERR0("request timed out\n");
IoCancelIrp(irp);
}
}
/* wait until completion routine is called */
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = irp->IoStatus.Status;
/* complete the request */
IoCompleteRequest(irp, IO_NO_INCREMENT);
USBDBG("status = %08Xh\n",status);
return status;
}
static NTSTATUS DDKAPI on_usbd_complete(DEVICE_OBJECT *device_object,
IRP *irp, void *context)
{
KeSetEvent((KEVENT *) context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS pass_irp_down(libusb_device_t *dev, IRP *irp,
PIO_COMPLETION_ROUTINE completion_routine,
void *context)
{
if (completion_routine)
{
IoCopyCurrentIrpStackLocationToNext(irp);
IoSetCompletionRoutine(irp, completion_routine, context,
TRUE, TRUE, TRUE);
}
else
{
IoSkipCurrentIrpStackLocation(irp);
}
return IoCallDriver(dev->next_stack_device, irp);
}
bool_t accept_irp(libusb_device_t *dev, IRP *irp)
{
/* check if the IRP is sent to libusb's device object or to */
/* the lower one. This check is neccassary since the device object */
/* might be a filter */
if (irp->Tail.Overlay.OriginalFileObject)
{
return irp->Tail.Overlay.OriginalFileObject->DeviceObject
== dev->self ? TRUE : FALSE;
}
return FALSE;
}
bool_t get_pipe_handle(libusb_device_t *dev, int endpoint_address,
USBD_PIPE_HANDLE *pipe_handle)
{
int i, j;
*pipe_handle = NULL;
for (i = 0; i < LIBUSB_MAX_NUMBER_OF_INTERFACES; i++)
{
if (dev->config.interfaces[i].valid)
{
for (j = 0; j < LIBUSB_MAX_NUMBER_OF_ENDPOINTS; j++)
{
if (dev->config.interfaces[i].endpoints[j].address
== endpoint_address)
{
*pipe_handle = dev->config.interfaces[i].endpoints[j].handle;
return !*pipe_handle ? FALSE : TRUE;
}
}
}
}
return FALSE;
}
bool_t get_pipe_info(libusb_device_t *dev, int endpoint_address,
libusb_endpoint_t** pipe_info)
{
int i, j;
*pipe_info = NULL;
for (i = 0; i < LIBUSB_MAX_NUMBER_OF_INTERFACES; i++)
{
if (dev->config.interfaces[i].valid)
{
for (j = 0; j < LIBUSB_MAX_NUMBER_OF_ENDPOINTS; j++)
{
if (dev->config.interfaces[i].endpoints[j].address
== endpoint_address)
{
*pipe_info = &dev->config.interfaces[i].endpoints[j];
return !*pipe_info ? FALSE : TRUE;
}
}
}
}
return FALSE;
}
void clear_pipe_info(libusb_device_t *dev)
{
memset(dev->config.interfaces, 0 , sizeof(dev->config.interfaces));
}
bool_t update_pipe_info(libusb_device_t *dev,
USBD_INTERFACE_INFORMATION *interface_info)
{
int i;
int number;
int maxTransferSize;
int maxPacketSize;
if (!interface_info)
{
return FALSE;
}
number = interface_info->InterfaceNumber;
if (interface_info->InterfaceNumber >= LIBUSB_MAX_NUMBER_OF_INTERFACES)
{
return FALSE;
}
USBMSG("interface %d\n", number);
dev->config.interfaces[number].valid = TRUE;
for (i = 0; i < LIBUSB_MAX_NUMBER_OF_ENDPOINTS; i++)
{
dev->config.interfaces[number].endpoints[i].address = 0;
dev->config.interfaces[number].endpoints[i].handle = NULL;
}
if (interface_info)
{
for (i = 0; i < (int)interface_info->NumberOfPipes
&& i < LIBUSB_MAX_NUMBER_OF_ENDPOINTS; i++)
{
maxPacketSize = interface_info->Pipes[i].MaximumPacketSize;
maxTransferSize = interface_info->Pipes[i].MaximumTransferSize;
USBMSG("EP%02Xh maximum-packet-size=%d maximum-transfer-size=%d\n",
interface_info->Pipes[i].EndpointAddress,
maxPacketSize,
maxTransferSize);
dev->config.interfaces[number].endpoints[i].handle = interface_info->Pipes[i].PipeHandle;
dev->config.interfaces[number].endpoints[i].address = interface_info->Pipes[i].EndpointAddress;
dev->config.interfaces[number].endpoints[i].maximum_packet_size = maxPacketSize;
dev->config.interfaces[number].endpoints[i].interval = interface_info->Pipes[i].Interval;
dev->config.interfaces[number].endpoints[i].pipe_type = interface_info->Pipes[i].PipeType;
dev->config.interfaces[number].endpoints[i].pipe_flags = interface_info->Pipes[i].PipeFlags;
if (maxPacketSize)
{
// set max the maximum transfer size default to an interval of max packet size.
maxTransferSize = maxTransferSize - (maxTransferSize % maxPacketSize);
if (maxTransferSize < maxPacketSize)
{
maxTransferSize = LIBUSB_MAX_READ_WRITE;
}
else if (maxTransferSize > LIBUSB_MAX_READ_WRITE)
{
maxTransferSize = LIBUSB_MAX_READ_WRITE - (LIBUSB_MAX_READ_WRITE % maxPacketSize);
}
if (maxTransferSize != interface_info->Pipes[i].MaximumTransferSize)
{
USBWRN("overriding EP%02Xh maximum-transfer-size=%d\n",
dev->config.interfaces[number].endpoints[i].address,
maxTransferSize);
}
}
else
{
if (!maxTransferSize)
{
// use the libusb-win32 default
maxTransferSize = LIBUSB_MAX_READ_WRITE;
}
}
dev->config.interfaces[number].endpoints[i].maximum_transfer_size = maxTransferSize;
}
}
return TRUE;
}
void remove_lock_initialize(libusb_device_t *dev)
{
KeInitializeEvent(&dev->remove_lock.event, NotificationEvent, FALSE);
dev->remove_lock.usage_count = 1;
dev->remove_lock.remove_pending = FALSE;
}
NTSTATUS remove_lock_acquire(libusb_device_t *dev)
{
InterlockedIncrement(&dev->remove_lock.usage_count);
if (dev->remove_lock.remove_pending)
{
if (InterlockedDecrement(&dev->remove_lock.usage_count) == 0)
{
KeSetEvent(&dev->remove_lock.event, 0, FALSE);
}
return STATUS_DELETE_PENDING;
}
return STATUS_SUCCESS;
}
void remove_lock_release(libusb_device_t *dev)
{
if (InterlockedDecrement(&dev->remove_lock.usage_count) == 0)
{
KeSetEvent(&dev->remove_lock.event, 0, FALSE);
}
}
void remove_lock_release_and_wait(libusb_device_t *dev)
{
dev->remove_lock.remove_pending = TRUE;
remove_lock_release(dev);
remove_lock_release(dev);
KeWaitForSingleObject(&dev->remove_lock.event, Executive, KernelMode,
FALSE, NULL);
}
USB_INTERFACE_DESCRIPTOR *
find_interface_desc(USB_CONFIGURATION_DESCRIPTOR *config_desc,
unsigned int size, int interface_number, int altsetting)
{
usb_descriptor_header_t *desc = (usb_descriptor_header_t *)config_desc;
char *p = (char *)desc;
USB_INTERFACE_DESCRIPTOR *if_desc = NULL;
if (!config_desc || (size < config_desc->wTotalLength))
return NULL;
while (size && desc->length <= size)
{
if (desc->type == USB_INTERFACE_DESCRIPTOR_TYPE)
{
if_desc = (USB_INTERFACE_DESCRIPTOR *)desc;
if ((if_desc->bInterfaceNumber == (UCHAR)interface_number)
&& (if_desc->bAlternateSetting == (UCHAR)altsetting))
{
return if_desc;
}
}
size -= desc->length;
p += desc->length;
desc = (usb_descriptor_header_t *)p;
}
return NULL;
}
ULONG get_current_frame(IN PDEVICE_EXTENSION deviceExtension, IN PIRP Irp)
/*++
Routine Description:
This routine send an irp/urb pair with
function code URB_FUNCTION_GET_CURRENT_FRAME_NUMBER
to fetch the current frame
Arguments:
DeviceObject - pointer to device object
PIRP - I/O request packet
Return Value:
Current frame
--*/
{
KEVENT event;
PIO_STACK_LOCATION nextStack;
struct _URB_GET_CURRENT_FRAME_NUMBER urb;
//
// initialize the urb
//
urb.Hdr.Function = URB_FUNCTION_GET_CURRENT_FRAME_NUMBER;
urb.Hdr.Length = sizeof(urb);
urb.FrameNumber = (ULONG) -1;
nextStack = IoGetNextIrpStackLocation(Irp);
nextStack->Parameters.Others.Argument1 = (PVOID) &urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
KeInitializeEvent(&event,
NotificationEvent,
FALSE);
IoSetCompletionRoutine(Irp,
on_usbd_complete,
&event,
TRUE,
TRUE,
TRUE);
IoCallDriver(deviceExtension->target_device, Irp);
KeWaitForSingleObject((PVOID) &event,
Executive,
KernelMode,
FALSE,
NULL);
return urb.FrameNumber;
}
@@ -0,0 +1,334 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LIBUSB_DRIVER_H__
#define __LIBUSB_DRIVER_H__
//#define SKIP_CONFIGURE_NORMAL_DEVICES
//#define SKIP_DEVICES_WINUSB
//#define SKIP_DEVICES_PICOPP
#ifdef __GNUC__
#include <ddk/usb100.h>
#include <ddk/usbdi.h>
#include <ddk/winddk.h>
#include "usbdlib_gcc.h"
#else
#include <ntifs.h>
#include <wdm.h>
#include "usbdi.h"
#include "usbdlib.h"
#endif
#include <wchar.h>
#include <initguid.h>
#undef interface
#include "driver_debug.h"
#include "error.h"
#include "driver_api.h"
/* some missing defines */
#ifdef __GNUC__
#define USBD_TRANSFER_DIRECTION_OUT 0
#define USBD_TRANSFER_DIRECTION_BIT 0
#define USBD_TRANSFER_DIRECTION_IN (1 << USBD_TRANSFER_DIRECTION_BIT)
#define USBD_SHORT_TRANSFER_OK_BIT 1
#define USBD_SHORT_TRANSFER_OK (1 << USBD_SHORT_TRANSFER_OK_BIT)
#define USBD_START_ISO_TRANSFER_ASAP_BIT 2
#define USBD_START_ISO_TRANSFER_ASAP (1 << USBD_START_ISO_TRANSFER_ASAP_BIT)
#endif
#define SET_CONFIG_ACTIVE_CONFIG -258
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
#define USB_TYPE_STANDARD 0x00
#define USB_TYPE_CLASS 0x01
#define USB_TYPE_VENDOR 0x02
#define LIBUSB_NT_DEVICE_NAME L"\\Device\\libusb0"
#define LIBUSB_SYMBOLIC_LINK_NAME L"\\DosDevices\\libusb0-"
#define LIBUSB_MAX_NUMBER_OF_ENDPOINTS 32
#define LIBUSB_MAX_NUMBER_OF_INTERFACES 32
#define LIBUSB_DEFAULT_TIMEOUT 5000
#define LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT 5000
#ifndef __GNUC__
#define DDKAPI
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!(FALSE))
#endif
typedef int bool_t;
#define IS_PIPE_TYPE(pipeInfo, pipeType) ((pipeInfo->pipe_type & 3)==pipeType)
#define IS_CTRL_PIPE(pipeInfo) IS_PIPE_TYPE(pipeInfo,UsbdPipeTypeControl)
#define IS_ISOC_PIPE(pipeInfo) IS_PIPE_TYPE(pipeInfo,UsbdPipeTypeIsochronous)
#define IS_BULK_PIPE(pipeInfo) IS_PIPE_TYPE(pipeInfo,UsbdPipeTypeBulk)
#define IS_INTR_PIPE(pipeInfo) IS_PIPE_TYPE(pipeInfo,UsbdPipeTypeInterrupt)
#define GetMaxTransferSize(pipeInfo, reqMaxTransferSize) ((reqMaxTransferSize) ? reqMaxTransferSize : pipeInfo->maximum_transfer_size)
#define UrbFunctionFromEndpoint(PipeInfo) ((IS_ISOC_PIPE(PipeInfo)) ? URB_FUNCTION_ISOCH_TRANSFER : URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER)
#define UsbdDirectionFromEndpoint(PipeInfo) ((PipeInfo->address & 0x80) ? USBD_TRANSFER_DIRECTION_IN : USBD_TRANSFER_DIRECTION_OUT)
#include <pshpack1.h>
typedef struct
{
unsigned char length;
unsigned char type;
} usb_descriptor_header_t;
#include <poppack.h>
typedef struct
{
long usage_count;
int remove_pending;
KEVENT event;
} libusb_remove_lock_t;
typedef struct
{
int address;
USBD_PIPE_HANDLE handle;
int maximum_packet_size; // Maximum packet size for this pipe
int interval; // Polling interval in ms if interrupt pipe
USBD_PIPE_TYPE pipe_type; // PipeType identifies type of transfer valid for this pipe
//
// INPUT
// These fields are filled in by the client driver
//
int maximum_transfer_size; // Maximum size for a single request
// in bytes.
int pipe_flags;
} libusb_endpoint_t;
typedef struct
{
bool_t valid;
FILE_OBJECT *file_object; /* file object this interface is bound to */
libusb_endpoint_t endpoints[LIBUSB_MAX_NUMBER_OF_ENDPOINTS];
} libusb_interface_t;
typedef struct
{
DEVICE_OBJECT *self;
DEVICE_OBJECT *physical_device_object;
DEVICE_OBJECT *next_stack_device;
DEVICE_OBJECT *target_device;
libusb_remove_lock_t remove_lock;
bool_t is_filter;
bool_t is_started;
bool_t surprise_removal_ok;
int id;
struct
{
USBD_CONFIGURATION_HANDLE handle;
int value;
int index;
libusb_interface_t interfaces[LIBUSB_MAX_NUMBER_OF_INTERFACES];
} config;
POWER_STATE power_state;
DEVICE_POWER_STATE device_power_states[PowerSystemMaximum];
int initial_config_value;
char device_id[256];
bool_t disallow_power_control;
char objname_plugplay_registry_key[512];
} libusb_device_t, DEVICE_EXTENSION, *PDEVICE_EXTENSION;
NTSTATUS DDKAPI add_device(DRIVER_OBJECT *driver_object,
DEVICE_OBJECT *physical_device_object);
NTSTATUS DDKAPI dispatch(DEVICE_OBJECT *device_object, IRP *irp);
NTSTATUS dispatch_pnp(libusb_device_t *dev, IRP *irp);
NTSTATUS dispatch_power(libusb_device_t *dev, IRP *irp);
NTSTATUS dispatch_ioctl(libusb_device_t *dev, IRP *irp);
NTSTATUS complete_irp(IRP *irp, NTSTATUS status, ULONG info);
#define call_usbd(dev, urb, control_code, timeout) \
call_usbd_ex(dev, urb, control_code, timeout, LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT)
NTSTATUS call_usbd_ex(libusb_device_t *dev,
void *urb,
ULONG control_code,
int timeout,
int max_timeout);
NTSTATUS pass_irp_down(libusb_device_t *dev, IRP *irp,
PIO_COMPLETION_ROUTINE completion_routine,
void *context);
bool_t accept_irp(libusb_device_t *dev, IRP *irp);
bool_t get_pipe_handle(libusb_device_t *dev, int endpoint_address,
USBD_PIPE_HANDLE *pipe_handle);
bool_t get_pipe_info(libusb_device_t *dev, int endpoint_address,
libusb_endpoint_t** pipe_info);
void clear_pipe_info(libusb_device_t *dev);
bool_t update_pipe_info(libusb_device_t *dev,
USBD_INTERFACE_INFORMATION *interface_info);
void remove_lock_initialize(libusb_device_t *dev);
NTSTATUS remove_lock_acquire(libusb_device_t *dev);
void remove_lock_release(libusb_device_t *dev);
void remove_lock_release_and_wait(libusb_device_t *dev);
NTSTATUS set_configuration(libusb_device_t *dev,
int configuration, int timeout);
NTSTATUS auto_configure(libusb_device_t *dev);
NTSTATUS get_configuration(libusb_device_t *dev,
unsigned char *configuration, int *ret,
int timeout);
NTSTATUS set_interface(libusb_device_t *dev,
int interface, int altsetting, int timeout);
NTSTATUS get_interface(libusb_device_t *dev,
int interface, unsigned char *altsetting,
int *ret, int timeout);
NTSTATUS set_feature(libusb_device_t *dev,
int recipient, int index, int feature, int timeout);
NTSTATUS clear_feature(libusb_device_t *dev,
int recipient, int index, int feature, int timeout);
NTSTATUS get_status(libusb_device_t *dev, int recipient,
int index, char *status, int *ret, int timeout);
NTSTATUS set_descriptor(libusb_device_t *dev,
void *buffer, int size,
int type, int recipient, int index, int language_id,
int *sent, int timeout);
NTSTATUS get_descriptor(libusb_device_t *dev, void *buffer, int size,
int type, int recipient, int index, int language_id,
int *received, int timeout);
PUSB_CONFIGURATION_DESCRIPTOR get_config_descriptor(
libusb_device_t *dev,
int value,
int *size,
int* index);
NTSTATUS vendor_class_request(libusb_device_t *dev,
int type, int recipient,
int request, int value, int index,
void *buffer, int size, int direction,
int *ret, int timeout);
NTSTATUS abort_endpoint(libusb_device_t *dev, int endpoint, int timeout);
NTSTATUS reset_endpoint(libusb_device_t *dev, int endpoint, int timeout);
NTSTATUS reset_device(libusb_device_t *dev, int timeout);
NTSTATUS claim_interface(libusb_device_t *dev, FILE_OBJECT *file_object,
int interface);
NTSTATUS release_interface(libusb_device_t *dev, FILE_OBJECT *file_object,
int interface);
NTSTATUS release_all_interfaces(libusb_device_t *dev,
FILE_OBJECT *file_object);
bool_t reg_get_hardware_id(DEVICE_OBJECT *physical_device_object,
char *data, int size);
bool_t reg_get_compatible_id(DEVICE_OBJECT *physical_device_object,
char *data, int size);
bool_t reg_get_properties(libusb_device_t *dev);
void power_set_device_state(libusb_device_t *dev,
DEVICE_POWER_STATE device_state, bool_t block);
USB_INTERFACE_DESCRIPTOR *
find_interface_desc(USB_CONFIGURATION_DESCRIPTOR *config_desc,
unsigned int size, int interface_number, int altsetting);
/*
Gets a device property for the device_object.
Returns: NTSTATUS code from IoGetDeviceProperty
STATUS_INVALID_PARAMETER
*/
NTSTATUS reg_get_device_property(PDEVICE_OBJECT device_object,
int property,
char* data_buffer,
int data_length,
int* actual_length);
NTSTATUS reg_get_custom_property(PDEVICE_OBJECT device_object,
char *data_buffer,
unsigned int data_length,
unsigned int name_offset,
int* actual_length);
NTSTATUS transfer(libusb_device_t* dev,
IN PIRP irp,
IN int direction,
IN int urbFunction,
IN libusb_endpoint_t* endpoint,
IN int packetSize,
IN int maxTransferSize,
IN int transferFlags,
IN int isoLatency,
IN PMDL mdlAddress,
IN int totalLength);
NTSTATUS large_transfer(IN libusb_device_t* dev,
IN PIRP irp,
IN int direction,
IN int urbFunction,
IN libusb_endpoint_t* endpoint,
IN int packetSize,
IN int maxTransferSize,
IN int transferFlags,
IN int isoLatency,
IN PMDL mdlAddress,
IN int totalLength);
ULONG get_current_frame(IN PDEVICE_EXTENSION dev, IN PIRP Irp);
#endif
@@ -0,0 +1,25 @@
/* LIBUSB-WIN32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define RC_FILE_TYPE VFT_DRV
#define RC_FILE_SUB_TYPE VFT2_DRV_SYSTEM
#define RC_PRODUCT_STR "LibUSB-Win32 - Kernel Driver"
#define RC_FILE_NAME_STR "libusb0.sys"
#include "libusb-win32_version.rc"
@@ -0,0 +1,263 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
static NTSTATUS DDKAPI
on_start_complete(DEVICE_OBJECT *device_object, IRP *irp,
void *context);
static NTSTATUS DDKAPI
on_device_usage_notification_complete(DEVICE_OBJECT *device_object,
IRP *irp, void *context);
static NTSTATUS DDKAPI
on_query_capabilities_complete(DEVICE_OBJECT *device_object,
IRP *irp, void *context);
NTSTATUS dispatch_pnp(libusb_device_t *dev, IRP *irp)
{
NTSTATUS status = STATUS_SUCCESS;
IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
UNICODE_STRING symbolic_link_name;
WCHAR tmp_name[128];
status = remove_lock_acquire(dev);
if (!NT_SUCCESS(status))
{
USBDBG("device %s is pending removal\n",dev->device_id);
return complete_irp(irp, status, 0);
}
switch (stack_location->MinorFunction)
{
case IRP_MN_REMOVE_DEVICE:
dev->is_started = FALSE;
USBMSG("IRP_MN_REMOVE_DEVICE: is-filter=%c %s\n",
dev->is_filter ? 'Y' : 'N',
dev->device_id);
/* wait until all outstanding requests are finished */
remove_lock_release_and_wait(dev);
status = pass_irp_down(dev, irp, NULL, NULL);
USBMSG("deleting device #%d %s\n", dev->id, dev->device_id);
_snwprintf(tmp_name, sizeof(tmp_name)/sizeof(WCHAR), L"%s%04d",
LIBUSB_SYMBOLIC_LINK_NAME, dev->id);
/* delete the symbolic link */
RtlInitUnicodeString(&symbolic_link_name, tmp_name);
IoDeleteSymbolicLink(&symbolic_link_name);
/* delete the device object */
IoDetachDevice(dev->next_stack_device);
IoDeleteDevice(dev->self);
return status;
case IRP_MN_SURPRISE_REMOVAL:
dev->is_started = FALSE;
USBMSG("IRP_MN_SURPRISE_REMOVAL: is-filter=%c %s\n",
dev->is_filter ? 'Y' : 'N',
dev->device_id);
break;
case IRP_MN_START_DEVICE:
USBMSG("IRP_MN_START_DEVICE: is-filter=%c %s\n",
dev->is_filter ? 'Y' : 'N',
dev->device_id);
// A driver calls this routine after receiving a device set-power
// request and before calling PoStartNextPowerIrp. When handling a
// PnP IRP_MN_START_DEVICE request, the driver should call
// PoSetPowerState to notify the power manager that the device is
// in the D0 state.
//
PoSetPowerState(dev->self, DevicePowerState, dev->power_state);
return pass_irp_down(dev, irp, on_start_complete, NULL);
case IRP_MN_STOP_DEVICE:
dev->is_started = FALSE;
USBDBG("IRP_MN_STOP_DEVICE: is-filter=%c %s\n",
dev->is_filter ? 'Y' : 'N',
dev->device_id);
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
USBDBG("IRP_MN_DEVICE_USAGE_NOTIFICATION: is-filter=%c %s\n",
dev->is_filter ? 'Y' : 'N',
dev->device_id);
if (!dev->self->AttachedDevice
|| (dev->self->AttachedDevice->Flags & DO_POWER_PAGABLE))
{
dev->self->Flags |= DO_POWER_PAGABLE;
}
return pass_irp_down(dev, irp, on_device_usage_notification_complete, NULL);
case IRP_MN_QUERY_CAPABILITIES:
USBDBG("IRP_MN_QUERY_CAPABILITIES: is-filter=%c %s\n",
dev->is_filter ? 'Y' : 'N',
dev->device_id);
if (!dev->is_filter)
{
/* apply registry setting */
stack_location->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = dev->surprise_removal_ok;
}
return pass_irp_down(dev, irp, on_query_capabilities_complete, NULL);
default:
break;
}
remove_lock_release(dev);
return pass_irp_down(dev, irp, NULL, NULL);
}
static NTSTATUS DDKAPI
on_start_complete(DEVICE_OBJECT *device_object, IRP *irp, void *context)
{
libusb_device_t *dev = device_object->DeviceExtension;
if (irp->PendingReturned)
{
IoMarkIrpPending(irp);
}
USBDBG("is-filter=%c %s\n",
dev->is_filter ? 'Y' : 'N',
dev->device_id);
if (dev->next_stack_device->Characteristics & FILE_REMOVABLE_MEDIA)
{
device_object->Characteristics |= FILE_REMOVABLE_MEDIA;
}
#ifndef SKIP_CONFIGURE_NORMAL_DEVICES
// select initial configuration if not a filter
if (!dev->is_filter && !dev->is_started)
{
// optionally, the initial configuration value can be specified
// in the inf file. See reg_get_properties()
// HKR,,"InitialConfigValue",0x00010001,<your config value>
// If initial_config_value is negative, the configuration will
// only be set if the device is not already configured.
if (dev->initial_config_value)
{
if (dev->initial_config_value == SET_CONFIG_ACTIVE_CONFIG)
{
USBDBG("applying active configuration for %s\n",
dev->device_id);
}
else
{
USBDBG("applying InitialConfigValue %d for %s\n",
dev->initial_config_value, dev->device_id);
}
if(!NT_SUCCESS(set_configuration(dev, dev->initial_config_value, LIBUSB_DEFAULT_TIMEOUT)))
{
// we should always be able to apply the active configuration,
// even in the case of composite devices.
if (dev->initial_config_value == SET_CONFIG_ACTIVE_CONFIG)
{
USBERR("failed applying active configuration for %s\n",
dev->device_id);
}
else
{
USBERR("failed applying InitialConfigValue %d for %s\n",
dev->initial_config_value, dev->device_id);
}
}
}
}
#endif
dev->is_started = TRUE;
remove_lock_release(dev);
return STATUS_SUCCESS;
}
static NTSTATUS DDKAPI
on_device_usage_notification_complete(DEVICE_OBJECT *device_object,
IRP *irp, void *context)
{
libusb_device_t *dev = device_object->DeviceExtension;
if (irp->PendingReturned)
{
IoMarkIrpPending(irp);
}
if (!(dev->next_stack_device->Flags & DO_POWER_PAGABLE))
{
device_object->Flags &= ~DO_POWER_PAGABLE;
}
remove_lock_release(dev);
return STATUS_SUCCESS;
}
static NTSTATUS DDKAPI
on_query_capabilities_complete(DEVICE_OBJECT *device_object,
IRP *irp, void *context)
{
libusb_device_t *dev = device_object->DeviceExtension;
IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
if (irp->PendingReturned)
{
IoMarkIrpPending(irp);
}
if (NT_SUCCESS(irp->IoStatus.Status))
{
if (!dev->is_filter)
{
/* apply registry setting */
stack_location->Parameters.DeviceCapabilities.Capabilities
->SurpriseRemovalOK = dev->surprise_removal_ok;
}
/* save supported device power states */
memcpy(dev->device_power_states, stack_location
->Parameters.DeviceCapabilities.Capabilities->DeviceState,
sizeof(dev->device_power_states));
}
remove_lock_release(dev);
return STATUS_SUCCESS;
}
@@ -0,0 +1,269 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
static NTSTATUS DDKAPI
on_power_state_complete(DEVICE_OBJECT *device_object,
IRP *irp,
void *context);
static NTSTATUS DDKAPI
on_filter_power_state_complete(DEVICE_OBJECT *device_object,
IRP *irp,
void *context);
static void DDKAPI
on_power_set_device_state_complete(DEVICE_OBJECT *device_object,
UCHAR minor_function,
POWER_STATE power_state,
void *context,
IO_STATUS_BLOCK *io_status);
/* [trobinso MOD 4/16/2010]
* If running as a filter, do not act as power policy owner.
*/
NTSTATUS dispatch_power(libusb_device_t *dev, IRP *irp)
{
IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
POWER_STATE power_state;
NTSTATUS status;
status = remove_lock_acquire(dev);
if (!NT_SUCCESS(status))
{
irp->IoStatus.Status = status;
PoStartNextPowerIrp(irp);
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
if (stack_location->MinorFunction == IRP_MN_SET_POWER)
{
power_state = stack_location->Parameters.Power.State;
if (stack_location->Parameters.Power.Type == SystemPowerState)
{
USBMSG("IRP_MN_SET_POWER: S%d %s\n",
power_state.SystemState - PowerSystemWorking, dev->device_id);
}
else
{
USBMSG("IRP_MN_SET_POWER: D%d %s\n",
power_state.DeviceState - PowerDeviceD0, dev->device_id);
if (power_state.DeviceState > dev->power_state.DeviceState)
{
/* device is powered down, report device state to the */
/* Power Manager before sending the IRP down */
/* (power up is handled by the completion routine) */
PoSetPowerState(dev->self, DevicePowerState, power_state);
}
}
/* TODO: should PoStartNextPowerIrp() be called here or from the */
/* completion routine? */
PoStartNextPowerIrp(irp);
IoCopyCurrentIrpStackLocationToNext(irp);
if (!dev->is_filter && !dev->disallow_power_control)
{
IoSetCompletionRoutine(irp,
on_power_state_complete,
dev,
TRUE, /* on success */
TRUE, /* on error */
TRUE);/* on cancel */
}
else
{
IoSetCompletionRoutine(irp,
on_filter_power_state_complete,
dev,
TRUE, /* on success */
TRUE, /* on error */
TRUE);/* on cancel */
}
return PoCallDriver(dev->next_stack_device, irp);
}
else
{
/* pass all other power IRPs down without setting a completion routine */
PoStartNextPowerIrp(irp);
IoSkipCurrentIrpStackLocation(irp);
status = PoCallDriver(dev->next_stack_device, irp);
remove_lock_release(dev);
return status;
}
}
static NTSTATUS DDKAPI
on_power_state_complete(DEVICE_OBJECT *device_object,
IRP *irp,
void *context)
{
libusb_device_t *dev = context;
IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
POWER_STATE power_state = stack_location->Parameters.Power.State;
DEVICE_POWER_STATE dev_power_state;
if (irp->PendingReturned)
{
IoMarkIrpPending(irp);
}
if (NT_SUCCESS(irp->IoStatus.Status))
{
if (stack_location->Parameters.Power.Type == SystemPowerState)
{
USBMSG("S%d %s\n",
power_state.SystemState - PowerSystemWorking, dev->device_id);
/* save current system state */
dev->power_state.SystemState = power_state.SystemState;
/* get supported device power state from the array reported by */
/* IRP_MN_QUERY_CAPABILITIES */
dev_power_state = dev->device_power_states[power_state.SystemState];
/* set the device power state, but don't block the thread */
power_set_device_state(dev, dev_power_state, FALSE);
}
else /* DevicePowerState */
{
USBMSG("D%d %s\n",
power_state.DeviceState - PowerDeviceD0, dev->device_id);
if (power_state.DeviceState <= dev->power_state.DeviceState)
{
/* device is powered up, */
/* report device state to Power Manager */
PoSetPowerState(dev->self, DevicePowerState, power_state);
}
/* save current device state */
dev->power_state.DeviceState = power_state.DeviceState;
}
}
else
{
USBMSG0("failed\n");
}
remove_lock_release(dev);
return STATUS_SUCCESS;
}
static NTSTATUS DDKAPI
on_filter_power_state_complete(DEVICE_OBJECT *device_object,
IRP *irp,
void *context)
{
libusb_device_t *dev = context;
IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
POWER_STATE power_state = stack_location->Parameters.Power.State;
if (NT_SUCCESS(irp->IoStatus.Status))
{
if (stack_location->Parameters.Power.Type == SystemPowerState)
{
USBMSG("S%d\n",
power_state.SystemState - PowerSystemWorking);
/* save current system state */
dev->power_state.SystemState = power_state.SystemState;
}
else /* DevicePowerState */
{
USBMSG("D%d\n",
power_state.DeviceState - PowerDeviceD0);
if (power_state.DeviceState <= dev->power_state.DeviceState)
{
/* device is powered up, */
/* report device state to Power Manager */
PoSetPowerState(dev->self, DevicePowerState, power_state);
}
/* save current device state */
dev->power_state.DeviceState = power_state.DeviceState;
}
}
else
{
USBMSG0("failed\n");
}
remove_lock_release(dev);
return STATUS_SUCCESS;
}
static void DDKAPI
on_power_set_device_state_complete(DEVICE_OBJECT *device_object,
UCHAR minor_function,
POWER_STATE power_state,
void *context,
IO_STATUS_BLOCK *io_status)
{
KeSetEvent((KEVENT *)context, EVENT_INCREMENT, FALSE);
}
void power_set_device_state(libusb_device_t *dev,
DEVICE_POWER_STATE device_state, bool_t block)
{
NTSTATUS status;
KEVENT event;
POWER_STATE power_state;
power_state.DeviceState = device_state;
USBMSG("setting device power state to D%d %s\n",
power_state.DeviceState - PowerDeviceD0, dev->device_id);
if (block) /* wait for IRP to complete */
{
KeInitializeEvent(&event, NotificationEvent, FALSE);
/* set the device power state and wait for completion */
status = PoRequestPowerIrp(dev->physical_device_object,
IRP_MN_SET_POWER,
power_state,
on_power_set_device_state_complete,
&event, NULL);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
}
}
else
{
PoRequestPowerIrp(dev->physical_device_object, IRP_MN_SET_POWER,
power_state, NULL, NULL, NULL);
}
}
@@ -0,0 +1,80 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS release_interface(libusb_device_t *dev, FILE_OBJECT *file_object,
int interface)
{
USBMSG("interface %d\n", interface);
if (!dev->config.value)
{
USBERR0("device is not configured\n");
return STATUS_INVALID_DEVICE_STATE;
}
if (interface >= LIBUSB_MAX_NUMBER_OF_INTERFACES)
{
USBERR("interface number %d too high\n",
interface);
return STATUS_INVALID_PARAMETER;
}
if (!dev->config.interfaces[interface].valid)
{
USBERR("invalid interface %02d\n", interface);
return STATUS_INVALID_PARAMETER;
}
if (!dev->config.interfaces[interface].file_object)
{
USBERR("could not release interface %d, interface is not claimed\n", interface);
return STATUS_INVALID_DEVICE_STATE;
}
if (dev->config.interfaces[interface].file_object != file_object)
{
USBERR("could not release interface %d, interface is not bound to this file object\n", interface);
return STATUS_DEVICE_BUSY;
}
dev->config.interfaces[interface].file_object = NULL;
return STATUS_SUCCESS;
}
NTSTATUS release_all_interfaces(libusb_device_t *dev, FILE_OBJECT *file_object)
{
int i;
USBMSG("releasing all interfaces bound to file object 0x%x\n", file_object);
for (i = 0; i < LIBUSB_MAX_NUMBER_OF_INTERFACES; i++)
{
if (dev->config.interfaces[i].file_object == file_object)
{
dev->config.interfaces[i].file_object = NULL;
}
}
return STATUS_SUCCESS;
}
@@ -0,0 +1,44 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS reset_device(libusb_device_t *dev, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
USBMSG0("resetting device\n");
status = call_usbd(dev, NULL, IOCTL_INTERNAL_USB_RESET_PORT, timeout);
if (!NT_SUCCESS(status))
{
USBERR("IOCTL_INTERNAL_USB_RESET_PORT failed: status: 0x%x\n", status);
}
status = call_usbd(dev, NULL, IOCTL_INTERNAL_USB_CYCLE_PORT, timeout);
if (!NT_SUCCESS(status))
{
USBERR("IOCTL_INTERNAL_USB_CYCLE_PORT failed: status: 0x%x\n", status);
}
return status;
}
@@ -0,0 +1,56 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS reset_endpoint(libusb_device_t *dev, int endpoint, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
USBMSG("endpoint: 0x%02x timeout: %d\n", endpoint, timeout);
if (!dev->config.value)
{
USBERR0("invalid configuration 0\n");
return STATUS_INVALID_DEVICE_STATE;
}
memset(&urb, 0, sizeof(struct _URB_PIPE_REQUEST));
urb.UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
urb.UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
if (!get_pipe_handle(dev, endpoint, &urb.UrbPipeRequest.PipeHandle))
{
USBERR0("getting endpoint pipe failed\n");
return STATUS_INVALID_PARAMETER;
}
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("request failed: status: 0x%x, urb-status: 0x%x\n", status, urb.UrbHeader.Status);
}
return status;
}
@@ -0,0 +1,197 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
#include <stdlib.h>
NTSTATUS set_configuration(libusb_device_t *dev,
int configuration,
int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb, *urb_ptr = NULL;
USB_CONFIGURATION_DESCRIPTOR *configuration_descriptor = NULL;
USB_INTERFACE_DESCRIPTOR *interface_descriptor = NULL;
USBD_INTERFACE_LIST_ENTRY *interfaces = NULL;
int i, j, interface_number, desc_size, config_index, ret;
// check if this config value is already set
if ((configuration > 0) && dev->config.value == configuration)
{
return STATUS_SUCCESS;
}
// check if this config index is already set
if ((configuration < 0) && dev->config.value && dev->config.index == (abs(configuration)-1))
{
return STATUS_SUCCESS;
}
memset(&urb, 0, sizeof(URB));
if (configuration == 0)
{
urb.UrbHeader.Function = URB_FUNCTION_SELECT_CONFIGURATION;
urb.UrbHeader.Length = sizeof(struct _URB_SELECT_CONFIGURATION);
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("setting configuration %d failed: status: 0x%x, urb-status: 0x%x\n",
configuration, status, urb.UrbHeader.Status);
return status;
}
dev->config.handle = urb.UrbSelectConfiguration.ConfigurationHandle;
dev->config.value = 0;
clear_pipe_info(dev);
return status;
}
if (configuration <= SET_CONFIG_ACTIVE_CONFIG)
{
// note: as of v1.2.4.0, the active/default configuration is
// always the first configuration the device returns. (index 0)
configuration=-1;
}
USBMSG("setting configuration %s %d timeout=%d",
(configuration < 0) ? "index" : "value",
(configuration < 0) ? abs(configuration) - 1 : configuration,
timeout);
// If configuration is negative, it is retrieved by index.
//
configuration_descriptor = get_config_descriptor(dev, configuration,
&desc_size, &config_index);
if (!configuration_descriptor)
{
USBERR0("getting configuration descriptor failed");
return STATUS_INVALID_PARAMETER;
}
// if we passed an index in we can check here to see
// if the device is already configured with this value
if (dev->config.value == configuration_descriptor->bConfigurationValue)
{
status = STATUS_SUCCESS;
goto SetConfigurationDone;
}
// MEMORY ALLOCATION BEGINS
interfaces =
ExAllocatePool(NonPagedPool,(configuration_descriptor->bNumInterfaces + 1)
* sizeof(USBD_INTERFACE_LIST_ENTRY));
if (!interfaces)
{
USBERR0("memory allocation failed\n");
status = STATUS_NO_MEMORY;
goto SetConfigurationDone;
}
memset(interfaces, 0, (configuration_descriptor->bNumInterfaces + 1)
* sizeof(USBD_INTERFACE_LIST_ENTRY));
interface_number = 0;
for (i = 0; i < configuration_descriptor->bNumInterfaces; i++)
{
for (j = interface_number; j < LIBUSB_MAX_NUMBER_OF_INTERFACES; j++)
{
interface_descriptor =
find_interface_desc(configuration_descriptor, desc_size, j, 0);
if (interface_descriptor)
{
interface_number = ++j;
break;
}
}
if (!interface_descriptor)
{
USBERR("unable to find interface descriptor at index %d\n", i);
status = STATUS_INVALID_PARAMETER;
goto SetConfigurationDone;
}
else
{
USBMSG("found interface %d\n",
interface_descriptor->bInterfaceNumber);
interfaces[i].InterfaceDescriptor = interface_descriptor;
}
}
urb_ptr = USBD_CreateConfigurationRequestEx(configuration_descriptor, interfaces);
if (!urb_ptr)
{
USBERR0("memory allocation failed\n");
status = STATUS_NO_MEMORY;
goto SetConfigurationDone;
}
for (i = 0; i < configuration_descriptor->bNumInterfaces; i++)
{
for (j = 0; j < (int)interfaces[i].Interface->NumberOfPipes; j++)
{
interfaces[i].Interface->Pipes[j].MaximumTransferSize = LIBUSB_MAX_READ_WRITE;
}
}
USBDBG("#%d %s passing configuration request to target-device.",
dev->id, dev->device_id);
status = call_usbd(dev, urb_ptr, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb_ptr->UrbHeader.Status))
{
USBERR("setting configuration %d failed: status: 0x%x, urb-status: 0x%x\n",
configuration, status, urb_ptr->UrbHeader.Status);
if (NT_SUCCESS(status)) status = urb_ptr->UrbHeader.Status;
goto SetConfigurationDone;
}
dev->config.handle = urb_ptr->UrbSelectConfiguration.ConfigurationHandle;
dev->config.value = configuration_descriptor->bConfigurationValue;
dev->config.index = config_index;
clear_pipe_info(dev);
for (i = 0; i < configuration_descriptor->bNumInterfaces; i++)
{
update_pipe_info(dev, interfaces[i].Interface);
}
SetConfigurationDone:
if (interfaces)
ExFreePool(interfaces);
if (urb_ptr)
ExFreePool(urb_ptr);
if (configuration_descriptor)
ExFreePool(configuration_descriptor);
return status;
}
@@ -0,0 +1,71 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS set_descriptor(libusb_device_t *dev,
void *buffer, int size, int type, int recipient,
int index, int language_id, int *sent, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
USBMSG("buffer size: %d type: %04d recipient: %04d index: %04d language id: %04d timeout: %d\n",
size,type,recipient,index,language_id,timeout);
memset(&urb, 0, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
switch (recipient)
{
case USB_RECIP_DEVICE:
urb.UrbHeader.Function = URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE;
break;
case USB_RECIP_INTERFACE:
urb.UrbHeader.Function = URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE;
break;
case USB_RECIP_ENDPOINT:
urb.UrbHeader.Function = URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT;
break;
default:
USBERR0("invalid recipient\n");
return STATUS_INVALID_PARAMETER;
}
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
urb.UrbControlDescriptorRequest.TransferBufferLength = size;
urb.UrbControlDescriptorRequest.TransferBuffer = buffer;
urb.UrbControlDescriptorRequest.DescriptorType = (UCHAR)type;
urb.UrbControlDescriptorRequest.Index = (UCHAR)index;
urb.UrbControlDescriptorRequest.LanguageId = (USHORT)language_id;
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("setting descriptor failed: status: 0x%x, urb-status: 0x%x\n", status, urb.UrbHeader.Status);
}
else
{
*sent = urb.UrbControlDescriptorRequest.TransferBufferLength;
}
return status;
}
@@ -0,0 +1,67 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS set_feature(libusb_device_t *dev, int recipient, int index,
int feature, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
USBMSG("recipient: %02d index: %04d feature %04d timeout: %d\n",
recipient,index,feature,timeout);
memset(&urb, 0, sizeof(struct _URB_CONTROL_FEATURE_REQUEST));
switch (recipient)
{
case USB_RECIP_DEVICE:
urb.UrbHeader.Function = URB_FUNCTION_SET_FEATURE_TO_DEVICE;
break;
case USB_RECIP_INTERFACE:
urb.UrbHeader.Function = URB_FUNCTION_SET_FEATURE_TO_INTERFACE;
break;
case USB_RECIP_ENDPOINT:
urb.UrbHeader.Function = URB_FUNCTION_SET_FEATURE_TO_ENDPOINT;
break;
case USB_RECIP_OTHER:
urb.UrbHeader.Function = URB_FUNCTION_SET_FEATURE_TO_OTHER;
urb.UrbControlFeatureRequest.Index = 0;
break;
default:
USBERR0("invalid recipient\n");
return STATUS_INVALID_PARAMETER;
}
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_FEATURE_REQUEST);
urb.UrbControlFeatureRequest.FeatureSelector = (USHORT)feature;
urb.UrbControlFeatureRequest.Index = (USHORT)index;
status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("setting feature failed: status: 0x%x, urb-status: 0x%x\n", status, urb.UrbHeader.Status);
}
return status;
}
@@ -0,0 +1,113 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS set_interface(libusb_device_t *dev, int interface, int altsetting,
int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB *urb;
int i, config_size, config_index, tmp_size;
USB_CONFIGURATION_DESCRIPTOR *configuration_descriptor = NULL;
USB_INTERFACE_DESCRIPTOR *interface_descriptor = NULL;
USBD_INTERFACE_INFORMATION *interface_information = NULL;
USBMSG("interface %d altsetting %d timeout %d\n",
interface,altsetting,timeout);
if (!dev->config.value)
{
USBERR0("device is not configured\n");
return STATUS_INVALID_DEVICE_STATE;
}
configuration_descriptor = get_config_descriptor(dev, dev->config.value,
&config_size, &config_index);
if (!configuration_descriptor)
{
USBERR0("memory_allocation error\n");
return STATUS_NO_MEMORY;
}
interface_descriptor =
find_interface_desc(configuration_descriptor, config_size,
interface, altsetting);
if (!interface_descriptor)
{
USBERR("interface %d or altsetting %d invalid\n",
interface, altsetting);
ExFreePool(configuration_descriptor);
return STATUS_UNSUCCESSFUL;
}
tmp_size = sizeof(struct _URB_SELECT_INTERFACE) + interface_descriptor->bNumEndpoints * sizeof(USBD_PIPE_INFORMATION);
urb = ExAllocatePool(NonPagedPool, tmp_size);
if (!urb)
{
USBERR0("memory_allocation error\n");
ExFreePool(configuration_descriptor);
return STATUS_NO_MEMORY;
}
memset(urb, 0, tmp_size);
urb->UrbHeader.Function = URB_FUNCTION_SELECT_INTERFACE;
urb->UrbHeader.Length = (USHORT)tmp_size;
urb->UrbSelectInterface.ConfigurationHandle = dev->config.handle;
urb->UrbSelectInterface.Interface.Length = sizeof(struct _USBD_INTERFACE_INFORMATION);
urb->UrbSelectInterface.Interface.NumberOfPipes = interface_descriptor->bNumEndpoints;
urb->UrbSelectInterface.Interface.Length += interface_descriptor->bNumEndpoints * sizeof(struct _USBD_PIPE_INFORMATION);
urb->UrbSelectInterface.Interface.InterfaceNumber = (UCHAR)interface;
urb->UrbSelectInterface.Interface.AlternateSetting = (UCHAR)altsetting;
interface_information = &urb->UrbSelectInterface.Interface;
for (i = 0; i < interface_descriptor->bNumEndpoints; i++)
{
interface_information->Pipes[i].MaximumTransferSize = LIBUSB_MAX_READ_WRITE;
}
status = call_usbd(dev, urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb->UrbHeader.Status))
{
USBERR("setting interface failed: status: 0x%x, urb-status: 0x%x\n", status, urb->UrbHeader.Status);
ExFreePool(configuration_descriptor);
ExFreePool(urb);
return STATUS_UNSUCCESSFUL;
}
update_pipe_info(dev, interface_information);
ExFreePool(configuration_descriptor);
ExFreePool(urb);
return status;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,35 @@
EXPORTS
USBD_AllocateDeviceName
USBD_CalculateUsbBandwidth
USBD_CompleteRequest
USBD_CreateConfigurationRequest
USBD_CreateConfigurationRequestEx
USBD_CreateDevice
USBD_Debug_GetHeap
USBD_Debug_LogEntry
USBD_Debug_RetHeap
USBD_Dispatch
USBD_FreeDeviceMutex
USBD_FreeDeviceName
USBD_GetDeviceInformation
USBD_GetInterfaceLength
USBD_GetPdoRegistryParameter
USBD_GetSuspendPowerState
USBD_GetUSBDIVersion
USBD_InitializeDevice
USBD_MakePdoName
USBD_ParseConfigurationDescriptor
USBD_ParseConfigurationDescriptorEx
USBD_ParseDescriptors
USBD_QueryBusTime
USBD_RegisterHcDeviceCapabilities
USBD_RegisterHcFilter
USBD_RegisterHostController
USBD_RemoveDevice
USBD_RestoreDevice
USBD_SetSuspendPowerState
USBD_WaitDeviceMutex
USBD_CreateConfigurationRequestEx@8=_USBD_CreateConfigurationRequestEx@8
USBD_ParseConfigurationDescriptorEx@28=_USBD_ParseConfigurationDescriptorEx@28
USBD_ParseDescriptors@16=_USBD_ParseDescriptors@16
@@ -0,0 +1,310 @@
#ifndef __USBDLIB_H
#define __USBDLIB_H
#if __GNUC__ >=3
#pragma GCC system_header
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#pragma pack(push,4)
typedef struct _USBD_INTERFACE_LIST_ENTRY
{
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
PUSBD_INTERFACE_INFORMATION Interface;
} USBD_INTERFACE_LIST_ENTRY, *PUSBD_INTERFACE_LIST_ENTRY;
#define URB_STATUS(urb) ((urb)->UrbHeader.Status)
#define GET_SELECT_CONFIGURATION_REQUEST_SIZE(totalInterfaces, totalPipes) \
(sizeof(struct _URB_SELECT_CONFIGURATION) \
+ ((totalInterfaces - 1) * sizeof(USBD_INTERFACE_INFORMATION)) \
+ ((totalPipes - 1) * sizeof(USBD_PIPE_INFORMATION)))
#define GET_SELECT_INTERFACE_REQUEST_SIZE(totalPipes) \
(sizeof(struct _URB_SELECT_INTERFACE) \
+ ((totalPipes - 1) * sizeof(USBD_PIPE_INFORMATION)))
#define GET_USBD_INTERFACE_SIZE(numEndpoints) \
(sizeof(USBD_INTERFACE_INFORMATION) \
+ (sizeof(USBD_PIPE_INFORMATION)*(numEndpoints)) \
- sizeof(USBD_PIPE_INFORMATION))
#define GET_ISO_URB_SIZE(n) (sizeof(struct _URB_ISOCH_TRANSFER) \
+ sizeof(USBD_ISO_PACKET_DESCRIPTOR) * n)
#define UsbBuildInterruptOrBulkTransferRequest(urb, \
length, \
pipeHandle, \
transferBuffer, \
transferBufferMDL, \
transferBufferLength, \
transferFlags, \
link) { \
(urb)->UrbHeader.Function = \
URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; \
(urb)->UrbHeader.Length = (length); \
(urb)->UrbBulkOrInterruptTransfer.PipeHandle = (pipeHandle); \
(urb)->UrbBulkOrInterruptTransfer.TransferBufferLength = \
(transferBufferLength); \
(urb)->UrbBulkOrInterruptTransfer.TransferBufferMDL = \
(transferBufferMDL); \
(urb)->UrbBulkOrInterruptTransfer.TransferBuffer = \
(transferBuffer); \
(urb)->UrbBulkOrInterruptTransfer.TransferFlags = \
(transferFlags); \
(urb)->UrbBulkOrInterruptTransfer.UrbLink = (link); }
#define UsbBuildGetDescriptorRequest(urb, \
length, \
descriptorType, \
descriptorIndex, \
languageId, \
transferBuffer, \
transferBufferMDL, \
transferBufferLength, \
link) { \
(urb)->UrbHeader.Function = \
URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE; \
(urb)->UrbHeader.Length = (length); \
(urb)->UrbControlDescriptorRequest.TransferBufferLength = \
(transferBufferLength); \
(urb)->UrbControlDescriptorRequest.TransferBufferMDL = \
(transferBufferMDL); \
(urb)->UrbControlDescriptorRequest.TransferBuffer = \
(transferBuffer); \
(urb)->UrbControlDescriptorRequest.DescriptorType = \
(descriptorType); \
(urb)->UrbControlDescriptorRequest.Index = (descriptorIndex); \
(urb)->UrbControlDescriptorRequest.LanguageId = (languageId); \
(urb)->UrbControlDescriptorRequest.UrbLink = (link); }
#define UsbBuildGetStatusRequest(urb, \
op, \
index, \
transferBuffer, \
transferBufferMDL, \
link) { \
(urb)->UrbHeader.Function = (op); \
(urb)->UrbHeader.Length = \
sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST); \
(urb)->UrbControlGetStatusRequest.TransferBufferLength = \
sizeof(USHORT); \
(urb)->UrbControlGetStatusRequest.TransferBufferMDL = \
(transferBufferMDL); \
(urb)->UrbControlGetStatusRequest.TransferBuffer = \
(transferBuffer); \
(urb)->UrbControlGetStatusRequest.Index = (index); \
(urb)->UrbControlGetStatusRequest.UrbLink = (link); }
#define UsbBuildFeatureRequest(urb, \
op, \
featureSelector, \
index, \
link) { \
(urb)->UrbHeader.Function = (op); \
(urb)->UrbHeader.Length = \
sizeof(struct _URB_CONTROL_FEATURE_REQUEST); \
(urb)->UrbControlFeatureRequest.FeatureSelector = \
(featureSelector); \
(urb)->UrbControlFeatureRequest.Index = (index); \
(urb)->UrbControlFeatureRequest.UrbLink = (link); }
#define UsbBuildSelectConfigurationRequest(urb, \
length, \
configurationDescriptor) { \
(urb)->UrbHeader.Function = URB_FUNCTION_SELECT_CONFIGURATION; \
(urb)->UrbHeader.Length = (length); \
(urb)->UrbSelectConfiguration.ConfigurationDescriptor = \
(configurationDescriptor); }
#define UsbBuildSelectInterfaceRequest(urb, \
length, \
configurationHandle, \
interfaceNumber, \
alternateSetting) { \
(urb)->UrbHeader.Function = URB_FUNCTION_SELECT_INTERFACE; \
(urb)->UrbHeader.Length = (length); \
(urb)->UrbSelectInterface.Interface.AlternateSetting = \
(alternateSetting); \
(urb)->UrbSelectInterface.Interface.InterfaceNumber = \
(interfaceNumber); \
(urb)->UrbSelectInterface.ConfigurationHandle = \
(configurationHandle); }
#define UsbBuildVendorRequest(urb, \
cmd, \
length, \
transferFlags, \
reservedbits, \
request, \
value, \
index, \
transferBuffer, \
transferBufferMDL, \
transferBufferLength, \
link) { \
(urb)->UrbHeader.Function = cmd; \
(urb)->UrbHeader.Length = (length); \
(urb)->UrbControlVendorClassRequest.TransferBufferLength = \
(transferBufferLength); \
(urb)->UrbControlVendorClassRequest.TransferBufferMDL = \
(transferBufferMDL); \
(urb)->UrbControlVendorClassRequest.TransferBuffer = \
(transferBuffer); \
(urb)->UrbControlVendorClassRequest.RequestTypeReservedBits = \
(reservedbits); \
(urb)->UrbControlVendorClassRequest.Request = (request); \
(urb)->UrbControlVendorClassRequest.Value = (value); \
(urb)->UrbControlVendorClassRequest.Index = (index); \
(urb)->UrbControlVendorClassRequest.TransferFlags = \
(transferFlags); \
(urb)->UrbControlVendorClassRequest.UrbLink = (link); }
#define UsbBuildOsFeatureDescriptorRequest(urb, \
length, \
interface, \
index, \
transferBuffer, \
transferBufferMDL, \
transferBufferLength, \
link) { \
(urb)->UrbHeader.Function = \
URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR; \
(urb)->UrbHeader.Length = (length); \
(urb)->UrbOSFeatureDescriptorRequest.TransferBufferLength = \
(transferBufferLength); \
(urb)->UrbOSFeatureDescriptorRequest.TransferBufferMDL = \
(transferBufferMDL); \
(urb)->UrbOSFeatureDescriptorRequest.TransferBuffer = \
(transferBuffer); \
(urb)->UrbOSFeatureDescriptorRequest.InterfaceNumber = \
(interface); \
(urb)->UrbOSFeatureDescriptorRequest.MS_FeatureDescriptorIndex = \
(index); \
(urb)->UrbOSFeatureDescriptorRequest.UrbLink = (link); }
VOID
DDKAPI
USBD_Debug_LogEntry(
IN CHAR *Name,
IN ULONG Info1,
IN ULONG Info2,
IN ULONG Info3
);
VOID
DDKAPI
USBD_GetUSBDIVersion(
PUSBD_VERSION_INFORMATION VersionInformation
);
PUSB_INTERFACE_DESCRIPTOR
DDKAPI
USBD_ParseConfigurationDescriptor(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN UCHAR InterfaceNumber,
IN UCHAR AlternateSetting
);
PURB
DDKAPI
USBD_CreateConfigurationRequest(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN OUT PUSHORT Siz
);
PUSB_COMMON_DESCRIPTOR
DDKAPI
USBD_ParseDescriptors(
IN PVOID DescriptorBuffer,
IN ULONG TotalLength,
IN PVOID StartPosition,
IN LONG DescriptorType
);
PUSB_INTERFACE_DESCRIPTOR
DDKAPI
USBD_ParseConfigurationDescriptorEx(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN PVOID StartPosition,
IN LONG InterfaceNumber,
IN LONG AlternateSetting,
IN LONG InterfaceClass,
IN LONG InterfaceSubClass,
IN LONG InterfaceProtocol
);
PURB
DDKAPI
USBD_CreateConfigurationRequestEx(
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
IN PUSBD_INTERFACE_LIST_ENTRY InterfaceList
);
ULONG
DDKAPI
USBD_GetInterfaceLength(
IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
IN PUCHAR BufferEnd
);
VOID
DDKAPI
USBD_RegisterHcFilter(
PDEVICE_OBJECT DeviceObject,
PDEVICE_OBJECT FilterDeviceObject
);
NTSTATUS
DDKAPI
USBD_GetPdoRegistryParameter(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN OUT PVOID Parameter,
IN ULONG ParameterLength,
IN PWCHAR KeyName,
IN ULONG KeyNameLength
);
NTSTATUS
DDKAPI
USBD_QueryBusTime(
IN PDEVICE_OBJECT RootHubPdo,
IN PULONG CurrentFrame
);
ULONG
DDKAPI
USBD_CalculateUsbBandwidth(
ULONG MaxPacketSize,
UCHAR EndpointType,
BOOLEAN LowSpeed
);
#pragma pack(pop)
#ifdef __cplusplus
}
#endif
#endif /* __USBDLIB_H */
@@ -0,0 +1,143 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libusb_driver.h"
NTSTATUS vendor_class_request(libusb_device_t *dev,
int type, int recipient,
int request, int value, int index,
void *buffer, int size, int direction,
int *ret, int timeout)
{
NTSTATUS status = STATUS_SUCCESS;
URB urb;
*ret = 0;
memset(&urb, 0, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
switch (type)
{
case USB_TYPE_CLASS:
USBMSG0("type: class\n");
switch (recipient)
{
case USB_RECIP_DEVICE:
USBMSG0("recipient: device\n");
urb.UrbHeader.Function = URB_FUNCTION_CLASS_DEVICE;
break;
case USB_RECIP_INTERFACE:
USBMSG0("recipient: interface\n");
urb.UrbHeader.Function = URB_FUNCTION_CLASS_INTERFACE;
break;
case USB_RECIP_ENDPOINT:
USBMSG0("recipient: endpoint\n");
urb.UrbHeader.Function = URB_FUNCTION_CLASS_ENDPOINT;
break;
case USB_RECIP_OTHER:
USBMSG0("recipient: other\n");
urb.UrbHeader.Function = URB_FUNCTION_CLASS_OTHER;
break;
default:
USBERR0("invalid recipient\n");
return STATUS_INVALID_PARAMETER;
}
break;
case USB_TYPE_VENDOR:
USBMSG0("type: vendor\n");
switch (recipient)
{
case USB_RECIP_DEVICE:
USBMSG0("recipient: device\n");
urb.UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;
break;
case USB_RECIP_INTERFACE:
USBMSG0("recipient: interface\n");
urb.UrbHeader.Function = URB_FUNCTION_VENDOR_INTERFACE;
break;
case USB_RECIP_ENDPOINT:
USBMSG0("recipient: endpoint\n");
urb.UrbHeader.Function = URB_FUNCTION_VENDOR_ENDPOINT;
break;
case USB_RECIP_OTHER:
USBMSG0("recipient: other\n");
urb.UrbHeader.Function = URB_FUNCTION_VENDOR_OTHER;
break;
default:
// [Kevin Timmerman Patch]
USBMSG("recipient: reserved (0x%02x)\n", recipient);
urb.UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;
urb.UrbControlVendorClassRequest.RequestTypeReservedBits = (UCHAR)recipient;
break;
/*
USBERR0("invalid recipient\n");
return STATUS_INVALID_PARAMETER;
*/
}
break;
default:
USBERR0("invalid type\n");
return STATUS_INVALID_PARAMETER;
}
USBMSG("request: 0x%02x\n", request);
USBMSG("value: 0x%04x\n", value);
USBMSG("index: 0x%04x\n", index);
USBMSG("size: %d\n", size);
if (direction == USBD_TRANSFER_DIRECTION_IN)
{
USBMSG0("direction: in\n");
}
else
{
USBMSG0("direction: out\n");
}
USBMSG("timeout: %d\n", timeout);
urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
urb.UrbControlVendorClassRequest.TransferFlags
= direction | USBD_SHORT_TRANSFER_OK ;
urb.UrbControlVendorClassRequest.TransferBufferLength = size;
urb.UrbControlVendorClassRequest.TransferBufferMDL = NULL;
urb.UrbControlVendorClassRequest.TransferBuffer = buffer;
urb.UrbControlVendorClassRequest.Request = (UCHAR)request;
urb.UrbControlVendorClassRequest.Value = (USHORT)value;
urb.UrbControlVendorClassRequest.Index = (USHORT)index;
// no maximum timeout check for vendor request.
status = call_usbd_ex(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout, 0);
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status))
{
USBERR("request failed: status: 0x%x, urb-status: 0x%x\n", status, urb.UrbHeader.Status);
}
else
{
if (direction == USBD_TRANSFER_DIRECTION_IN)
*ret = urb.UrbControlVendorClassRequest.TransferBufferLength;
USBMSG("%d bytes transmitted\n",
urb.UrbControlVendorClassRequest.TransferBufferLength);
}
return status;
}
@@ -0,0 +1,416 @@
/* Error & Logging functions
Copyright © 2010 Travis Robinson. <libusbdotnet@gmail.com>
website: http://sourceforge.net/projects/libusb-win32
This program 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 program 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 program; if not, please visit www.gnu.org.
*/
#include "error.h"
#include <errno.h>
#include <string.h>
#include <stdio.h>
#if IS_DRIVER
#ifdef __GNUC__
#define OBJ_KERNEL_HANDLE 0x00000200L
#include <ddk/usb100.h>
#include <ddk/usbdi.h>
#include <ddk/winddk.h>
#include "usbdlib_gcc.h"
#else
#include <ntddk.h>
#endif
#else
#include <windows.h>
#endif
#define USB_ERROR_BEGIN 500000
#ifndef LOG_APPNAME
#define LOG_APPNAME "LOG_APPNAME define missing"
#endif
#define GetLogLevel(UsbLogLevel) ((UsbLogLevel & LOG_LEVEL_MASK)>LOG_LEVEL_MAX?LOG_LEVEL_MAX:UsbLogLevel & LOG_LEVEL_MASK)
#define GetLogOuput(LogOutputType) (LogOutputType>0?(_LOG_OUTPUT_TYPE & LogOutputType):1)
void usb_err_v (const char* function, const char* format, va_list args);
void usb_wrn_v (const char* function, const char* format, va_list args);
void usb_msg_v (const char* function, const char* format, va_list args);
void usb_dbg_v (const char* function, const char* format, va_list args);
void usb_log_v (enum USB_LOG_LEVEL level, const char* function, const char* format, va_list args);
void _usb_log (enum USB_LOG_LEVEL level, const char* app_name, const char* function, const char* format, ...);
void _usb_log_v (enum USB_LOG_LEVEL level, const char* app_name, const char* function, const char* format, va_list args);
static int usb_log_def_handler(enum USB_LOG_LEVEL level,
const char* app_name,
const char* prefix,
const char* func,
int app_prefix_func_end,
char* message,
int message_length);
#define STRIP_PREFIX(stringSrc, stringPrefix) \
(strstr(stringSrc,stringPrefix)==stringSrc?stringSrc+strlen(stringPrefix):stringSrc)
static const char *log_level_string[LOG_LEVEL_MAX+1] =
{
"off",
"err",
"wrn",
"",
"dbg",
"unknown",
};
static const char *skipped_function_prefix_list[] =
{
"usb_registry_",
"usb_",
NULL
};
int usb_error_errno = 0;
log_hander_t user_log_hander = NULL;
#if (defined(_DEBUG) || defined(DEBUG) || defined(DBG))
int __usb_log_level = LOG_LEVEL_MAX;
#else
int __usb_log_level = LOG_OFF;
#endif
usb_error_type_t usb_error_type = USB_ERROR_TYPE_NONE;
const char** skipped_function_prefix = skipped_function_prefix_list;
#if !IS_DRIVER
char usb_error_str[LOGBUF_SIZE] = "";
char *usb_strerror(void)
{
switch (usb_error_type)
{
case USB_ERROR_TYPE_NONE:
return "No error";
case USB_ERROR_TYPE_STRING:
return usb_error_str;
case USB_ERROR_TYPE_ERRNO:
if (usb_error_errno > -USB_ERROR_BEGIN)
return strerror(usb_error_errno);
else
/* Any error we don't know falls under here */
return "Unknown error";
}
return "Unknown error";
}
/* returns Windows' last error in a human readable form */
const char *usb_win_error_to_string(void)
{
static char tmp[LOGBUF_SIZE];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
LANG_USER_DEFAULT, tmp, sizeof(tmp) - 1, NULL);
return tmp;
}
int usb_win_error_to_errno(void)
{
switch (GetLastError())
{
case ERROR_SUCCESS:
return 0;
case ERROR_INVALID_PARAMETER:
return EINVAL;
case ERROR_SEM_TIMEOUT:
case ERROR_OPERATION_ABORTED:
return ETRANSFER_TIMEDOUT;
case ERROR_NOT_ENOUGH_MEMORY:
return ENOMEM;
default:
return EIO;
}
}
#endif
void usb_err(const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
usb_err_v(function, format, args);
va_end(args);
}
void usb_wrn(const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
usb_wrn_v(function, format, args);
va_end(args);
}
void usb_msg(const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
usb_msg_v(function, format, args);
va_end(args);
}
void usb_dbg(const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
usb_dbg_v(function, format, args);
va_end(args);
}
void usb_log(enum USB_LOG_LEVEL level, const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
usb_log_v(level, function, format, args);
va_end(args);
}
void usb_err_v(const char* function, const char* format, va_list args)
{
usb_log_v(LOG_ERROR, function, format, args);
}
void usb_wrn_v(const char* function, const char* format, va_list args)
{
usb_log_v(LOG_WARNING, function, format, args);
}
void usb_msg_v(const char* function, const char* format, va_list args)
{
usb_log_v(LOG_INFO, function, format, args);
}
void usb_dbg_v(const char* function, const char* format, va_list args)
{
usb_log_v(LOG_DEBUG, function, format, args);
}
void usb_log_v(enum USB_LOG_LEVEL level, const char* function, const char* format, va_list args)
{
_usb_log_v(level, LOG_APPNAME, function, format, args);
}
void _usb_log(enum USB_LOG_LEVEL level, const char* app_name, const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
_usb_log_v(level, app_name, function, format, args);
va_end(args);
}
void _usb_log_v(enum USB_LOG_LEVEL level,
const char* app_name,
const char* function,
const char* format,
va_list args)
{
char local_buffer[LOGBUF_SIZE];
int totalCount, count;
const char* prefix;
const char* func;
char* buffer;
int masked_level;
int app_prefix_func_end;
#ifndef LOG_STYLE_SHORT
const char** skip_list = NULL;
#endif
masked_level = GetLogLevel(level);
if (__usb_log_level < masked_level && masked_level != LOG_ERROR) return;
buffer = local_buffer;
totalCount = 0;
count = 0;
prefix = log_level_string[masked_level];
func = function;
app_prefix_func_end = 0;
if (masked_level > LOG_LEVEL_MAX) masked_level = LOG_LEVEL_MAX;
if ((level & LOG_RAW) == LOG_RAW)
{
count = _vsnprintf(buffer, LOGBUF_SIZE-1, format, args);
if (count > 0)
{
buffer += count;
totalCount += count;
}
}
else
{
#ifdef LOG_STYLE_SHORT
if ((prefix) && strlen(prefix))
{
count = _snprintf(buffer, (LOGBUF_SIZE-1), "%s: ", prefix);
}
else
{
count = 0;
}
func = "";
#else
func = function;
if (func)
{
// strip some prefixes to shorten function names
skip_list=skipped_function_prefix;
while(*skip_list && ((func)) && func[0])
{
func = STRIP_PREFIX(func,skip_list[0]);
skip_list++;
}
}
if(!func) func="none";
// print app name, level string and short function name
if ((prefix) && strlen(prefix))
{
count = _snprintf(buffer, (LOGBUF_SIZE-1), "%s:%s [%s] ", app_name, prefix, func);
}
else
{
count = _snprintf(buffer, (LOGBUF_SIZE-1), "%s:[%s] ", app_name, func);
}
#endif
if (count >= 0)
{
app_prefix_func_end = count;
buffer += count;
totalCount += count;
count = _vsnprintf(buffer, (LOGBUF_SIZE-1) - totalCount, format, args);
if (count > 0)
{
buffer += count;
totalCount += count;
}
}
}
if (count < 0)
totalCount = LOGBUF_SIZE - 1;
// make sure its null terminated
local_buffer[totalCount] = 0;
#if (!IS_DRIVER)
if (masked_level == LOG_ERROR)
{
// if this is an error message then store it
strncpy(usb_error_str, local_buffer, totalCount);
usb_error_str[totalCount] = '\0';
usb_error_type = USB_ERROR_TYPE_STRING;
}
#endif
if (user_log_hander)
{
if (user_log_hander(level, app_name, prefix, func, app_prefix_func_end, local_buffer, totalCount))
return;
}
if (__usb_log_level >= masked_level)
{
usb_log_def_handler(level, app_name, prefix, func, app_prefix_func_end, local_buffer, totalCount);
}
}
void usb_log_set_level(enum USB_LOG_LEVEL level)
{
// Debug builds of the driver force all messages on; all the time;
// Application can no longer change this.
//
#if (defined(_DEBUG) || defined(DEBUG) || defined(DBG))
__usb_log_level = LOG_LEVEL_MAX;
#else
__usb_log_level = level > LOG_LEVEL_MAX ? LOG_LEVEL_MAX : level;
#endif
}
int usb_log_get_level()
{
return __usb_log_level;
}
/* Default log handler
*/
static int usb_log_def_handler(enum USB_LOG_LEVEL level,
const char* app_name,
const char* prefix,
const char* func,
int app_prefix_func_end,
char* message,
int message_length)
{
#if IS_DRIVER
DbgPrint("%s",message);
#else
#if GetLogOuput(LOG_OUTPUT_TYPE_FILE)
FILE* file;
file = fopen(LOG_FILE_PATH,"a");
if (file)
{
fwrite(message,1,strlen(message),file);
fflush(file);
fclose(file);
}
#endif
#if GetLogOuput(LOG_OUTPUT_TYPE_STDERR)
fprintf(stderr, "%s", message);
#endif
#if GetLogOuput(LOG_OUTPUT_TYPE_DEBUGWINDOW)
OutputDebugStringA(message);
#endif
#if GetLogOuput(LOG_OUTPUT_TYPE_MSGBOX)
if (GetLogLevel(level)==LOG_ERROR)
{
message[app_prefix_func_end-1]='\0';
MessageBoxA(NULL,message+strlen(message),message,MB_OK|MB_ICONERROR);
}
#endif
#endif // IS_DRIVER
return 1;
}
void usb_log_set_handler(log_hander_t log_hander)
{
user_log_hander = log_hander;
}
log_hander_t usb_log_get_handler(void)
{
return user_log_hander;
}
@@ -0,0 +1,187 @@
/* Error & Logging functions
Copyright © 2010 Travis Robinson. <libusbdotnet@gmail.com>
website: http://sourceforge.net/projects/libusb-win32
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU (LGPL) General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 (LGPL) General Public
License for more details.
You should have received a copy of the GNU (LGPL) General Public License
along with this program; if not, please visit www.gnu.org.
*/
#ifndef __ERROR_H__
#define __ERROR_H__
#include <stdarg.h>
enum USB_LOG_LEVEL
{
LOG_OFF,
LOG_ERROR,
LOG_WARNING,
LOG_INFO,
LOG_DEBUG,
LOG_LEVEL_MAX,
LOG_LEVEL_MASK=0xff,
LOG_RAW=0x100
};
/* Connection timed out */
#define ETRANSFER_TIMEDOUT 116
#define LOGBUF_SIZE 512
// TARGETTYPEs
#define PROGRAMconsole 0
#define PROGRAMwindows 1
#define DYNLINK 2
#define DRIVER 3
// default TARGETTYPE
#ifndef TARGETTYPE
#define TARGETTYPE PROGRAMconsole
#endif
#define IS_DRIVER (TARGETTYPE==DRIVER)
#define IS_CONSOLE_APP (TARGETTYPE==PROGRAMconsole)
#define IS_WINDOW_APP (TARGETTYPE==PROGRAMwindows)
#define IS_APP (IS_CONSOLE_APP || IS_WINDOW_APP)
#define IS_DLL (TARGETTYPE==DYNLINK)
// NOTE: LOG_OUTPUT_TYPEs can be combined
// writes log messages to standard error output
#define LOG_OUTPUT_TYPE_STDERR 0x001
// writes log messages to Win32 OutputDebugString (DbgPrint for drivers)
#define LOG_OUTPUT_TYPE_DEBUGWINDOW 0x0002
#define LOG_OUTPUT_TYPE_DBGPRINT 0x0002
// displays error log messages to a messagebox (not recommended)
#define LOG_OUTPUT_TYPE_MSGBOX 0x0004
// writes log messages to Kernel-mode DbgPrint
// writes log messages directly to a file
#define LOG_OUTPUT_TYPE_FILE 0x0010
// strips all log messages except errors
#define LOG_OUTPUT_TYPE_REMOVE 0x0020
#define LOG_OUTPUT_TYPE_DEFAULT 0x0100
// File logging is never enabled by default.
// The LOG_OUTPUT_TYPE define must be manually
// set to enable file logging.
#if !IS_DRIVER
#ifndef LOG_DIRECTORY
#define LOG_FILE_PATH LOG_APPNAME ".log"
#else
#define LOG_FILE_PATH LOG_DIRECTORY LOG_APPNAME ".log"
#endif
#endif
#if (IS_DRIVER) || (IS_DLL) || (IS_WINDOW_APP)
// default logging for drivers and dlls
#define DEF_LOG_OUTPUT_TYPE LOG_OUTPUT_TYPE_DEBUGWINDOW
#else
// default logging for applications and everything else
#define DEF_LOG_OUTPUT_TYPE LOG_OUTPUT_TYPE_STDERR
#endif
#define _usb_log_do_nothing() while(0)
// Default logging output
#ifdef LOG_OUTPUT_TYPE
// all log messages (except errors) are stripped
#if (LOG_OUTPUT_TYPE & LOG_OUTPUT_TYPE_REMOVE)
#define USBMSG(format,...) _usb_log_do_nothing()
#define USBWRN(format,...) _usb_log_do_nothing()
#define USBDBG(format,...) _usb_log_do_nothing()
#define USBRAWMSG(format,...) _usb_log_do_nothing()
#define USBMSG0(format) _usb_log_do_nothing()
#define USBWRN0(format) _usb_log_do_nothing()
#define USBDBG0(format) _usb_log_do_nothing()
#define USBRAWMSG0(format) _usb_log_do_nothing()
#endif
#if (LOG_OUTPUT_TYPE & LOG_OUTPUT_TYPE_DEFAULT)
#define _LOG_OUTPUT_TYPE ((LOG_OUTPUT_TYPE & 0xff)|DEF_LOG_OUTPUT_TYPE)
#else
#define _LOG_OUTPUT_TYPE (LOG_OUTPUT_TYPE)
#endif
#else
// if the LOG_OUTPUT_TYPE has not been manually set use
// the as defaults.
#define _LOG_OUTPUT_TYPE DEF_LOG_OUTPUT_TYPE
#endif
// always keep error messages
#define USBERR(format,...) usb_err(__FUNCTION__,format,__VA_ARGS__)
#define USBERR0(format) usb_err(__FUNCTION__,"%s",format)
// only keep debug log messages in debug builds
#if !(defined(_DEBUG) || defined(DEBUG) || defined(DBG)) && !defined(USBDBG)
#define USBDBG(format,...) _usb_log_do_nothing()
#define USBDBG0(format) _usb_log_do_nothing()
#endif
// if USBMSG has not been defined as empty (see above)
// then keep all the info and warning log messages
#ifndef USBMSG
#define USBMSG(format,...) usb_msg(__FUNCTION__,format,__VA_ARGS__)
#define USBWRN(format,...) usb_wrn(__FUNCTION__,format,__VA_ARGS__)
#define USBRAWMSG(format,...) usb_log(LOG_INFO|LOG_RAW,__FUNCTION__,format,__VA_ARGS__)
#define USBMSG0(format) usb_msg(__FUNCTION__,"%s",format)
#define USBWRN0(format) usb_wrn(__FUNCTION__,"%s",format)
#define USBRAWMSG0(format) usb_log(LOG_INFO|LOG_RAW,__FUNCTION__,"%s",format)
#endif
// if USBDBG has not been defined as empty (see above)
// then keep all the debug log messages
#ifndef USBDBG
#define USBDBG(format,...) usb_dbg(__FUNCTION__,format,__VA_ARGS__)
#define USBDBG0(format) usb_dbg(__FUNCTION__,"%s",format)
#endif
typedef enum
{
USB_ERROR_TYPE_NONE = 0,
USB_ERROR_TYPE_STRING,
USB_ERROR_TYPE_ERRNO,
} usb_error_type_t;
typedef int (*log_hander_t)(enum USB_LOG_LEVEL level, const char*,const char*,const char*, int, char*, int);
#if (!IS_DRIVER)
const char *usb_win_error_to_string(void);
int usb_win_error_to_errno(void);
#endif
void usb_log_set_level(enum USB_LOG_LEVEL level);
int usb_log_get_level(void);
void usb_log_set_handler(log_hander_t log_hander);
log_hander_t usb_log_get_handler(void);
// these are the core logging functions used by the logging macros
// (not used directly)
void usb_err (const char* function, const char* format, ...);
void usb_wrn (const char* function, const char* format, ...);
void usb_msg (const char* function, const char* format, ...);
void usb_dbg (const char* function, const char* format, ...);
void usb_log (enum USB_LOG_LEVEL level, const char* function, const char* format, ...);
#endif /* _ERROR_H_ */
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

@@ -0,0 +1,129 @@
#ifdef __GNUC__
#define _WIN32_IE 0x0501
#endif
#include <windows.h>
#include <commctrl.h>
#define IDR_MAIN_ICON 128
#define ID_DIALOG_0 10000
#define ID_DIALOG_1 10001
#define ID_DIALOG_2 10002
#define ID_DIALOG_3 10003
#define ID_BUTTON_CANCEL 10003
#define ID_BUTTON_NEXT 10004
#define ID_BUTTON_BACK 10005
#define ID_LIST 10006
#define ID_TEXT_VID 10007
#define ID_TEXT_PID 10008
#define ID_TEXT_MANUFACTURER 10009
#define ID_TEXT_DEV_NAME 10010
#define ID_INFO_TEXT 10012
#define ID_LIST_HEADER_TEXT 10013
#define ID_BUTTON_INSTALLNOW 10014
#define ID_TEXT_MI 10015
#define ID_TEXT_HIGHLIGHT_INFO 10016
#define IDG_MAIN 11000
#define IDL_VID 11010
#define IDL_PID 11011
#define IDL_MI 11012
#define IDL_MANUFACTURER 11013
#define IDL_DEV_NAME 11014
#define IDL_INSTALLING_TEXT 11015
//#define DIALOG_FONT "MS Sans Serif"
#define DIALOG_FONT "Tahoma"
#define DIALOG_FONT_SIZE 8
#define DIALOG_CAPTION "libusb-win32 Inf-Wizard\0"
#ifndef __INF_WIZARD_C__
#define RC_FILE_TYPE VFT_APP
#define RC_FILE_SUB_TYPE VFT2_UNKNOWN
#define RC_PRODUCT_STR DIALOG_CAPTION
#define RC_FILE_NAME_STR "inf-wizard.exe"
#include "libusb-win32_version.rc"
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAIN_ICON ICON "inf_wizard.ico"
ID_DIALOG_0 DIALOG DISCARDABLE 0,0,310,200
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER |
WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION DIALOG_CAPTION
FONT DIALOG_FONT_SIZE, DIALOG_FONT
BEGIN
DEFPUSHBUTTON "Next >",ID_BUTTON_NEXT,190,175,50,15
PUSHBUTTON "Cancel",ID_BUTTON_CANCEL,250,175,50,15
GROUPBOX "Information",IDG_MAIN,10,10,290,155
LTEXT 0,ID_INFO_TEXT,20,25,270,100
END
ID_DIALOG_1 DIALOG DISCARDABLE 0, 0, 310, 200
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER |
WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION DIALOG_CAPTION
FONT DIALOG_FONT_SIZE, DIALOG_FONT
BEGIN
DEFPUSHBUTTON "Next >",ID_BUTTON_NEXT,190,175,50,15
PUSHBUTTON "< Back",ID_BUTTON_BACK,130,175,50,15
PUSHBUTTON "Cancel",ID_BUTTON_CANCEL,250,175,50,15
GROUPBOX "Device Selection",IDG_MAIN,10,10,290,155
LTEXT 0,ID_LIST_HEADER_TEXT,20,25,270,30
CONTROL "List2",ID_LIST,WC_LISTVIEW,
WS_BORDER | WS_TABSTOP | LVS_REPORT | LVS_SINGLESEL
| LVS_SHOWSELALWAYS, 20,60,270,95
END
ID_DIALOG_2 DIALOG DISCARDABLE 0, 0, 310, 200
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER |
WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION DIALOG_CAPTION
FONT DIALOG_FONT_SIZE, DIALOG_FONT
BEGIN
DEFPUSHBUTTON "Next >",ID_BUTTON_NEXT,190,175,50,15
PUSHBUTTON "< Back",ID_BUTTON_BACK,130,175,50,15
PUSHBUTTON "Cancel",ID_BUTTON_CANCEL,250,175,50,15
EDITTEXT ID_TEXT_VID, 125, 35,160,14
EDITTEXT ID_TEXT_PID, 125, 55,160,14
EDITTEXT ID_TEXT_MI, 125, 75,160,14
EDITTEXT ID_TEXT_MANUFACTURER, 125, 95,160,14
EDITTEXT ID_TEXT_DEV_NAME, 125,115,160,14
LTEXT "Vendor ID (hex format)",IDL_VID, 25,35, 95,15, SS_CENTERIMAGE
LTEXT "Product ID (hex format)",IDL_PID, 25,55, 95,15, SS_CENTERIMAGE
LTEXT "MI (hex format)",IDL_MI, 25,75, 95,15, SS_CENTERIMAGE
LTEXT "Manufacturer Name",IDL_MANUFACTURER, 25,95, 95,15, SS_CENTERIMAGE
LTEXT "Device Name",IDL_DEV_NAME, 25,115,95,15, SS_CENTERIMAGE
GROUPBOX "Device Configuration",IDG_MAIN,10,10,290,155
END
ID_DIALOG_3 DIALOG DISCARDABLE 0,0,310,200
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER |
WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION DIALOG_CAPTION
FONT DIALOG_FONT_SIZE, DIALOG_FONT
BEGIN
PUSHBUTTON "Done",ID_BUTTON_NEXT, 250,175,50,15
LTEXT "",IDL_INSTALLING_TEXT, 70,175,165,15, SS_CENTER
GROUPBOX "Information",IDG_MAIN,10,10,290,155
PUSHBUTTON "Install Now..",ID_BUTTON_INSTALLNOW, 20,140,70,15
END
ID_MANIFEST RT_MANIFEST "common_controls.manifest"
#endif
@@ -0,0 +1,96 @@
WARNING:
Improper use of libusb-win32 install-filter can cause devices to
malfunction and in some cases complete system failure.
DISCLAIMER:
THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE ORGANIZATION SHALL
NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
USAGE: install-filter [install|uninstall|list] <-ac> <-dc> <-ad>
<-c=> <-d=> <-f=>
<-p=> <-w=>
Commands: Compatible Switches:
install (i/-i) <-ac> <-c=> <-d=> <-f=> <-p=> <-w=>
uninstall (u/-u) <-ac> <-c=> <-d=> <-f=> <-p=> <-w=> <-ad>
list (l/-l) <-ac> <-dc> <-c=> <-p=> <-w=>
NOTE:
* If no switches are specified, the default class key list is used.
* 64bit OSes must use the 64bit version of this application.
Switches For Class Filters:
--all-classes (-ac)
install : Adds libusb-win32 as an upper class filter for all
classes in the USB enumerator. (Same as -dc in install mode)
uninstall: Removes libusb-win32 as an upper class filter for all
known classes. This is a FULL class removal.
list : Displays all known classes.
--device-classes (-dc)
install : Adds libusb-win32 as an upper class filter for all
classes in the USB enumerator.
uninstall: Removes libusb-win32 as an upper class filter for all
classes in the USB enumerator.
list : Displays all classes in the USB enumerator and the devices
contained within them.
--class=<nameOrGuid> (-c=)
install : Adds libusb-win32 as an upper class filter for the
specified class only. Classes can be specified by name or
guid.
uninstall: Removes libusb-win32 as an upper class filter for the
specified class only. Classes can be specified by name or
guid.
list : Displays information about the specified classes and the
devices contained within them.
Switches For Device Filters:
--device=<hwid> (-d=)
install : Adds libusb-win32 as an upper device filter for the
specified device.
uninstall: Removes libusb-win32 as an upper device filter for the
specified device.
list : <NA>
--all-devices (-ad)
install
install : <NA>
uninstall: Removes libusb-win32 device filters from all devices in the
USB enumerator.
list : <NA>
Switches For INF Files:
--inf=<your_file.inf> (-f=)
install : Installs usb device(s) from an inf file.
uninstall: Attempts to roll back a device driver installation. If
rollback fails or is unavailable, the device is removed and
all root hubs are restarted.
list : <NA>
Common Switches:
--prompt=<your_prompt_string> (-p=)
Prompts the user with the specified string before running. To include
spaces in the prompt string, place the entire switch in double quotes.
Example: "-p=Are you sure?"
--wait=<your_wait_string> (-w=)
After the operation completes, displays the specified string and waits for
user input. To include spaces in the prompt string, place the entire
switch in double quotes.
Example: "-w=Press any key.."
Examples:
install-filter install --device-classes
install-filter uninstall --all-classes
install-filter list --device-classes
install-filter install --class={00000000-0000-0000-0000-000000000000}
install-filter install "--device=USB\Vid_04d8&Pid_000c&Rev_0000"
install-filter install --device=USB\Vid_04d8.Pid_000c.Rev_0000
install-filter install --inf=your_file.inf
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,27 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
* Copyright (c) 2010 Travis Robinson <libusbdotnet@gmail.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 <stdio.h>
#include "usb.h"
int main()
{
return usb_install_npW(NULL, NULL, GetCommandLineW(), 1);
}
@@ -0,0 +1,21 @@
#ifndef __INSTALL_FILTER_RC__
#define ID_HELP_TEXT 10020
#define ID_DOS_TEXT 300
#ifdef __GNUC__
#define _WIN32_IE 0x0501
#endif
#include <windows.h>
#define RC_FILE_TYPE VFT_APP
#define RC_FILE_SUB_TYPE VFT2_UNKNOWN
#define RC_PRODUCT_STR "libusb-win32 - Install-Filter"
#define RC_FILE_NAME_STR "install-filter.exe"
#include "libusb-win32_version.rc"
ID_HELP_TEXT ID_DOS_TEXT "install-filter-help.txt"
#endif
@@ -0,0 +1,712 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2006 Stephan Meyer <ste_meyer@web.de>
* Copyright (c) 2010 Travis Robinson <libusbdotnet@gmail.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
*/
#define INITGUID
#include <windows.h>
#ifdef __GNUC__
#if defined(_WIN64)
#include <cfgmgr32.h>
#else
#include <ddk/cfgmgr32.h>
#endif
#else
#include <cfgmgr32.h>
#define strlwr(p) _strlwr(p)
#endif
#include <commdlg.h>
#include <dbt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <initguid.h>
#include <commctrl.h>
#include <setupapi.h>
#include <time.h>
#include "libusb-win32_version.h"
#include "registry.h"
#define __INSTALL_FILTER_WIN_C__
#include "install_filter_win_rc.rc"
#define MAX_TEXT_LENGTH 256
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
// Used for device notification
DEFINE_GUID(GUID_DEVINTERFACE_USB_HUB, 0xf18a0e88, 0xc30c, 0x11d0, 0x88, \
0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8);
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, \
0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
typedef struct
{
UINT controlID;
const char* message;
}create_tooltip_t;
typedef struct
{
filter_mode_e mode;
filter_type_e type;
struct
{
// device plugged notification
HDEVNOTIFY handle_hub;
HDEVNOTIFY handle_dev;
}notify;
}install_filter_win_t,*pinstall_filter_win_t;
const char info_text_0[] =
"This program adds/removes libusb-win32 as a driver to an existing device installation.\r\n\r\n"
"The libusb-win32 filter driver allows access to usb devices using the libusb-win32 api while maintaining "
"compatibility with software which uses the original driver.";
const char info_text_1[] =
"A windows driver installation package has been created for the following "
"device:";
const char package_contents_fmt_0[] =
"This package contains %s v%d.%d.%d.%d drivers and support for the following platforms: %s.";
const char package_contents_fmt_1[] =
"This package contains an inf file only.";
const char list_header_text_install[] =
"Connect your device and select it from the list of unfiltered devices below. "
"If your device isn't listed, it may already be filtered, be in a \"driverless\" state, "
"or incompatible with the libusb-win32 filter driver.";
const char list_header_text_remove[] =
"Select your device from the list of filtered devices below. "
"If your device isn't listed, it does not have a device filter.";
create_tooltip_t tooltips_dlg0[]=
{
{IDC_INSTALL_DEVICE_FILTER,
"Install libusb-win32 as a device upper filter for a single device. This device is selected on the next wizard page."},
{IDC_REMOVE_DEVICE_FILTER,
"Remove a libusb-win32 device upper filter for a single device. This device is selected on the next wizard page."},
{IDC_REMOVE_DEVICE_FILTERS,
"Remove all libusb-win32 device upper filters."},
{0,NULL}
};
create_tooltip_t tooltips_dlg1[]=
{
{IDC_SHOW_CONNECTED_DEVICES,
"A VID is a 16-bit vendor number (Vendor ID). A vendor ID is "
"necessary for developing a USB product. The USB-IF is responsible "
"for issuing USB vendor ID's to product manufacturers."},
{IDC_SHOW_ALL_DEVICES,
"A PID is a 16-bit product number (Product ID)."},
{ID_LIST,
LPSTR_TEXTCALLBACK},
{0,NULL}
};
HICON mIcon;
HINSTANCE g_hInst = NULL;
// see install.c
extern int usb_install_npA(HWND hwnd, HINSTANCE instance, LPCSTR cmd_line, int starg_arg);
HWND create_tooltip(HWND hMain, HINSTANCE hInstance, UINT max_tip_width, create_tooltip_t tool_tips[]);
BOOL CALLBACK dialog_proc_0(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam);
BOOL CALLBACK dialog_proc_1(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam);
static void device_list_init(pinstall_filter_win_t context, HWND list);
static bool_t device_list_refresh(pinstall_filter_win_t context, HWND list);
static void device_list_add(pinstall_filter_win_t context, HWND list, filter_device_t* device);
static void device_list_clean(pinstall_filter_win_t context, HWND list);
void output_debug(char* format,...)
{
va_list args;
char msg[256];
va_start (args, format);
vsprintf(msg, format, args);
va_end (args);
OutputDebugStringA(msg);
}
void init_install_filter_context(install_filter_win_t* context)
{
memset(context, 0, sizeof(*context));
context->mode = FM_INSTALL;
context->type = FT_DEVICE_UPPERFILTER;
}
int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev_instance,
LPSTR cmd_line, int cmd_show)
{
install_filter_win_t context;
int next_dialog;
LoadLibrary("comctl32.dll");
InitCommonControls();
if (cmd_line && strlen(cmd_line))
{
HWND hwnd = GetDesktopWindow();
return usb_install_npA(hwnd, instance, cmd_line, 0);
}
init_install_filter_context(&context);
next_dialog = ID_DIALOG_0;
mIcon = LoadIcon(instance, MAKEINTRESOURCE(IDR_MAIN_ICON));
g_hInst = instance;
while (next_dialog)
{
switch (next_dialog)
{
case ID_DIALOG_0:
next_dialog = (int)DialogBoxParam(instance,
MAKEINTRESOURCE(next_dialog),
NULL, (DLGPROC)dialog_proc_0,
(LPARAM)&context);
break;
case ID_DIALOG_1:
next_dialog = (int)DialogBoxParam(instance,
MAKEINTRESOURCE(next_dialog),
NULL, (DLGPROC)dialog_proc_1,
(LPARAM)&context);
break;
default:
;
}
}
if (mIcon)
{
DestroyIcon(mIcon);
mIcon = NULL;
}
return 0;
}
static void device_notification_register(HWND dialog, pinstall_filter_win_t context)
{
DEV_BROADCAST_DEVICEINTERFACE dev_if;
dev_if.dbcc_size = sizeof(dev_if);
dev_if.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
// register for device hub hot-plugs
if (!context->notify.handle_hub)
{
dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_HUB;
context->notify.handle_hub = RegisterDeviceNotification(dialog, &dev_if, 0);
}
// register for device hot-plugs
if (!context->notify.handle_dev)
{
dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
context->notify.handle_dev = RegisterDeviceNotification(dialog, &dev_if, 0);
}
}
static void device_notification_unregister(pinstall_filter_win_t context)
{
if (context->notify.handle_hub)
{
UnregisterDeviceNotification(context->notify.handle_hub);
context->notify.handle_hub = NULL;
}
if (context->notify.handle_dev)
{
UnregisterDeviceNotification(context->notify.handle_dev);
context->notify.handle_dev = NULL;
}
}
BOOL CALLBACK dialog_proc_0(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam)
{
static install_filter_win_t* context = NULL;
switch (message)
{
case WM_INITDIALOG:
SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon);
SendMessage(dialog,WM_SETICON,ICON_BIG, (LPARAM)mIcon);
context = (install_filter_win_t*)lParam;
SetWindowText(GetDlgItem(dialog, ID_INFO_TEXT), info_text_0);
create_tooltip(dialog, g_hInst, 300, tooltips_dlg0);
switch(context->mode)
{
case FM_INSTALL:
CheckRadioButton(dialog, IDC_INSTALL_DEVICE_FILTER, IDC_REMOVE_DEVICE_FILTERS, IDC_INSTALL_DEVICE_FILTER);
break;
case FM_REMOVE:
CheckRadioButton(dialog, IDC_INSTALL_DEVICE_FILTER, IDC_REMOVE_DEVICE_FILTERS, IDC_REMOVE_DEVICE_FILTER);
break;
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_BUTTON_NEXT:
context->type = FT_DEVICE_UPPERFILTER;
if (IsDlgButtonChecked(dialog, IDC_INSTALL_DEVICE_FILTER))
{
context->mode = FM_INSTALL;
}
else if (IsDlgButtonChecked(dialog, IDC_REMOVE_DEVICE_FILTER))
{
context->mode = FM_REMOVE;
}
else if (IsDlgButtonChecked(dialog, IDC_REMOVE_DEVICE_FILTERS))
{
if (MessageBox(dialog,
"This will remove libusb-win32 as a device filter for all known devices. Are you sure you wich to continue?",
"Remove all device filters",
MB_OKCANCEL|MB_ICONWARNING) == IDOK)
{
if (usb_install_npA(dialog, g_hInst, "uninstall -ad", 0) == 0)
{
MessageBox(dialog,
"All libusb-win32 device filters removed successfully.",
"Remove all device filters",
MB_OK|MB_ICONINFORMATION);
// reset to wizard defaults
init_install_filter_context(context);
EndDialog(dialog, ID_DIALOG_0);
}
else
{
// if an error occurs, usb_install_np() displays the error message.
}
}
return TRUE ;
}
EndDialog(dialog, ID_DIALOG_1);
return TRUE ;
case ID_BUTTON_CANCEL:
case IDCANCEL:
EndDialog(dialog, 0);
return TRUE ;
}
}
return FALSE;
}
BOOL CALLBACK dialog_proc_1(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam)
{
static install_filter_win_t* context = NULL;
DEV_BROADCAST_HDR *hdr = (DEV_BROADCAST_HDR *) lParam;
filter_device_t* selected_device;
HWND list = GetDlgItem(dialog, ID_LIST);
LVITEM item;
switch (message)
{
case WM_DESTROY:
if (list)
{
device_list_clean(context, list);
}
break;
case WM_INITDIALOG:
SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon);
SendMessage(dialog,WM_SETICON,ICON_BIG, (LPARAM)mIcon);
context = (install_filter_win_t *)lParam;
device_list_init(context, list);
switch (context->mode)
{
case FM_INSTALL:
SetWindowText(GetDlgItem(dialog, ID_LIST_HEADER_TEXT), list_header_text_install);
SetWindowText(GetDlgItem(dialog, ID_BUTTON_NEXT), "Install");
break;
case FM_REMOVE:
SetWindowText(GetDlgItem(dialog, ID_LIST_HEADER_TEXT), list_header_text_remove);
SetWindowText(GetDlgItem(dialog, ID_BUTTON_NEXT), "Remove");
break;
}
EnableWindow(GetDlgItem(dialog, ID_BUTTON_NEXT), FALSE);
device_list_refresh(context, list);
device_notification_register(dialog, context);
return TRUE;
case WM_DEVICECHANGE:
switch (wParam)
{
case DBT_DEVICEREMOVECOMPLETE:
if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
EnableWindow(GetDlgItem(dialog, ID_BUTTON_NEXT), FALSE);
device_list_refresh(context, list);
}
break;
case DBT_DEVICEARRIVAL:
if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
EnableWindow(GetDlgItem(dialog, ID_BUTTON_NEXT), FALSE);
device_list_refresh(context, list);
}
break;
default:;
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_BUTTON_NEXT:
device_notification_unregister(context);
memset(&item, 0, sizeof(item));
item.mask = LVIF_TEXT | LVIF_PARAM;
item.iItem = ListView_GetNextItem(list, -1, LVNI_SELECTED);
if (item.iItem >= 0)
{
if (ListView_GetItem(list, &item))
{
selected_device = (filter_device_t*)item.lParam;
if (selected_device)
{
char tmp[MAX_PATH];
sprintf(tmp,"%s \"-di=%s\"",
(context->mode == FM_INSTALL) ? "i":"u",
selected_device->device_id);
if (usb_install_npA(dialog, g_hInst, tmp, 0) == 0)
{
char msg_title[MAX_PATH];
char msg_txt[MAX_PATH*3];
sprintf(msg_title,
"%s device filter",
(context->mode == FM_INSTALL) ? "Install":"Remove");
sprintf(msg_txt,
"libusb-win32 device filter successfully %s for %s (%s)",
(context->mode == FM_INSTALL) ? "installed":"removed",
selected_device->device_name,
selected_device->device_hwid);
MessageBox(dialog, msg_txt, msg_title, MB_OK|MB_ICONINFORMATION);
device_list_clean(context, list);
EndDialog(dialog, ID_DIALOG_1);
return TRUE;
}
}
}
}
EndDialog(dialog, 0);
return TRUE;
case ID_BUTTON_BACK:
device_notification_unregister(context);
device_list_clean(context, list);
EndDialog(dialog, ID_DIALOG_0);
return TRUE ;
case ID_BUTTON_CANCEL:
case IDCANCEL:
device_notification_unregister(context);
device_list_clean(context, list);
EndDialog(dialog, 0);
return TRUE ;
}
break;
case WM_NOTIFY:
if ( (lParam) && (((LPNMHDR)lParam)->idFrom == ID_LIST) )
{
LPNMLISTVIEW pnmv;
HWND hwnd;
switch (((LPNMHDR)lParam)->code)
{
case LVN_ITEMCHANGED:
pnmv = (LPNMLISTVIEW) lParam;
if (pnmv->uNewState & LVIS_SELECTED)
{
hwnd = GetDlgItem(dialog, ID_BUTTON_NEXT);
if (!IsWindowEnabled(hwnd))
{
EnableWindow(hwnd, TRUE);
}
}
break;
}
}
break;
}
return FALSE;
}
static void device_list_init(pinstall_filter_win_t context, HWND list)
{
LVCOLUMN lvc;
int ignored, width;
RECT list_rect;
GetClientRect(list, &list_rect);
width = list_rect.right - GetSystemMetrics(SM_CXVSCROLL);
ignored = (int)ListView_SetExtendedListViewStyle(list, LVS_EX_FULLROWSELECT);
memset(&lvc, 0, sizeof(lvc));
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = width / 2;
lvc.iSubItem = 0;
lvc.pszText = "Hardware ID";
ignored = ListView_InsertColumn(list, 1, &lvc);
lvc.iSubItem = 1;
lvc.pszText = "Description";
ignored = ListView_InsertColumn(list, 2, &lvc);
lvc.iSubItem = 2;
lvc.pszText = "Manufacturer";
ignored = ListView_InsertColumn(list, 3, &lvc);
}
static bool_t device_list_refresh(pinstall_filter_win_t context, HWND list)
{
HDEVINFO dev_info;
SP_DEVINFO_DATA dev_info_data;
filter_device_t* device = NULL;
filter_device_t* prev = NULL;
filter_device_t temp;
int dev_index = -1;
bool_t is_service_libusb;
filter_type_e filter_type;
DWORD flags;
bool_t remove;
if (!context) return FALSE;
device_list_clean(context, list);
flags = context->mode == FM_INSTALL ? (DIGCF_ALLCLASSES | DIGCF_PRESENT) : DIGCF_ALLCLASSES;
remove = context->mode == FM_INSTALL ? FALSE : TRUE;
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, flags);
if (dev_info == INVALID_HANDLE_VALUE)
{
MessageBox(GetParent(list),
"failed enumerating devices",
"install-filter error",
MB_OK|MB_ICONERROR);
return FALSE;
}
while (SetupDiEnumDeviceInfo(dev_info, ++dev_index, &dev_info_data))
{
if (!usb_registry_is_service_libusb(dev_info, &dev_info_data, &is_service_libusb))
continue;
// don't list libusb devices
if (is_service_libusb)
continue;
memset(&temp, 0, sizeof(temp));
// get the compatible ids
if (!usb_registry_get_property(SPDRP_COMPATIBLEIDS, dev_info, &dev_info_data,
temp.device_hwid, sizeof(temp.device_hwid)))
continue;
usb_registry_mz_string_lower(temp.device_hwid);
// don't list usb hubs
if (usb_registry_mz_string_find_sub(temp.device_hwid, "class_09"))
continue;
// get the hardware ids
if (!usb_registry_get_hardware_id(dev_info, &dev_info_data, temp.device_hwid))
continue;
usb_registry_mz_string_lower(temp.device_hwid);
// don't list root hubs
if (usb_registry_mz_string_find_sub(temp.device_hwid, "root_hub"))
continue;
// get the device instance id
if (CM_Get_Device_ID(dev_info_data.DevInst, temp.device_id, sizeof(temp.device_id), 0) != CR_SUCCESS)
continue;
// get the libusb0 device upper/lower filter type
if (!usb_registry_get_device_filter_type(dev_info, &dev_info_data, &filter_type))
continue;
// list devices for removal that currently have a device filter
if (remove && ((filter_type & (FT_DEVICE_UPPERFILTER | FT_DEVICE_LOWERFILTER)) == FT_NONE))
continue;
// don't list devices for install that are already filtered
if (!remove && ((filter_type & (FT_DEVICE_UPPERFILTER | FT_DEVICE_LOWERFILTER)) != FT_NONE))
continue;
// get the manufacturer
usb_registry_get_property(SPDRP_MFG, dev_info, &dev_info_data,
temp.device_mfg, sizeof(temp.device_mfg));
// get the description
usb_registry_get_property(SPDRP_DEVICEDESC, dev_info, &dev_info_data,
temp.device_name, sizeof(temp.device_name));
device = (filter_device_t*) malloc(sizeof(filter_device_t));
memcpy(device, &temp, sizeof(filter_device_t));
device_list_add(context, list, device);
if (prev)
prev->next = device;
prev = device;
}
SetupDiDestroyDeviceInfoList(dev_info);
return TRUE;
}
static void device_list_add(pinstall_filter_win_t context, HWND list, filter_device_t *device)
{
LVITEM item;
int ignored;
char hwid[MAX_PATH];
char* hwid_ch;
memset(&item, 0, sizeof(item));
// strip "usb\"
strcpy(hwid, device->device_hwid+4);
// replace '&' with ' '
while( (hwid_ch = strchr(hwid,'&')) )
*hwid_ch = ' ';
// replace '_' with ':'
while( (hwid_ch = strchr(hwid,'_')) )
*hwid_ch = ':';
item.mask = LVIF_TEXT | LVIF_PARAM;
item.lParam = (LPARAM)device;
ignored = ListView_InsertItem(list, &item);
ListView_SetItemText(list, 0, 0, hwid);
ListView_SetItemText(list, 0, 1, device->device_name);
ListView_SetItemText(list, 0, 2, device->device_mfg);
}
static void device_list_clean(pinstall_filter_win_t context, HWND list)
{
LVITEM item;
BOOL ignored;
memset(&item, 0, sizeof(LVITEM));
while (ListView_GetItem(list, &item))
{
if (item.lParam)
free((void *)item.lParam);
ignored = ListView_DeleteItem(list, 0);
memset(&item, 0, sizeof(LVITEM));
}
}
int device_filter_install(pinstall_filter_win_t context, HWND dialog, filter_device_t *device)
{
// TODO
MessageBoxA(dialog, "error","Error Installing Driver", MB_OK|MB_ICONWARNING);
return 0;
}
/*
* Create a tooltip for the controls in tool_tips
*/
HWND create_tooltip(HWND hMain, HINSTANCE hInstance, UINT max_tip_width, create_tooltip_t tool_tips[])
{
HWND hTip;
TOOLINFO toolInfo = {0};
int i;
// Create the tooltip window
hTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hMain, NULL,
hInstance, NULL);
if (hTip == NULL) {
return (HWND)NULL;
}
// Associate the tooltip to the control
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = hMain;
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
for (i=0; tool_tips[i].controlID != 0 && tool_tips[i].message != NULL; i++)
{
toolInfo.uId =(UINT_PTR)GetDlgItem(hMain,tool_tips[i].controlID);
toolInfo.lpszText = (LPSTR)tool_tips[i].message;
SendMessage(hTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
}
SendMessage(hTip, TTM_SETMAXTIPWIDTH, 0, max_tip_width);
return hTip;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

@@ -0,0 +1,93 @@
#ifdef __GNUC__
#define _WIN32_IE 0x0501
#endif
#include <windows.h>
#include <commctrl.h>
#define IDR_MAIN_ICON 128
#define ID_DIALOG_0 10000
#define ID_DIALOG_1 10001
#define ID_BUTTON_CANCEL 10010
#define ID_BUTTON_NEXT 10011
#define ID_BUTTON_BACK 10012
#define ID_INFO_TEXT 10020
#define ID_LIST 10021
#define ID_LIST_HEADER_TEXT 10022
#define IDC_SHOW_CONNECTED_DEVICES 10100
#define IDC_SHOW_ALL_DEVICES 10101
#define IDC_INSTALL_DEVICE_FILTER 10102
#define IDC_REMOVE_DEVICE_FILTER 10103
#define IDC_REMOVE_DEVICE_FILTERS 10104
#define IDG_MAIN 11000
#define IDG_DEVICES 11001
#define IDG_CLASSES 11002
//#define DIALOG_FONT "MS Sans Serif"
#define DIALOG_FONT "Tahoma"
#define DIALOG_FONT_SIZE 8
#define DIALOG_CAPTION "libusb-win32 filter installer\0"
#ifndef __INSTALL_FILTER_WIN_C__
#define RC_FILE_TYPE VFT_APP
#define RC_FILE_SUB_TYPE VFT2_UNKNOWN
#define RC_PRODUCT_STR DIALOG_CAPTION
#define RC_FILE_NAME_STR "install-filter-win.exe"
#include "libusb-win32_version.rc"
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAIN_ICON ICON "install_filter_win.ico"
ID_DIALOG_0 DIALOG DISCARDABLE 0,0,310,200
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER |
WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION DIALOG_CAPTION
FONT DIALOG_FONT_SIZE, DIALOG_FONT
BEGIN
DEFPUSHBUTTON "Next >",ID_BUTTON_NEXT,190,175,50,15
PUSHBUTTON "Cancel",ID_BUTTON_CANCEL,250,175,50,15
GROUPBOX "Information",IDG_MAIN,10,10,290,70
LTEXT 0,ID_INFO_TEXT,20,20,270,50
GROUPBOX "Install/Remove Device Filter(s)",IDG_DEVICES,10,90,130,65
CONTROL "Install a device filter",IDC_INSTALL_DEVICE_FILTER,"Button",WS_GROUP|BS_AUTORADIOBUTTON,15,105,120,10
CONTROL "Remove a device filter",IDC_REMOVE_DEVICE_FILTER,"Button",BS_AUTORADIOBUTTON,15,120,120,10
CONTROL "Remove all device filters",IDC_REMOVE_DEVICE_FILTERS,"Button",BS_AUTORADIOBUTTON,15,135,120,10
END
ID_DIALOG_1 DIALOG DISCARDABLE 0, 0, 310, 200
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER |
WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION DIALOG_CAPTION
FONT DIALOG_FONT_SIZE, DIALOG_FONT
BEGIN
DEFPUSHBUTTON "Next >",ID_BUTTON_NEXT,190,175,50,15
PUSHBUTTON "< Back",ID_BUTTON_BACK,130,175,50,15
PUSHBUTTON "Cancel",ID_BUTTON_CANCEL,250,175,50,15
GROUPBOX "Device Selection",IDG_MAIN,10,10,290,155
LTEXT 0,ID_LIST_HEADER_TEXT,20,25,270,30
CONTROL "List2",ID_LIST,WC_LISTVIEW,
WS_BORDER | WS_TABSTOP | LVS_REPORT | LVS_SINGLESEL
| LVS_SHOWSELALWAYS, 20,60,270,95
END
ID_MANIFEST RT_MANIFEST "common_controls_admin.manifest"
#endif
@@ -0,0 +1,18 @@
/* libusb-win32_version.h ++ auto-generated
*/
#ifndef __LIBUSB_WIN32_VERSION_H
#define __LIBUSB_WIN32_VERSION_H
#define __DEFTOSTR(x) #x
#define _DEFTOSTR(x) __DEFTOSTR(x)
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_MICRO 4
#define VERSION_NANO 0
#define VERSION_DATE 04/08/2011
#define VERSION VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO.VERSION_NANO
#define RC_VERSION VERSION_MAJOR,VERSION_MINOR,VERSION_MICRO,VERSION_NANO
#endif
@@ -0,0 +1,54 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* 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 <winver.h>
#include "libusb-win32_version.h"
#define RT_MANIFEST 24
#define ID_MANIFEST 1
VS_VERSION_INFO VERSIONINFO
FILEVERSION RC_VERSION
PRODUCTVERSION RC_VERSION
FILEFLAGSMASK 0x3FL
FILEFLAGS 0x0L
FILEOS VOS_NT_WINDOWS32
FILETYPE RC_FILE_TYPE
FILESUBTYPE RC_FILE_SUB_TYPE
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "http://libusb-win32.sourceforge.net"
VALUE "FileDescription", RC_PRODUCT_STR
VALUE "FileVersion", _DEFTOSTR(VERSION)
VALUE "InternalName", RC_FILE_NAME_STR
VALUE "LegalCopyright", "2002-2009 S. Meyer; 2010 T. Robinson"
VALUE "OriginalFilename",RC_FILE_NAME_STR
VALUE "ProductName", RC_PRODUCT_STR
VALUE "ProductVersion", _DEFTOSTR(VERSION)
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
@@ -0,0 +1,18 @@
/* libusb-win32_version.h ++ auto-generated
*/
#ifndef __LIBUSB_WIN32_VERSION_H
#define __LIBUSB_WIN32_VERSION_H
#define __DEFTOSTR(x) #x
#define _DEFTOSTR(x) __DEFTOSTR(x)
#define VERSION_MAJOR @VERSION_MAJOR@
#define VERSION_MINOR @VERSION_MINOR@
#define VERSION_MICRO @VERSION_MICRO@
#define VERSION_NANO @VERSION_NANO@
#define VERSION_DATE @_MM_@/@_DD_@/@_YYYY_@
#define VERSION VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO.VERSION_NANO
#define RC_VERSION VERSION_MAJOR,VERSION_MINOR,VERSION_MICRO,VERSION_NANO
#endif
@@ -0,0 +1,485 @@
/* LIBUSB-WIN32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* 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 <windows.h>
#include <errno.h>
#include "usb.h"
#define LIBUSB_DLL_NAME "libusb0.dll"
typedef usb_dev_handle * (*usb_open_t)(struct usb_device *dev);
typedef int (*usb_close_t)(usb_dev_handle *dev);
typedef int (*usb_get_string_t)(usb_dev_handle *dev, int index, int langid,
char *buf, size_t buflen);
typedef int (*usb_get_string_simple_t)(usb_dev_handle *dev, int index,
char *buf, size_t buflen);
typedef int (*usb_get_descriptor_by_endpoint_t)(usb_dev_handle *udev, int ep,
unsigned char type,
unsigned char index,
void *buf, int size);
typedef int (*usb_get_descriptor_t)(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, int size);
typedef int (*usb_bulk_write_t)(usb_dev_handle *dev, int ep, char *bytes,
int size, int timeout);
typedef int (*usb_bulk_read_t)(usb_dev_handle *dev, int ep, char *bytes,
int size, int timeout);
typedef int (*usb_interrupt_write_t)(usb_dev_handle *dev, int ep, char *bytes,
int size, int timeout);
typedef int (*usb_interrupt_read_t)(usb_dev_handle *dev, int ep, char *bytes,
int size, int timeout);
typedef int (*usb_control_msg_t)(usb_dev_handle *dev, int requesttype,
int request, int value, int index,
char *bytes, int size, int timeout);
typedef int (*usb_set_configuration_t)(usb_dev_handle *dev, int configuration);
typedef int (*usb_claim_interface_t)(usb_dev_handle *dev, int interface);
typedef int (*usb_release_interface_t)(usb_dev_handle *dev, int interface);
typedef int (*usb_set_altinterface_t)(usb_dev_handle *dev, int alternate);
typedef int (*usb_resetep_t)(usb_dev_handle *dev, unsigned int ep);
typedef int (*usb_clear_halt_t)(usb_dev_handle *dev, unsigned int ep);
typedef int (*usb_reset_t)(usb_dev_handle *dev);
typedef char * (*usb_strerror_t)(void);
typedef void (*usb_init_t)(void);
typedef void (*usb_set_debug_t)(int level);
typedef int (*usb_find_busses_t)(void);
typedef int (*usb_find_devices_t)(void);
typedef struct usb_device * (*usb_device_t)(usb_dev_handle *dev);
typedef struct usb_bus * (*usb_get_busses_t)(void);
typedef int (*usb_install_service_np_t)(void);
typedef int (*usb_uninstall_service_np_t)(void);
typedef int (*usb_install_driver_np_t)(const char *inf_file);
typedef const struct usb_version * (*usb_get_version_t)(void);
typedef int (*usb_isochronous_setup_async_t)(usb_dev_handle *dev,
void **context,
unsigned char ep, int pktsize);
typedef int (*usb_bulk_setup_async_t)(usb_dev_handle *dev, void **context,
unsigned char ep);
typedef int (*usb_interrupt_setup_async_t)(usb_dev_handle *dev, void **context,
unsigned char ep);
typedef int (*usb_submit_async_t)(void *context, char *bytes, int size);
typedef int (*usb_reap_async_t)(void *context, int timeout);
typedef int (*usb_free_async_t)(void **context);
static usb_open_t _usb_open = NULL;
static usb_close_t _usb_close = NULL;
static usb_get_string_t _usb_get_string = NULL;
static usb_get_string_simple_t _usb_get_string_simple = NULL;
static usb_get_descriptor_by_endpoint_t _usb_get_descriptor_by_endpoint = NULL;
static usb_get_descriptor_t _usb_get_descriptor = NULL;
static usb_bulk_write_t _usb_bulk_write = NULL;
static usb_bulk_read_t _usb_bulk_read = NULL;
static usb_interrupt_write_t _usb_interrupt_write = NULL;
static usb_interrupt_read_t _usb_interrupt_read = NULL;
static usb_control_msg_t _usb_control_msg = NULL;
static usb_set_configuration_t _usb_set_configuration = NULL;
static usb_claim_interface_t _usb_claim_interface = NULL;
static usb_release_interface_t _usb_release_interface = NULL;
static usb_set_altinterface_t _usb_set_altinterface = NULL;
static usb_resetep_t _usb_resetep = NULL;
static usb_clear_halt_t _usb_clear_halt = NULL;
static usb_reset_t _usb_reset = NULL;
static usb_strerror_t _usb_strerror = NULL;
static usb_init_t _usb_init = NULL;
static usb_set_debug_t _usb_set_debug = NULL;
static usb_find_busses_t _usb_find_busses = NULL;
static usb_find_devices_t _usb_find_devices = NULL;
static usb_device_t _usb_device = NULL;
static usb_get_busses_t _usb_get_busses = NULL;
static usb_install_service_np_t _usb_install_service_np = NULL;
static usb_uninstall_service_np_t _usb_uninstall_service_np = NULL;
static usb_install_driver_np_t _usb_install_driver_np = NULL;
static usb_get_version_t _usb_get_version = NULL;
static usb_isochronous_setup_async_t _usb_isochronous_setup_async = NULL;
static usb_bulk_setup_async_t _usb_bulk_setup_async = NULL;
static usb_interrupt_setup_async_t _usb_interrupt_setup_async = NULL;
static usb_submit_async_t _usb_submit_async = NULL;
static usb_reap_async_t _usb_reap_async = NULL;
static usb_free_async_t _usb_free_async = NULL;
void usb_init(void)
{
HINSTANCE libusb_dll = LoadLibrary(LIBUSB_DLL_NAME);
if (!libusb_dll)
return;
_usb_open = (usb_open_t)
GetProcAddress(libusb_dll, "usb_open");
_usb_close = (usb_close_t)
GetProcAddress(libusb_dll, "usb_close");
_usb_get_string = (usb_get_string_t)
GetProcAddress(libusb_dll, "usb_get_string");
_usb_get_string_simple = (usb_get_string_simple_t)
GetProcAddress(libusb_dll, "usb_get_string_simple");
_usb_get_descriptor_by_endpoint = (usb_get_descriptor_by_endpoint_t)
GetProcAddress(libusb_dll, "usb_get_descriptor_by_endpoint");
_usb_get_descriptor = (usb_get_descriptor_t)
GetProcAddress(libusb_dll, "usb_get_descriptor");
_usb_bulk_write = (usb_bulk_write_t)
GetProcAddress(libusb_dll, "usb_bulk_write");
_usb_bulk_read = (usb_bulk_read_t)
GetProcAddress(libusb_dll, "usb_bulk_read");
_usb_interrupt_write = (usb_interrupt_write_t)
GetProcAddress(libusb_dll, "usb_interrupt_write");
_usb_interrupt_read = (usb_interrupt_read_t)
GetProcAddress(libusb_dll, "usb_interrupt_read");
_usb_control_msg = (usb_control_msg_t)
GetProcAddress(libusb_dll, "usb_control_msg");
_usb_set_configuration = (usb_set_configuration_t)
GetProcAddress(libusb_dll, "usb_set_configuration");
_usb_claim_interface = (usb_claim_interface_t)
GetProcAddress(libusb_dll, "usb_claim_interface");
_usb_release_interface = (usb_release_interface_t)
GetProcAddress(libusb_dll, "usb_release_interface");
_usb_set_altinterface = (usb_set_altinterface_t)
GetProcAddress(libusb_dll, "usb_set_altinterface");
_usb_resetep = (usb_resetep_t)
GetProcAddress(libusb_dll, "usb_resetep");
_usb_clear_halt = (usb_clear_halt_t)
GetProcAddress(libusb_dll, "usb_clear_halt");
_usb_reset = (usb_reset_t)
GetProcAddress(libusb_dll, "usb_reset");
_usb_strerror = (usb_strerror_t)
GetProcAddress(libusb_dll, "usb_strerror");
_usb_init = (usb_init_t)
GetProcAddress(libusb_dll, "usb_init");
_usb_set_debug = (usb_set_debug_t)
GetProcAddress(libusb_dll, "usb_set_debug");
_usb_find_busses = (usb_find_busses_t)
GetProcAddress(libusb_dll, "usb_find_busses");
_usb_find_devices = (usb_find_devices_t)
GetProcAddress(libusb_dll, "usb_find_devices");
_usb_device = (usb_device_t)
GetProcAddress(libusb_dll, "usb_device");
_usb_get_busses = (usb_get_busses_t)
GetProcAddress(libusb_dll, "usb_get_busses");
_usb_install_service_np = (usb_install_service_np_t)
GetProcAddress(libusb_dll, "usb_install_service_np");
_usb_uninstall_service_np = (usb_uninstall_service_np_t)
GetProcAddress(libusb_dll, "usb_uninstall_service_np");
_usb_install_driver_np = (usb_install_driver_np_t)
GetProcAddress(libusb_dll, "usb_install_driver_np");
_usb_get_version = (usb_get_version_t)
GetProcAddress(libusb_dll, "usb_get_version");
_usb_isochronous_setup_async = (usb_isochronous_setup_async_t)
GetProcAddress(libusb_dll, "usb_isochronous_setup_async");
_usb_bulk_setup_async = (usb_bulk_setup_async_t)
GetProcAddress(libusb_dll, "usb_bulk_setup_async");
_usb_interrupt_setup_async = (usb_interrupt_setup_async_t)
GetProcAddress(libusb_dll, "usb_interrupt_setup_async");
_usb_submit_async = (usb_submit_async_t)
GetProcAddress(libusb_dll, "usb_submit_async");
_usb_reap_async = (usb_reap_async_t)
GetProcAddress(libusb_dll, "usb_reap_async");
_usb_free_async = (usb_free_async_t)
GetProcAddress(libusb_dll, "usb_free_async");
if (_usb_init)
_usb_init();
}
usb_dev_handle *usb_open(struct usb_device *dev)
{
if (_usb_open)
return _usb_open(dev);
else
return NULL;
}
int usb_close(usb_dev_handle *dev)
{
if (_usb_close)
return _usb_close(dev);
else
return -ENOFILE;
}
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
size_t buflen)
{
if (_usb_get_string)
return _usb_get_string(dev, index, langid, buf, buflen);
else
return -ENOFILE;
}
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf,
size_t buflen)
{
if (_usb_get_string_simple)
return _usb_get_string_simple(dev, index, buf, buflen);
else
return -ENOFILE;
}
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
unsigned char type, unsigned char index,
void *buf, int size)
{
if (_usb_get_descriptor_by_endpoint)
return _usb_get_descriptor_by_endpoint(udev, ep, type, index, buf, size);
else
return -ENOFILE;
}
int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, int size)
{
if (_usb_get_descriptor)
return _usb_get_descriptor(udev, type, index, buf, size);
else
return -ENOFILE;
}
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
if (_usb_bulk_write)
return _usb_bulk_write(dev, ep, bytes, size, timeout);
else
return -ENOFILE;
}
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
if (_usb_bulk_read)
return _usb_bulk_read(dev, ep, bytes, size, timeout);
else
return -ENOFILE;
}
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
if (_usb_interrupt_write)
return _usb_interrupt_write(dev, ep, bytes, size, timeout);
else
return -ENOFILE;
}
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
if (_usb_interrupt_read)
return _usb_interrupt_read(dev, ep, bytes, size, timeout);
else
return -ENOFILE;
}
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
int value, int index, char *bytes, int size,
int timeout)
{
if (_usb_control_msg)
return _usb_control_msg(dev, requesttype, request, value, index, bytes,
size, timeout);
else
return -ENOFILE;
}
int usb_set_configuration(usb_dev_handle *dev, int configuration)
{
if (_usb_set_configuration)
return _usb_set_configuration(dev, configuration);
else
return -ENOFILE;
}
int usb_claim_interface(usb_dev_handle *dev, int interface)
{
if (_usb_claim_interface)
return _usb_claim_interface(dev, interface);
else
return -ENOFILE;
}
int usb_release_interface(usb_dev_handle *dev, int interface)
{
if (_usb_release_interface)
return _usb_release_interface(dev, interface);
else
return -ENOFILE;
}
int usb_set_altinterface(usb_dev_handle *dev, int alternate)
{
if (_usb_set_altinterface)
return _usb_set_altinterface(dev, alternate);
else
return -ENOFILE;
}
int usb_resetep(usb_dev_handle *dev, unsigned int ep)
{
if (_usb_resetep)
return _usb_resetep(dev, ep);
else
return -ENOFILE;
}
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
{
if (_usb_clear_halt)
return _usb_clear_halt(dev, ep);
else
return -ENOFILE;
}
int usb_reset(usb_dev_handle *dev)
{
if (_usb_reset)
return _usb_reset(dev);
else
return -ENOFILE;
}
char *usb_strerror(void)
{
if (_usb_strerror)
return _usb_strerror();
else
return NULL;
}
void usb_set_debug(int level)
{
if (_usb_set_debug)
return _usb_set_debug(level);
}
int usb_find_busses(void)
{
if (_usb_find_busses)
return _usb_find_busses();
else
return -ENOFILE;
}
int usb_find_devices(void)
{
if (_usb_find_devices)
return _usb_find_devices();
else
return -ENOFILE;
}
struct usb_device *usb_device(usb_dev_handle *dev)
{
if (_usb_device)
return _usb_device(dev);
else
return NULL;
}
struct usb_bus *usb_get_busses(void)
{
if (_usb_get_busses)
return _usb_get_busses();
else
return NULL;
}
int usb_install_service_np(void)
{
if (_usb_install_service_np)
return _usb_install_service_np();
else
return -ENOFILE;
}
int usb_uninstall_service_np(void)
{
if (_usb_uninstall_service_np)
return _usb_uninstall_service_np();
else
return -ENOFILE;
}
int usb_install_driver_np(const char *inf_file)
{
if (_usb_install_driver_np)
return _usb_install_driver_np(inf_file);
else
return -ENOFILE;
}
const struct usb_version *usb_get_version(void)
{
if (_usb_get_version)
return _usb_get_version();
else
return NULL;
}
int usb_isochronous_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep, int pktsize)
{
if (_usb_isochronous_setup_async)
return _usb_isochronous_setup_async(dev, context, ep, pktsize);
else
return -ENOFILE;
}
int usb_bulk_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep)
{
if (_usb_bulk_setup_async)
return _usb_bulk_setup_async(dev, context, ep);
else
return -ENOFILE;
}
int usb_interrupt_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep)
{
if (_usb_interrupt_setup_async)
return _usb_interrupt_setup_async(dev, context, ep);
else
return -ENOFILE;
}
int usb_submit_async(void *context, char *bytes, int size)
{
if (_usb_submit_async)
return _usb_submit_async(context, bytes, size);
else
return -ENOFILE;
}
int usb_reap_async(void *context, int timeout)
{
if (_usb_reap_async)
return _usb_reap_async(context, timeout);
else
return -ENOFILE;
}
int usb_free_async(void **context)
{
if (_usb_free_async)
return _usb_free_async(context);
else
return -ENOFILE;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,221 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
* Copyright (c) 2010 Travis Robinson <libusbdotnet@gmail.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
*/
#ifndef __USB_REGISTRY_H__
#define __USB_REGISTRY_H__
#include <windows.h>
#include <setupapi.h>
#define LIBUSB_DRIVER_NAME_NT "libusb0"
#define LIBUSB_DRIVER_NAME_9X "libusb0.sys"
typedef int bool_t;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!(FALSE))
#endif
#define REGISTRY_BUF_SIZE 512
typedef struct _filter_file_t filter_file_t;
struct _filter_file_t
{
filter_file_t* next;
char name[MAX_PATH];
};
typedef int filter_mode_e;
enum _filter_mode_e
{
FM_NONE = 0,
FM_LIST = 1 << 0,
FM_INSTALL = 1 << 1,
FM_REMOVE = 1 << 2,
};
typedef int filter_type_e;
enum _filter_type_e
{
FT_NONE = 0,
FT_CLASS_UPPERFILTER = 1 << 0,
FT_CLASS_LOWERFILTER = 1 << 1,
FT_DEVICE_UPPERFILTER = 1 << 2,
FT_DEVICE_LOWERFILTER = 1 << 3,
};
typedef struct _filter_hwid_t filter_hwid_t;
struct _filter_hwid_t
{
int vid;
int pid;
int mi;
int rev;
};
typedef struct _filter_device_t filter_device_t;
struct _filter_device_t
{
filter_device_t* next;
char device_name[MAX_PATH];
char device_hwid[MAX_PATH];
char device_mfg[MAX_PATH];
char device_uppers[MAX_PATH];
char device_lowers[MAX_PATH];
char device_id[MAX_PATH];
filter_type_e action;
};
typedef struct _filter_class_t filter_class_t;
struct _filter_class_t
{
filter_class_t* next;
char name[MAX_PATH]; // key
char class_name[MAX_PATH];
char class_guid[MAX_PATH];
char class_uppers[MAX_PATH];
char class_lowers[MAX_PATH];
filter_device_t* class_filter_devices;
filter_type_e action;
};
typedef struct _filter_context_t filter_context_t;
struct _filter_context_t
{
union
{
int switches_value;
struct
{
bool_t add_all_classes:1;
bool_t add_device_classes:1;
bool_t add_default_classes:1;
};
}switches;
filter_mode_e filter_mode;
filter_class_t* class_filters;
filter_device_t* device_filters;
filter_file_t* inf_files;
bool_t show_help_only;
bool_t remove_all_device_filters;
bool_t class_filters_modified;
char* prompt_string;
char* wait_string;
};
bool_t usb_registry_is_nt(void);
bool_t usb_registry_restart_device(HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data);
bool_t usb_registry_stop_device(HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data);
bool_t usb_registry_start_device(HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data);
bool_t usb_registry_get_property(DWORD which, HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data,
char *buf, int size);
bool_t usb_registry_set_property(DWORD which, HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data,
char *buf, int size);
bool_t usb_registry_restart_all_devices(void);
void usb_registry_stop_libusb_devices(void);
void usb_registry_start_libusb_devices(void);
bool_t usb_registry_get_mz_value(const char *key, const char *value,
char *buf, int size);
bool_t usb_registry_set_mz_value(const char *key, const char *value,
char *buf, int size);
int usb_registry_mz_string_size(const char *src);
char *usb_registry_mz_string_find(const char *src, const char *str, bool_t no_case);
char *usb_registry_mz_string_find_sub(const char *src, const char *str);
bool_t usb_registry_mz_string_insert(char *src, const char *str);
bool_t usb_registry_mz_string_remove(char *src, const char *str, bool_t no_case);
void usb_registry_mz_string_lower(char *src);
bool_t usb_registry_get_hardware_id(HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data,
char* max_path_buffer);
bool_t usb_registry_is_service_libusb(HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data,
bool_t* is_libusb_service);
bool_t usb_registry_is_service_or_filter_libusb(HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data,
bool_t* is_libusb_service);
bool_t usb_registry_insert_class_filter(filter_context_t* filter_context);
bool_t usb_registry_remove_class_filter(filter_context_t* filter_context);
bool_t usb_registry_remove_device_filter(filter_context_t* filter_context);
bool_t usb_registry_free_class_keys(filter_class_t **head);
bool_t usb_registry_get_usb_class_keys(filter_context_t* filter_context, bool_t refresh_only);
bool_t usb_registry_get_all_class_keys(filter_context_t* filter_context, bool_t refresh_only);
bool_t usb_registry_get_device_filter_type(HDEVINFO dev_info,
SP_DEVINFO_DATA *dev_info_data,
filter_type_e* filter_type);
bool_t usb_registry_add_usb_class_key(filter_context_t* filter_context, const char* class_guid);
bool_t usb_registry_add_filter_device_keys(filter_device_t** head,
const char* id,
const char* hwid,
const char* name,
const char* mfg,
const char* uppers_mz,
const char* lowers_mz,
filter_device_t** found);
bool_t usb_registry_add_filter_file_keys(filter_file_t** head,
const char* name,
filter_file_t** found);
bool_t usb_registry_lookup_class_keys_by_name(filter_class_t** head);
bool_t usb_registry_add_class_key(filter_class_t **head,
const char *key,
const char *class_name,
const char *class_guid,
filter_class_t **found,
bool_t update_only);
bool_t usb_registry_insert_device_filters(filter_context_t* filter_context);
bool_t usb_registry_insert_device_filter(filter_context_t* filter_context, char* hwid, bool_t upper,
HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_data);
bool_t usb_registry_free_filter_devices(filter_device_t **head);
bool_t usb_registry_free_filter_files(filter_file_t **head);
filter_device_t* usb_registry_match_filter_device(filter_device_t** head,
HDEVINFO dev_info, PSP_DEVINFO_DATA dev_info_data);
bool_t usb_registry_mz_to_sz(char* buf_mz, char separator);
bool_t usb_registry_fill_filter_hwid(const char* hwid, filter_hwid_t* filter_hwid);
#endif
@@ -0,0 +1,26 @@
/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
*
* 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
*/
#define RC_FILE_TYPE VFT_DLL
#define RC_FILE_SUB_TYPE VFT2_UNKNOWN
#define RC_PRODUCT_STR "libusb-win32 - DLL"
#define RC_FILE_NAME_STR "libusb0.dll"
#include "libusb-win32_version.rc"
@@ -0,0 +1,317 @@
/*
* Main API entry point
*
* Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is covered by the LGPL, read LICENSE for details.
*/
#include <stdlib.h> /* getenv */
#include <stdio.h> /* stderr */
#include <string.h> /* strcmp */
#include <errno.h>
#include "usbi.h"
int usb_debug = 0;
struct usb_bus *_usb_busses = NULL;
int usb_find_busses(void)
{
struct usb_bus *busses, *bus;
int ret, changes = 0;
ret = usb_os_find_busses(&busses);
if (ret < 0)
return ret;
/*
* Now walk through all of the busses we know about and compare against
* this new list. Any duplicates will be removed from the new list.
* If we don't find it in the new list, the bus was removed. Any
* busses still in the new list, are new to us.
*/
bus = _usb_busses;
while (bus)
{
int found = 0;
struct usb_bus *nbus, *tbus = bus->next;
nbus = busses;
while (nbus)
{
struct usb_bus *tnbus = nbus->next;
if (!strcmp(bus->dirname, nbus->dirname))
{
/* Remove it from the new busses list */
LIST_DEL(busses, nbus);
usb_free_bus(nbus);
found = 1;
break;
}
nbus = tnbus;
}
if (!found)
{
/* The bus was removed from the system */
LIST_DEL(_usb_busses, bus);
usb_free_bus(bus);
changes++;
}
bus = tbus;
}
/*
* Anything on the *busses list is new. So add them to usb_busses and
* process them like the new bus it is.
*/
bus = busses;
while (bus)
{
struct usb_bus *tbus = bus->next;
/*
* Remove it from the temporary list first and add it to the real
* usb_busses list.
*/
LIST_DEL(busses, bus);
LIST_ADD(_usb_busses, bus);
changes++;
bus = tbus;
}
return changes;
}
int usb_find_devices(void)
{
struct usb_bus *bus;
int ret, changes = 0;
for (bus = usb_busses; bus; bus = bus->next)
{
struct usb_device *devices, *dev;
/* Find all of the devices and put them into a temporary list */
ret = usb_os_find_devices(bus, &devices);
if (ret < 0)
return ret;
/*
* Now walk through all of the devices we know about and compare
* against this new list. Any duplicates will be removed from the new
* list. If we don't find it in the new list, the device was removed.
* Any devices still in the new list, are new to us.
*/
dev = bus->devices;
while (dev)
{
int found = 0;
struct usb_device *ndev, *tdev = dev->next;
ndev = devices;
while (ndev)
{
struct usb_device *tndev = ndev->next;
if (!strcmp(dev->filename, ndev->filename))
{
/* Remove it from the new devices list */
LIST_DEL(devices, ndev);
usb_free_dev(ndev);
found = 1;
break;
}
ndev = tndev;
}
if (!found)
{
/* The device was removed from the system */
LIST_DEL(bus->devices, dev);
usb_free_dev(dev);
changes++;
}
dev = tdev;
}
/*
* Anything on the *devices list is new. So add them to bus->devices and
* process them like the new device it is.
*/
dev = devices;
while (dev)
{
struct usb_device *tdev = dev->next;
/*
* Remove it from the temporary list first and add it to the real
* bus->devices list.
*/
LIST_DEL(devices, dev);
/*
* Some ports fetch the descriptors on scanning (like Linux) so we don't
* need to fetch them again.
*/
if (!dev->config)
{
usb_dev_handle *udev;
udev = usb_open(dev);
if (udev)
{
usb_fetch_and_parse_descriptors(udev);
usb_close(udev);
}
}
// [ID:2928293 Tim Green]
//
if (dev->config)
{
LIST_ADD(bus->devices, dev);
changes++;
}
dev = tdev;
}
usb_os_determine_children(bus);
}
return changes;
}
void usb_init(void)
{
if (getenv("USB_DEBUG"))
usb_set_debug(atoi(getenv("USB_DEBUG")));
usb_os_init();
}
usb_dev_handle *usb_open(struct usb_device *dev)
{
usb_dev_handle *udev;
udev = malloc(sizeof(*udev));
if (!udev)
return NULL;
udev->fd = -1;
udev->device = dev;
udev->bus = dev->bus;
udev->config = udev->interface = udev->altsetting = -1;
if (usb_os_open(udev) < 0)
{
free(udev);
return NULL;
}
return udev;
}
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
size_t buflen)
{
/*
* We can't use usb_get_descriptor() because it's lacking the index
* parameter. This will be fixed in libusb 1.0
*/
return usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) + index, langid, buf, (int)buflen, 1000);
}
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, size_t buflen)
{
char tbuf[255]; /* Some devices choke on size > 255 */
int ret, langid, si, di;
/*
* Asking for the zero'th index is special - it returns a string
* descriptor that contains all the language IDs supported by the
* device. Typically there aren't many - often only one. The
* language IDs are 16 bit numbers, and they start at the third byte
* in the descriptor. See USB 2.0 specification, section 9.6.7, for
* more information on this. */
ret = usb_get_string(dev, 0, 0, tbuf, sizeof(tbuf));
if (ret < 0)
return ret;
if (ret < 4)
return -EIO;
langid = tbuf[2] | (tbuf[3] << 8);
ret = usb_get_string(dev, index, langid, tbuf, sizeof(tbuf));
if (ret < 0)
return ret;
if (tbuf[1] != USB_DT_STRING)
return -EIO;
if (tbuf[0] > ret)
return -EFBIG;
for (di = 0, si = 2; si < tbuf[0]; si += 2)
{
if (di >= ((int)buflen - 1))
break;
if (tbuf[si + 1]) /* high byte */
buf[di++] = '?';
else
buf[di++] = tbuf[si];
}
buf[di] = 0;
return di;
}
int usb_close(usb_dev_handle *dev)
{
int ret;
ret = usb_os_close(dev);
free(dev);
return ret;
}
struct usb_device *usb_device(usb_dev_handle *dev)
{
return dev->device;
}
void usb_free_dev(struct usb_device *dev)
{
usb_destroy_configuration(dev);
free(dev->children);
free(dev);
}
struct usb_bus *usb_get_busses(void)
{
return _usb_busses;
}
void usb_free_bus(struct usb_bus *bus)
{
free(bus);
}
@@ -0,0 +1,416 @@
#ifndef __USB_H__
#define __USB_H__
#include <stdlib.h>
#include <windows.h>
/*
* 'interface' is defined somewhere in the Windows header files. This macro
* is deleted here to avoid conflicts and compile errors.
*/
#ifdef interface
#undef interface
#endif
/*
* PATH_MAX from limits.h can't be used on Windows if the dll and
* import libraries are build/used by different compilers
*/
#define LIBUSB_PATH_MAX 512
/*
* USB spec information
*
* This is all stuff grabbed from various USB specs and is pretty much
* not subject to change
*/
/*
* Device and/or Interface Class codes
*/
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
#define USB_CLASS_AUDIO 1
#define USB_CLASS_COMM 2
#define USB_CLASS_HID 3
#define USB_CLASS_PRINTER 7
#define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9
#define USB_CLASS_DATA 10
#define USB_CLASS_VENDOR_SPEC 0xff
/*
* Descriptor types
*/
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
#define USB_DT_HID 0x21
#define USB_DT_REPORT 0x22
#define USB_DT_PHYSICAL 0x23
#define USB_DT_HUB 0x29
/*
* Descriptor sizes per descriptor type
*/
#define USB_DT_DEVICE_SIZE 18
#define USB_DT_CONFIG_SIZE 9
#define USB_DT_INTERFACE_SIZE 9
#define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
#define USB_DT_HUB_NONVAR_SIZE 7
/* ensure byte-packed structures */
#include <pshpack1.h>
/* All standard descriptors have these 2 fields in common */
struct usb_descriptor_header
{
unsigned char bLength;
unsigned char bDescriptorType;
};
/* String descriptor */
struct usb_string_descriptor
{
unsigned char bLength;
unsigned char bDescriptorType;
unsigned short wData[1];
};
/* HID descriptor */
struct usb_hid_descriptor
{
unsigned char bLength;
unsigned char bDescriptorType;
unsigned short bcdHID;
unsigned char bCountryCode;
unsigned char bNumDescriptors;
};
/* Endpoint descriptor */
#define USB_MAXENDPOINTS 32
struct usb_endpoint_descriptor
{
unsigned char bLength;
unsigned char bDescriptorType;
unsigned char bEndpointAddress;
unsigned char bmAttributes;
unsigned short wMaxPacketSize;
unsigned char bInterval;
unsigned char bRefresh;
unsigned char bSynchAddress;
unsigned char *extra; /* Extra descriptors */
int extralen;
};
#define USB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */
#define USB_ENDPOINT_DIR_MASK 0x80
#define USB_ENDPOINT_TYPE_MASK 0x03 /* in bmAttributes */
#define USB_ENDPOINT_TYPE_CONTROL 0
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 1
#define USB_ENDPOINT_TYPE_BULK 2
#define USB_ENDPOINT_TYPE_INTERRUPT 3
/* Interface descriptor */
#define USB_MAXINTERFACES 32
struct usb_interface_descriptor
{
unsigned char bLength;
unsigned char bDescriptorType;
unsigned char bInterfaceNumber;
unsigned char bAlternateSetting;
unsigned char bNumEndpoints;
unsigned char bInterfaceClass;
unsigned char bInterfaceSubClass;
unsigned char bInterfaceProtocol;
unsigned char iInterface;
struct usb_endpoint_descriptor *endpoint;
unsigned char *extra; /* Extra descriptors */
int extralen;
};
#define USB_MAXALTSETTING 128 /* Hard limit */
struct usb_interface
{
struct usb_interface_descriptor *altsetting;
int num_altsetting;
};
/* Configuration descriptor information.. */
#define USB_MAXCONFIG 8
struct usb_config_descriptor
{
unsigned char bLength;
unsigned char bDescriptorType;
unsigned short wTotalLength;
unsigned char bNumInterfaces;
unsigned char bConfigurationValue;
unsigned char iConfiguration;
unsigned char bmAttributes;
unsigned char MaxPower;
struct usb_interface *interface;
unsigned char *extra; /* Extra descriptors */
int extralen;
};
/* Device descriptor */
struct usb_device_descriptor
{
unsigned char bLength;
unsigned char bDescriptorType;
unsigned short bcdUSB;
unsigned char bDeviceClass;
unsigned char bDeviceSubClass;
unsigned char bDeviceProtocol;
unsigned char bMaxPacketSize0;
unsigned short idVendor;
unsigned short idProduct;
unsigned short bcdDevice;
unsigned char iManufacturer;
unsigned char iProduct;
unsigned char iSerialNumber;
unsigned char bNumConfigurations;
};
struct usb_ctrl_setup
{
unsigned char bRequestType;
unsigned char bRequest;
unsigned short wValue;
unsigned short wIndex;
unsigned short wLength;
};
/*
* Standard requests
*/
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
/* 0x02 is reserved */
#define USB_REQ_SET_FEATURE 0x03
/* 0x04 is reserved */
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
/*
* Various libusb API related stuff
*/
#define USB_ENDPOINT_IN 0x80
#define USB_ENDPOINT_OUT 0x00
/* Error codes */
#define USB_ERROR_BEGIN 500000
/*
* This is supposed to look weird. This file is generated from autoconf
* and I didn't want to make this too complicated.
*/
#define USB_LE16_TO_CPU(x)
/* Data types */
/* struct usb_device; */
/* struct usb_bus; */
struct usb_device
{
struct usb_device *next, *prev;
char filename[LIBUSB_PATH_MAX];
struct usb_bus *bus;
struct usb_device_descriptor descriptor;
struct usb_config_descriptor *config;
void *dev; /* Darwin support */
unsigned char devnum;
unsigned char num_children;
struct usb_device **children;
};
struct usb_bus
{
struct usb_bus *next, *prev;
char dirname[LIBUSB_PATH_MAX];
struct usb_device *devices;
unsigned long location;
struct usb_device *root_dev;
};
/* Version information, Windows specific */
struct usb_version
{
struct
{
int major;
int minor;
int micro;
int nano;
} dll;
struct
{
int major;
int minor;
int micro;
int nano;
} driver;
};
struct usb_dev_handle;
typedef struct usb_dev_handle usb_dev_handle;
/* Variables */
#ifndef __USB_C__
#define usb_busses usb_get_busses()
#endif
#include <poppack.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* Function prototypes */
/* usb.c */
usb_dev_handle *usb_open(struct usb_device *dev);
int usb_close(usb_dev_handle *dev);
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
size_t buflen);
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf,
size_t buflen);
/* descriptors.c */
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
unsigned char type, unsigned char index,
void *buf, int size);
int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, int size);
/* <arch>.c */
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
int value, int index, char *bytes, int size,
int timeout);
int usb_set_configuration(usb_dev_handle *dev, int configuration);
int usb_claim_interface(usb_dev_handle *dev, int interface);
int usb_release_interface(usb_dev_handle *dev, int interface);
int usb_set_altinterface(usb_dev_handle *dev, int alternate);
int usb_resetep(usb_dev_handle *dev, unsigned int ep);
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
int usb_reset(usb_dev_handle *dev);
char *usb_strerror(void);
void usb_init(void);
void usb_set_debug(int level);
int usb_find_busses(void);
int usb_find_devices(void);
struct usb_device *usb_device(usb_dev_handle *dev);
struct usb_bus *usb_get_busses(void);
/* Windows specific functions */
#define LIBUSB_HAS_INSTALL_SERVICE_NP 1
int usb_install_service_np(void);
void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1
int usb_uninstall_service_np(void);
void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_INSTALL_DRIVER_NP 1
int usb_install_driver_np(const char *inf_file);
void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_TOUCH_INF_FILE_NP 1
int usb_touch_inf_file_np(const char *inf_file);
void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1
int usb_install_needs_restart_np(void);
#define LIBUSB_HAS_INSTALL_NP 1
int usb_install_npW(HWND hwnd, HINSTANCE instance, LPCWSTR cmd_line, int starg_arg);
int usb_install_npA(HWND hwnd, HINSTANCE instance, LPCSTR cmd_line, int starg_arg);
#define usb_install_np usb_install_npA
void CALLBACK usb_install_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show);
const struct usb_version *usb_get_version(void);
int usb_isochronous_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep, int pktsize);
int usb_bulk_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep);
int usb_interrupt_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep);
int usb_submit_async(void *context, char *bytes, int size);
int usb_reap_async(void *context, int timeout);
int usb_reap_async_nocancel(void *context, int timeout);
int usb_cancel_async(void *context);
int usb_free_async(void **context);
#ifdef __cplusplus
}
#endif
#endif /* __USB_H__ */
@@ -0,0 +1,79 @@
#ifndef _USBI_H_
#define _USBI_H_
#include "usb.h"
#include "error.h"
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
extern int usb_debug;
/* Some quick and generic macros for the simple kind of lists we use */
#define LIST_ADD(begin, ent) \
do { \
if (begin) { \
ent->next = begin; \
ent->next->prev = ent; \
} else \
ent->next = NULL; \
ent->prev = NULL; \
begin = ent; \
} while(0)
#define LIST_DEL(begin, ent) \
do { \
if (ent->prev) \
ent->prev->next = ent->next; \
else \
begin = ent->next; \
if (ent->next) \
ent->next->prev = ent->prev; \
ent->prev = NULL; \
ent->next = NULL; \
} while (0)
#define DESC_HEADER_LENGTH 2
#define DEVICE_DESC_LENGTH 18
#define CONFIG_DESC_LENGTH 9
#define INTERFACE_DESC_LENGTH 9
#define ENDPOINT_DESC_LENGTH 7
#define ENDPOINT_AUDIO_DESC_LENGTH 9
struct usb_dev_handle
{
int fd;
struct usb_bus *bus;
struct usb_device *device;
int config;
int interface;
int altsetting;
/* Added by RMT so implementations can store other per-open-device data */
void *impl_info;
};
/* descriptors.c */
int usb_parse_descriptor(unsigned char *source, char *description, void *dest);
int usb_parse_configuration(struct usb_config_descriptor *config,
unsigned char *buffer);
void usb_fetch_and_parse_descriptors(usb_dev_handle *udev);
void usb_destroy_configuration(struct usb_device *dev);
/* OS specific routines */
int usb_os_find_busses(struct usb_bus **busses);
int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices);
int usb_os_determine_children(struct usb_bus *bus);
void usb_os_init(void);
int usb_os_open(usb_dev_handle *dev);
int usb_os_close(usb_dev_handle *dev);
void usb_free_dev(struct usb_device *dev);
void usb_free_bus(struct usb_bus *bus);
#endif /* _USBI_H_ */
File diff suppressed because it is too large Load Diff