USBProxyDevice-darwin.cpp revision 9de2fa82343af2df7df171b18afbe32b6f37ed84
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/* $Id$ */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** @file
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * USB device proxy - the Darwin backend.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/*
b3eb676cebf5407921b8f535095ca7655edb9db3vboxsync * Copyright (C) 2006-2007 Oracle Corporation
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Oracle Corporation confidential
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * All rights reserved
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/*******************************************************************************
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync* Header Files *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync*******************************************************************************/
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#define LOG_GROUP LOG_GROUP_DRV_USBPROXY
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#define __STDC_LIMIT_MACROS
8f28e374e0b8ea801e7b5364bccd8a7e0a6211d3vboxsync#define __STDC_CONSTANT_MACROS
8f28e374e0b8ea801e7b5364bccd8a7e0a6211d3vboxsync
8f28e374e0b8ea801e7b5364bccd8a7e0a6211d3vboxsync#include <mach/mach.h>
8f28e374e0b8ea801e7b5364bccd8a7e0a6211d3vboxsync#include <Carbon/Carbon.h>
8f28e374e0b8ea801e7b5364bccd8a7e0a6211d3vboxsync#include <IOKit/IOKitLib.h>
8f28e374e0b8ea801e7b5364bccd8a7e0a6211d3vboxsync#include <mach/mach_error.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <IOKit/usb/IOUSBLib.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <IOKit/IOCFPlugIn.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <VBox/log.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <VBox/err.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <VBox/pdm.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <iprt/assert.h>
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync#include <iprt/critsect.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <iprt/mem.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <iprt/once.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <iprt/string.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <iprt/time.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include "../USBProxyDevice.h"
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#include <VBox/usblib.h>
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/*******************************************************************************
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync* Defined Constants And Macros *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync*******************************************************************************/
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** An experiment... */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync//#define USE_LOW_LATENCY_API 1
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/*******************************************************************************
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync* Structures and Typedefs *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync*******************************************************************************/
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** Forward declaration of the Darwin interface structure. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsynctypedef struct USBPROXYIFOSX *PUSBPROXYIFOSX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * A low latency isochronous buffer.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * These are allocated in chunks on an interface level, see USBPROXYISOCBUFCOL.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsynctypedef struct USBPROXYISOCBUF
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Whether this buffer is in use or not. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync bool volatile fUsed;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the buffer. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync void *pvBuf;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to an array of 8 frames. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOUSBLowLatencyIsocFrame *paFrames;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync} USBPROXYISOCBUF, *PUSBPROXYISOCBUF;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Isochronous buffer collection (associated with an interface).
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * These are allocated in decent sized chunks and there isn't supposed
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * to be too many of these per interface.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsynctypedef struct USBPROXYISOCBUFCOL
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Write or Read buffers? */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync USBLowLatencyBufferType enmType;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The next buffer collection on this interface. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync struct USBPROXYISOCBUFCOL *pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The buffer. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync void *pvBuffer;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The frame. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync void *pvFrames;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The buffers.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * The number of buffers here is decided by pvFrame begin allocated in
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * PAGE_SIZE chunks. The size of IOUSBLowLatencyIsocFrame is 16 bytes
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * and we require 8 of those per buffer. PAGE_SIZE / (16 * 8) = 32.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @remarks Don't allocate too many as it may temporarily halt the system if
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * some pool is low / exhausted. (Contiguous memory woes on mach.)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync USBPROXYISOCBUF aBuffers[/*32*/ 4];
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync} USBPROXYISOCBUFCOL, *PUSBPROXYISOCBUFCOL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncAssertCompileSize(IOUSBLowLatencyIsocFrame, 16);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Per-urb data for the Darwin usb proxy backend.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * This is required to track in-flight and landed URBs
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * since we take down the URBs in a different thread (perhaps).
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsynctypedef struct USBPROXYURBOSX
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the next Darwin URB. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync struct USBPROXYURBOSX *pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the previous Darwin URB. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync struct USBPROXYURBOSX *pPrev;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The millisecond timestamp when this URB was submitted. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint64_t u64SubmitTS;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the VUSB URB.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * This is set to NULL if canceled. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PVUSBURB pVUsbUrb;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the Darwin device. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync struct USBPROXYDEVOSX *pDevOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The transfer type. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync VUSBXFERTYPE enmType;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Union with data depending on transfer type. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync union
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The control message. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOUSBDevRequest ControlMsg;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The Isochronous Data. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync struct
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifdef USE_LOW_LATENCY_API
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The low latency isochronous buffer. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYISOCBUF pBuf;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Array of frames parallel to the one in VUSBURB. (Same as pBuf->paFrames.) */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOUSBLowLatencyIsocFrame *aFrames;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Array of frames parallel to the one in VUSBURB. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOUSBIsocFrame aFrames[8];
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync } Isoc;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync } u;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync} USBPROXYURBOSX, *PUSBPROXYURBOSX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Per-pipe data for the Darwin usb proxy backend.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsynctypedef struct USBPROXYPIPEOSX
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The endpoint number. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8Endpoint;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The IOKit pipe reference. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8PipeRef;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The pipe Transfer type type. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8TransferType;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The pipe direction. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8Direction;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The endpoint interval. (interrupt) */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8Interval;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The max packet size. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint16_t u16MaxPacketSize;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The next frame number (isochronous pipes only). */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint64_t u64NextFrameNo;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync} USBPROXYPIPEOSX, *PUSBPROXYPIPEOSX, **PPUSBPROXYPIPEOSX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Per-interface data for the Darwin usb proxy backend.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsynctypedef struct USBPROXYIFOSX
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the next interface. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync struct USBPROXYIFOSX *pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The interface number. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8Interface;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The current alternative interface setting.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * This is used to skip unnecessary SetAltInterface calls. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8AltSetting;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The interface class. (not really used) */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8Class;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The interface protocol. (not really used) */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t u8Protocol;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The number of pipes. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint8_t cPipes;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Array containing all the pipes. (Currently unsorted.) */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync USBPROXYPIPEOSX aPipes[kUSBMaxPipes];
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The IOUSBDeviceInterface. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOUSBInterfaceInterface245 **ppIfI;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The run loop source for the async operations on the interface level. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRunLoopSourceRef RunLoopSrcRef;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** List of isochronous buffer collections.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * These are allocated on demand by the URB queuing routine and then recycled until the interface is destroyed. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYISOCBUFCOL pIsocBufCols;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync} USBPROXYIFOSX, *PUSBPROXYIFOSX, **PPUSBPROXYIFOSX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** Pointer to a pointer to an darwin interface. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsynctypedef USBPROXYIFOSX **PPUSBPROXYIFOSX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Per-device Data for the Darwin usb proxy backend.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsynctypedef struct USBPROXYDEVOSX
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The USB Device IOService object. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync io_object_t USBDevice;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The IOUSBDeviceInterface. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOUSBDeviceInterface245 **ppDevI;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The run loop source for the async operations on the device level
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * (i.e. the default control pipe stuff). */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRunLoopSourceRef RunLoopSrcRef;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The run loop this device and its interfaces send their events to. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRunLoopRef RunLoopRef;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the proxy device instance. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYDEV pProxyDev;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the first interface. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYIFOSX pIfHead;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Pointer to the last interface. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYIFOSX pIfTail;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** Critical section protecting the lists. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCRITSECT CritSect;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The list of free Darwin URBs. Singly linked. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYURBOSX pFreeHead;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The list of active Darwin URBs. Doubly linked.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Only the split head will appear in this list. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYURBOSX pInFlightHead;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The list of landed Darwin URBs. Doubly linked.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Only the split head will appear in this list. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYURBOSX pTaxingHead;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** The tail of the landed Darwin URBs. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYURBOSX pTaxingTail;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync} USBPROXYDEVOSX, *PUSBPROXYDEVOSX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/*******************************************************************************
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync* Global Variables *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync*******************************************************************************/
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic RTONCE g_usbProxyDarwinOnce = RTONCE_INITIALIZER;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** The runloop mode we use.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Since it's difficult to remove this, we leak it to prevent crashes.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @bugref{4407} */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic CFStringRef g_pRunLoopMode = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/** The IO Master Port.
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync * Not worth cleaning up. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic mach_port_t g_MasterPort = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Init once callback that sets up g_MasterPort and g_pRunLoopMode.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns IPRT status code.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pvUser1 NULL, ignored.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pvUser2 NULL, ignored.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic DECLCALLBACK(int32_t) usbProxyDarwinInitOnce(void *pvUser1, void *pvUser2)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync int rc;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync kern_return_t krc = IOMasterPort(MACH_PORT_NULL, &g_MasterPort);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (krc == KERN_SUCCESS)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync g_pRunLoopMode = CFStringCreateWithCString(kCFAllocatorDefault, "VBoxUsbProxyMode", kCFStringEncodingUTF8);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (g_pRunLoopMode)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return VINF_SUCCESS;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VERR_INTERNAL_ERROR_5;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = RTErrConvertFromDarwin(krc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return rc;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Allocates a Darwin URB request structure.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns Pointer to an active URB request.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns NULL on failure.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pDevOsX The darwin proxy device.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic PUSBPROXYURBOSX usbProxyDarwinUrbAlloc(PUSBPROXYDEVOSX pDevOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYURBOSX pUrbOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCritSectEnter(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Try remove a Darwin URB from the free list, if none there allocate a new one.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX = pDevOsX->pFreeHead;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrbOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pFreeHead = pUrbOsX->pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCritSectLeave(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX = (PUSBPROXYURBOSX)RTMemAlloc(sizeof(*pUrbOsX));
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync if (!pUrbOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCritSectEnter(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pVUsbUrb = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pDevOsX = pDevOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->enmType = VUSBXFERTYPE_INVALID;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Link it into the active list
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pPrev = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pNext = pDevOsX->pInFlightHead;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrbOsX->pNext)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pNext->pPrev = pUrbOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pInFlightHead = pUrbOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCritSectLeave(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return pUrbOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifdef USE_LOW_LATENCY_API
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Allocates an low latency isochronous buffer.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns VBox status code.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pUrbOsX The OsX URB to allocate it for.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pIf The interface to allocated it from.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic int usbProxyDarwinUrbAllocIsocBuf(PUSBPROXYURBOSX pUrbOsX, PUSBPROXYIFOSX pIf)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync USBLowLatencyBufferType enmLLType = pUrbOsX->pVUsbUrb->enmDir == VUSBDIRECTION_IN
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync ? kUSBLowLatencyWriteBuffer : kUSBLowLatencyReadBuffer;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Walk the buffer collection list and look for an unused one.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.pBuf = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (PUSBPROXYISOCBUFCOL pCur = pIf->pIsocBufCols; pCur; pCur = pCur->pNext)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pCur->enmType == enmLLType)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pCur->aBuffers); i++)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (!pCur->aBuffers[i].fUsed)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pCur->aBuffers[i].fUsed = true;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.pBuf = &pCur->aBuffers[i];
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertPtr(pUrbOsX->u.Isoc.pBuf);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertPtr(pUrbOsX->u.Isoc.pBuf->pvBuf);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames = pCur->aBuffers[i].paFrames;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertPtr(pUrbOsX->u.Isoc.aFrames);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return VINF_SUCCESS;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Didn't find an empty one, create a new buffer collection and take the first buffer.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYISOCBUFCOL pNew = (PUSBPROXYISOCBUFCOL)RTMemAllocZ(sizeof(*pNew));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertReturn(pNew, VERR_NO_MEMORY);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOReturn irc = (*pIf->ppIfI)->LowLatencyCreateBuffer(pIf->ppIfI, &pNew->pvBuffer, 8192 * RT_ELEMENTS(pNew->aBuffers), enmLLType);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnSuccess != VALID_PTR(pNew->pvBuffer))
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertPtr(pNew->pvBuffer);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = kIOReturnNoMemory;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->LowLatencyCreateBuffer(pIf->ppIfI, &pNew->pvFrames, PAGE_SIZE, kUSBLowLatencyFrameListBuffer);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnSuccess != VALID_PTR(pNew->pvFrames))
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertPtr(pNew->pvFrames);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = kIOReturnNoMemory;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pNew->aBuffers); i++)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //pNew->aBuffers[i].fUsed = false;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pNew->aBuffers[i].paFrames = &((IOUSBLowLatencyIsocFrame *)pNew->pvFrames)[i * 8];
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pNew->aBuffers[i].pvBuf = (uint8_t *)pNew->pvBuffer + i * 8192;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pNew->aBuffers[0].fUsed = true;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames = pNew->aBuffers[0].paFrames;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.pBuf = &pNew->aBuffers[0];
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pNew->enmType = enmLLType;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pNew->pNext = pIf->pIsocBufCols;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->pIsocBufCols = pNew;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#if 0 /* doesn't help :-/ */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * If this is the first time we're here, try mess with the policy?
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (!pNew->pNext)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (unsigned iPipe = 0; iPipe < pIf->cPipes; iPipe++)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pIf->aPipes[iPipe].u8TransferType == kUSBIsoc)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->SetPipePolicy(pIf->ppIfI, pIf->aPipes[iPipe].u8PipeRef,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->aPipes[iPipe].u16MaxPacketSize, pIf->aPipes[iPipe].u8Interval);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertMsg(irc == kIOReturnSuccess, ("%#x\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return VINF_SUCCESS;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* bail out */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync (*pIf->ppIfI)->LowLatencyDestroyBuffer(pIf->ppIfI, pNew->pvBuffer);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertMsgFailed(("%#x\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTMemFree(pNew);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return RTErrConvertFromDarwin(irc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif /* USE_LOW_LATENCY_API */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Frees a Darwin URB request structure.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pDevOsX The darwin proxy device.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pUrbOsX The Darwin URB to free.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic void usbProxyDarwinUrbFree(PUSBPROXYDEVOSX pDevOsX, PUSBPROXYURBOSX pUrbOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCritSectEnter(&pDevOsX->CritSect);
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Remove from the active or taxing list.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrbOsX->pNext)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pNext->pPrev = pUrbOsX->pPrev;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else if (pDevOsX->pTaxingTail == pUrbOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pTaxingTail = pUrbOsX->pPrev;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrbOsX->pPrev)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pPrev->pNext = pUrbOsX->pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else if (pDevOsX->pTaxingHead == pUrbOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pTaxingHead = pUrbOsX->pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else if (pDevOsX->pInFlightHead == pUrbOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pInFlightHead = pUrbOsX->pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertFailed();
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifdef USE_LOW_LATENCY_API
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Free low latency stuff.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if ( pUrbOsX->enmType == VUSBXFERTYPE_ISOC
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync && pUrbOsX->u.Isoc.pBuf)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.pBuf->fUsed = false;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.pBuf = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Link it into the free list.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pPrev = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pNext = pDevOsX->pFreeHead;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pFreeHead = pUrbOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pVUsbUrb = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pDevOsX = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->enmType = VUSBXFERTYPE_INVALID;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCritSectLeave(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Translate the IOKit status code to a VUSB status.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns VUSB URB status code.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param irc IOKit status code.
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic VUSBSTATUS vusbProxyDarwinStatusToVUsbStatus(IOReturn irc)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync switch (irc)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* IOKit OHCI VUSB */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOReturnSuccess: /* 0 */ return VUSBSTATUS_OK;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOUSBCRCErr: /* 1 */ return VUSBSTATUS_CRC;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //case kIOUSBBitstufErr: /* 2 */ return VUSBSTATUS_;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //case kIOUSBDataToggleErr: /* 3 */ return VUSBSTATUS_;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOUSBPipeStalled: /* 4 */ return VUSBSTATUS_STALL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOReturnNotResponding: /* 5 */ return VUSBSTATUS_DNR;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //case kIOUSBPIDCheckErr: /* 6 */ return VUSBSTATUS_;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //case kIOUSBWrongPIDErr: /* 7 */ return VUSBSTATUS_;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOReturnOverrun: /* 8 */ return VUSBSTATUS_DATA_OVERRUN;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOReturnUnderrun: /* 9 */ return VUSBSTATUS_DATA_UNDERRUN;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //case kIOUSBReserved1Err: /* 10 */ return VUSBSTATUS_;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //case kIOUSBReserved2Err: /* 11 */ return VUSBSTATUS_;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //case kIOUSBBufferOverrunErr: /* 12 */ return VUSBSTATUS_;
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync //case kIOUSBBufferUnderrunErr: /* 13 */ return VUSBSTATUS_;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOUSBNotSent1Err: /* 14 */ return VUSBSTATUS_NOT_ACCESSED/*VUSBSTATUS_OK*/;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOUSBNotSent2Err: /* 15 */ return VUSBSTATUS_NOT_ACCESSED/*VUSBSTATUS_OK*/;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* Other errors */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync case kIOUSBTransactionTimeout: return VUSBSTATUS_DNR;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //case kIOReturnAborted: return VUSBSTATUS_CRC; - see on SET_INTERFACE...
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync default:
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Log(("vusbProxyDarwinStatusToVUsbStatus: irc=%#x!!\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return VUSBSTATUS_STALL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Completion callback for an async URB transfer.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pvUrbOsX The Darwin URB.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param irc The status of the operation.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param Size Possible the transfer size.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic void usbProxyDarwinUrbAsyncComplete(void *pvUrbOsX, IOReturn irc, void *Size)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYURBOSX pUrbOsX = (PUSBPROXYURBOSX)pvUrbOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYDEVOSX pDevOsX = pUrbOsX->pDevOsX;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync const uint32_t cb = (uintptr_t)Size;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCritSectEnter(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Do status updates.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PVUSBURB pUrb = pUrbOsX->pVUsbUrb;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrb)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Assert(pUrb->u32Magic == VUSBURB_MAGIC);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrb->enmType == VUSBXFERTYPE_ISOC)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifdef USE_LOW_LATENCY_API
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* copy the data. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync //if (pUrb->enmDir == VUSBDIRECTION_IN)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync memcpy(pUrb->abData, pUrbOsX->u.Isoc.pBuf->pvBuf, pUrb->cbData);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Log3(("AsyncComplete isoc - raw data (%d bytes):\n"
d4a8f6749f70bad88edc04de808643d372faa35avboxsync "%16.*Rhxd\n", pUrb->cbData, pUrb->cbData, pUrb->abData));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync uint32_t off = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
d4a8f6749f70bad88edc04de808643d372faa35avboxsync#ifdef USE_LOW_LATENCY_API
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Log2((" %d{%d/%d-%x-%RX64}", i, pUrbOsX->u.Isoc.aFrames[i].frActCount, pUrb->aIsocPkts[i].cb, pUrbOsX->u.Isoc.aFrames[i].frStatus,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RT_MAKE_U64(pUrbOsX->u.Isoc.aFrames[i].frTimeStamp.lo, pUrbOsX->u.Isoc.aFrames[i].frTimeStamp.hi) ));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Log2((" %d{%d/%d-%x}", i, pUrbOsX->u.Isoc.aFrames[i].frActCount, pUrb->aIsocPkts[i].cb, pUrbOsX->u.Isoc.aFrames[i].frStatus));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync pUrb->aIsocPkts[i].enmStatus = vusbProxyDarwinStatusToVUsbStatus(pUrbOsX->u.Isoc.aFrames[i].frStatus);
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrb->aIsocPkts[i].cb = pUrbOsX->u.Isoc.aFrames[i].frActCount;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync off += pUrbOsX->u.Isoc.aFrames[i].frActCount;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync }
d4a8f6749f70bad88edc04de808643d372faa35avboxsync Log2(("\n"));
d4a8f6749f70bad88edc04de808643d372faa35avboxsync#if 0 /** @todo revisit this, wasn't working previously. */
d4a8f6749f70bad88edc04de808643d372faa35avboxsync for (int i = (int)pUrb->cIsocPkts - 1; i >= 0; i--)
d4a8f6749f70bad88edc04de808643d372faa35avboxsync Assert( !pUrbOsX->u.Isoc.aFrames[i].frActCount
d4a8f6749f70bad88edc04de808643d372faa35avboxsync && !pUrbOsX->u.Isoc.aFrames[i].frReqCount
d4a8f6749f70bad88edc04de808643d372faa35avboxsync && !pUrbOsX->u.Isoc.aFrames[i].frStatus);
d4a8f6749f70bad88edc04de808643d372faa35avboxsync#endif
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrb->cbData = off; /* 'Size' seems to be pointing at an error code or something... */
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrb->enmStatus = VUSBSTATUS_OK; /* Don't use 'irc'. OHCI expects OK unless it's a really bad error. */
d4a8f6749f70bad88edc04de808643d372faa35avboxsync }
d4a8f6749f70bad88edc04de808643d372faa35avboxsync else
d4a8f6749f70bad88edc04de808643d372faa35avboxsync {
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrb->cbData = cb;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrb->enmStatus = vusbProxyDarwinStatusToVUsbStatus(irc);
d4a8f6749f70bad88edc04de808643d372faa35avboxsync if (pUrb->enmType == VUSBXFERTYPE_MSG)
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrb->cbData += sizeof(VUSBSETUP);
d4a8f6749f70bad88edc04de808643d372faa35avboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Remove from the active list.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrbOsX->pNext)
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync pUrbOsX->pNext->pPrev = pUrbOsX->pPrev;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync if (pUrbOsX->pPrev)
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrbOsX->pPrev->pNext = pUrbOsX->pNext;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync else
d4a8f6749f70bad88edc04de808643d372faa35avboxsync {
d4a8f6749f70bad88edc04de808643d372faa35avboxsync Assert(pDevOsX->pInFlightHead == pUrbOsX);
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pDevOsX->pInFlightHead = pUrbOsX->pNext;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync }
d4a8f6749f70bad88edc04de808643d372faa35avboxsync
d4a8f6749f70bad88edc04de808643d372faa35avboxsync /*
d4a8f6749f70bad88edc04de808643d372faa35avboxsync * Link it into the taxing list.
d4a8f6749f70bad88edc04de808643d372faa35avboxsync */
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrbOsX->pNext = NULL;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pUrbOsX->pPrev = pDevOsX->pTaxingTail;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync if (pDevOsX->pTaxingTail)
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pDevOsX->pTaxingTail->pNext = pUrbOsX;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync else
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pDevOsX->pTaxingHead = pUrbOsX;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync pDevOsX->pTaxingTail = pUrbOsX;
d4a8f6749f70bad88edc04de808643d372faa35avboxsync
d4a8f6749f70bad88edc04de808643d372faa35avboxsync RTCritSectLeave(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogFlow(("%s: usbProxyDarwinUrbAsyncComplete: cb=%d EndPt=%#x irc=%#x (%d)\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrb->pszDesc, cb, pUrb ? pUrb->EndPt : 0xff, irc, pUrb ? pUrb->enmStatus : 0xff));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
d4a8f6749f70bad88edc04de808643d372faa35avboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Release all interfaces (current config).
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
d4a8f6749f70bad88edc04de808643d372faa35avboxsync * @param pDevOsX The darwin proxy device.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic void usbProxyDarwinReleaseAllInterfaces(PUSBPROXYDEVOSX pDevOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYIFOSX pIf = pDevOsX->pIfHead;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pIfHead = pDevOsX->pIfTail = NULL;
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync while (pIf)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYIFOSX pNext = pIf->pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOReturn irc;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pIf->RunLoopSrcRef)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pIf->RunLoopSrcRef, g_pRunLoopMode);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRelease(pIf->RunLoopSrcRef);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->RunLoopSrcRef = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync while (pIf->pIsocBufCols)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYISOCBUFCOL pCur = pIf->pIsocBufCols;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->pIsocBufCols = pCur->pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pCur->pNext = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->LowLatencyDestroyBuffer(pIf->ppIfI, pCur->pvBuffer);
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync AssertMsg(irc == kIOReturnSuccess || irc == MACH_SEND_INVALID_DEST, ("%#x\n", irc));
a4b800433571901dfbe3fe952d6ddfe1a8be70b2vboxsync pCur->pvBuffer = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->LowLatencyDestroyBuffer(pIf->ppIfI, pCur->pvFrames);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertMsg(irc == kIOReturnSuccess || irc == MACH_SEND_INVALID_DEST, ("%#x\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pCur->pvFrames = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTMemFree(pCur);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->USBInterfaceClose(pIf->ppIfI);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertMsg(irc == kIOReturnSuccess || irc == kIOReturnNoDevice, ("%#x\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync (*pIf->ppIfI)->Release(pIf->ppIfI);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->ppIfI = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTMemFree(pIf);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf = pNext;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Get the properties all the pipes associated with an interface.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * This is used when we seize all the interface and after SET_INTERFACE.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns VBox status code.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pDevOsX The darwin proxy device.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pIf The interface to get pipe props for.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic int usbProxyDarwinGetPipeProperties(PUSBPROXYDEVOSX pDevOsX, PUSBPROXYIFOSX pIf)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Get the pipe (endpoint) count (it might have changed - even on open).
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync int rc = VINF_SUCCESS;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync UInt8 cPipes;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOReturn irc = (*pIf->ppIfI)->GetNumEndpoints(pIf->ppIfI, &cPipes);
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync if (irc != kIOReturnSuccess)
a4b800433571901dfbe3fe952d6ddfe1a8be70b2vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->cPipes = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnNoDevice)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VERR_VUSB_DEVICE_NOT_ATTACHED;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = RTErrConvertFromDarwin(irc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return rc;
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync }
a4b800433571901dfbe3fe952d6ddfe1a8be70b2vboxsync AssertRelease(cPipes < RT_ELEMENTS(pIf->aPipes));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->cPipes = cPipes + 1;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Get the properties of each pipe.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (unsigned i = 0; i < pIf->cPipes; i++)
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync {
a4b800433571901dfbe3fe952d6ddfe1a8be70b2vboxsync pIf->aPipes[i].u8PipeRef = i;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->aPipes[i].u64NextFrameNo = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->GetPipeProperties(pIf->ppIfI, i,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync &pIf->aPipes[i].u8Direction,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync &pIf->aPipes[i].u8Endpoint,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync &pIf->aPipes[i].u8TransferType,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync &pIf->aPipes[i].u16MaxPacketSize,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync &pIf->aPipes[i].u8Interval);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc != kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogRel(("USB: Failed to query properties for pipe %#d / interface %#x on device '%s'. (prot=%#x class=%#x)\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync i, pIf->u8Interface, pDevOsX->pProxyDev->pUsbIns->pszName, pIf->u8Protocol, pIf->u8Class));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnNoDevice)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VERR_VUSB_DEVICE_NOT_ATTACHED;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = RTErrConvertFromDarwin(irc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->cPipes = i;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync break;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* reconstruct bEndpoint */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pIf->aPipes[i].u8Direction == kUSBIn)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->aPipes[i].u8Endpoint |= 0x80;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Log2(("usbProxyDarwinGetPipeProperties: #If=%d EndPt=%#x Dir=%d Type=%d PipeRef=%#x MaxPktSize=%#x Interval=%#x\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->u8Interface, pIf->aPipes[i].u8Endpoint, pIf->aPipes[i].u8Direction, pIf->aPipes[i].u8TransferType,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pIf->aPipes[i].u8PipeRef, pIf->aPipes[i].u16MaxPacketSize, pIf->aPipes[i].u8Interval));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** @todo sort or hash these for speedy lookup... */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return VINF_SUCCESS;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Seize all interfaces (current config).
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns VBox status code.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pDevOsX The darwin proxy device.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param fMakeTheBestOfIt If set we will not give up on error. This is for
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * use during SET_CONFIGURATION and similar.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic int usbProxyDarwinSeizeAllInterfaces(PUSBPROXYDEVOSX pDevOsX, bool fMakeTheBestOfIt)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYDEV pProxyDev = pDevOsX->pProxyDev;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Create a interface enumerator for all the interface (current config).
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync io_iterator_t Interfaces = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOUSBFindInterfaceRequest Req;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Req.bInterfaceClass = kIOUSBFindInterfaceDontCare;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Req.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Req.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOReturn irc = (*pDevOsX->ppDevI)->CreateInterfaceIterator(pDevOsX->ppDevI, &Req, &Interfaces);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync int rc;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Iterate the interfaces.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync io_object_t Interface;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync rc = VINF_SUCCESS;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync while ((Interface = IOIteratorNext(Interfaces)))
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Create a plug-in and query the IOUSBInterfaceInterface (cute name).
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOCFPlugInInterface **ppPlugInInterface = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync kern_return_t krc;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync SInt32 Score = 0;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync krc = IOCreatePlugInInterfaceForService(Interface, kIOUSBInterfaceUserClientTypeID,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync kIOCFPlugInInterfaceID, &ppPlugInInterface, &Score);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOObjectRelease(Interface);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync Interface = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (krc == KERN_SUCCESS)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOUSBInterfaceInterface245 **ppIfI;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync HRESULT hrc = (*ppPlugInInterface)->QueryInterface(ppPlugInInterface,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID245),
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync (LPVOID *)&ppIfI);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync krc = IODestroyPlugInInterface(ppPlugInInterface); Assert(krc == KERN_SUCCESS);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync ppPlugInInterface = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (hrc == S_OK)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * Query some basic properties first.
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * (This means we can print more informative messages on failure
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * to seize the interface.)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync */
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync UInt8 u8Interface = 0xff;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync irc = (*ppIfI)->GetInterfaceNumber(ppIfI, &u8Interface);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync UInt8 u8AltSetting = 0xff;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (irc == kIOReturnSuccess)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync irc = (*ppIfI)->GetAlternateSetting(ppIfI, &u8AltSetting);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync UInt8 u8Class = 0xff;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (irc == kIOReturnSuccess)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync irc = (*ppIfI)->GetInterfaceClass(ppIfI, &u8Class);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync UInt8 u8Protocol = 0xff;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (irc == kIOReturnSuccess)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync irc = (*ppIfI)->GetInterfaceProtocol(ppIfI, &u8Protocol);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync UInt8 cEndpoints = 0;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (irc == kIOReturnSuccess)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync irc = (*ppIfI)->GetNumEndpoints(ppIfI, &cEndpoints);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (irc == kIOReturnSuccess)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync {
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync /*
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * Try seize the interface.
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync */
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync irc = (*ppIfI)->USBInterfaceOpenSeize(ppIfI);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (irc == kIOReturnSuccess)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync {
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync PUSBPROXYIFOSX pIf = (PUSBPROXYIFOSX)RTMemAllocZ(sizeof(*pIf));
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (pIf)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync {
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync /*
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * Create the per-interface entry and query the
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * endpoint data.
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync */
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync /* initialize the entry */
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pIf->u8Interface = u8Interface;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pIf->u8AltSetting = u8AltSetting;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pIf->u8Class = u8Class;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pIf->u8Protocol = u8Protocol;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pIf->cPipes = cEndpoints;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pIf->ppIfI = ppIfI;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync /* query pipe/endpoint properties. */
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync rc = usbProxyDarwinGetPipeProperties(pDevOsX, pIf);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (RT_SUCCESS(rc))
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync {
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync /*
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * Create the async event source and add it to the
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * default current run loop.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * (Later: Add to the worker thread run loop instead.)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*ppIfI)->CreateInterfaceAsyncEventSource(ppIfI, &pIf->RunLoopSrcRef);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRunLoopAddSource(pDevOsX->RunLoopRef, pIf->RunLoopSrcRef, g_pRunLoopMode);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync /*
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync * Just link the interface into the list and we're good.
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync */
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pIf->pNext = NULL;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync Log(("USB: Seized interface %#x (alt=%d prot=%#x class=%#x)\n",
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync u8Interface, u8AltSetting, u8Protocol, u8Class));
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync if (pDevOsX->pIfTail)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pDevOsX->pIfTail = pDevOsX->pIfTail->pNext = pIf;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync else
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync pDevOsX->pIfTail = pDevOsX->pIfHead = pIf;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync continue;
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync }
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync rc = RTErrConvertFromDarwin(irc);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync }
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync /* failure cleanup. */
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync RTMemFree(pIf);
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync }
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync }
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync else if (irc == kIOReturnExclusiveAccess)
374f0b5fc4e70777b3f9ad8586ad7aa2551f37ccvboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogRel(("USB: Interface %#x on device '%s' is being used by another process. (prot=%#x class=%#x)\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync u8Interface, pProxyDev->pUsbIns->pszName, u8Protocol, u8Class));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VERR_SHARING_VIOLATION;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
a8c0cd113e4c194efbc13ef339c7f79137d6dd3bvboxsync LogRel(("USB: Failed to open interface %#x on device '%s'. (prot=%#x class=%#x) krc=%#x\n",
a8c0cd113e4c194efbc13ef339c7f79137d6dd3bvboxsync u8Interface, pProxyDev->pUsbIns->pszName, u8Protocol, u8Class, irc));
a8c0cd113e4c194efbc13ef339c7f79137d6dd3bvboxsync rc = VERR_OPEN_FAILED;
a8c0cd113e4c194efbc13ef339c7f79137d6dd3bvboxsync }
a8c0cd113e4c194efbc13ef339c7f79137d6dd3bvboxsync }
a8c0cd113e4c194efbc13ef339c7f79137d6dd3bvboxsync else
a8c0cd113e4c194efbc13ef339c7f79137d6dd3bvboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = RTErrConvertFromDarwin(irc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogRel(("USB: Failed to query interface properties on device '%s', irc=%#x.\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pProxyDev->pUsbIns->pszName, irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync (*ppIfI)->Release(ppIfI);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync ppIfI = NULL;
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync }
a4b800433571901dfbe3fe952d6ddfe1a8be70b2vboxsync else if (RT_SUCCESS(rc))
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = RTErrConvertFromDarwinCOM(hrc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else if (RT_SUCCESS(rc))
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = RTErrConvertFromDarwin(krc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (!fMakeTheBestOfIt)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync usbProxyDarwinReleaseAllInterfaces(pDevOsX);
a4b800433571901dfbe3fe952d6ddfe1a8be70b2vboxsync break;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync } /* iterate */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOObjectRelease(Interfaces);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else if (irc == kIOReturnNoDevice)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VERR_VUSB_DEVICE_NOT_ATTACHED;
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertMsgFailed(("%#x\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VERR_GENERAL_FAILURE;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return rc;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Find a particular interface.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns The requested interface or NULL if not found.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pDevOsX The darwin proxy device.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param u8Interface The interface number.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic PUSBPROXYIFOSX usbProxyDarwinGetInterface(PUSBPROXYDEVOSX pDevOsX, uint8_t u8Interface)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (!pDevOsX->pIfHead)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync usbProxyDarwinSeizeAllInterfaces(pDevOsX, true /* make the best out of it */);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYIFOSX pIf;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (pIf = pDevOsX->pIfHead; pIf; pIf = pIf->pNext)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pIf->u8Interface == u8Interface)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return pIf;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/* AssertMsgFailed(("Cannot find If#=%d\n", u8Interface)); - the 3rd quickcam interface is capture by the ****ing audio crap. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Find a particular endpoint.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns The requested interface or NULL if not found.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pDevOsX The darwin proxy device.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param u8Endpoint The endpoint.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pu8PipeRef Where to store the darwin pipe ref.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * @param ppPipe Where to store the darwin pipe pointer. (optional)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsyncstatic PUSBPROXYIFOSX usbProxyDarwinGetInterfaceForEndpoint(PUSBPROXYDEVOSX pDevOsX, uint8_t u8Endpoint,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync uint8_t *pu8PipeRef, PPUSBPROXYPIPEOSX ppPipe)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync{
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (!pDevOsX->pIfHead)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinSeizeAllInterfaces(pDevOsX, true /* make the best out of it */);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync PUSBPROXYIFOSX pIf;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync for (pIf = pDevOsX->pIfHead; pIf; pIf = pIf->pNext)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync unsigned i = pIf->cPipes;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync while (i-- > 0)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pIf->aPipes[i].u8Endpoint == u8Endpoint)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *pu8PipeRef = pIf->aPipes[i].u8PipeRef;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (ppPipe)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *ppPipe = &pIf->aPipes[i];
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return pIf;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertMsgFailed(("Cannot find EndPt=%#x\n", u8Endpoint));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Gets an unsigned 32-bit integer value.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns Success indicator (true/false).
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param DictRef The dictionary.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param KeyStrRef The key name.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pu32 Where to store the key value.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic bool usbProxyDarwinDictGetU32(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint32_t *pu32)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (ValRef)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt32Type, pu32))
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return true;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync *pu32 = 0;
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync return false;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync/**
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync * Gets an unsigned 64-bit integer value.
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync *
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync * @returns Success indicator (true/false).
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync * @param DictRef The dictionary.
f6f5b68ebbb3a264e0a27e2a5848774722fccfd2vboxsync * @param KeyStrRef The key name.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pu64 Where to store the key value.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic bool usbProxyDarwinDictGetU64(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint64_t *pu64)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (ValRef)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt64Type, pu64))
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync return true;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync *pu64 = 0;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync return false;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync}
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync/* -=-=-=-=-=- The exported methods -=-=-=-=-=- */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync/**
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * Opens the USB Device.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync *
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * @returns VBox status code.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * @param pProxyDev The device instance.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * @param pszAddress The session id and/or location id of the device to open.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * The format of this string is something iokit.c in Main defines, currently
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * it's sequences of "[l|s]=<value>" separated by ";".
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * @param pvBackend Backend specific pointer, unused for the Darwin backend.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsyncstatic int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend)
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync{
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync int vrc;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync LogFlow(("usbProxyDarwinOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress));
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync /*
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * Init globals once.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync vrc = RTOnce(&g_usbProxyDarwinOnce, usbProxyDarwinInitOnce, NULL, NULL);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync AssertRCReturn(vrc, vrc);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync /*
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * The idea here was to create a matching directory with the sessionID
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * and locationID included, however this doesn't seem to work. So, we'll
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * use the product id and vendor id to limit the set of matching device
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * and manually match these two properties. sigh.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * (Btw. vendor and product id must be used *together* apparently.)
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync *
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * Wonder if we could use the entry path? Docs indicates says we must
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * use IOServiceGetMatchingServices and I'm not in a mood to explore
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * this subject further right now. Maybe check this later.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync CFMutableDictionaryRef RefMatchingDict = IOServiceMatching(kIOUSBDeviceClassName);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertReturn(RefMatchingDict, NULL);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync uint64_t u64SessionId = 0;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync uint32_t u32LocationId = 0;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync const char *psz = pszAddress;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync do
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync const char chValue = *psz;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync AssertReleaseReturn(psz[1] == '=', VERR_INTERNAL_ERROR);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync uint64_t u64Value;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync int rc = RTStrToUInt64Ex(psz + 2, (char **)&psz, 0, &u64Value);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync AssertReleaseRCReturn(rc, rc);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync AssertReleaseReturn(!*psz || *psz == ';', rc);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync switch (chValue)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync case 'l':
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync u32LocationId = (uint32_t)u64Value;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync break;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync case 's':
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync u64SessionId = u64Value;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync break;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync case 'p':
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync case 'v':
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync#if 0 /* Guess what, this doesn't 'ing work either! */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync SInt32 i32 = (int16_t)u64Value;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFNumberRef Num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i32);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync AssertBreak(Num);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFDictionarySetValue(RefMatchingDict, chValue == 'p' ? CFSTR(kUSBProductID) : CFSTR(kUSBVendorID), Num);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFRelease(Num);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync#endif
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync break;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync default:
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync AssertReleaseMsgFailedReturn(("chValue=%#x\n", chValue), VERR_INTERNAL_ERROR);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (*psz == ';')
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync psz++;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync } while (*psz);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync io_iterator_t USBDevices = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOReturn irc = IOServiceGetMatchingServices(g_MasterPort, RefMatchingDict, &USBDevices);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync AssertMsgReturn(irc == kIOReturnSuccess, ("irc=%#x\n", irc), NULL);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync RefMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync unsigned cMatches = 0;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync io_object_t USBDevice;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync while ((USBDevice = IOIteratorNext(USBDevices)))
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync cMatches++;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFMutableDictionaryRef PropsRef = 0;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync kern_return_t krc = IORegistryEntryCreateCFProperties(USBDevice, &PropsRef, kCFAllocatorDefault, kNilOptions);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (krc == KERN_SUCCESS)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync uint64_t u64CurSessionId;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync uint32_t u32CurLocationId;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if ( ( !u64SessionId
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync || ( usbProxyDarwinDictGetU64(PropsRef, CFSTR("sessionID"), &u64CurSessionId)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync && u64CurSessionId == u64SessionId))
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync && ( !u32LocationId
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync || ( usbProxyDarwinDictGetU32(PropsRef, CFSTR(kUSBDevicePropertyLocationID), &u32CurLocationId)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync && u32CurLocationId == u32LocationId))
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync )
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFRelease(PropsRef);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync break;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFRelease(PropsRef);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOObjectRelease(USBDevice);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOObjectRelease(USBDevices);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync USBDevices = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (!USBDevice)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync LogRel(("USB: Device '%s' not found (%d pid+vid matches)\n", pszAddress, cMatches));
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOObjectRelease(USBDevices);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return VERR_VUSB_DEVICE_NAME_NOT_FOUND;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Call the USBLib init to make sure we're a valid VBoxUSB client.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * For now we'll ignore failures here and just plunge on, it might still work...
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync vrc = USBLibInit();
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (RT_FAILURE(vrc))
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync LogRel(("USB: USBLibInit failed - %Rrc\n", vrc));
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync#endif
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Create a plugin interface for the device and query its IOUSBDeviceInterface.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync SInt32 Score = 0;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOCFPlugInInterface **ppPlugInInterface = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync irc = IOCreatePlugInInterfaceForService(USBDevice, kIOUSBDeviceUserClientTypeID,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync kIOCFPlugInInterfaceID, &ppPlugInInterface, &Score);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (irc == kIOReturnSuccess)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOUSBDeviceInterface245 **ppDevI = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync HRESULT hrc = (*ppPlugInInterface)->QueryInterface(ppPlugInInterface,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID245),
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync (LPVOID *)&ppDevI);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync irc = IODestroyPlugInInterface(ppPlugInInterface); Assert(irc == kIOReturnSuccess);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync ppPlugInInterface = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (hrc == S_OK)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Try open the device for exclusive access.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * If we fail, we'll try figure out who is using the device and
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * convince them to let go of it...
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync irc = (*ppDevI)->USBDeviceOpenSeize(ppDevI);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (irc == kIOReturnExclusiveAccess)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync RTThreadSleep(20);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync irc = (*ppDevI)->USBDeviceOpenSeize(ppDevI);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (irc == kIOReturnSuccess)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Create a proxy device instance.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync vrc = VERR_NO_MEMORY;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)RTMemAllocZ(sizeof(*pDevOsX));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pDevOsX)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync vrc = RTCritSectInit(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (RT_SUCCESS(vrc))
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->USBDevice = USBDevice;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->ppDevI = ppDevI;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pProxyDev = pProxyDev;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->RunLoopRef = CFRunLoopGetCurrent();
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRetain(pDevOsX->RunLoopRef); /* paranoia */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync /*
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * Try seize all the interface.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync char *pszDummyName = pProxyDev->pUsbIns->pszName;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync pProxyDev->pUsbIns->pszName = (char *)pszAddress;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync vrc = usbProxyDarwinSeizeAllInterfaces(pDevOsX, false /* give up on failure */);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync pProxyDev->pUsbIns->pszName = pszDummyName;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync if (RT_SUCCESS(vrc))
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync {
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync /*
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * Create the async event source and add it to the run loop.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync irc = (*ppDevI)->CreateDeviceAsyncEventSource(ppDevI, &pDevOsX->RunLoopSrcRef);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync if (irc == kIOReturnSuccess)
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync {
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync CFRunLoopAddSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync /*
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * Determin the active configuration.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync * Can cause hangs, so drop it for now.
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync /** @todo test Palm. */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync //uint8_t u8Cfg;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync //irc = (*ppDevI)->GetConfiguration(ppDevI, &u8Cfg);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync if (irc != kIOReturnNoDevice)
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync {
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync //pProxyDev->iActiveCfg = irc == kIOReturnSuccess ? u8Cfg : -1;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync pProxyDev->iActiveCfg = -1;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync pProxyDev->cIgnoreSetConfigs = 1;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync pProxyDev->Backend.pv = pDevOsX;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync return VINF_SUCCESS; /* return */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync }
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync vrc = VERR_VUSB_DEVICE_NOT_ATTACHED;
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync }
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync else
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync vrc = RTErrConvertFromDarwin(irc);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync usbProxyDarwinReleaseAllInterfaces(pDevOsX);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync }
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync /* else: already bitched */
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync RTCritSectDelete(&pDevOsX->CritSect);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync }
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync RTMemFree(pDevOsX);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync }
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync irc = (*ppDevI)->USBDeviceClose(ppDevI);
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync AssertMsg(irc == kIOReturnSuccess, ("%#x\n", irc));
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync }
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync else if (irc == kIOReturnExclusiveAccess)
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync {
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync LogRel(("USB: Device '%s' is being used by another process\n", pszAddress));
324e9d5fe84f23a35c4feb6853ed3ee9b3b1fad9vboxsync vrc = VERR_SHARING_VIOLATION;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogRel(("USB: Failed to open device '%s', irc=%#x.\n", pszAddress, irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync vrc = VERR_OPEN_FAILED;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogRel(("USB: Failed to create plugin interface for device '%s', hrc=%#x.\n", pszAddress, hrc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync vrc = VERR_OPEN_FAILED;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync (*ppDevI)->Release(ppDevI);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogRel(("USB: Failed to open device '%s', plug-in creation failed with irc=%#x.\n", pszAddress, irc));
7dfd3f41f200bede0714c89735d9cc8d310e3f1cvboxsync vrc = RTErrConvertFromDarwin(irc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync USBLibTerm();
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return vrc;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
7dfd3f41f200bede0714c89735d9cc8d310e3f1cvboxsync/**
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Closes the proxy device.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic void usbProxyDarwinClose(PUSBPROXYDEV pProxyDev)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogFlow(("usbProxyDarwinClose: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)pProxyDev->Backend.pv;
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync Assert(pDevOsX);
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync if (!pDevOsX)
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync return;
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync /*
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync * Release interfaces we've laid claim to, then reset the device
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync * and finally close it.
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync */
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync RTCritSectEnter(&pDevOsX->CritSect);
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync /* ?? */
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync RTCritSectLeave(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync usbProxyDarwinReleaseAllInterfaces(pDevOsX);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pDevOsX->RunLoopSrcRef)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync CFRelease(pDevOsX->RunLoopSrcRef);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->RunLoopSrcRef = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOReturn irc = (*pDevOsX->ppDevI)->ResetDevice(pDevOsX->ppDevI);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync if (irc == kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pDevOsX->ppDevI)->USBDeviceReEnumerate(pDevOsX->ppDevI, 0);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pDevOsX->ppDevI)->USBDeviceClose(pDevOsX->ppDevI);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc != kIOReturnSuccess && irc != kIOReturnNoDevice)
7dfd3f41f200bede0714c89735d9cc8d310e3f1cvboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogRel(("USB: USBDeviceClose -> %#x\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertMsgFailed(("irc=%#x\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync (*pDevOsX->ppDevI)->Release(pDevOsX->ppDevI);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->ppDevI = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync kern_return_t krc = IOObjectRelease(pDevOsX->USBDevice); Assert(krc == KERN_SUCCESS); NOREF(krc);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->USBDevice = NULL;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pDevOsX->pProxyDev = NULL;
7dfd3f41f200bede0714c89735d9cc8d310e3f1cvboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Free all the resources.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync RTCritSectDelete(&pDevOsX->CritSect);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pDevOsX->RunLoopRef)
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync {
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync CFRelease(pDevOsX->RunLoopRef);
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync pDevOsX->RunLoopRef = NULL;
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync }
7dfd3f41f200bede0714c89735d9cc8d310e3f1cvboxsync
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync PUSBPROXYURBOSX pUrbOsX;
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync while ((pUrbOsX = pDevOsX->pInFlightHead) != NULL)
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync {
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync pDevOsX->pInFlightHead = pUrbOsX->pNext;
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync //RTMemFree(pUrbOsX); - leak these for now, fix later.
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync }
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync while ((pUrbOsX = pDevOsX->pFreeHead) != NULL)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync pDevOsX->pFreeHead = pUrbOsX->pNext;
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync RTMemFree(pUrbOsX);
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync }
7dfd3f41f200bede0714c89735d9cc8d310e3f1cvboxsync
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync RTMemFree(pDevOsX);
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync pProxyDev->Backend.pv = NULL;
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync USBLibTerm();
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync#endif
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync LogFlow(("usbProxyDarwinClose: returns\n"));
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync}
7dfd3f41f200bede0714c89735d9cc8d310e3f1cvboxsync
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync/**
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync * Reset a device.
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync *
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @returns VBox status code.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pDev The device to reset.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic int usbProxyDarwinReset(PUSBPROXYDEV pProxyDev, bool fResetOnLinux)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)pProxyDev->Backend.pv;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogFlow(("usbProxyDarwinReset: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync IOReturn irc = (*pDevOsX->ppDevI)->ResetDevice(pDevOsX->ppDevI);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync int rc;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /** @todo Some docs say that some drivers will do a default config, check this out ... */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pProxyDev->cIgnoreSetConfigs = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pProxyDev->iActiveCfg = -1;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync rc = VINF_SUCCESS;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync else if (irc == kIOReturnNoDevice)
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync rc = VERR_VUSB_DEVICE_NOT_ATTACHED;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync {
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync AssertMsgFailed(("irc=%#x\n", irc));
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync rc = VERR_GENERAL_FAILURE;
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync }
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync LogFlow(("usbProxyDarwinReset: returns success %Rrc\n", rc));
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync return rc;
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
b7640e1373d7f1eeaf6e0efd5ec8690432048342vboxsync
b7640e1373d7f1eeaf6e0efd5ec8690432048342vboxsync/**
b7640e1373d7f1eeaf6e0efd5ec8690432048342vboxsync * SET_CONFIGURATION.
b7640e1373d7f1eeaf6e0efd5ec8690432048342vboxsync *
b7640e1373d7f1eeaf6e0efd5ec8690432048342vboxsync * The caller makes sure that it's not called first time after open or reset
b7640e1373d7f1eeaf6e0efd5ec8690432048342vboxsync * with the active interface.
b7640e1373d7f1eeaf6e0efd5ec8690432048342vboxsync *
b7640e1373d7f1eeaf6e0efd5ec8690432048342vboxsync * @returns success indicator.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param pProxyDev The device instance data.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * @param iCfg The configuration to set.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsyncstatic int usbProxyDarwinSetConfig(PUSBPROXYDEV pProxyDev, int iCfg)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync{
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)pProxyDev->Backend.pv;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogFlow(("usbProxyDarwinSetConfig: pProxyDev=%s cfg=%#x\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pProxyDev->pUsbIns->pszName, iCfg));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOReturn irc = (*pDevOsX->ppDevI)->SetConfiguration(pDevOsX->ppDevI, (uint8_t)iCfg);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (irc != kIOReturnSuccess)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Log(("usbProxyDarwinSetConfig: Set configuration -> %#x\n", irc));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return false;
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync usbProxyDarwinReleaseAllInterfaces(pDevOsX);
a13bd47f22085c82960265c150f10f2195369630vboxsync usbProxyDarwinSeizeAllInterfaces(pDevOsX, true /* make the best out of it */);
a13bd47f22085c82960265c150f10f2195369630vboxsync return true;
a13bd47f22085c82960265c150f10f2195369630vboxsync}
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync/**
a13bd47f22085c82960265c150f10f2195369630vboxsync * Claims an interface.
ea4433aedd4105e6599e57e0c5f6cb32a68e963cvboxsync *
a13bd47f22085c82960265c150f10f2195369630vboxsync * This is a stub on Darwin since we release/claim all interfaces at
a13bd47f22085c82960265c150f10f2195369630vboxsync * open/reset/setconfig time.
a13bd47f22085c82960265c150f10f2195369630vboxsync *
a13bd47f22085c82960265c150f10f2195369630vboxsync * @returns success indicator (always true).
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsyncstatic int usbProxyDarwinClaimInterface(PUSBPROXYDEV pProxyDev, int iIf)
a13bd47f22085c82960265c150f10f2195369630vboxsync{
a13bd47f22085c82960265c150f10f2195369630vboxsync return true;
a13bd47f22085c82960265c150f10f2195369630vboxsync}
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync/**
a13bd47f22085c82960265c150f10f2195369630vboxsync * Releases an interface.
a13bd47f22085c82960265c150f10f2195369630vboxsync *
a13bd47f22085c82960265c150f10f2195369630vboxsync * This is a stub on Darwin since we release/claim all interfaces at
a13bd47f22085c82960265c150f10f2195369630vboxsync * open/reset/setconfig time.
a13bd47f22085c82960265c150f10f2195369630vboxsync *
a13bd47f22085c82960265c150f10f2195369630vboxsync * @returns success indicator.
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsyncstatic int usbProxyDarwinReleaseInterface(PUSBPROXYDEV pProxyDev, int iIf)
a13bd47f22085c82960265c150f10f2195369630vboxsync{
a13bd47f22085c82960265c150f10f2195369630vboxsync return true;
a13bd47f22085c82960265c150f10f2195369630vboxsync}
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync/**
a13bd47f22085c82960265c150f10f2195369630vboxsync * SET_INTERFACE.
a13bd47f22085c82960265c150f10f2195369630vboxsync *
a13bd47f22085c82960265c150f10f2195369630vboxsync * @returns success indicator.
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsyncstatic int usbProxyDarwinSetInterface(PUSBPROXYDEV pProxyDev, int iIf, int iAlt)
a13bd47f22085c82960265c150f10f2195369630vboxsync{
a13bd47f22085c82960265c150f10f2195369630vboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)pProxyDev->Backend.pv;
a13bd47f22085c82960265c150f10f2195369630vboxsync IOReturn irc = kIOReturnSuccess;
a13bd47f22085c82960265c150f10f2195369630vboxsync PUSBPROXYIFOSX pIf = usbProxyDarwinGetInterface(pDevOsX, iIf);
a13bd47f22085c82960265c150f10f2195369630vboxsync LogFlow(("usbProxyDarwinSetInterface: pProxyDev=%s iIf=%#x iAlt=%#x iCurAlt=%#x\n",
a13bd47f22085c82960265c150f10f2195369630vboxsync pProxyDev->pUsbIns->pszName, iIf, iAlt, pIf ? pIf->u8AltSetting : 0xbeef));
a13bd47f22085c82960265c150f10f2195369630vboxsync if (pIf)
a13bd47f22085c82960265c150f10f2195369630vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync /* Avoid SetAlternateInterface when possible as it will recreate the pipes. */
a13bd47f22085c82960265c150f10f2195369630vboxsync if (iAlt != pIf->u8AltSetting)
a13bd47f22085c82960265c150f10f2195369630vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync irc = (*pIf->ppIfI)->SetAlternateInterface(pIf->ppIfI, iAlt);
a13bd47f22085c82960265c150f10f2195369630vboxsync if (irc == kIOReturnSuccess)
a13bd47f22085c82960265c150f10f2195369630vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync usbProxyDarwinGetPipeProperties(pDevOsX, pIf);
a13bd47f22085c82960265c150f10f2195369630vboxsync return true;
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync else
a13bd47f22085c82960265c150f10f2195369630vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync /*
a13bd47f22085c82960265c150f10f2195369630vboxsync * Just send the request anyway?
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsync IOUSBDevRequest Req;
a13bd47f22085c82960265c150f10f2195369630vboxsync Req.bmRequestType = 0x01;
a13bd47f22085c82960265c150f10f2195369630vboxsync Req.bRequest = 0x0b; /* SET_INTERFACE */
a13bd47f22085c82960265c150f10f2195369630vboxsync Req.wIndex = iIf;
a13bd47f22085c82960265c150f10f2195369630vboxsync Req.wValue = iAlt;
a13bd47f22085c82960265c150f10f2195369630vboxsync Req.wLength = 0;
a13bd47f22085c82960265c150f10f2195369630vboxsync Req.wLenDone = 0;
a13bd47f22085c82960265c150f10f2195369630vboxsync Req.pData = NULL;
a13bd47f22085c82960265c150f10f2195369630vboxsync irc = (*pDevOsX->ppDevI)->DeviceRequest(pDevOsX->ppDevI, &Req);
a13bd47f22085c82960265c150f10f2195369630vboxsync Log(("usbProxyDarwinSetInterface: SET_INTERFACE(%d,%d) -> irc=%#x\n", iIf, iAlt, irc));
a13bd47f22085c82960265c150f10f2195369630vboxsync return true;
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync LogFlow(("usbProxyDarwinSetInterface: pProxyDev=%s eiIf=%#x iAlt=%#x - failure - pIf=%p irc=%#x\n",
a13bd47f22085c82960265c150f10f2195369630vboxsync pProxyDev->pUsbIns->pszName, iIf, iAlt, pIf, irc));
a13bd47f22085c82960265c150f10f2195369630vboxsync return false;
a13bd47f22085c82960265c150f10f2195369630vboxsync}
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync/**
a13bd47f22085c82960265c150f10f2195369630vboxsync * Clears the halted endpoint 'EndPt'.
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsyncstatic bool usbProxyDarwinClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int EndPt)
a13bd47f22085c82960265c150f10f2195369630vboxsync{
a13bd47f22085c82960265c150f10f2195369630vboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)pProxyDev->Backend.pv;
a13bd47f22085c82960265c150f10f2195369630vboxsync LogFlow(("usbProxyDarwinClearHaltedEp: pProxyDev=%s EndPt=%#x\n", pProxyDev->pUsbIns->pszName, EndPt));
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync /*
a13bd47f22085c82960265c150f10f2195369630vboxsync * Clearing the zero control pipe doesn't make sense and isn't
a13bd47f22085c82960265c150f10f2195369630vboxsync * supported by the API. Just ignore it.
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsync if (EndPt == 0)
a13bd47f22085c82960265c150f10f2195369630vboxsync return true;
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync /*
a13bd47f22085c82960265c150f10f2195369630vboxsync * Find the interface/pipe combination and invoke the ClearPipeStallBothEnds
a13bd47f22085c82960265c150f10f2195369630vboxsync * method. (The ResetPipe and ClearPipeStall methods will not send the
a13bd47f22085c82960265c150f10f2195369630vboxsync * CLEAR_FEATURE(ENDPOINT_HALT) request that this method implements.)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsync IOReturn irc = kIOReturnSuccess;
a13bd47f22085c82960265c150f10f2195369630vboxsync uint8_t u8PipeRef;
a13bd47f22085c82960265c150f10f2195369630vboxsync PUSBPROXYIFOSX pIf = usbProxyDarwinGetInterfaceForEndpoint(pDevOsX, EndPt, &u8PipeRef, NULL);
a13bd47f22085c82960265c150f10f2195369630vboxsync if (pIf)
a13bd47f22085c82960265c150f10f2195369630vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync irc = (*pIf->ppIfI)->ClearPipeStallBothEnds(pIf->ppIfI, u8PipeRef);
a13bd47f22085c82960265c150f10f2195369630vboxsync if (irc == kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync return true;
a13bd47f22085c82960265c150f10f2195369630vboxsync AssertMsg(irc == kIOReturnNoDevice || irc == kIOReturnNotResponding, ("irc=#x (control pipe?)\n", irc));
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync LogFlow(("usbProxyDarwinClearHaltedEp: pProxyDev=%s EndPt=%#x - failure - pIf=%p irc=%#x\n",
a13bd47f22085c82960265c150f10f2195369630vboxsync pProxyDev->pUsbIns->pszName, EndPt, pIf, irc));
a13bd47f22085c82960265c150f10f2195369630vboxsync return false;
a13bd47f22085c82960265c150f10f2195369630vboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync/**
a13bd47f22085c82960265c150f10f2195369630vboxsync * @copydoc USBPROXYBACK::pfnUrbQueue
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsyncstatic int usbProxyDarwinUrbQueue(PVUSBURB pUrb)
a13bd47f22085c82960265c150f10f2195369630vboxsync{
a13bd47f22085c82960265c150f10f2195369630vboxsync PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)pProxyDev->Backend.pv;
a13bd47f22085c82960265c150f10f2195369630vboxsync LogFlow(("%s: usbProxyDarwinUrbQueue: pProxyDev=%s pUrb=%p EndPt=%d cbData=%d\n",
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb, pUrb->EndPt, pUrb->cbData));
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync /*
a13bd47f22085c82960265c150f10f2195369630vboxsync * Find the target interface / pipe.
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsync uint8_t u8PipeRef = 0xff;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync PUSBPROXYIFOSX pIf = NULL;
a13bd47f22085c82960265c150f10f2195369630vboxsync PUSBPROXYPIPEOSX pPipe = NULL;
a13bd47f22085c82960265c150f10f2195369630vboxsync if (pUrb->EndPt)
a13bd47f22085c82960265c150f10f2195369630vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync const uint8_t EndPt = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0);
a13bd47f22085c82960265c150f10f2195369630vboxsync pIf = usbProxyDarwinGetInterfaceForEndpoint(pDevOsX, EndPt, &u8PipeRef, &pPipe);
a13bd47f22085c82960265c150f10f2195369630vboxsync if (!pIf)
a13bd47f22085c82960265c150f10f2195369630vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync LogFlow(("%s: usbProxyDarwinUrbQueue: pProxyDev=%s EndPt=%d cbData=%d - can't find interface / pipe!!!\n",
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb->EndPt, pUrb->cbData));
a13bd47f22085c82960265c150f10f2195369630vboxsync return false;
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync /* else: pIf == NULL -> default control pipe.*/
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync /*
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync * Allocate a Darwin urb.
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsync PUSBPROXYURBOSX pUrbOsX = usbProxyDarwinUrbAlloc(pDevOsX);
a13bd47f22085c82960265c150f10f2195369630vboxsync if (!pUrbOsX)
a13bd47f22085c82960265c150f10f2195369630vboxsync return false;
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->u64SubmitTS = RTTimeMilliTS();
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->pVUsbUrb = pUrb;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->pDevOsX = pDevOsX;
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->enmType = pUrb->enmType;
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync /*
a13bd47f22085c82960265c150f10f2195369630vboxsync * Submit the request.
a13bd47f22085c82960265c150f10f2195369630vboxsync */
a13bd47f22085c82960265c150f10f2195369630vboxsync IOReturn irc = kIOReturnError;
a13bd47f22085c82960265c150f10f2195369630vboxsync switch (pUrb->enmType)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync case VUSBXFERTYPE_MSG:
a13bd47f22085c82960265c150f10f2195369630vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync AssertMsgBreak(pUrb->cbData >= sizeof(VUSBSETUP), ("cbData=%d\n", pUrb->cbData));
a13bd47f22085c82960265c150f10f2195369630vboxsync PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->u.ControlMsg.bmRequestType = pSetup->bmRequestType;
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->u.ControlMsg.bRequest = pSetup->bRequest;
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->u.ControlMsg.wValue = pSetup->wValue;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.ControlMsg.wIndex = pSetup->wIndex;
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->u.ControlMsg.wLength = pSetup->wLength;
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->u.ControlMsg.pData = pSetup + 1;
a13bd47f22085c82960265c150f10f2195369630vboxsync pUrbOsX->u.ControlMsg.wLenDone = pSetup->wLength;
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync if (pIf)
a13bd47f22085c82960265c150f10f2195369630vboxsync irc = (*pIf->ppIfI)->ControlRequestAsync(pIf->ppIfI, u8PipeRef, &pUrbOsX->u.ControlMsg,
a13bd47f22085c82960265c150f10f2195369630vboxsync usbProxyDarwinUrbAsyncComplete, pUrbOsX);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
a13bd47f22085c82960265c150f10f2195369630vboxsync irc = (*pDevOsX->ppDevI)->DeviceRequestAsync(pDevOsX->ppDevI, &pUrbOsX->u.ControlMsg,
a13bd47f22085c82960265c150f10f2195369630vboxsync usbProxyDarwinUrbAsyncComplete, pUrbOsX);
a13bd47f22085c82960265c150f10f2195369630vboxsync break;
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync case VUSBXFERTYPE_BULK:
a13bd47f22085c82960265c150f10f2195369630vboxsync case VUSBXFERTYPE_INTR:
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync AssertBreak(pIf);
a13bd47f22085c82960265c150f10f2195369630vboxsync Assert(pUrb->enmDir == VUSBDIRECTION_IN || pUrb->enmDir == VUSBDIRECTION_OUT);
a13bd47f22085c82960265c150f10f2195369630vboxsync if (pUrb->enmDir == VUSBDIRECTION_OUT)
a13bd47f22085c82960265c150f10f2195369630vboxsync irc = (*pIf->ppIfI)->WritePipeAsync(pIf->ppIfI, u8PipeRef, pUrb->abData, pUrb->cbData,
a13bd47f22085c82960265c150f10f2195369630vboxsync usbProxyDarwinUrbAsyncComplete, pUrbOsX);
a13bd47f22085c82960265c150f10f2195369630vboxsync else
a13bd47f22085c82960265c150f10f2195369630vboxsync irc = (*pIf->ppIfI)->ReadPipeAsync(pIf->ppIfI, u8PipeRef, pUrb->abData, pUrb->cbData,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync usbProxyDarwinUrbAsyncComplete, pUrbOsX);
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync break;
a13bd47f22085c82960265c150f10f2195369630vboxsync }
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync case VUSBXFERTYPE_ISOC:
a13bd47f22085c82960265c150f10f2195369630vboxsync {
a13bd47f22085c82960265c150f10f2195369630vboxsync AssertBreak(pIf);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Assert(pUrb->enmDir == VUSBDIRECTION_IN || pUrb->enmDir == VUSBDIRECTION_OUT);
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync#ifdef USE_LOW_LATENCY_API
a13bd47f22085c82960265c150f10f2195369630vboxsync /* Allocate an isochronous buffer and copy over the data. */
a13bd47f22085c82960265c150f10f2195369630vboxsync AssertBreak(pUrb->cbData <= 8192);
a13bd47f22085c82960265c150f10f2195369630vboxsync int rc = usbProxyDarwinUrbAllocIsocBuf(pUrbOsX, pIf);
a13bd47f22085c82960265c150f10f2195369630vboxsync AssertRCBreak(rc);
a13bd47f22085c82960265c150f10f2195369630vboxsync if (pUrb->enmDir == VUSBDIRECTION_OUT)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync memcpy(pUrbOsX->u.Isoc.pBuf->pvBuf, pUrb->abData, pUrb->cbData);
a13bd47f22085c82960265c150f10f2195369630vboxsync else
a13bd47f22085c82960265c150f10f2195369630vboxsync memset(pUrbOsX->u.Isoc.pBuf->pvBuf, 0xfe, pUrb->cbData);
a13bd47f22085c82960265c150f10f2195369630vboxsync#endif
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync /* Get the current frame number (+2) and make sure it doesn't
a13bd47f22085c82960265c150f10f2195369630vboxsync overlap with the previous request. See WARNING in
a13bd47f22085c82960265c150f10f2195369630vboxsync ApplUSBUHCI::CreateIsochTransfer for details on the +2. */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync UInt64 FrameNo;
a13bd47f22085c82960265c150f10f2195369630vboxsync AbsoluteTime FrameTime;
a13bd47f22085c82960265c150f10f2195369630vboxsync irc = (*pIf->ppIfI)->GetBusFrameNumber(pIf->ppIfI, &FrameNo, &FrameTime);
a13bd47f22085c82960265c150f10f2195369630vboxsync AssertMsg(irc == kIOReturnSuccess, ("GetBusFrameNumber -> %#x\n", irc));
0bbe08c3ee3c834593be35ccfbe0183116509ae2vboxsync FrameNo += 2;
a13bd47f22085c82960265c150f10f2195369630vboxsync if (FrameNo <= pPipe->u64NextFrameNo)
a13bd47f22085c82960265c150f10f2195369630vboxsync FrameNo = pPipe->u64NextFrameNo;
a13bd47f22085c82960265c150f10f2195369630vboxsync
a13bd47f22085c82960265c150f10f2195369630vboxsync for (unsigned j = 0; ; j++)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync unsigned i;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (i = 0; i < pUrb->cIsocPkts; i++)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frReqCount = pUrb->aIsocPkts[i].cb;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frActCount = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frStatus = kIOUSBNotSent1Err;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifdef USE_LOW_LATENCY_API
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frTimeStamp.hi = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frTimeStamp.lo = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync for (; i < RT_ELEMENTS(pUrbOsX->u.Isoc.aFrames); i++)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frReqCount = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frActCount = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frStatus = kIOReturnError;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifdef USE_LOW_LATENCY_API
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frTimeStamp.hi = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.aFrames[i].frTimeStamp.lo = 0;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#ifdef USE_LOW_LATENCY_API
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrb->enmDir == VUSBDIRECTION_OUT)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->LowLatencyWriteIsochPipeAsync(pIf->ppIfI, u8PipeRef,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.pBuf->pvBuf, FrameNo, pUrb->cIsocPkts, 0, pUrbOsX->u.Isoc.aFrames,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync usbProxyDarwinUrbAsyncComplete, pUrbOsX);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->LowLatencyReadIsochPipeAsync(pIf->ppIfI, u8PipeRef,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrbOsX->u.Isoc.pBuf->pvBuf, FrameNo, pUrb->cIsocPkts, 0, pUrbOsX->u.Isoc.aFrames,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync usbProxyDarwinUrbAsyncComplete, pUrbOsX);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (pUrb->enmDir == VUSBDIRECTION_OUT)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->WriteIsochPipeAsync(pIf->ppIfI, u8PipeRef,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrb->abData, FrameNo, pUrb->cIsocPkts, &pUrbOsX->u.Isoc.aFrames[0],
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync usbProxyDarwinUrbAsyncComplete, pUrbOsX);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync else
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->ReadIsochPipeAsync(pIf->ppIfI, u8PipeRef,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrb->abData, FrameNo, pUrb->cIsocPkts, &pUrbOsX->u.Isoc.aFrames[0],
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync usbProxyDarwinUrbAsyncComplete, pUrbOsX);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync#endif
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if ( irc != kIOReturnIsoTooOld
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync || j >= 5)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync {
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync Log(("%s: usbProxyDarwinUrbQueue: isoc: u64NextFrameNo=%RX64 FrameNo=%RX64 #Frames=%d j=%d (pipe=%d)\n",
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pUrb->pszDesc, pPipe->u64NextFrameNo, FrameNo, pUrb->cIsocPkts, j, u8PipeRef));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (irc == kIOReturnSuccess)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync pPipe->u64NextFrameNo = FrameNo + pUrb->cIsocPkts;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync break;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync /* try again... */
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync irc = (*pIf->ppIfI)->GetBusFrameNumber(pIf->ppIfI, &FrameNo, &FrameTime);
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync if (FrameNo <= pPipe->u64NextFrameNo)
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync FrameNo = pPipe->u64NextFrameNo;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync FrameNo += j;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync break;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync default:
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync AssertMsgFailed(("%s: enmType=%#x\n", pUrb->pszDesc, pUrb->enmType));
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync break;
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync }
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Success?
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (RT_LIKELY(irc == kIOReturnSuccess))
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync return true;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync switch (irc)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync case kIOUSBPipeStalled:
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinUrbAsyncComplete(pUrbOsX, kIOUSBPipeStalled, 0);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync Log(("%s: usbProxyDarwinUrbQueue: pProxyDev=%s EndPt=%d cbData=%d - failed irc=%#x! (stall)\n",
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb->EndPt, pUrb->cbData, irc));
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync return true;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync Log(("%s: usbProxyDarwinUrbQueue: pProxyDev=%s EndPt=%d cbData=%d - failed irc=%#x!\n",
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb->EndPt, pUrb->cbData, irc));
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync return false;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync}
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync/**
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Reap URBs in-flight on a device.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync *
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * @returns Pointer to a completed URB.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * @returns NULL if no URB was completed.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * @param pProxyDev The device.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * @param cMillies Number of milliseconds to wait. Use 0 to not wait at all.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsyncstatic PVUSBURB usbProxyDarwinUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync{
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync PVUSBURB pUrb = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)pProxyDev->Backend.pv;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * If we've got any in-flight URBs, excercise the runloop.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (pDevOsX->pInFlightHead)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFRunLoopRunInMode(g_pRunLoopMode, 0.0, false);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if ( !pDevOsX->pTaxingHead
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync && cMillies
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync && pDevOsX->pInFlightHead)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync CFRunLoopRunInMode(g_pRunLoopMode, cMillies / 1000.0, true);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Any URBs pending delivery?
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync while ( pDevOsX->pTaxingHead
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync && !pUrb)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync RTCritSectEnter(&pDevOsX->CritSect);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync PUSBPROXYURBOSX pUrbOsX = pDevOsX->pTaxingHead;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (pUrbOsX)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync pUrb = pUrbOsX->pVUsbUrb;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (pUrb)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync pUrb->Dev.pvPrivate = NULL;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinUrbFree(pDevOsX, pUrbOsX);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync RTCritSectLeave(&pDevOsX->CritSect);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (pUrb)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync LogFlow(("%s: usbProxyDarwinUrbReap: pProxyDev=%s returns %p\n", pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb));
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync return pUrb;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync}
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync/**
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Cancels a URB.
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync *
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * The URB requires reaping, so we don't change its state.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync *
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * @remark There isn't any way to cancel a specific async request
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * on darwin. The interface only supports the aborting of
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * all URBs pending on an interface / pipe pair. Provided
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * the card does the URB cancelling before submitting new
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * requests, we should probably be fine...
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsyncstatic void usbProxyDarwinUrbCancel(PVUSBURB pUrb)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync{
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)pProxyDev->Backend.pv;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync //PUSBPROXYURBOSX pUrbOsX = (PUSBPROXYURBOSX)pUrb->Dev.pvProxyUrb;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync LogFlow(("%s: usbProxyDarwinUrbCancel: pProxyDev=%s EndPt=%d\n",
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb->EndPt));
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync /*
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * Determin the interface / endpoint ref and invoke AbortPipe.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync IOReturn irc = kIOReturnSuccess;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (!pUrb->EndPt)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync irc = (*pDevOsX->ppDevI)->USBDeviceAbortPipeZero(pDevOsX->ppDevI);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync else
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync {
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync uint8_t u8PipeRef;
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync const uint8_t EndPt = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync PUSBPROXYIFOSX pIf = usbProxyDarwinGetInterfaceForEndpoint(pDevOsX, EndPt, &u8PipeRef, NULL);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (pIf)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync irc = (*pIf->ppIfI)->AbortPipe(pIf->ppIfI, u8PipeRef);
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync else /* this may happen if a device reset, set configuration or set interface has been performed. */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync Log(("usbProxyDarwinUrbCancel: pProxyDev=%s pUrb=%p EndPt=%d - cannot find the interface / pipe!\n",
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync pProxyDev->pUsbIns->pszName, pUrb, pUrb->EndPt));
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync }
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync if (irc != kIOReturnSuccess)
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync Log(("usbProxyDarwinUrbCancel: pProxyDev=%s pUrb=%p EndPt=%d -> %#x!\n",
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync pProxyDev->pUsbIns->pszName, pUrb, pUrb->EndPt, irc));
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync}
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync/**
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync * The Darwin USB Proxy Backend.
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync */
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsyncextern const USBPROXYBACK g_USBProxyDeviceHost =
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync{
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync "host",
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinOpen,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync NULL,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinClose,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinReset,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinSetConfig,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinClaimInterface,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinReleaseInterface,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinSetInterface,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinClearHaltedEp,
65c72795ab90d3daefa759b716fbb5c6352c7a56vboxsync usbProxyDarwinUrbQueue,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinUrbCancel,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync usbProxyDarwinUrbReap,
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync 0
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync};
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync
cda57af9589fa1c4aedbee904fc3f3139409c97bvboxsync