Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some bugfixes to get devices with multiple configurations to function correctly #58

Merged
merged 2 commits into from
Jul 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions driver/stub/stub_devconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
#include "stub_usbd.h"
#include "devconf.h"

PUSB_CONFIGURATION_DESCRIPTOR get_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR bVal);

#ifdef DBG

const char *
Expand Down Expand Up @@ -54,26 +52,23 @@ dup_info_intf(PUSBD_INTERFACE_INFORMATION info_intf)
}

static BOOLEAN
build_infos_intf(devconf_t *devconf, PUSBD_INTERFACE_INFORMATION infos_intf)
build_infos_intf(devconf_t *devconf, PUSBD_INTERFACE_LIST_ENTRY pintf_list)
{
PUSBD_INTERFACE_INFORMATION info_intf;
unsigned i;

info_intf = infos_intf;
for (i = 0; i < devconf->bNumInterfaces; i++) {
PUSBD_INTERFACE_INFORMATION info_intf_copied = dup_info_intf(info_intf);
PUSBD_INTERFACE_INFORMATION info_intf_copied = dup_info_intf(pintf_list[i].Interface);
if (info_intf_copied == NULL) {
DBGE(DBG_GENERAL, "build_infos_intf: out of memory\n");
return FALSE;
}
devconf->infos_intf[i] = info_intf_copied;
info_intf = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)info_intf + INFO_INTF_SIZE(info_intf));
}
return TRUE;
}

devconf_t *
create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE hconf, PUSBD_INTERFACE_INFORMATION infos_intf)
create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE hconf, PUSBD_INTERFACE_LIST_ENTRY pintf_list)
{
devconf_t *devconf;
int size_devconf;
Expand All @@ -98,7 +93,7 @@ create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE
devconf->hConf = hconf;
RtlZeroMemory(devconf->infos_intf, sizeof(PUSBD_INTERFACE_INFORMATION) * devconf->bNumInterfaces);

if (!build_infos_intf(devconf, infos_intf)) {
if (!build_infos_intf(devconf, pintf_list)) {
free_devconf(devconf);
return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion driver/stub/stub_devconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ typedef struct {
PUSBD_INTERFACE_INFORMATION infos_intf[1];
} devconf_t;

devconf_t *create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE hconf, PUSBD_INTERFACE_INFORMATION infos_intf);
devconf_t *create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE hconf, PUSBD_INTERFACE_LIST_ENTRY pintf_list);
void free_devconf(devconf_t *devconf);
void update_devconf(devconf_t *devconf, PUSBD_INTERFACE_INFORMATION info_intf);

Expand Down
48 changes: 30 additions & 18 deletions driver/stub/stub_usbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,24 +174,24 @@ get_usb_device_desc(usbip_stub_dev_t* devstub, PUSB_DEVICE_DESCRIPTOR pdesc)
return get_usb_desc(devstub, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, pdesc, &len);
}

static BOOLEAN
static INT
find_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR bVal, PUSB_CONFIGURATION_DESCRIPTOR dsc_conf)
{
USB_DEVICE_DESCRIPTOR DevDesc;
UCHAR i;

if (!get_usb_device_desc(devstub, &DevDesc)) {
return FALSE;
return -1;
}

for (i = 0; i < DevDesc.bNumConfigurations; i++) {
ULONG len = sizeof(USB_CONFIGURATION_DESCRIPTOR);
if (get_usb_desc(devstub, USB_CONFIGURATION_DESCRIPTOR_TYPE, i, 0, dsc_conf, &len)) {
if (dsc_conf->bConfigurationValue == bVal)
return TRUE;
return i;
}
}
return FALSE;
return -1;
}

PUSB_CONFIGURATION_DESCRIPTOR
Expand All @@ -200,16 +200,18 @@ get_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR bVal)
USB_CONFIGURATION_DESCRIPTOR ConfDesc;
PUSB_CONFIGURATION_DESCRIPTOR dsc_conf;
ULONG len;

if (!find_usb_dsc_conf(devstub, bVal, &ConfDesc))
INT iConfiguration;

