Machine Interface Utility:VER1.0
This commit is contained in:
+15
@@ -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>
|
||||
+22
@@ -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;
|
||||
}
|
||||
|
||||
+56
@@ -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;
|
||||
}
|
||||
+63
@@ -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;
|
||||
}
|
||||
+64
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+227
@@ -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
|
||||
+75
@@ -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
|
||||
}
|
||||
+30
@@ -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
|
||||
+275
@@ -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;
|
||||
}
|
||||
+56
@@ -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;
|
||||
}
|
||||
+161
@@ -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;
|
||||
}
|
||||
+64
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+74
@@ -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;
|
||||
}
|
||||
+748
@@ -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;
|
||||
}
|
||||
+334
@@ -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
|
||||
+25
@@ -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);
|
||||
}
|
||||
}
|
||||
+80
@@ -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;
|
||||
}
|
||||
+44
@@ -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;
|
||||
}
|
||||
+56
@@ -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;
|
||||
}
|
||||
+197
@@ -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;
|
||||
}
|
||||
+71
@@ -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;
|
||||
}
|
||||
+67
@@ -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;
|
||||
}
|
||||
+113
@@ -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;
|
||||
}
|
||||
|
||||
+1430
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
|
||||
+310
@@ -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 */
|
||||
|
||||
+143
@@ -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
|
||||
|
||||
+96
@@ -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);
|
||||
}
|
||||
+21
@@ -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
|
||||
+712
@@ -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;
|
||||
}
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
+93
@@ -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
|
||||
|
||||
+18
@@ -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
|
||||
+54
@@ -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
|
||||
|
||||
+18
@@ -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
Reference in New Issue
Block a user