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