USBProxyDevice-usbip.cpp revision 193fb7370cff6370ec20f3948b78bcb68d2849e7
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/* $Id$ */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** @file
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * USB device proxy - USB/IP backend.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/*
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Copyright (C) 2014 Oracle Corporation
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * available from http://www.virtualbox.org. This file is free software;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * you can redistribute it and/or modify it under the terms of the GNU
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * General Public License (GPL) as published by the Free Software
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/*******************************************************************************
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync* Header Files *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync*******************************************************************************/
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define LOG_GROUP LOG_GROUP_DRV_USBPROXY
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <VBox/log.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <VBox/err.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <VBox/vmm/pdm.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <iprt/asm.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <iprt/assert.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <iprt/alloc.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <iprt/string.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <iprt/socket.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <iprt/poll.h>
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync#include <iprt/tcp.h>
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync#include <iprt/pipe.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <iprt/list.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include <iprt/semaphore.h>
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#include "../USBProxyDevice.h"
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/*******************************************************************************
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync* Constants And Macros, Structures and Typedefs *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync*******************************************************************************/
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** The USB version number used for the protocol. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_VERSION UINT16_C(0x0100)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Request indicator in the command code. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync#define USBIP_INDICATOR_REQ RT_BIT(15)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Command/Reply code for OP_REQ/RET_DEVLIST. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_REQ_RET_DEVLIST UINT16_C(5)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Command/Reply code for OP_REQ/REP_IMPORT. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_REQ_RET_IMPORT UINT16_C(3)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** USB submit command identifier. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_CMD_SUBMIT UINT32_C(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** USB submit status identifier. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_RET_SUBMIT UINT32_C(2)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** URB unlink (cancel) command identifier. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_CMD_UNLINK UINT32_C(3)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** URB unlink (cancel) reply identifier. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_RET_UNLINK UINT32_C(4)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Short read is not okay for the specified URB. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_XFER_FLAGS_SHORT_NOT_OK RT_BIT_32(0)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Queue the isochronous URB as soon as possible. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_XFER_FLAGS_ISO_ASAP RT_BIT_32(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Don't use DMA mappings for this URB. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_XFER_FLAGS_NO_TRANSFER_DMA_MAP RT_BIT_32(2)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Explain - only applies to UHCI. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_XFER_FLAGS_FSBR RT_BIT_32(4)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** URB direction - input. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_DIR_IN UINT32_C(0)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** URB direction - output. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_DIR_OUT UINT32_C(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Exported device entry in the OP_RET_DEVLIST reply.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpExportedDevice
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Path of the device, zero terminated string. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync char szPath[256];
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Bus ID of the exported device, zero terminated string. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync char szBusId[32];
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Bus number. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32BusNum;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Device number. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32DevNum;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Speed indicator of the device. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32Speed;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Vendor ID of the device. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint16_t u16VendorId;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Product ID of the device. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint16_t u16ProductId;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Device release number. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint16_t u16BcdDevice;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Device class. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bDeviceClass;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Device Subclass. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bDeviceSubClass;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Device protocol. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bDeviceProtocol;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Current configuration value of the device. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bNumConfigurations;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Number of interfaces for the device. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bNumInterfaces;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpExportedDevice;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a exported device entry. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpExportedDevice *PUsbIpExportedDevice;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Interface descriptor entry for an exported device.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpDeviceInterface
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Intefrace class. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bInterfaceClass;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Interface sub class. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bInterfaceSubClass;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Interface protocol identifier. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bInterfaceProtocol;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Padding byte for alignment. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint8_t bPadding;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpDeviceInterface;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to an interface descriptor entry. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpDeviceInterface *PUsbIpDeviceInterface;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * USB/IP Import request.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpReqImport
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Protocol version number. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint16_t u16Version;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Command code. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint16_t u16Cmd;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Status field, unused. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32Status;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Bus Id of the device as zero terminated string. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync char aszBusId[32];
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpReqImport;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a import request. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpReqImport *PUsbIpReqImport;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * USB/IP Import reply.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * This is only the header, for successful
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * imports the device details are sent to as
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * defined in UsbIpExportedDevice.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpRetImport
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Protocol version number. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint16_t u16Version;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Command code. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint16_t u16Cmd;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Status field, unused. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32Status;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpRetImport;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a import reply. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpRetImport *PUsbIpRetImport;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Command/Reply header common to the submit and unlink commands
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * replies.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpReqRetHdr
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Request/Return code. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32ReqRet;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Sequence number to identify the URB. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32SeqNum;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Device id. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32DevId;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Direction of the endpoint (host->device, device->host). */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32Direction;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Endpoint number. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32Endpoint;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpReqRetHdr;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a request/reply header. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpReqRetHdr *PUsbIpReqRetHdr;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * USB/IP Submit request.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpReqSubmit
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** The request header. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpReqRetHdr Hdr;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Transfer flags for the URB. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32XferFlags;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Transfer buffer length. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32TransferBufferLength;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Frame to transmit an ISO frame. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32StartFrame;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Number of isochronous packets. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32NumIsocPkts;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Maximum time for the request on the server side host controller. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32Interval;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Setup data for a control URB. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync VUSBSETUP Setup;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpReqSubmit;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a submit request. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpReqSubmit *PUsbIpReqSubmit;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * USB/IP Submit reply.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpRetSubmit
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** The reply header. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpReqRetHdr Hdr;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Status code. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32Status;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Actual length of the reply buffer. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32ActualLength;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** The actual selected frame for a isochronous transmit. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32StartFrame;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Number of isochronous packets. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32NumIsocPkts;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Number of failed isochronous packets. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32ErrorCount;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Setup data for a control URB. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync VUSBSETUP Setup;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpRetSubmit;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a submit reply. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpRetSubmit *PUsbIpRetSubmit;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Unlink URB request.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpReqUnlink
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** The request header. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpReqRetHdr Hdr;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** The sequence number to unlink. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32SeqNum;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpReqUnlink;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a URB unlink request. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpReqUnlink *PUsbIpReqUnlink;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Unlink URB reply.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack(1)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct UsbIpRetUnlink
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** The reply header. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpReqRetHdr Hdr;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Status of the request. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32Status;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} UsbIpRetUnlink;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a URB unlink request. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef UsbIpRetUnlink *PUsbIpRetUnlink;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#pragma pack()
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync/**
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * Union of possible replies from the server during normal operation.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync#pragma pack(1)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsynctypedef union UsbIpRet
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /** The header. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync UsbIpReqRetHdr Hdr;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /** Submit reply. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync UsbIpRetSubmit RetSubmit;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /** Unlink reply. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync UsbIpRetUnlink RetUnlink;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /** Byte view. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync uint8_t abReply[1];
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync} UsbIpRet;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync/** Pointer to a reply union. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsynctypedef UsbIpRet *PUsbIpRet;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync#pragma pack()
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * USB/IP backend specific data for one URB.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Required for tracking in flight and landed URBs.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct USBPROXYURBUSBIP
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** List node for the in flight or landed URB list. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTLISTNODE NodeList;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Sequence number the assigned URB is identified by. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32SeqNumUrb;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Pointer to the VUSB URB. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PVUSBURB pVUsbUrb;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} USBPROXYURBUSBIP;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pointer to a USB/IP URB. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef USBPROXYURBUSBIP *PUSBPROXYURBUSBIP;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Backend data for the USB/IP USB Proxy device backend.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsynctypedef struct USBPROXYDEVUSBIP
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** IPRT socket handle. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTSOCKET hSocket;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Pollset with the wakeup pipe and socket. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTPOLLSET hPollSet;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Pipe endpoint - read (in the pollset). */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTPIPE hPipeR;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Pipe endpoint - write. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTPIPE hPipeW;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Flag whether the reaper thread was woken up. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync volatile bool fWokenUp;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Next sequence number to use for identifying submitted URBs. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync volatile uint32_t u32SeqNumNext;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Fast mutex protecting the lists below against concurrent access. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTSEMFASTMUTEX hMtxLists;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** List of in flight URBs. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTLISTANCHOR ListUrbsInFlight;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** List of landed URBs. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTLISTANCHOR ListUrbsLanded;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** Port of the USB/IP host to connect to. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t uPort;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** USB/IP host address. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync char *pszHost;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** USB Bus ID of the device to capture. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync char *pszBusId;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** The device ID to use to identify the device. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32DevId;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync} USBPROXYDEVUSBIP, *PUSBPROXYDEVUSBIP;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pollset id of the socket. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_POLL_ID_SOCKET 0
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/** Pollset id of the pipe. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync#define USBIP_POLL_ID_PIPE 1
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Converts a request/reply header from network to host endianness.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns nothing.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pHdr The header to convert.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncDECLINLINE(void) usbProxyUsbIpReqRetHdrN2H(PUsbIpReqRetHdr pHdr)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32ReqRet = RT_H2N_U32(pHdr->u32ReqRet);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32SeqNum = RT_H2N_U32(pHdr->u32SeqNum);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32DevId = RT_H2N_U32(pHdr->u32DevId);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32Direction = RT_H2N_U32(pHdr->u32Direction);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32Endpoint = RT_H2N_U32(pHdr->u32Endpoint);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Converts a request/reply header from host to network endianness.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns nothing.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pHdr The header to convert.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncDECLINLINE(void) usbProxyUsbIpReqRetHdrH2N(PUsbIpReqRetHdr pHdr)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32ReqRet = RT_N2H_U32(pHdr->u32ReqRet);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32SeqNum = RT_N2H_U32(pHdr->u32SeqNum);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32DevId = RT_N2H_U32(pHdr->u32DevId);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32Direction = RT_N2H_U32(pHdr->u32Direction);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pHdr->u32Endpoint = RT_N2H_U32(pHdr->u32Endpoint);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Converts a submit request from host to network endianness.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns nothing.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pReqSubmit The submit request to convert.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncDECLINLINE(void) usbProxyUsbIpReqSubmitH2N(PUsbIpReqSubmit pReqSubmit)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpReqRetHdrH2N(&pReqSubmit->Hdr);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pReqSubmit->u32XferFlags = RT_H2N_U32(pReqSubmit->u32XferFlags);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pReqSubmit->u32TransferBufferLength = RT_H2N_U32(pReqSubmit->u32TransferBufferLength);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pReqSubmit->u32StartFrame = RT_H2N_U32(pReqSubmit->u32StartFrame);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pReqSubmit->u32NumIsocPkts = RT_H2N_U32(pReqSubmit->u32NumIsocPkts);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pReqSubmit->u32Interval = RT_H2N_U32(pReqSubmit->u32Interval);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Converts a submit reply from network to host endianness.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns nothing.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pReqSubmit The submit reply to convert.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncDECLINLINE(void) usbProxyUsbIpRetSubmitN2H(PUsbIpRetSubmit pRetSubmit)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpReqRetHdrN2H(&pRetSubmit->Hdr);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pRetSubmit->u32Status = RT_N2H_U32(pRetSubmit->u32Status);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pRetSubmit->u32ActualLength = RT_N2H_U32(pRetSubmit->u32ActualLength);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pRetSubmit->u32StartFrame = RT_N2H_U32(pRetSubmit->u32StartFrame);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pRetSubmit->u32NumIsocPkts = RT_N2H_U32(pRetSubmit->u32NumIsocPkts);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pRetSubmit->u32ErrorCount = RT_N2H_U32(pRetSubmit->u32ErrorCount);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync/**
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * Converts a unlink request from host to network endianness.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync *
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @returns nothing.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pReqUnlink The unlink request to convert.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsyncDECLINLINE(void) usbProxyUsbIpReqUnlinkH2N(PUsbIpReqUnlink pReqUnlink)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpReqRetHdrH2N(&pReqUnlink->Hdr);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pReqUnlink->u32SeqNum = RT_H2N_U32(pReqUnlink->u32SeqNum);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync}
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync/**
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * Converts a unlink reply from network to host endianness.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync *
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @returns nothing.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pRetUnlink The unlink reply to convert.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsyncDECLINLINE(void) usbProxyUsbIpRetUnlinkN2H(PUsbIpRetUnlink pRetUnlink)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpReqRetHdrN2H(&pRetUnlink->Hdr);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pRetUnlink->u32Status = RT_N2H_U32(pRetUnlink->u32Status);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync}
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Convert the given exported device structure from host to network byte order.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns nothing.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pDevice The device structure to convert.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncDECLINLINE(void) usbProxyUsbIpExportedDeviceN2H(PUsbIpExportedDevice pDevice)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevice->u32BusNum = RT_N2H_U32(pDevice->u32BusNum);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevice->u32DevNum = RT_N2H_U32(pDevice->u32DevNum);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevice->u32Speed = RT_N2H_U16(pDevice->u32Speed);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevice->u16VendorId = RT_N2H_U16(pDevice->u16VendorId);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevice->u16ProductId = RT_N2H_U16(pDevice->u16ProductId);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevice->u16BcdDevice = RT_N2H_U16(pDevice->u16BcdDevice);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Converts a USB/IP status code to VBox status code.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns VBox status code.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param u32Status The USB/IP status code from the reply.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncDECLINLINE(int) usbProxyUsbIpErrConvertFromStatus(uint32_t u32Status)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_LIKELY(u32Status == 0))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return VERR_NOT_IMPLEMENTED;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Gets the next free sequence number.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns Next free sequence number.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncDECLINLINE(uint32_t) usbProxyUsbIpSeqNumGet(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return ASMAtomicIncU32(&pProxyDevUsbIp->u32SeqNumNext);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync/**
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * Links a given URB into the given list.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync *
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @returns nothing.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pList The list to link the URB into.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pUrbUsbIp The URB to link.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsyncDECLINLINE(void) usbProxyUsbIpLinkUrb(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PRTLISTANCHOR pList, PUSBPROXYURBUSBIP pUrbUsbIp)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync AssertRC(rc);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTListAppend(pList, &pUrbUsbIp->NodeList);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync}
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync/**
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * Unlinks a given URB from the current assigned list.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync *
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @returns nothing.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pUrbUsbIp The URB to unlink.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsyncDECLINLINE(void) usbProxyUsbIpUnlinkUrb(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PUSBPROXYURBUSBIP pUrbUsbIp)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync AssertRC(rc);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTListNodeRemove(&pUrbUsbIp->NodeList);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync}
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync/**
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * Allocates a USB/IP proxy specific URB state.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync *
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @returns Pointer to the USB/IP specific URB data or NULL on failure.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsyncstatic PUSBPROXYURBUSBIP usbProxyUsbIpUrbAlloc(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync NOREF(pProxyDevUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync return (PUSBPROXYURBUSBIP)RTMemAllocZ(sizeof(USBPROXYURBUSBIP));
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync}
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync/**
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * Frees the given USB/IP URB state.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync *
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @returns nothing.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync * @param pUrbUsbIp The USB/IP speciic URB data.
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsyncstatic void usbProxyUsbIpUrbFree(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PUSBPROXYURBUSBIP pUrbUsbIp)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync NOREF(pProxyDevUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTMemFree(pUrbUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync}
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Parse the string representation of the host address.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns VBox status code.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data to parse the address for.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pszAddress The address string to parse.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic int usbProxyUsbIpParseAddress(PUSBPROXYDEVUSBIP pProxyDevUsbIp, const char *pszAddress)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync int rc = VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t uPort;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync char *pszPortStart = RTStrStr(pszAddress, ":");
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync char *pszHost = NULL;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (pszPortStart)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync size_t cbHost = pszPortStart - pszAddress;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pszPortStart++;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTStrToUInt32Ex(pszPortStart, NULL, 10 /* uBase */, &pProxyDevUsbIp->uPort);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if ( rc == VINF_SUCCESS
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync || cbHost == 0)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTStrAllocEx(&pProxyDevUsbIp->pszHost, cbHost + 1);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTStrCopyEx(pProxyDevUsbIp->pszHost, cbHost + 1, pszAddress, cbHost);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync else
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = VERR_INVALID_PARAMETER;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync else
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = VERR_INVALID_PARAMETER;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return rc;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Connects to the USB/IP host and claims the device given in the proxy device data.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns VBox status.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic int usbProxyUsbIpConnect(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync int rc = VINF_SUCCESS;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTTcpClientConnect(pProxyDevUsbIp->pszHost, pProxyDevUsbIp->uPort, &pProxyDevUsbIp->hSocket);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Disable send coalescing. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTTcpSetSendCoalescing(pProxyDevUsbIp->hSocket, false);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_FAILURE(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogRel(("UsbIp: Disabling send coalescing failed (rc=%Rrc), continuing nevertheless but expect reduced performance\n", rc));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Import the device, i.e. claim it for our use. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpReqImport ReqImport;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqImport.u16Version = RT_H2N_U16(USBIP_VERSION);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqImport.u16Cmd = RT_H2N_U16(USBIP_INDICATOR_REQ | USBIP_REQ_RET_IMPORT);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqImport.u32Status = RT_H2N_U32(0);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTStrCopy(&ReqImport.aszBusId[0], sizeof(ReqImport.aszBusId[0]), pProxyDevUsbIp->pszBusId);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (rc == VINF_SUCCESS)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqImport, sizeof(ReqImport));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Read the reply. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpRetImport RetImport;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTTcpRead(pProxyDevUsbIp->hSocket, &RetImport, sizeof(RetImport), NULL);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RetImport.u16Version = RT_N2H_U16(RetImport.u16Version);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RetImport.u16Cmd = RT_N2H_U16(RetImport.u16Cmd);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RetImport.u32Status = RT_N2H_U16(RetImport.u32Status);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if ( RetImport.u16Version == USBIP_VERSION
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync && RetImport.u16Cmd == USBIP_REQ_RET_IMPORT
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync && RetImport.u32Status == 0)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Read the device data. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpExportedDevice Device;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTTcpRead(pProxyDevUsbIp->hSocket, &Device, sizeof(Device), NULL);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpExportedDeviceN2H(&Device);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pProxyDevUsbIp->u32DevId = (Device.u32BusNum << 16) | Device.u32DevNum;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTPollSetAddSocket(pProxyDevUsbIp->hPollSet, pProxyDevUsbIp->hSocket,
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, USBIP_POLL_ID_SOCKET);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync else
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Check what went wrong and leave a meaningful error message in the log. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RetImport.u16Version != USBIP_VERSION)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogRel(("UsbIp: Unexpected protocol version received from host (%#x vs. %#x)\n",
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RetImport.u16Version, USBIP_VERSION));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync else if (RetImport.u16Cmd != USBIP_REQ_RET_IMPORT)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogRel(("UsbIp: Unexpected reply code received from host (%#x vs. %#x)\n",
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RetImport.u16Cmd, USBIP_REQ_RET_IMPORT));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync else if (RetImport.u32Status != 0)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogRel(("UsbIp: Claiming the device has failed on the host with an unspecified error\n"));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync else
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertMsgFailed(("Something went wrong with if condition\n"));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync else
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogRel(("UsbIp: Given bus ID is exceeds permitted protocol length: %u vs %u\n",
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync strlen(pProxyDevUsbIp->pszBusId) + 1, sizeof(ReqImport.aszBusId[0])));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = VERR_INVALID_PARAMETER;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_FAILURE(rc))
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTTcpClientCloseEx(pProxyDevUsbIp->hSocket, false /*fGracefulShutdown*/);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_FAILURE(rc))
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync LogRel(("UsbIp: Connecting to the host %s failed with %Rrc\n", pProxyDevUsbIp->pszHost, rc));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return rc;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Disconnects from the USB/IP host releasing the device given in the proxy device data.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @returns VBox status code.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic int usbProxyUsbIpDisconnect(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync int rc = VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTTcpClientCloseEx(pProxyDevUsbIp->hSocket, false /*fGracefulShutdown*/);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pProxyDevUsbIp->hSocket = NIL_RTSOCKET;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return rc;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * Synchronously exchange a given control message with the remote device.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @eturns VBox status code.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pProxyDevUsbIp The USB/IP proxy device data.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @param pSetup The setup message.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync *
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @note This method is only used to implement the *SetConfig, *SetInterface and *ClearHaltedEp
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * callbacks because the USB/IP protocol lacks dedicated requests for these.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * @remark It is assumed that this method is never called while usbProxyUsbIpUrbReap is called
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * on another thread.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic int usbProxyUsbIpCtrlUrbExchangeSync(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PVUSBSETUP pSetup)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync int rc = VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpReqSubmit ReqSubmit;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync uint32_t u32SeqNum = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.Hdr.u32ReqRet = USBIP_CMD_SUBMIT;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.Hdr.u32SeqNum = u32SeqNum;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.Hdr.u32DevId = pProxyDevUsbIp->u32DevId;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.Hdr.u32Direction = USBIP_DIR_OUT;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.Hdr.u32Endpoint = 0; /* Only default control endpoint is allowed for these kind of messages. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.u32XferFlags = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.u32TransferBufferLength = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.u32StartFrame = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.u32NumIsocPkts = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync ReqSubmit.u32Interval = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync memcpy(&ReqSubmit.Setup, pSetup, sizeof(ReqSubmit.Setup));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpReqSubmitH2N(&ReqSubmit);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Send the command. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqSubmit, sizeof(ReqSubmit));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Wait for the response. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /** @todo: Don't wait indefinitely long. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpRetSubmit RetSubmit;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTTcpRead(pProxyDevUsbIp->hSocket, &RetSubmit, sizeof(RetSubmit), NULL);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpRetSubmitN2H(&RetSubmit);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = usbProxyUsbIpErrConvertFromStatus(RetSubmit.u32Status);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return rc;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/*
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * The USB proxy device functions.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pProxyDev=%p pszAddress=%s, pvBackend=%p\n", pProxyDev, pszAddress, pvBackend));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYDEVUSBIP pDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync int rc = VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTListInit(&pDevUsbIp->ListUrbsInFlight);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTListInit(&pDevUsbIp->ListUrbsLanded);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevUsbIp->hSocket = NIL_RTSOCKET;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevUsbIp->hPollSet = NIL_RTPOLLSET;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevUsbIp->hPipeW = NIL_RTPIPE;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevUsbIp->hPipeR = NIL_RTPIPE;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevUsbIp->fWokenUp = false;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevUsbIp->u32SeqNumNext = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevUsbIp->pszHost = NULL;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync pDevUsbIp->pszBusId = NULL;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Setup wakeup pipe and poll set first. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPipeCreate(&pDevUsbIp->hPipeR, &pDevUsbIp->hPipeW, 0);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPollSetCreate(&pDevUsbIp->hPollSet);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPollSetAddPipe(pDevUsbIp->hPollSet, pDevUsbIp->hPipeR,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTPOLL_EVT_READ, USBIP_POLL_ID_PIPE);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Connect to the USB/IP host. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = usbProxyUsbIpParseAddress(pDevUsbIp, pszAddress);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_SUCCESS(rc))
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = usbProxyUsbIpConnect(pDevUsbIp);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_FAILURE(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTPollSetRemove(pDevUsbIp->hPollSet, USBIP_POLL_ID_PIPE);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync int rc2 = RTPollSetDestroy(pDevUsbIp->hPollSet);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc2);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (RT_FAILURE(rc))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync int rc2 = RTPipeClose(pDevUsbIp->hPipeR);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc2);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc2 = RTPipeClose(pDevUsbIp->hPipeW);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc2);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return rc;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(void) usbProxyUsbIpClose(PUSBPROXYDEV pProxyDev)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync int rc = VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pProxyDev = %p\n", pProxyDev));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYDEVUSBIP pDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Destroy the pipe and pollset if necessary. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (pDevUsbIp->hPollSet != NIL_RTPOLLSET)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (pDevUsbIp->hSocket != NIL_RTSOCKET)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPollSetRemove(pDevUsbIp->hPollSet, USBIP_POLL_ID_SOCKET);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPollSetRemove(pDevUsbIp->hPollSet, USBIP_POLL_ID_PIPE);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPollSetDestroy(pDevUsbIp->hPollSet);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPipeClose(pDevUsbIp->hPipeR);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPipeClose(pDevUsbIp->hPipeW);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (pDevUsbIp->hSocket != NIL_RTSOCKET)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpDisconnect(pDevUsbIp);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (pDevUsbIp->pszHost)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTStrFree(pDevUsbIp->pszHost);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync if (pDevUsbIp->pszBusId)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTStrFree(pDevUsbIp->pszBusId);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* Clear the URB lists. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync rc = RTSemFastMutexRequest(pDevUsbIp->hMtxLists);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync AssertRC(rc);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYURBUSBIP pIter = NULL;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYURBUSBIP pIterNext = NULL;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTListForEachSafe(&pDevUsbIp->ListUrbsInFlight, pIter, pIterNext, USBPROXYURBUSBIP, NodeList)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTListNodeRemove(&pIter->NodeList);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTMemFree(pIter);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTListForEachSafe(&pDevUsbIp->ListUrbsLanded, pIter, pIterNext, USBPROXYURBUSBIP, NodeList)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTListNodeRemove(&pIter->NodeList);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTMemFree(pIter);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTSemFastMutexRelease(pDevUsbIp->hMtxLists);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync RTSemFastMutexDestroy(pDevUsbIp->hMtxLists);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpReset(PUSBPROXYDEV pProxyDev, bool fResetOnLinux)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pProxyDev = %p\n", pProxyDev));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync return VINF_SUCCESS; /* No way to reset the device with the current protocol. */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpSetConfig(PUSBPROXYDEV pProxyDev, int iCfg)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync LogFlowFunc(("pProxyDev=%s cfg=%#x\n", pProxyDev->pUsbIns->pszName, iCfg));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync VUSBSETUP Setup;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.bmRequestType = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.bRequest = 0x09;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wValue = iCfg;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wIndex = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wLength = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return usbProxyUsbIpCtrlUrbExchangeSync(pDev, &Setup);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpClaimInterface(PUSBPROXYDEV pProxyDev, int ifnum)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pProxyDev=%s ifnum=%#x\n", pProxyDev->pUsbIns->pszName, ifnum));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpReleaseInterface(PUSBPROXYDEV pProxyDev, int ifnum)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pProxyDev=%s ifnum=%#x\n", pProxyDev->pUsbIns->pszName, ifnum));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpSetInterface(PUSBPROXYDEV pProxyDev, int ifnum, int setting)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pProxyDev=%p ifnum=%#x setting=%#x\n", pProxyDev, ifnum, setting));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync VUSBSETUP Setup;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.bmRequestType = 0x1;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.bRequest = 0x11; /* SET_INTERFACE */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wValue = setting;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wIndex = ifnum;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wLength = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return usbProxyUsbIpCtrlUrbExchangeSync(pDev, &Setup);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int iEp)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync LogFlowFunc(("pProxyDev=%s ep=%u\n", pProxyDev->pUsbIns->pszName, iEp));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync VUSBSETUP Setup;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.bmRequestType = 0x2;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.bRequest = 0x01; /* CLEAR_FEATURE */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wValue = 0x00; /* ENDPOINT_HALT */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wIndex = iEp;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Setup.wLength = 0;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return usbProxyUsbIpCtrlUrbExchangeSync(pDev, &Setup);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpUrbQueue(PUSBPROXYDEV pProxyDev, PVUSBURB pUrb)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pUrb=%p\n", pUrb));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /* Allocate a USB/IP Urb. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync PUSBPROXYURBUSBIP pUrbUsbIp = usbProxyUsbIpUrbAlloc(pProxyDevUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (!pUrbUsbIp)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync return VERR_NO_MEMORY;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pUrbUsbIp->u32SeqNumUrb = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync UsbIpReqSubmit ReqSubmit;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.Hdr.u32ReqRet = USBIP_CMD_SUBMIT;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.Hdr.u32SeqNum = pUrbUsbIp->u32SeqNumUrb;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.Hdr.u32DevId = pProxyDevUsbIp->u32DevId;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.Hdr.u32Endpoint = pUrb->EndPt;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.Hdr.u32Direction = pUrb->enmDir == VUSBDIRECTION_IN ? USBIP_DIR_IN : USBIP_DIR_OUT;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.u32XferFlags = 0;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (pUrb->enmDir == VUSBDIRECTION_IN && pUrb->fShortNotOk)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.u32XferFlags |= USBIP_XFER_FLAGS_SHORT_NOT_OK;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.u32TransferBufferLength = pUrb->cbData;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.u32StartFrame = 0;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.u32NumIsocPkts = 0;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.u32Interval = 0;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync switch (pUrb->enmType)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync case VUSBXFERTYPE_MSG:
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync memcpy(&ReqSubmit.Setup, &pUrb->abData, sizeof(ReqSubmit.Setup));
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync LogFlowFunc(("Message (Control) URB\n"));
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync break;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync case VUSBXFERTYPE_ISOC:
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.u32XferFlags |= USBIP_XFER_FLAGS_ISO_ASAP;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqSubmit.u32NumIsocPkts = pUrb->cIsocPkts;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync#if 0
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pUrbLnx->KUrb.iso_frame_desc[i].length = pUrb->aIsocPkts[i].cb;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pUrbLnx->KUrb.iso_frame_desc[i].actual_length = 0;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pUrbLnx->KUrb.iso_frame_desc[i].status = 0x7fff;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync }
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync#else /** @todo: Implement isochronous support */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync return VERR_NOT_SUPPORTED;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync#endif
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync break;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync case VUSBXFERTYPE_BULK:
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync case VUSBXFERTYPE_INTR:
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync break;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync default:
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync return VERR_INVALID_PARAMETER; /** @todo: better status code. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync }
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpReqSubmitH2N(&ReqSubmit);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /* Send the command. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTSGBUF SgBufReq;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTSGSEG aSegReq[2];
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync aSegReq[0].pvSeg = &ReqSubmit;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync aSegReq[0].cbSeg = sizeof(ReqSubmit);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync aSegReq[1].pvSeg = &pUrb->abData[0];
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync aSegReq[1].cbSeg = pUrb->cbData;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync RTSgBufInit(&SgBufReq, &aSegReq[0], RT_ELEMENTS(aSegReq));
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync int rc = RTTcpSgWrite(pProxyDevUsbIp->hSocket, &SgBufReq);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (RT_SUCCESS(rc))
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /* Link the URB into the list of in flight URBs. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pUrb->Dev.pvPrivate = pUrbUsbIp;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pUrbUsbIp->pVUsbUrb = pUrb;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpLinkUrb(pProxyDevUsbIp, &pProxyDevUsbIp->ListUrbsInFlight, pUrbUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync }
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync else
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync return rc;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(PVUSBURB) usbProxyUsbIpUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYDEVUSBIP pDev = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync PUSBPROXYURBUSBIP pUrbUsbIp = NULL;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync PVUSBURB pUrb = NULL;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /* Any URBs pending delivery? */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (!RTListIsEmpty(&pDev->ListUrbsLanded))
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync pUrbUsbIp = RTListGetFirst(&pDev->ListUrbsLanded, USBPROXYURBUSBIP, NodeList);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (pUrbUsbIp)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /* unlink from the pending delivery list */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync usbProxyUsbIpUnlinkUrb(pDev, pUrbUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync }
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync }
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (!pUrbUsbIp)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync uint32_t uIdReady = 0;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync uint32_t fEventsRecv = 0;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (!ASMAtomicXchgBool(&pDev->fWokenUp, false))
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync int rc = RTPoll(pDev->hPollSet, cMillies, &fEventsRecv, &uIdReady);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync }
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync UsbIpRet Reply;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync }
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (pUrbUsbIp)
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync }
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync return pUrb;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpUrbCancel(PUSBPROXYDEV pProxyDev, PVUSBURB pUrb)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pUrb=%p\n", pUrb));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYURBUSBIP pUrbUsbIp = (PUSBPROXYURBUSBIP)pUrb->Dev.pvPrivate;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync UsbIpReqUnlink ReqUnlink;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync uint32_t u32SeqNum = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqUnlink.Hdr.u32ReqRet = USBIP_CMD_UNLINK;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqUnlink.Hdr.u32SeqNum = u32SeqNum;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqUnlink.Hdr.u32DevId = pProxyDevUsbIp->u32DevId;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqUnlink.Hdr.u32Direction = USBIP_DIR_OUT;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqUnlink.Hdr.u32Endpoint = pUrb->EndPt;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync ReqUnlink.u32SeqNum = pUrbUsbIp->u32SeqNumUrb;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync int rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqUnlink, sizeof(ReqUnlink));
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync /* Wait for the reply. */
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync return rc;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncstatic DECLCALLBACK(int) usbProxyUsbIpWakeup(PUSBPROXYDEV pProxyDev)
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync LogFlowFunc(("pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync PUSBPROXYDEVUSBIP pDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync int rc = VINF_SUCCESS;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync if (!ASMAtomicXchgBool(&pDevUsbIp->fWokenUp, true))
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync {
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync size_t cbWritten = 0;
193fb7370cff6370ec20f3948b78bcb68d2849e7vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync rc = RTPipeWrite(pDevUsbIp->hPipeW, "", 1, &cbWritten);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync Assert(RT_SUCCESS(rc) || cbWritten == 0);
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync }
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync return rc;
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync}
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync/**
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync * The USB/IP USB Proxy Backend operations.
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsyncextern const USBPROXYBACK g_USBProxyDeviceUsbIp =
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync{
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* pszName */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync "usbip",
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync /* cbBackend */
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync sizeof(USBPROXYDEVUSBIP),
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpOpen,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync NULL,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpClose,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpReset,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpSetConfig,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpClaimInterface,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpReleaseInterface,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpSetInterface,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpClearHaltedEp,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpUrbQueue,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpUrbCancel,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpUrbReap,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync usbProxyUsbIpWakeup,
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync 0
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync};
dc90b2bed0e77e6ff8b99ddd7abc218ec274cb59vboxsync