Skip to content

Commit

Permalink
return stall pid to host and forward reset_pipe_request to device
Browse files Browse the repository at this point in the history
Followings are commit logs by cezanne@codemayo.com.
This work is slightly modified to beautify and remove unused code.
This commit may have a fix for multi configurations device problem.
  • Loading branch information
chenfayu authored and cezanne committed Jul 26, 2019
1 parent d0804f1 commit 781e315
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 20 deletions.
2 changes: 1 addition & 1 deletion driver/lib/usbd_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ to_usbd_status(int usbip_status)
return USBD_STATUS_SUCCESS;
/* I guess it */
case -EPIPE:
return USBD_STATUS_ENDPOINT_HALTED;
return USBD_STATUS_STALL_PID;
case -EOVERFLOW:
return USBD_STATUS_DATA_OVERRUN;
case -EREMOTEIO:
Expand Down
4 changes: 3 additions & 1 deletion driver/lib/usbd_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ void to_usbd_iso_descs(ULONG n_pkts, USBD_ISO_PACKET_DESCRIPTOR *usbd_iso_descs,
void to_iso_descs(ULONG n_pkts, struct usbip_iso_packet_descriptor *iso_descs, USBD_ISO_PACKET_DESCRIPTOR *usbd_iso_descs, BOOLEAN as_result);

ULONG get_iso_descs_len(ULONG n_pkts, struct usbip_iso_packet_descriptor *iso_descs, BOOLEAN is_actual);
ULONG get_usbd_iso_descs_len(ULONG n_pkts, USBD_ISO_PACKET_DESCRIPTOR *usbd_iso_descs);
ULONG get_usbd_iso_descs_len(ULONG n_pkts, USBD_ISO_PACKET_DESCRIPTOR *usbd_iso_descs);

#define USB_REQUEST_RESET_PIPE 0xfe
2 changes: 1 addition & 1 deletion driver/stub/stub_devconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "stub_usbd.h"
#include "devconf.h"

PUSB_CONFIGURATION_DESCRIPTOR get_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR idx);
PUSB_CONFIGURATION_DESCRIPTOR get_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR bVal);

#ifdef DBG

Expand Down
14 changes: 14 additions & 0 deletions driver/stub/stub_usbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ select_usb_intf(usbip_stub_dev_t *devstub, UCHAR intf_num, USHORT alt_setting)
return FALSE;
}

PUSB_INTERFACE_DESCRIPTOR dsc_intf = dsc_find_intf(devstub->devconf->dsc_conf, intf_num, alt_setting);
if (dsc_intf == NULL) {
DBGW(DBG_GENERAL, "select_usb_intf: empty dsc_intf: num: %hhu, alt:%hu\n", intf_num, alt_setting);
return FALSE;
}

info_intf_size = get_info_intf_size(devstub->devconf, intf_num, alt_setting);
if (info_intf_size == 0) {
DBGW(DBG_GENERAL, "select_usb_intf: non-existent interface: num: %hhu, alt:%hu\n", intf_num, alt_setting);
Expand All @@ -309,6 +315,12 @@ select_usb_intf(usbip_stub_dev_t *devstub, UCHAR intf_num, USHORT alt_setting)
}
UsbBuildSelectInterfaceRequest(purb, (USHORT)len_urb, devstub->devconf->hConf, intf_num, (UCHAR)alt_setting);
purb_seli = &purb->UrbSelectInterface;
memset(&purb_seli->Interface.Pipes, 0, sizeof(USBD_PIPE_INFORMATION)*dsc_intf->bNumEndpoints);

purb_seli->Interface.Class = dsc_intf->bInterfaceClass;
purb_seli->Interface.SubClass = dsc_intf->bInterfaceSubClass;
purb_seli->Interface.Protocol = dsc_intf->bInterfaceProtocol;
purb_seli->Interface.NumberOfPipes = dsc_intf->bNumEndpoints;

status = call_usbd(devstub, purb);
ExFreePoolWithTag(purb, USBIP_STUB_POOL_TAG);
Expand Down Expand Up @@ -370,6 +382,8 @@ done_bulk_intr_transfer(usbip_stub_dev_t *devstub, NTSTATUS status, PURB purb, s
sres->header.u.ret_submit.actual_length = purb->UrbBulkOrInterruptTransfer.TransferBufferLength;
}
else {
sres->data_len = 0;
sres->header.u.ret_submit.actual_length = 0;
sres->header.u.ret_submit.status = to_usbip_status(purb->UrbHeader.Status);
}
reply_stub_req(devstub, sres);
Expand Down
30 changes: 29 additions & 1 deletion driver/stub/stub_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,28 @@ process_data_transfer(usbip_stub_dev_t *devstub, struct usbip_header *hdr)
}
}