iConfiguration = find_usb_dsc_conf(devstub, bVal, &ConfDesc);
if (iConfiguration == -1)
return NULL;

dsc_conf = ExAllocatePoolWithTag(NonPagedPool, ConfDesc.wTotalLength, USBIP_STUB_POOL_TAG);
if (dsc_conf == NULL)
return NULL;

len = ConfDesc.wTotalLength;
if (!get_usb_desc(devstub, USB_CONFIGURATION_DESCRIPTOR_TYPE, ConfDesc.iConfiguration, 0, dsc_conf, &len)) {
if (!get_usb_desc(devstub, USB_CONFIGURATION_DESCRIPTOR_TYPE, (UCHAR)iConfiguration, 0, dsc_conf, &len)) {
cezuni marked this conversation as resolved.
Show resolved Hide resolved
ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG);
return NULL;
}
Expand All @@ -225,6 +227,9 @@ build_default_intf_list(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf)

size = sizeof(USBD_INTERFACE_LIST_ENTRY) * (dsc_conf->bNumInterfaces + 1);
pintf_list = ExAllocatePoolWithTag(NonPagedPool, size, USBIP_STUB_POOL_TAG);
if (pintf_list == NULL)
return NULL;

RtlZeroMemory(pintf_list, size);

for (i = 0; i < dsc_conf->bNumInterfaces; i++) {
Expand All @@ -244,41 +249,48 @@ select_usb_conf(usbip_stub_dev_t *devstub, USHORT bVal)
PURB purb;
PUSBD_INTERFACE_LIST_ENTRY pintf_list;
NTSTATUS status;

struct _URB_SELECT_CONFIGURATION *purb_selc;

dsc_conf = get_usb_dsc_conf(devstub, (UCHAR)bVal);
if (dsc_conf == NULL) {
DBGE(DBG_GENERAL, "select_usb_conf: non-existent configuration descriptor: index: %hu\n", bVal);
return FALSE;
}

pintf_list = build_default_intf_list(dsc_conf);
if (pintf_list == NULL) {
DBGE(DBG_GENERAL, "select_usb_conf: out of memory: pintf_list\n");
ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG);
return FALSE;
}

status = USBD_SelectConfigUrbAllocateAndBuild(devstub->hUSBD, dsc_conf, pintf_list, &purb);
if (NT_ERROR(status)) {
DBGE(DBG_GENERAL, "select_usb_conf: failed to selectConfigUrb: %s\n", dbg_ntstatus(status));
ExFreePoolWithTag(pintf_list, USBIP_STUB_POOL_TAG);
ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG);
return FALSE;
}

status = call_usbd(devstub, purb);
if (NT_SUCCESS(status)) {
cezuni marked this conversation as resolved.
Show resolved Hide resolved
struct _URB_SELECT_CONFIGURATION *purb_selc = &purb->UrbSelectConfiguration;

if (devstub->devconf)
free_devconf(devstub->devconf);
devstub->devconf = create_devconf(purb_selc->ConfigurationDescriptor, purb_selc->ConfigurationHandle, &purb_selc->Interface);
if (NT_ERROR(status)) {
DBGI(DBG_GENERAL, "select_usb_conf: failed to select configuration: %s\n", dbg_devstub(devstub));
USBD_UrbFree(devstub->hUSBD, purb);
ExFreePoolWithTag(pintf_list, USBIP_STUB_POOL_TAG);
ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG);
return TRUE;
return FALSE;
}
else {
DBGI(DBG_GENERAL, "select_usb_conf: failed to select configuration: %s\n", dbg_devstub(devstub));

purb_selc = &purb->UrbSelectConfiguration;

if (devstub->devconf) {
free_devconf(devstub->devconf);
}
devstub->devconf = create_devconf(purb_selc->ConfigurationDescriptor, purb_selc->ConfigurationHandle, pintf_list);
USBD_UrbFree(devstub->hUSBD, purb);
ExFreePoolWithTag(pintf_list, USBIP_STUB_POOL_TAG);
ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG);
return FALSE;
return TRUE;
}

BOOLEAN
Expand Down