static void
process_reset_pipe(usbip_stub_dev_t *devstub, struct usbip_header *hdr)
{
PUSBD_PIPE_INFORMATION info_pipe;
UCHAR epaddr;

epaddr = get_epaddr_from_hdr(hdr);
info_pipe = get_info_pipe(devstub->devconf, epaddr);
if (info_pipe == NULL) {
DBGW(DBG_READWRITE, "reset_pipe: non-existent pipe: %hhx\n", epaddr);
reply_stub_req_err(devstub, USBIP_RET_SUBMIT, hdr->base.seqnum, -1);
return;
}

DBGI(DBG_READWRITE, "reset pipe: pipeHandle = %p\n", info_pipe->PipeHandle);

if (NT_SUCCESS(reset_pipe(devstub, info_pipe->PipeHandle)))
reply_stub_req_data(devstub, hdr->base.seqnum, NULL, 0, FALSE);
else
reply_stub_req_err(devstub, USBIP_RET_SUBMIT, hdr->base.seqnum, -8);
}

static NTSTATUS
process_cmd_submit(usbip_stub_dev_t *devstub, PIRP irp, struct usbip_header *hdr)
{
Expand All @@ -338,7 +360,13 @@ process_cmd_submit(usbip_stub_dev_t *devstub, PIRP irp, struct usbip_header *hdr
process_control_transfer(devstub, hdr);
}
else {
process_data_transfer(devstub, hdr);
usb_cspkt_t *csp = (usb_cspkt_t *)hdr->u.cmd_submit.setup;
if (CSPKT_REQUEST_TYPE(csp) == BMREQUEST_STANDARD && CSPKT_RECIPIENT(csp) == BMREQUEST_TO_ENDPOINT && CSPKT_REQUEST(csp) == USB_REQUEST_RESET_PIPE) {
process_reset_pipe(devstub, hdr);
}
else {
process_data_transfer(devstub, hdr);
}
}

irpstack = IoGetCurrentIrpStackLocation(irp);
Expand Down
2 changes: 1 addition & 1 deletion driver/vhci/vhci_dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct namecode namecodes_urb_func[] = {
K_V(URB_FUNCTION_CONTROL_TRANSFER)
K_V(URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER)
K_V(URB_FUNCTION_ISOCH_TRANSFER)
K_V(URB_FUNCTION_RESET_PIPE)
K_V(URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL)
K_V(URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
K_V(URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT)
K_V(URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE)
Expand Down
13 changes: 1 addition & 12 deletions driver/vhci/vhci_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ vhci_get_ports_status(ioctl_usbip_vhci_get_ports_status *st, pusbip_vhub_dev_t v
extern PAGEABLE NTSTATUS
vhci_eject_device(PUSBIP_VHCI_EJECT_HARDWARE Eject, pusbip_vhub_dev_t vhub);

static NTSTATUS
process_urb_reset_pipe(pusbip_vpdo_dev_t vpdo)
{
UNREFERENCED_PARAMETER(vpdo);

////TODO need to check
DBGI(DBG_IOCTL, "reset_pipe:\n");
return STATUS_SUCCESS;
}

static NTSTATUS
process_urb_abort_pipe(pusbip_vpdo_dev_t vpdo, PURB urb)
{
Expand Down Expand Up @@ -71,8 +61,6 @@ process_irp_urb_req(pusbip_vpdo_dev_t vpdo, PIRP irp, PURB urb)
DBGI(DBG_IOCTL, "process_irp_urb_req: function: %s\n", dbg_urbfunc(urb->UrbHeader.Function));

switch (urb->UrbHeader.Function) {
case URB_FUNCTION_RESET_PIPE:
return process_urb_reset_pipe(vpdo);
case URB_FUNCTION_ABORT_PIPE:
return process_urb_abort_pipe(vpdo, urb);
case URB_FUNCTION_GET_CURRENT_FRAME_NUMBER:
Expand All @@ -91,6 +79,7 @@ process_irp_urb_req(pusbip_vpdo_dev_t vpdo, PIRP irp, PURB urb)
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
case URB_FUNCTION_SELECT_INTERFACE:
case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
return submit_urbr_irp(vpdo, irp);
default:
DBGW(DBG_IOCTL, "process_irp_urb_req: unhandled function: %s: len: %d\n",
Expand Down
41 changes: 38 additions & 3 deletions driver/vhci/vhci_read.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "usbip_proto.h"
#include "usbreq.h"
#include "usbd_helper.h"

extern struct urb_req *
find_pending_urbr(pusbip_vpdo_dev_t vpdo);
Expand Down Expand Up @@ -75,6 +76,36 @@ store_urb_reset_dev(PIRP irp, struct urb_req *urbr)
return STATUS_SUCCESS;
}

static NTSTATUS
store_urb_reset_pipe(PIRP irp, PURB urb, struct urb_req *urbr)
{
struct _URB_PIPE_REQUEST *urb_rp = &urb->UrbPipeRequest;
struct usbip_header *hdr;
int in, type;

hdr = get_usbip_hdr_from_read_irp(irp);
if (hdr == NULL) {
return STATUS_BUFFER_TOO_SMALL;
}

in = PIPE2DIRECT(urb_rp->PipeHandle);
type = PIPE2TYPE(urb_rp->PipeHandle);
if (type != USB_ENDPOINT_TYPE_BULK && type != USB_ENDPOINT_TYPE_INTERRUPT) {
DBGE(DBG_READ, "Error, not a bulk pipe\n");
return STATUS_INVALID_PARAMETER;
}

set_cmd_submit_usbip_header(hdr, urbr->seq_num, urbr->vpdo->devid, in, urb_rp->PipeHandle, 0, 0);
RtlZeroMemory(hdr->u.cmd_submit.setup, 8);

usb_cspkt_t *csp = (usb_cspkt_t *)hdr->u.cmd_submit.setup;
build_setup_packet(csp, 0, BMREQUEST_STANDARD, BMREQUEST_TO_ENDPOINT, USB_REQUEST_RESET_PIPE);

irp->IoStatus.Information = sizeof(struct usbip_header);

return STATUS_SUCCESS;
}

static PVOID
get_buf(PVOID buf, PMDL bufMDL)
{
Expand Down Expand Up @@ -248,8 +279,9 @@ store_urb_class_vendor(PIRP irp, PURB urb, struct urb_req *urbr)
}

static NTSTATUS
store_urb_select_config(PIRP irp, struct urb_req *urbr)
store_urb_select_config(PIRP irp, PURB urb, struct urb_req *urbr)
{
struct _URB_SELECT_CONFIGURATION *urb_sc = &urb->UrbSelectConfiguration;
struct usbip_header *hdr;
usb_cspkt_t *csp;

Expand All @@ -263,7 +295,7 @@ store_urb_select_config(PIRP irp, struct urb_req *urbr)
set_cmd_submit_usbip_header(hdr, urbr->seq_num, urbr->vpdo->devid, 0, 0, 0, 0);
build_setup_packet(csp, 0, BMREQUEST_STANDARD, BMREQUEST_TO_DEVICE, USB_REQUEST_SET_CONFIGURATION);
csp->wLength = 0;
csp->wValue.W = 1;
csp->wValue.W = urb_sc->ConfigurationDescriptor->bConfigurationValue;
csp->wIndex.W = 0;

irp->IoStatus.Information = sizeof(struct usbip_header);
Expand Down Expand Up @@ -509,11 +541,14 @@ store_urbr_submit(PIRP irp, struct urb_req *urbr)
status = store_urb_class_vendor(irp, urb, urbr);
break;
case URB_FUNCTION_SELECT_CONFIGURATION:
status = store_urb_select_config(irp, urbr);
status = store_urb_select_config(irp, urb, urbr);
break;
case URB_FUNCTION_SELECT_INTERFACE:
status = store_urb_select_interface(irp, urb, urbr);
break;
case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
status = store_urb_reset_pipe(irp, urb, urbr);
break;
default:
irp->IoStatus.Information = 0;
DBGE(DBG_READ, "unhandled urb function: %s\n", dbg_urbfunc(code_func));
Expand Down
6 changes: 6 additions & 0 deletions driver/vhci/vhci_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ store_urb_data(PURB urb, struct usbip_header *hdr)
case URB_FUNCTION_SELECT_INTERFACE:
status = STATUS_SUCCESS;
break;
case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
status = STATUS_SUCCESS;
break;
default:
DBGE(DBG_WRITE, "not supported func: %s\n", dbg_urbfunc(urb->UrbHeader.Function));
status = STATUS_INVALID_PARAMETER;
Expand All @@ -241,6 +244,9 @@ process_urb_res_submit(pusbip_vpdo_dev_t vpdo, PURB urb, struct usbip_header *hd

if (hdr->u.ret_submit.status != 0) {
urb->UrbHeader.Status = to_usbd_status(hdr->u.ret_submit.status);
if (urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) {
urb->UrbBulkOrInterruptTransfer.TransferBufferLength = hdr->u.ret_submit.actual_length;
}
return STATUS_UNSUCCESSFUL;
}
status = store_urb_data(urb, hdr);
Expand Down

0 comments on commit 781e315

Please sign in to comment.