Changeset 59117 in vbox for trunk/src/VBox
- Timestamp:
- Dec 14, 2015 2:04:37 PM (9 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 19 edited
- 3 copied
- 6 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/USBProxyDevice.cpp
r59089 r59117 40 40 static char g_szDummyName[] = "proxy xxxx:yyyy"; 41 41 42 42 /** 43 * Array of supported proxy backends. 44 */ 45 static PCUSBPROXYBACK g_aUsbProxies[] = 46 { 47 &g_USBProxyDeviceHost, 48 &g_USBProxyDeviceVRDP, 49 &g_USBProxyDeviceUsbIp 50 }; 43 51 44 52 /* Synchronously obtain a standard USB descriptor for a device, used in order … … 847 855 AssertRCReturn(rc, rc); 848 856 849 bool fRemote;850 rc = CFGMR3Query Bool(pCfg, "Remote", &fRemote);857 char szBackend[64]; 858 rc = CFGMR3QueryString(pCfg, "Backend", szBackend, sizeof(szBackend)); 851 859 AssertRCReturn(rc, rc); 852 860 … … 858 866 * Select backend and open the device. 859 867 */ 860 if (!fRemote) 861 pThis->pOps = &g_USBProxyDeviceHost; 862 else 863 pThis->pOps = &g_USBProxyDeviceVRDP; 868 rc = VERR_NOT_FOUND; 869 for (unsigned i = 0; i < RT_ELEMENTS(g_aUsbProxies); i++) 870 { 871 if (!RTStrICmp(szBackend, g_aUsbProxies[i]->pszName)) 872 { 873 pThis->pOps = g_aUsbProxies[i]; 874 rc = VINF_SUCCESS; 875 break; 876 } 877 } 878 if (RT_FAILURE(rc)) 879 return PDMUSB_SET_ERROR(pUsbIns, rc, N_("USBProxy: Failed to find backend")); 864 880 865 881 pThis->pvInstanceDataR3 = RTMemAllocZ(pThis->pOps->cbBackend); -
trunk/src/VBox/Devices/USB/USBProxyDevice.h
r58158 r59117 175 175 /** The remote desktop backend. */ 176 176 extern const USBPROXYBACK g_USBProxyDeviceVRDP; 177 /** The USB/IP backend. */ 178 extern const USBPROXYBACK g_USBProxyDeviceUsbIp; 177 179 178 180 #ifdef RDESKTOP -
trunk/src/VBox/Main/Makefile.kmk
r58885 r59117 449 449 ifdef VBOX_WITH_USB 450 450 ifdef VBOX_WITH_SYSFS_BY_DEFAULT 451 src-server/linux/USBProxy ServiceLinux.cpp_DEFS += VBOX_WITH_SYSFS_BY_DEFAULT451 src-server/linux/USBProxyBackendLinux.cpp_DEFS += VBOX_WITH_SYSFS_BY_DEFAULT 452 452 endif 453 453 VBoxSVC_SOURCES += \ 454 454 src-server/USBDeviceFilterImpl.cpp \ 455 455 src-server/USBProxyService.cpp \ 456 src-server/USBProxyBackend.cpp \ 457 src-server/generic/USBProxyBackendUsbIp.cpp \ 456 458 src-server/HostUSBDeviceImpl.cpp 457 VBoxSVC_SOURCES.darwin += src-server/darwin/USBProxy ServiceDarwin.cpp458 VBoxSVC_SOURCES.linux += src-server/linux/USBProxy ServiceLinux.cpp459 VBoxSVC_SOURCES.darwin += src-server/darwin/USBProxyBackendDarwin.cpp 460 VBoxSVC_SOURCES.linux += src-server/linux/USBProxyBackendLinux.cpp 459 461 VBoxSVC_SOURCES.linux += src-server/linux/USBGetDevices.cpp 460 VBoxSVC_SOURCES.os2 += src-server/os2/USBProxy ServiceOs2.cpp461 VBoxSVC_SOURCES.solaris += src-server/solaris/USBProxy ServiceSolaris.cpp462 VBoxSVC_SOURCES.win += src-server/win/USBProxy ServiceWindows.cpp463 VBoxSVC_SOURCES.freebsd += src-server/freebsd/USBProxy ServiceFreeBSD.cpp462 VBoxSVC_SOURCES.os2 += src-server/os2/USBProxyBackendOs2.cpp 463 VBoxSVC_SOURCES.solaris += src-server/solaris/USBProxyBackendSolaris.cpp 464 VBoxSVC_SOURCES.win += src-server/win/USBProxyBackendWindows.cpp 465 VBoxSVC_SOURCES.freebsd += src-server/freebsd/USBProxyBackendFreeBSD.cpp 464 466 endif 465 467 -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r58677 r59117 18021 18021 uuid="5915d179-83c7-4f2b-a323-9a97f46f4e29" 18022 18022 wsmap="managed" 18023 reservedAttributes=" 4"18023 reservedAttributes="3" 18024 18024 > 18025 18025 <desc> … … 18102 18102 Whether the device is physically connected to a remote VRDE 18103 18103 client or to a local host machine. 18104 </desc> 18105 </attribute> 18106 18107 <attribute name="backend" type="wstring" readonly="yes"> 18108 <desc> 18109 The backend which will be used to communicate with this device. 18104 18110 </desc> 18105 18111 </attribute> -
trunk/src/VBox/Main/include/ConsoleImpl.h
r58383 r59117 707 707 708 708 static DECLCALLBACK(int) i_usbAttachCallback(Console *that, PUVM pUVM, IUSBDevice *aHostDevice, PCRTUUID aUuid, 709 bool aRemote, const char *aAddress, void *pvRemoteBackend,709 const char *aBackend, const char *aAddress, void *pvRemoteBackend, 710 710 USHORT aPortVersion, ULONG aMaskedIfs, const char *pszCaptureFilename); 711 711 static DECLCALLBACK(int) i_usbDetachCallback(Console *that, PUVM pUVM, PCRTUUID aUuid); -
trunk/src/VBox/Main/include/HostUSBDeviceImpl.h
r57994 r59117 21 21 #include "VirtualBoxBase.h" 22 22 #include "USBDeviceFilterImpl.h" 23 /* #include "USBProxyService.h" circular on Host/HostUSBDevice, the includer24 * must include this. */25 26 23 #include <VBox/usb.h> 27 24 #include "Logging.h" … … 29 26 30 27 class SessionMachine; 31 class USBProxy Service;28 class USBProxyBackend; 32 29 33 30 /** … … 179 176 180 177 // public initializer/uninitializer for internal purposes only 181 HRESULT init(PUSBDEVICE aUsb, USBProxy Service *aUSBProxyService);178 HRESULT init(PUSBDEVICE aUsb, USBProxyBackend *aUSBProxyBackend); 182 179 void uninit(); 183 180 … … 206 203 /** @note Must be called from under the object read lock. */ 207 204 PCUSBDEVICE i_getUsbData() const { return mUsb; } 205 206 USBProxyBackend *i_getUsbProxyBackend() const { return mUSBProxyBackend; } 208 207 209 208 com::Utf8Str i_getName(); … … 227 226 HostUSBDeviceState aPendingState = kHostUSBDeviceState_Invalid, 228 227 HostUSBDeviceSubState aSubState = kHostUSBDeviceSubState_Default); 228 229 void *i_getBackendUserData() { return m_pvBackendUser; } 230 void i_setBackendUserData(void *pvBackendUser) { m_pvBackendUser = pvBackendUser; } 229 231 230 232 protected: … … 261 263 HRESULT getName(com::Utf8Str &aName); 262 264 HRESULT getState(USBDeviceState_T *aState); 265 HRESULT getBackend(com::Utf8Str &aBackend); 263 266 264 267 … … 289 292 /** The machine the usb device is (being) attached to. */ 290 293 ComObjPtr<SessionMachine> mMachine; 291 /** Pointer to the USB Proxy Serviceinstance. */292 USBProxy Service *mUSBProxyService;294 /** Pointer to the USB Proxy Backend instance. */ 295 USBProxyBackend *mUSBProxyBackend; 293 296 /** Pointer to the USB Device structure owned by this device. 294 297 * Only used for host devices. */ … … 304 307 /** The filename to capture the USB traffic to. */ 305 308 com::Utf8Str mCaptureFilename; 306 307 friend class USBProxyService; 308 #ifdef RT_OS_SOLARIS 309 friend class USBProxyServiceSolaris; 310 311 /** One-shot filter id only for new code */ 312 void *mOneShotId; 313 #endif 314 #ifdef RT_OS_LINUX 315 friend class USBProxyServiceLinux; 316 #endif 317 #ifdef RT_OS_DARWIN 318 /** One-shot filter id. */ 319 void *mOneShotId; 320 321 friend class USBProxyServiceDarwin; 322 #endif 323 #ifdef RT_OS_FreeBSD 324 friend class USBProxyServiceFreeBSD; 325 #endif 309 /** Optional opaque user data assigned by the USB proxy backend owning the device. */ 310 void *m_pvBackendUser; 326 311 }; 327 312 -
trunk/src/VBox/Main/include/RemoteUSBDeviceImpl.h
r56584 r59117 79 79 HRESULT getSpeed(USBConnectionSpeed_T *aSpeed); 80 80 HRESULT getRemote(BOOL *aRemote); 81 HRESULT getBackend(com::Utf8Str &aBackend); 81 82 82 83 // wrapped IHostUSBDevice properties … … 101 102 102 103 const Utf8Str address; 104 const Utf8Str backend; 103 105 104 106 const uint16_t port; -
trunk/src/VBox/Main/include/USBDeviceImpl.h
r56584 r59117 59 59 HRESULT getSpeed(USBConnectionSpeed_T *aSpeed); 60 60 HRESULT getRemote(BOOL *aRemote); 61 HRESULT getBackend(com::Utf8Str &aBackend); 61 62 62 63 struct Data … … 84 85 /** The host specific address of the device. */ 85 86 const com::Utf8Str address; 87 /** The device specific backend. */ 88 const com::Utf8Str backend; 86 89 /** The host port number. */ 87 90 const USHORT port; -
trunk/src/VBox/Main/include/USBProxyBackend.h
r59043 r59117 1 1 /* $Id$ */ 2 2 /** @file 3 * VirtualBox USB Proxy Service(base) class.3 * VirtualBox USB Proxy Backend (base) class. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2005-201 2Oracle Corporation7 * Copyright (C) 2005-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 17 17 18 18 19 #ifndef ____H_USBPROXY SERVICE20 #define ____H_USBPROXY SERVICE19 #ifndef ____H_USBPROXYBACKEND 20 #define ____H_USBPROXYBACKEND 21 21 22 22 #include <VBox/usb.h> 23 23 #include <VBox/usbfilter.h> 24 25 #include <iprt/socket.h> 26 #include <iprt/poll.h> 27 #include <iprt/semaphore.h> 24 28 25 29 #include "VirtualBoxBase.h" 26 30 #include "VirtualBoxImpl.h" 27 31 #include "HostUSBDeviceImpl.h" 28 class Host;29 30 /** 31 * Base class for the USB Proxy service.32 */ 33 class USBProxy Service32 class USBProxyService; 33 34 /** 35 * Base class for the USB Proxy Backend. 36 */ 37 class USBProxyBackend 34 38 : public VirtualBoxTranslatable 35 39 { 36 40 public: 37 USBProxy Service(Host *aHost);38 virtual HRESULTinit(void);39 virtual ~USBProxy Service();41 USBProxyBackend(USBProxyService *pUsbProxyService); 42 virtual int init(void); 43 virtual ~USBProxyBackend(); 40 44 41 45 /** … … 51 55 52 56 bool isActive(void); 53 int getLastError(void);54 HRESULT getLastErrorMessage(BSTR *aError);55 57 56 58 RWLockHandle *lockHandle() const; 57 58 /** @name Host Interfaces59 * @{ */60 HRESULT getDeviceCollection(std::vector<ComPtr<IHostUSBDevice> > &aUSBDevices);61 /** @} */62 63 /** @name SessionMachine Interfaces64 * @{ */65 HRESULT captureDeviceForVM(SessionMachine *aMachine, IN_GUID aId, const com::Utf8Str &aCaptureFilename);66 HRESULT detachDeviceFromVM(SessionMachine *aMachine, IN_GUID aId, bool aDone);67 HRESULT autoCaptureDevicesForVM(SessionMachine *aMachine);68 HRESULT detachAllDevicesFromVM(SessionMachine *aMachine, bool aDone, bool aAbnormal);69 /** @} */70 59 71 60 /** @name Interface for the USBController and the Host object. … … 85 74 /** @} */ 86 75 76 static void freeDevice(PUSBDEVICE pDevice); 77 78 HRESULT runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice, 79 SessionMachinesList &llOpenedMachines, 80 SessionMachine *aIgnoreMachine); 81 bool runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice); 82 83 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice); 84 virtual void deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice); 85 virtual void deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines, SessionMachine *aIgnoreMachine); 86 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine); 87 87 88 protected: 88 89 int start(void); … … 94 95 virtual int interruptWait(void); 95 96 virtual PUSBDEVICE getDevices(void); 96 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice);97 virtual void deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice);98 virtual void deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines, SessionMachine *aIgnoreMachine);99 97 bool updateDeviceStateFake(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine); 100 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);101 102 ComObjPtr<HostUSBDevice> findDeviceById(IN_GUID aId);103 98 104 99 static HRESULT setError(HRESULT aResultCode, const char *aText, ...); … … 106 101 static void initFilterFromDevice(PUSBFILTER aFilter, HostUSBDevice *aDevice); 107 102 static void freeDeviceMembers(PUSBDEVICE pDevice); 108 public: 109 static void freeDevice(PUSBDEVICE pDevice); 110 111 private: 112 HRESULT runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice, 113 SessionMachinesList &llOpenedMachines, 114 SessionMachine *aIgnoreMachine); 115 bool runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice); 116 void processChanges(void); 103 104 private: 105 117 106 static DECLCALLBACK(int) serviceThread(RTTHREAD Thread, void *pvUser); 118 107 119 108 protected: 120 /** Pointer to the Hostobject. */121 Host *mHost;109 /** Pointer to the owning USB Proxy Service object. */ 110 USBProxyService *m_pUsbProxyService; 122 111 /** Thread handle of the service thread. */ 123 RTTHREAD mThread;112 RTTHREAD mThread; 124 113 /** Flag which stop() sets to cause serviceThread to return. */ 125 bool volatile mTerminate; 126 /** VBox status code of the last failure. 127 * (Only used by start(), stop() and the child constructors.) */ 128 int mLastError; 129 /** Optional error message to complement mLastError. */ 130 Bstr mLastErrorMessage; 131 /** List of smart HostUSBDevice pointers. */ 132 typedef std::list<ComObjPtr<HostUSBDevice> > HostUSBDeviceList; 133 /** List of the known USB devices. */ 134 HostUSBDeviceList mDevices; 114 bool volatile mTerminate; 135 115 }; 136 116 … … 145 125 146 126 /** 147 * The Darwin hosted USB Proxy Service.148 */ 149 class USBProxy ServiceDarwin : public USBProxyService150 { 151 public: 152 USBProxy ServiceDarwin(Host *aHost);153 HRESULTinit(void);154 ~USBProxy ServiceDarwin();127 * The Darwin hosted USB Proxy Backend. 128 */ 129 class USBProxyBackendDarwin : public USBProxyBackend 130 { 131 public: 132 USBProxyBackendDarwin(USBProxyService *pUsbProxyService); 133 int init(void); 134 ~USBProxyBackendDarwin(); 155 135 156 136 virtual void *insertFilter(PCUSBFILTER aFilter); … … 194 174 195 175 /** 196 * The Linux hosted USB Proxy Service. 197 */ 198 class USBProxyServiceLinux 199 : public USBProxyService 200 { 201 public: 202 USBProxyServiceLinux(Host *aHost); 203 HRESULT init(void); 204 ~USBProxyServiceLinux(); 176 * The Linux hosted USB Proxy Backend. 177 */ 178 class USBProxyBackendLinux: public USBProxyBackend 179 { 180 public: 181 USBProxyBackendLinux(USBProxyService *pUsbProxyService); 182 int init(void); 183 ~USBProxyBackendLinux(); 205 184 206 185 virtual int captureDevice(HostUSBDevice *aDevice); … … 246 225 247 226 /** 248 * The Linux hosted USB Proxy Service.249 */ 250 class USBProxy ServiceOs2 : public USBProxyService251 { 252 public: 253 USBProxy ServiceOs2 (Host *aHost);254 /// @todo virtual HRESULTinit(void);255 ~USBProxy ServiceOs2();227 * The Linux hosted USB Proxy Backend. 228 */ 229 class USBProxyBackendOs2 : public USBProxyBackend 230 { 231 public: 232 USBProxyBackendOs2 (USBProxyService *pUsbProxyService); 233 /// @todo virtual int init(void); 234 ~USBProxyBackendOs2(); 256 235 257 236 virtual int captureDevice (HostUSBDevice *aDevice); … … 288 267 289 268 /** 290 * The Solaris hosted USB Proxy Service.291 */ 292 class USBProxy ServiceSolaris : public USBProxyService293 { 294 public: 295 USBProxy ServiceSolaris(Host *aHost);296 HRESULTinit(void);297 ~USBProxy ServiceSolaris();269 * The Solaris hosted USB Proxy Backend. 270 */ 271 class USBProxyBackendSolaris : public USBProxyBackend 272 { 273 public: 274 USBProxyBackendSolaris(USBProxyService *pUsbProxyService); 275 int init(void); 276 ~USBProxyBackendSolaris(); 298 277 299 278 virtual void *insertFilter (PCUSBFILTER aFilter); … … 321 300 # ifdef RT_OS_WINDOWS 322 301 /** 323 * The Windows hosted USB Proxy Service.324 */ 325 class USBProxy ServiceWindows : public USBProxyService326 { 327 public: 328 USBProxy ServiceWindows(Host *aHost);329 HRESULTinit(void);330 ~USBProxy ServiceWindows();302 * The Windows hosted USB Proxy Backend. 303 */ 304 class USBProxyBackendWindows : public USBProxyBackend 305 { 306 public: 307 USBProxyBackendWindows(USBProxyService *pUsbProxyService); 308 int init(void); 309 ~USBProxyBackendWindows(); 331 310 332 311 virtual void *insertFilter (PCUSBFILTER aFilter); … … 350 329 # ifdef RT_OS_FREEBSD 351 330 /** 352 * The FreeBSD hosted USB Proxy Service.353 */ 354 class USBProxy ServiceFreeBSD : public USBProxyService355 { 356 public: 357 USBProxy ServiceFreeBSD(Host *aHost);358 HRESULTinit(void);359 ~USBProxy ServiceFreeBSD();331 * The FreeBSD hosted USB Proxy Backend. 332 */ 333 class USBProxyBackendFreeBSD : public USBProxyBackend 334 { 335 public: 336 USBProxyBackendFreeBSD(USBProxyService *pUsbProxyService); 337 int init(void); 338 ~USBProxyBackendFreeBSD(); 360 339 361 340 virtual int captureDevice(HostUSBDevice *aDevice); … … 377 356 # endif /* RT_OS_FREEBSD */ 378 357 379 #endif /* !____H_USBPROXYSERVICE */ 380 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ 358 /** 359 * USB/IP Proxy receive state. 360 */ 361 typedef enum USBIPRECVSTATE 362 { 363 /** Invalid state. */ 364 kUsbIpRecvState_Invalid = 0, 365 /** There is no request waiting for an answer. */ 366 kUsbIpRecvState_None, 367 /** Waiting for the complete reception of UsbIpRetDevList. */ 368 kUsbIpRecvState_Hdr, 369 /** Waiting for the complete reception of a UsbIpExportedDevice structure. */ 370 kUsbIpRecvState_ExportedDevice, 371 /** Waiting for a complete reception a UsbIpDeviceInterface strucutre to skip. */ 372 kUsbIpRecvState_DeviceInterface, 373 /** 32bit hack. */ 374 kUsbIpRecvState_32Bit_Hack = 0x7fffffff 375 } USBIPRECVSTATE; 376 /** Pointer to a USB/IP receive state enum. */ 377 typedef USBIPRECVSTATE *PUSBIPRECVSTATE; 378 379 struct UsbIpExportedDevice; 380 381 /** 382 * The USB/IP Proxy Backend. 383 */ 384 class USBProxyBackendUsbIp: public USBProxyBackend 385 { 386 public: 387 USBProxyBackendUsbIp(USBProxyService *pUsbProxyService); 388 int init(void); 389 ~USBProxyBackendUsbIp(); 390 391 virtual int captureDevice(HostUSBDevice *aDevice); 392 virtual int releaseDevice(HostUSBDevice *aDevice); 393 394 protected: 395 virtual int wait(RTMSINTERVAL aMillies); 396 virtual int interruptWait(void); 397 virtual PUSBDEVICE getDevices(void); 398 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine); 399 400 private: 401 int updateDeviceList(bool *pfDeviceListChanged); 402 bool hasDevListChanged(PUSBDEVICE pDevices); 403 void freeDeviceList(PUSBDEVICE pHead); 404 void resetRecvState(); 405 int reconnect(); 406 void disconnect(); 407 int startListExportedDevicesReq(); 408 void advanceState(USBIPRECVSTATE enmRecvState); 409 int receiveData(); 410 int processData(); 411 int addDeviceToList(UsbIpExportedDevice *pDev); 412 413 struct Data; // opaque data struct, defined in USBProxyBackendUsbIp.cpp 414 Data *m; 415 }; 416 417 #endif /* !____H_USBPROXYBACKEND */ 418 -
trunk/src/VBox/Main/include/USBProxyService.h
r57990 r59117 26 26 #include "VirtualBoxImpl.h" 27 27 #include "HostUSBDeviceImpl.h" 28 #include "USBProxyBackend.h" 28 29 class Host; 29 30 … … 52 53 bool isActive(void); 53 54 int getLastError(void); 54 HRESULT getLastErrorMessage(BSTR *aError);55 55 56 56 RWLockHandle *lockHandle() const; 57 58 /** @name Interface for the USBController and the Host object. 59 * @{ */ 60 void *insertFilter(PCUSBFILTER aFilter); 61 void removeFilter(void *aId); 62 /** @} */ 57 63 58 64 /** @name Host Interfaces … … 69 75 /** @} */ 70 76 71 /** @name Interface for the USBController and the Host object. 72 * @{ */ 73 virtual void *insertFilter(PCUSBFILTER aFilter); 74 virtual void removeFilter(void *aId); 75 /** @} */ 77 typedef std::list< ComObjPtr<HostUSBDeviceFilter> > USBDeviceFilterList; 76 78 77 /** @name Interfaces for the HostUSBDevice 78 * @{ */ 79 virtual int captureDevice(HostUSBDevice *aDevice); 80 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess); 81 /** @todo unused */ 82 virtual void detachingDevice(HostUSBDevice *aDevice); 83 virtual int releaseDevice(HostUSBDevice *aDevice); 84 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess); 85 /** @} */ 79 void i_updateDeviceList(USBProxyBackend *pUsbProxyBackend, PUSBDEVICE pDevices); 80 void i_getUSBFilters(USBDeviceFilterList *pGlobalFiltes); 86 81 87 82 protected: 88 int start(void);89 int stop(void);90 virtual void serviceThreadInit(void);91 virtual void serviceThreadTerm(void);92 93 virtual int wait(RTMSINTERVAL aMillies);94 virtual int interruptWait(void);95 virtual PUSBDEVICE getDevices(void);96 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice);97 virtual void deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice);98 virtual void deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines, SessionMachine *aIgnoreMachine);99 bool updateDeviceStateFake(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);100 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);101 102 83 ComObjPtr<HostUSBDevice> findDeviceById(IN_GUID aId); 103 84 104 85 static HRESULT setError(HRESULT aResultCode, const char *aText, ...); 105 86 106 static void initFilterFromDevice(PUSBFILTER aFilter, HostUSBDevice *aDevice); 107 static void freeDeviceMembers(PUSBDEVICE pDevice); 108 public: 109 static void freeDevice(PUSBDEVICE pDevice); 87 private: 110 88 111 private:112 HRESULT runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice,113 SessionMachinesList &llOpenedMachines,114 SessionMachine *aIgnoreMachine);115 bool runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice);116 void processChanges(void);117 static DECLCALLBACK(int) serviceThread(RTTHREAD Thread, void *pvUser);118 119 protected:120 89 /** Pointer to the Host object. */ 121 90 Host *mHost; 122 /** Thread handle of the service thread. */123 RTTHREAD mThread;124 /** Flag which stop() sets to cause serviceThread to return. */125 bool volatile mTerminate;126 /** VBox status code of the last failure.127 * (Only used by start(), stop() and the child constructors.) */128 int mLastError;129 /** Optional error message to complement mLastError. */130 Bstr mLastErrorMessage;131 91 /** List of smart HostUSBDevice pointers. */ 132 92 typedef std::list<ComObjPtr<HostUSBDevice> > HostUSBDeviceList; 133 93 /** List of the known USB devices. */ 134 94 HostUSBDeviceList mDevices; 95 /** List of USBProxyBackend pointers. */ 96 typedef std::list<USBProxyBackend *> USBProxyBackendList; 97 /** List of active USB backends. */ 98 USBProxyBackendList mBackends; 99 int mLastError; 135 100 }; 136 137 138 # ifdef RT_OS_DARWIN139 # include <VBox/param.h>140 # undef PAGE_SHIFT141 # undef PAGE_SIZE142 # define OSType Carbon_OSType143 # include <Carbon/Carbon.h>144 # undef OSType145 146 /**147 * The Darwin hosted USB Proxy Service.148 */149 class USBProxyServiceDarwin : public USBProxyService150 {151 public:152 USBProxyServiceDarwin(Host *aHost);153 HRESULT init(void);154 ~USBProxyServiceDarwin();155 156 virtual void *insertFilter(PCUSBFILTER aFilter);157 virtual void removeFilter(void *aId);158 159 virtual int captureDevice(HostUSBDevice *aDevice);160 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);161 /** @todo unused */162 virtual void detachingDevice(HostUSBDevice *aDevice);163 virtual int releaseDevice(HostUSBDevice *aDevice);164 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);165 166 protected:167 virtual int wait(RTMSINTERVAL aMillies);168 virtual int interruptWait (void);169 virtual PUSBDEVICE getDevices (void);170 virtual void serviceThreadInit (void);171 virtual void serviceThreadTerm (void);172 virtual bool updateDeviceState (HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);173 174 private:175 /** Reference to the runloop of the service thread.176 * This is NULL if the service thread isn't running. */177 CFRunLoopRef mServiceRunLoopRef;178 /** The opaque value returned by DarwinSubscribeUSBNotifications. */179 void *mNotifyOpaque;180 /** A hack to work around the problem with the usb device enumeration181 * not including newly attached devices. */182 bool mWaitABitNextTime;183 /** Whether we've successfully initialized the USBLib and should call USBLibTerm in the destructor. */184 bool mUSBLibInitialized;185 };186 # endif /* RT_OS_DARWIN */187 188 189 # ifdef RT_OS_LINUX190 # include <stdio.h>191 # ifdef VBOX_USB_WITH_SYSFS192 # include <HostHardwareLinux.h>193 # endif194 195 /**196 * The Linux hosted USB Proxy Service.197 */198 class USBProxyServiceLinux199 : public USBProxyService200 {201 public:202 USBProxyServiceLinux(Host *aHost);203 HRESULT init(void);204 ~USBProxyServiceLinux();205 206 virtual int captureDevice(HostUSBDevice *aDevice);207 virtual int releaseDevice(HostUSBDevice *aDevice);208 209 protected:210 int initUsbfs(void);211 int initSysfs(void);212 void doUsbfsCleanupAsNeeded(void);213 virtual int wait(RTMSINTERVAL aMillies);214 virtual int interruptWait(void);215 virtual PUSBDEVICE getDevices(void);216 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice);217 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);218 219 private:220 int waitUsbfs(RTMSINTERVAL aMillies);221 int waitSysfs(RTMSINTERVAL aMillies);222 223 private:224 /** File handle to the '/proc/bus/usb/devices' file. */225 RTFILE mhFile;226 /** Pipe used to interrupt wait(), the read end. */227 RTPIPE mhWakeupPipeR;228 /** Pipe used to interrupt wait(), the write end. */229 RTPIPE mhWakeupPipeW;230 /** The root of usbfs. */231 Utf8Str mDevicesRoot;232 /** Whether we're using <mUsbfsRoot>/devices or /sys/whatever. */233 bool mUsingUsbfsDevices;234 /** Number of 500ms polls left to do. See usbDeterminState for details. */235 unsigned mUdevPolls;236 # ifdef VBOX_USB_WITH_SYSFS237 /** Object used for polling for hotplug events from hal. */238 VBoxMainHotplugWaiter *mpWaiter;239 # endif240 };241 # endif /* RT_OS_LINUX */242 243 244 # ifdef RT_OS_OS2245 # include <usbcalls.h>246 247 /**248 * The Linux hosted USB Proxy Service.249 */250 class USBProxyServiceOs2 : public USBProxyService251 {252 public:253 USBProxyServiceOs2 (Host *aHost);254 /// @todo virtual HRESULT init(void);255 ~USBProxyServiceOs2();256 257 virtual int captureDevice (HostUSBDevice *aDevice);258 virtual int releaseDevice (HostUSBDevice *aDevice);259 260 protected:261 virtual int wait(RTMSINTERVAL aMillies);262 virtual int interruptWait(void);263 virtual PUSBDEVICE getDevices(void);264 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);265 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);266 267 private:268 /** The notification event semaphore */269 HEV mhev;270 /** The notification id. */271 USBNOTIFY mNotifyId;272 /** The usbcalls.dll handle. */273 HMODULE mhmod;274 /** UsbRegisterChangeNotification */275 APIRET (APIENTRY *mpfnUsbRegisterChangeNotification)(PUSBNOTIFY, HEV, HEV);276 /** UsbDeregisterNotification */277 APIRET (APIENTRY *mpfnUsbDeregisterNotification)(USBNOTIFY);278 /** UsbQueryNumberDevices */279 APIRET (APIENTRY *mpfnUsbQueryNumberDevices)(PULONG);280 /** UsbQueryDeviceReport */281 APIRET (APIENTRY *mpfnUsbQueryDeviceReport)(ULONG, PULONG, PVOID);282 };283 # endif /* RT_OS_LINUX */284 285 286 # ifdef RT_OS_SOLARIS287 # include <libdevinfo.h>288 289 /**290 * The Solaris hosted USB Proxy Service.291 */292 class USBProxyServiceSolaris : public USBProxyService293 {294 public:295 USBProxyServiceSolaris(Host *aHost);296 HRESULT init(void);297 ~USBProxyServiceSolaris();298 299 virtual void *insertFilter (PCUSBFILTER aFilter);300 virtual void removeFilter (void *aID);301 302 virtual int captureDevice (HostUSBDevice *aDevice);303 virtual int releaseDevice (HostUSBDevice *aDevice);304 virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);305 virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);306 307 protected:308 virtual int wait(RTMSINTERVAL aMillies);309 virtual int interruptWait(void);310 virtual PUSBDEVICE getDevices(void);311 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);312 313 private:314 RTSEMEVENT mNotifyEventSem;315 /** Whether we've successfully initialized the USBLib and should call USBLibTerm in the destructor. */316 bool mUSBLibInitialized;317 };318 #endif /* RT_OS_SOLARIS */319 320 321 # ifdef RT_OS_WINDOWS322 /**323 * The Windows hosted USB Proxy Service.324 */325 class USBProxyServiceWindows : public USBProxyService326 {327 public:328 USBProxyServiceWindows(Host *aHost);329 HRESULT init(void);330 ~USBProxyServiceWindows();331 332 virtual void *insertFilter (PCUSBFILTER aFilter);333 virtual void removeFilter (void *aID);334 335 virtual int captureDevice (HostUSBDevice *aDevice);336 virtual int releaseDevice (HostUSBDevice *aDevice);337 338 protected:339 virtual int wait(RTMSINTERVAL aMillies);340 virtual int interruptWait(void);341 virtual PUSBDEVICE getDevices(void);342 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);343 344 private:345 346 HANDLE mhEventInterrupt;347 };348 # endif /* RT_OS_WINDOWS */349 350 # ifdef RT_OS_FREEBSD351 /**352 * The FreeBSD hosted USB Proxy Service.353 */354 class USBProxyServiceFreeBSD : public USBProxyService355 {356 public:357 USBProxyServiceFreeBSD(Host *aHost);358 HRESULT init(void);359 ~USBProxyServiceFreeBSD();360 361 virtual int captureDevice(HostUSBDevice *aDevice);362 virtual int releaseDevice(HostUSBDevice *aDevice);363 364 protected:365 int initUsbfs(void);366 int initSysfs(void);367 virtual int wait(RTMSINTERVAL aMillies);368 virtual int interruptWait(void);369 virtual PUSBDEVICE getDevices(void);370 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);371 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice);372 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine);373 374 private:375 RTSEMEVENT mNotifyEventSem;376 };377 # endif /* RT_OS_FREEBSD */378 101 379 102 #endif /* !____H_USBPROXYSERVICE */ -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r58414 r59117 8631 8631 ComAssertComRCRetRC(hrc); 8632 8632 8633 Bstr BstrBackend; 8634 hrc = aHostDevice->COMGETTER(Backend)(BstrBackend.asOutParam()); 8635 ComAssertComRCRetRC(hrc); 8636 8637 Utf8Str Backend(BstrBackend); 8638 8633 8639 /* Get the VM handle. */ 8634 8640 SafeVMPtr ptrVM(this); … … 8655 8661 int vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), 0 /* idDstCpu (saved state, see #6232) */, 8656 8662 (PFNRT)i_usbAttachCallback, 10, 8657 this, ptrVM.rawUVM(), aHostDevice, uuid.raw(), fRemote,8663 this, ptrVM.rawUVM(), aHostDevice, uuid.raw(), Backend.c_str(), 8658 8664 Address.c_str(), pvRemoteBackend, portVersion, aMaskedIfs, 8659 8665 aCaptureFilename.isEmpty() ? NULL : aCaptureFilename.c_str()); … … 8706 8712 //static 8707 8713 DECLCALLBACK(int) 8708 Console::i_usbAttachCallback(Console *that, PUVM pUVM, IUSBDevice *aHostDevice, PCRTUUID aUuid, bool aRemote,8714 Console::i_usbAttachCallback(Console *that, PUVM pUVM, IUSBDevice *aHostDevice, PCRTUUID aUuid, const char *pszBackend, 8709 8715 const char *aAddress, void *pvRemoteBackend, USHORT aPortVersion, ULONG aMaskedIfs, 8710 8716 const char *pszCaptureFilename) … … 8716 8722 AssertReturn(!that->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE); 8717 8723 8718 int vrc = PDMR3UsbCreateProxyDevice(pUVM, aUuid, aRemote, aAddress, pvRemoteBackend,8724 int vrc = PDMR3UsbCreateProxyDevice(pUVM, aUuid, pszBackend, aAddress, pvRemoteBackend, 8719 8725 aPortVersion == 3 ? VUSB_STDVER_30 : 8720 8726 aPortVersion == 2 ? VUSB_STDVER_20 : VUSB_STDVER_11, -
trunk/src/VBox/Main/src-client/RemoteUSBDeviceImpl.cpp
r56584 r59117 76 76 RTStrPrintf(id, sizeof(id), REMOTE_USB_BACKEND_PREFIX_S "0x%08X&0x%08X", pDevDesc->id, u32ClientId); 77 77 unconst(mData.address) = id; 78 RTStrPrintf(id, sizeof(id), "vrdp"); 79 unconst(mData.backend) = id; 78 80 79 81 unconst(mData.port) = pDevDesc->idPort; … … 151 153 152 154 unconst(mData.address).setNull(); 155 unconst(mData.backend).setNull(); 153 156 154 157 unconst(mData.port) = 0; … … 269 272 } 270 273 274 HRESULT RemoteUSBDevice::getBackend(com::Utf8Str &aBackend) 275 { 276 /* this is const, no need to lock */ 277 aBackend = mData.backend; 278 279 return S_OK; 280 } 281 271 282 // IHostUSBDevice properties 272 283 //////////////////////////////////////////////////////////////////////////////// -
trunk/src/VBox/Main/src-client/USBDeviceImpl.cpp
r53297 r59117 87 87 unconst(mData.address) = Utf8Str(tmp); 88 88 89 hrc = aUSBDevice->COMGETTER(Backend)(bptr); 90 ComAssertComRCRet(hrc, hrc); 91 unconst(mData.backend) = Utf8Str(tmp); 92 89 93 hrc = aUSBDevice->COMGETTER(Port)(&unconst(mData.port)); 90 94 ComAssertComRCRet(hrc, hrc); … … 137 141 138 142 unconst(mData.address).setNull(); 143 unconst(mData.backend).setNull(); 139 144 140 145 unconst(mData.port) = 0; … … 306 311 } 307 312 313 /** 314 * Returns the device specific backend. 315 * 316 * @returns COM status code 317 * @param aBackend Where to put the return string. 318 */ 319 HRESULT OUSBDevice::getBackend(com::Utf8Str &aBackend) 320 { 321 /* this is const, no need to lock */ 322 aBackend = mData.backend; 323 324 return S_OK; 325 } 326 308 327 // private methods 309 328 ///////////////////////////////////////////////////////////////////////////// -
trunk/src/VBox/Main/src-server/HostImpl.cpp
r58794 r59117 277 277 * Create and initialize the USB Proxy Service. 278 278 */ 279 # if defined(RT_OS_DARWIN)280 m->pUSBProxyService = new USBProxyServiceDarwin(this);281 # elif defined(RT_OS_LINUX)282 m->pUSBProxyService = new USBProxyServiceLinux(this);283 # elif defined(RT_OS_OS2)284 m->pUSBProxyService = new USBProxyServiceOs2(this);285 # elif defined(RT_OS_SOLARIS)286 m->pUSBProxyService = new USBProxyServiceSolaris(this);287 # elif defined(RT_OS_WINDOWS)288 m->pUSBProxyService = new USBProxyServiceWindows(this);289 # elif defined(RT_OS_FREEBSD)290 m->pUSBProxyService = new USBProxyServiceFreeBSD(this);291 # else292 279 m->pUSBProxyService = new USBProxyService(this); 293 # endif294 280 hrc = m->pUSBProxyService->init(); 295 281 AssertComRCReturn(hrc, hrc); -
trunk/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp
r58016 r59117 23 23 #include "HostImpl.h" 24 24 #include "VirtualBoxErrorInfoImpl.h" 25 #include "USBProxy Service.h"25 #include "USBProxyBackend.h" 26 26 #include "USBIdDatabase.h" 27 27 … … 39 39 HRESULT HostUSBDevice::FinalConstruct() 40 40 { 41 mUSBProxy Service= NULL;41 mUSBProxyBackend = NULL; 42 42 mUsb = NULL; 43 43 … … 61 61 * This structure is now fully owned by the HostUSBDevice object and will be 62 62 * freed when it is destructed. 63 * @param aUSBProxy Service Pointer to the USB Proxy Service object.64 */ 65 HRESULT HostUSBDevice::init(PUSBDEVICE aUsb, USBProxy Service *aUSBProxyService)63 * @param aUSBProxyBackend Pointer to the USB Proxy Backend object owning the device. 64 */ 65 HRESULT HostUSBDevice::init(PUSBDEVICE aUsb, USBProxyBackend *aUSBProxyBackend) 66 66 { 67 67 ComAssertRet(aUsb, E_INVALIDARG); … … 90 90 91 91 /* Other data members */ 92 mUSBProxy Service = aUSBProxyService;92 mUSBProxyBackend = aUSBProxyBackend; 93 93 mUsb = aUsb; 94 94 … … 116 116 if (mUsb != NULL) 117 117 { 118 USBProxy Service::freeDevice(mUsb);118 USBProxyBackend::freeDevice(mUsb); 119 119 mUsb = NULL; 120 120 } 121 121 122 mUSBProxy Service= NULL;122 mUSBProxyBackend = NULL; 123 123 mUniState = kHostUSBDeviceState_Invalid; 124 124 } … … 306 306 } 307 307 308 309 HRESULT HostUSBDevice::getBackend(com::Utf8Str &aBackend) 310 { 311 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 312 313 aBackend = mUsb->pszBackend; 314 315 return S_OK; 316 } 308 317 309 318 // public methods only for internal purposes … … 448 457 mCaptureFilename = aCaptureFilename; 449 458 alock.release(); 450 int rc = mUSBProxy Service->captureDevice(this);459 int rc = mUSBProxyBackend->captureDevice(this); 451 460 if (RT_FAILURE(rc)) 452 461 { … … 707 716 #endif 708 717 alock.release(); 709 int rc = mUSBProxy Service->releaseDevice(this);718 int rc = mUSBProxyBackend->releaseDevice(this); 710 719 if (RT_FAILURE(rc)) 711 720 { … … 760 769 #endif 761 770 alock.release(); 762 int rc = mUSBProxy Service->captureDevice(this);771 int rc = mUSBProxyBackend->captureDevice(this); 763 772 if (RT_FAILURE(rc)) 764 773 { … … 980 989 int HostUSBDevice::i_compare(PCUSBDEVICE aDev1, PCUSBDEVICE aDev2, bool aIsAwaitingReAttach /*= false */) 981 990 { 991 if (strcmp(aDev1->pszBackend, aDev2->pszBackend)) 992 { 993 return 1; 994 } 995 982 996 /* 983 997 * Things that stays the same everywhere. … … 1152 1166 aDev->pNext = mUsb->pNext; 1153 1167 aDev->pPrev = mUsb->pPrev; 1154 USBProxy Service::freeDevice(mUsb);1168 USBProxyBackend::freeDevice(mUsb); 1155 1169 mUsb = aDev; 1156 1170 } … … 1194 1208 case kHostUSBDeviceState_Capturing: 1195 1209 LogThisFunc(("{%s} capture failed! (#1)\n", mName)); 1196 mUSBProxy Service->captureDeviceCompleted(this, false /* aSuccess */);1210 mUSBProxyBackend->captureDeviceCompleted(this, false /* aSuccess */); 1197 1211 *aRunFilters = i_failTransition(kHostUSBDeviceState_UsedByHost); 1198 1212 mMachine.setNull(); … … 1202 1216 case kHostUSBDeviceState_ReleasingToHost: 1203 1217 LogThisFunc(("{%s} %s -> %s\n", mName, i_getStateName(), i_stateName(kHostUSBDeviceState_UsedByHost))); 1204 mUSBProxy Service->releaseDeviceCompleted(this, true /* aSuccess */);1218 mUSBProxyBackend->releaseDeviceCompleted(this, true /* aSuccess */); 1205 1219 *aRunFilters = i_setState(kHostUSBDeviceState_UsedByHost); 1206 1220 break; … … 1262 1276 case kHostUSBDeviceState_Capturing: 1263 1277 LogThisFunc(("{%s} capture failed! (#2)\n", mName)); 1264 mUSBProxy Service->captureDeviceCompleted(this, false /* aSuccess */);1278 mUSBProxyBackend->captureDeviceCompleted(this, false /* aSuccess */); 1265 1279 *aRunFilters = i_failTransition(kHostUSBDeviceState_Capturable); 1266 1280 mMachine.setNull(); … … 1270 1284 case kHostUSBDeviceState_ReleasingToHost: 1271 1285 LogThisFunc(("{%s} %s -> %s\n", mName, i_getStateName(), i_stateName(kHostUSBDeviceState_Capturable))); 1272 mUSBProxy Service->releaseDeviceCompleted(this, true /* aSuccess */);1286 mUSBProxyBackend->releaseDeviceCompleted(this, true /* aSuccess */); 1273 1287 *aRunFilters = i_setState(kHostUSBDeviceState_Capturable); 1274 1288 break; … … 1330 1344 { 1331 1345 LogThisFunc(("{%s} capture failed! (#3)\n", mName)); 1332 mUSBProxy Service->captureDeviceCompleted(this, false /* aSuccess */);1346 mUSBProxyBackend->captureDeviceCompleted(this, false /* aSuccess */); 1333 1347 *aRunFilters = i_failTransition(kHostUSBDeviceState_Unused); 1334 1348 mMachine.setNull(); … … 1339 1353 case kHostUSBDeviceState_ReleasingToHost: 1340 1354 LogThisFunc(("{%s} %s -> %s\n", mName, i_getStateName(), i_stateName(kHostUSBDeviceState_Unused))); 1341 mUSBProxy Service->releaseDeviceCompleted(this, true /* aSuccess */);1355 mUSBProxyBackend->releaseDeviceCompleted(this, true /* aSuccess */); 1342 1356 *aRunFilters = i_setState(kHostUSBDeviceState_Unused); 1343 1357 break; … … 1380 1394 case kHostUSBDeviceState_Capturing: 1381 1395 LogThisFunc(("{%s} capture succeeded!\n", mName)); 1382 mUSBProxy Service->captureDeviceCompleted(this, true /* aSuccess */);1396 mUSBProxyBackend->captureDeviceCompleted(this, true /* aSuccess */); 1383 1397 *aRunFilters = i_advanceTransition(true /* fast forward thru re-attach */); 1384 1398 … … 1395 1409 case kHostUSBDeviceState_ReleasingToHost: 1396 1410 LogThisFunc(("{%s} %s failed!\n", mName, i_getStateName())); 1397 mUSBProxy Service->releaseDeviceCompleted(this, false /* aSuccess */);1411 mUSBProxyBackend->releaseDeviceCompleted(this, false /* aSuccess */); 1398 1412 *aRunFilters = i_setState(kHostUSBDeviceState_HeldByProxy); 1399 1413 break; … … 1510 1524 aDev->pNext = mUsb->pNext; 1511 1525 aDev->pPrev = mUsb->pPrev; 1512 USBProxy Service::freeDevice(mUsb);1526 USBProxyBackend::freeDevice(mUsb); 1513 1527 mUsb = aDev; 1514 1528 } … … 1516 1530 /* call the completion method */ 1517 1531 if (enmState == kHostUSBDeviceState_Capturing) 1518 mUSBProxy Service->captureDeviceCompleted(this, true /* aSuccess */);1532 mUSBProxyBackend->captureDeviceCompleted(this, true /* aSuccess */); 1519 1533 else 1520 mUSBProxy Service->releaseDeviceCompleted(this, true /* aSuccess */);1534 mUSBProxyBackend->releaseDeviceCompleted(this, true /* aSuccess */); 1521 1535 1522 1536 /* Take action if we're supposed to attach it to a VM. */ -
trunk/src/VBox/Main/src-server/USBProxyBackend.cpp
r59043 r59117 16 16 */ 17 17 18 #include "USBProxyBackend.h" 18 19 #include "USBProxyService.h" 19 20 #include "HostUSBDeviceImpl.h" … … 37 38 * Initialize data members. 38 39 */ 39 USBProxy Service::USBProxyService(Host *aHost)40 : m Host(aHost), mThread(NIL_RTTHREAD), mTerminate(false), mLastError(VINF_SUCCESS), mDevices()41 { 42 LogFlowThisFunc((" aHost=%p\n", aHost));40 USBProxyBackend::USBProxyBackend(USBProxyService *pUsbProxyService) 41 : m_pUsbProxyService(pUsbProxyService), mThread(NIL_RTTHREAD), mTerminate(false) 42 { 43 LogFlowThisFunc(("pUsbProxyService=%p\n", pUsbProxyService)); 43 44 } 44 45 … … 47 48 * Stub needed as long as the class isn't virtual 48 49 */ 49 HRESULT USBProxyService::init(void)50 { 51 return S_OK;50 int USBProxyBackend::init(void) 51 { 52 return VINF_SUCCESS; 52 53 } 53 54 … … 56 57 * Empty destructor. 57 58 */ 58 USBProxy Service::~USBProxyService()59 USBProxyBackend::~USBProxyBackend() 59 60 { 60 61 LogFlowThisFunc(("\n")); 61 62 Assert(mThread == NIL_RTTHREAD); 62 mDevices.clear();63 63 mTerminate = true; 64 m Host= NULL;64 m_pUsbProxyService = NULL; 65 65 } 66 66 … … 72 72 * @returns false if the service isn't running. 73 73 */ 74 bool USBProxy Service::isActive(void)74 bool USBProxyBackend::isActive(void) 75 75 { 76 76 return mThread != NIL_RTTHREAD; 77 }78 79 80 /**81 * Get last error.82 * Can be used to check why the proxy !isActive() upon construction.83 *84 * @returns VBox status code.85 */86 int USBProxyService::getLastError(void)87 {88 return mLastError;89 }90 91 92 /**93 * Get last error message.94 * Can be used to check why the proxy !isActive() upon construction as an95 * extension to getLastError(). May return a NULL error.96 *97 * @param98 * @returns VBox status code.99 */100 HRESULT USBProxyService::getLastErrorMessage(BSTR *aError)101 {102 AssertPtrReturn(aError, E_POINTER);103 mLastErrorMessage.cloneTo(aError);104 return S_OK;105 77 } 106 78 … … 115 87 * @returns Lock handle. 116 88 */ 117 RWLockHandle *USBProxyService::lockHandle() const 118 { 119 return mHost->lockHandle(); 120 } 121 122 123 /** 124 * Gets the collection of USB devices, slave of Host::USBDevices. 125 * 126 * This is an interface for the HostImpl::USBDevices property getter. 127 * 128 * 129 * @param aUSBDevices Where to store the pointer to the collection. 130 * 131 * @returns COM status code. 132 * 133 * @remarks The caller must own the write lock of the host object. 134 */ 135 HRESULT USBProxyService::getDeviceCollection(std::vector<ComPtr<IHostUSBDevice> > &aUSBDevices) 136 { 137 AssertReturn(isWriteLockOnCurrentThread(), E_FAIL); 138 139 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 140 141 aUSBDevices.resize(mDevices.size()); 142 size_t i = 0; 143 for (HostUSBDeviceList::const_iterator it = mDevices.begin(); it != mDevices.end(); ++it, ++i) 144 aUSBDevices[i] = *it; 145 146 return S_OK; 147 } 148 149 150 /** 151 * Request capture of a specific device. 152 * 153 * This is in an interface for SessionMachine::CaptureUSBDevice(), which is 154 * an internal worker used by Console::AttachUSBDevice() from the VM process. 155 * 156 * When the request is completed, SessionMachine::onUSBDeviceAttach() will 157 * be called for the given machine object. 158 * 159 * 160 * @param aMachine The machine to attach the device to. 161 * @param aId The UUID of the USB device to capture and attach. 162 * 163 * @returns COM status code and error info. 164 * 165 * @remarks This method may operate synchronously as well as asynchronously. In the 166 * former case it will temporarily abandon locks because of IPC. 167 */ 168 HRESULT USBProxyService::captureDeviceForVM(SessionMachine *aMachine, IN_GUID aId, const com::Utf8Str &aCaptureFilename) 169 { 170 ComAssertRet(aMachine, E_INVALIDARG); 171 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 172 173 /* 174 * Translate the device id into a device object. 175 */ 176 ComObjPtr<HostUSBDevice> pHostDevice = findDeviceById(aId); 177 if (pHostDevice.isNull()) 178 return setError(E_INVALIDARG, 179 tr("The USB device with UUID {%RTuuid} is not currently attached to the host"), Guid(aId).raw()); 180 181 /* 182 * Try to capture the device 183 */ 184 alock.release(); 185 return pHostDevice->i_requestCaptureForVM(aMachine, true /* aSetError */, aCaptureFilename); 186 } 187 188 189 /** 190 * Notification from VM process about USB device detaching progress. 191 * 192 * This is in an interface for SessionMachine::DetachUSBDevice(), which is 193 * an internal worker used by Console::DetachUSBDevice() from the VM process. 194 * 195 * @param aMachine The machine which is sending the notification. 196 * @param aId The UUID of the USB device is concerns. 197 * @param aDone \a false for the pre-action notification (necessary 198 * for advancing the device state to avoid confusing 199 * the guest). 200 * \a true for the post-action notification. The device 201 * will be subjected to all filters except those of 202 * of \a Machine. 203 * 204 * @returns COM status code. 205 * 206 * @remarks When \a aDone is \a true this method may end up doing IPC to other 207 * VMs when running filters. In these cases it will temporarily 208 * abandon its locks. 209 */ 210 HRESULT USBProxyService::detachDeviceFromVM(SessionMachine *aMachine, IN_GUID aId, bool aDone) 211 { 212 LogFlowThisFunc(("aMachine=%p{%s} aId={%RTuuid} aDone=%RTbool\n", 213 aMachine, 214 aMachine->i_getName().c_str(), 215 Guid(aId).raw(), 216 aDone)); 217 218 // get a list of all running machines while we're outside the lock 219 // (getOpenedMachines requests locks which are incompatible with the lock of the machines list) 220 SessionMachinesList llOpenedMachines; 221 mHost->i_parent()->i_getOpenedMachines(llOpenedMachines); 222 223 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 224 225 ComObjPtr<HostUSBDevice> pHostDevice = findDeviceById(aId); 226 ComAssertRet(!pHostDevice.isNull(), E_FAIL); 227 AutoWriteLock devLock(pHostDevice COMMA_LOCKVAL_SRC_POS); 228 229 /* 230 * Work the state machine. 231 */ 232 LogFlowThisFunc(("id={%RTuuid} state=%s aDone=%RTbool name={%s}\n", 233 pHostDevice->i_getId().raw(), pHostDevice->i_getStateName(), aDone, pHostDevice->i_getName().c_str())); 234 bool fRunFilters = false; 235 HRESULT hrc = pHostDevice->i_onDetachFromVM(aMachine, aDone, &fRunFilters); 236 237 /* 238 * Run filters if necessary. 239 */ 240 if ( SUCCEEDED(hrc) 241 && fRunFilters) 242 { 243 Assert(aDone && pHostDevice->i_getUnistate() == kHostUSBDeviceState_HeldByProxy && pHostDevice->i_getMachine().isNull()); 244 devLock.release(); 245 alock.release(); 246 HRESULT hrc2 = runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine); 247 ComAssertComRC(hrc2); 248 } 249 return hrc; 250 } 251 252 253 /** 254 * Apply filters for the machine to all eligible USB devices. 255 * 256 * This is in an interface for SessionMachine::CaptureUSBDevice(), which 257 * is an internal worker used by Console::AutoCaptureUSBDevices() from the 258 * VM process at VM startup. 259 * 260 * Matching devices will be attached to the VM and may result IPC back 261 * to the VM process via SessionMachine::onUSBDeviceAttach() depending 262 * on whether the device needs to be captured or not. If capture is 263 * required, SessionMachine::onUSBDeviceAttach() will be called 264 * asynchronously by the USB proxy service thread. 265 * 266 * @param aMachine The machine to capture devices for. 267 * 268 * @returns COM status code, perhaps with error info. 269 * 270 * @remarks Temporarily locks this object, the machine object and some USB 271 * device, and the called methods will lock similar objects. 272 */ 273 HRESULT USBProxyService::autoCaptureDevicesForVM(SessionMachine *aMachine) 274 { 275 LogFlowThisFunc(("aMachine=%p{%s}\n", 276 aMachine, 277 aMachine->i_getName().c_str())); 278 279 /* 280 * Make a copy of the list because we cannot hold the lock protecting it. 281 * (This will not make copies of any HostUSBDevice objects, only reference them.) 282 */ 283 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 284 HostUSBDeviceList ListCopy = mDevices; 285 alock.release(); 286 287 for (HostUSBDeviceList::iterator it = ListCopy.begin(); 288 it != ListCopy.end(); 289 ++it) 290 { 291 ComObjPtr<HostUSBDevice> device = *it; 292 AutoReadLock devLock(device COMMA_LOCKVAL_SRC_POS); 293 if ( device->i_getUnistate() == kHostUSBDeviceState_HeldByProxy 294 || device->i_getUnistate() == kHostUSBDeviceState_Unused 295 || device->i_getUnistate() == kHostUSBDeviceState_Capturable) 296 { 297 devLock.release(); 298 runMachineFilters(aMachine, device); 299 } 300 } 301 302 return S_OK; 303 } 304 305 306 /** 307 * Detach all USB devices currently attached to a VM. 308 * 309 * This is in an interface for SessionMachine::DetachAllUSBDevices(), which 310 * is an internal worker used by Console::powerDown() from the VM process 311 * at VM startup, and SessionMachine::uninit() at VM abend. 312 * 313 * This is, like #detachDeviceFromVM(), normally a two stage journey 314 * where \a aDone indicates where we are. In addition we may be called 315 * to clean up VMs that have abended, in which case there will be no 316 * preparatory call. Filters will be applied to the devices in the final 317 * call with the risk that we have to do some IPC when attaching them 318 * to other VMs. 319 * 320 * @param aMachine The machine to detach devices from. 321 * 322 * @returns COM status code, perhaps with error info. 323 * 324 * @remarks Write locks the host object and may temporarily abandon 325 * its locks to perform IPC. 326 */ 327 HRESULT USBProxyService::detachAllDevicesFromVM(SessionMachine *aMachine, bool aDone, bool aAbnormal) 328 { 329 // get a list of all running machines while we're outside the lock 330 // (getOpenedMachines requests locks which are incompatible with the host object lock) 331 SessionMachinesList llOpenedMachines; 332 mHost->i_parent()->i_getOpenedMachines(llOpenedMachines); 333 334 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 335 336 /* 337 * Make a copy of the device list (not the HostUSBDevice objects, just 338 * the list) since we may end up performing IPC and temporarily have 339 * to abandon locks when applying filters. 340 */ 341 HostUSBDeviceList ListCopy = mDevices; 342 343 for (HostUSBDeviceList::iterator it = ListCopy.begin(); 344 it != ListCopy.end(); 345 ++it) 346 { 347 ComObjPtr<HostUSBDevice> pHostDevice = *it; 348 AutoWriteLock devLock(pHostDevice COMMA_LOCKVAL_SRC_POS); 349 if (pHostDevice->i_getMachine() == aMachine) 350 { 351 /* 352 * Same procedure as in detachUSBDevice(). 353 */ 354 bool fRunFilters = false; 355 HRESULT hrc = pHostDevice->i_onDetachFromVM(aMachine, aDone, &fRunFilters, aAbnormal); 356 if ( SUCCEEDED(hrc) 357 && fRunFilters) 358 { 359 Assert( aDone 360 && pHostDevice->i_getUnistate() == kHostUSBDeviceState_HeldByProxy 361 && pHostDevice->i_getMachine().isNull()); 362 devLock.release(); 363 alock.release(); 364 HRESULT hrc2 = runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine); 365 ComAssertComRC(hrc2); 366 alock.acquire(); 367 } 368 } 369 } 370 371 return S_OK; 89 RWLockHandle *USBProxyBackend::lockHandle() const 90 { 91 return m_pUsbProxyService->lockHandle(); 372 92 } 373 93 … … 394 114 * @note The caller is expected to own no locks. 395 115 */ 396 HRESULT USBProxy Service::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice,116 HRESULT USBProxyBackend::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice, 397 117 SessionMachinesList &llOpenedMachines, 398 118 SessionMachine *aIgnoreMachine) … … 415 135 Host::USBDeviceFilterList globalFilters; 416 136 417 m Host->i_getUSBFilters(&globalFilters);137 m_pUsbProxyService->i_getUSBFilters(&globalFilters); 418 138 419 139 /* … … 508 228 * @note Locks several objects temporarily for reading or writing. 509 229 */ 510 bool USBProxy Service::runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice)230 bool USBProxyBackend::runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice) 511 231 { 512 232 LogFlowThisFunc(("{%s} aMachine=%p \n", aDevice->i_getName().c_str(), aMachine)); … … 543 263 * @return ID of the inserted filter 544 264 */ 545 void *USBProxy Service::insertFilter(PCUSBFILTER aFilter)265 void *USBProxyBackend::insertFilter(PCUSBFILTER aFilter) 546 266 { 547 267 // return non-NULL to fake success. … … 556 276 * @param aId ID of the filter to remove 557 277 */ 558 void USBProxy Service::removeFilter(void *aId)278 void USBProxyBackend::removeFilter(void *aId) 559 279 { 560 280 NOREF(aId); … … 568 288 * @param aDevice The device in question. 569 289 */ 570 int USBProxy Service::captureDevice(HostUSBDevice *aDevice)290 int USBProxyBackend::captureDevice(HostUSBDevice *aDevice) 571 291 { 572 292 NOREF(aDevice); … … 584 304 * @param aSuccess Whether it succeeded or failed. 585 305 */ 586 void USBProxy Service::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)306 void USBProxyBackend::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess) 587 307 { 588 308 NOREF(aDevice); … … 598 318 * @todo unused 599 319 */ 600 void USBProxy Service::detachingDevice(HostUSBDevice *aDevice)320 void USBProxyBackend::detachingDevice(HostUSBDevice *aDevice) 601 321 { 602 322 NOREF(aDevice); … … 610 330 * @param aDevice The device in question. 611 331 */ 612 int USBProxy Service::releaseDevice(HostUSBDevice *aDevice)332 int USBProxyBackend::releaseDevice(HostUSBDevice *aDevice) 613 333 { 614 334 NOREF(aDevice); … … 626 346 * @param aSuccess Whether it succeeded or failed. 627 347 */ 628 void USBProxy Service::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)348 void USBProxyBackend::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess) 629 349 { 630 350 NOREF(aDevice); … … 642 362 * @returns VBox status code. 643 363 */ 644 int USBProxy Service::start(void)364 int USBProxyBackend::start(void) 645 365 { 646 366 int rc = VINF_SUCCESS; … … 653 373 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED || RT_SUCCESS(rc)) 654 374 { 655 processChanges(); 375 PUSBDEVICE pDevices = getDevices(); 376 m_pUsbProxyService->i_updateDeviceList(this, pDevices); 656 377 657 378 /* … … 659 380 */ 660 381 mTerminate = false; 661 rc = RTThreadCreate(&mThread, USBProxy Service::serviceThread, this,382 rc = RTThreadCreate(&mThread, USBProxyBackend::serviceThread, this, 662 383 0, RTTHREADTYPE_INFREQUENT_POLLER, RTTHREADFLAGS_WAITABLE, "USBPROXY"); 663 384 AssertRC(rc); … … 667 388 mThread = NIL_RTTHREAD; 668 389 } 669 mLastError = rc;670 390 } 671 391 else … … 680 400 * @returns VBox status code. 681 401 */ 682 int USBProxy Service::stop(void)402 int USBProxyBackend::stop(void) 683 403 { 684 404 int rc = VINF_SUCCESS; … … 705 425 } 706 426 else 707 {708 427 AssertRC(rc); 709 mLastError = rc;710 }711 428 } 712 429 else … … 721 438 * 722 439 * @param Thread The thread handle. 723 * @param pvUser Pointer to the USBProxy Serviceinstance.724 */ 725 /*static*/ DECLCALLBACK(int) USBProxy Service::serviceThread(RTTHREAD /* Thread */, void *pvUser)726 { 727 USBProxy Service *pThis = (USBProxyService*)pvUser;440 * @param pvUser Pointer to the USBProxyBackend instance. 441 */ 442 /*static*/ DECLCALLBACK(int) USBProxyBackend::serviceThread(RTTHREAD /* Thread */, void *pvUser) 443 { 444 USBProxyBackend *pThis = (USBProxyBackend *)pvUser; 728 445 LogFlowFunc(("pThis=%p\n", pThis)); 729 446 pThis->serviceThreadInit(); … … 740 457 if (pThis->mTerminate) 741 458 break; 742 pThis->processChanges(); 459 460 PUSBDEVICE pDevices = pThis->getDevices(); 461 pThis->m_pUsbProxyService->i_updateDeviceList(pThis, pDevices); 743 462 } 744 463 … … 753 472 * thread initialization. 754 473 * 755 * The default implementation in USBProxy Servicejust a dummy stub.756 */ 757 void USBProxy Service::serviceThreadInit(void)474 * The default implementation in USBProxyBackend just a dummy stub. 475 */ 476 void USBProxyBackend::serviceThreadInit(void) 758 477 { 759 478 } … … 764 483 * thread termination. 765 484 */ 766 void USBProxy Service::serviceThreadTerm(void)485 void USBProxyBackend::serviceThreadTerm(void) 767 486 { 768 487 } … … 772 491 * Wait for a change in the USB devices attached to the host. 773 492 * 774 * The default implementation in USBProxy Servicejust a dummy stub.493 * The default implementation in USBProxyBackend just a dummy stub. 775 494 * 776 495 * @returns VBox status code. VERR_INTERRUPTED and VERR_TIMEOUT are considered … … 778 497 * @param aMillies Number of milliseconds to wait. 779 498 */ 780 int USBProxy Service::wait(RTMSINTERVAL aMillies)499 int USBProxyBackend::wait(RTMSINTERVAL aMillies) 781 500 { 782 501 return RTThreadSleep(RT_MIN(aMillies, 250)); … … 787 506 * Interrupt any wait() call in progress. 788 507 * 789 * The default implementation in USBProxy Servicejust a dummy stub.508 * The default implementation in USBProxyBackend just a dummy stub. 790 509 * 791 510 * @returns VBox status code. 792 511 */ 793 int USBProxy Service::interruptWait(void)512 int USBProxyBackend::interruptWait(void) 794 513 { 795 514 return VERR_NOT_IMPLEMENTED; … … 798 517 799 518 /** 800 * Sort a list of USB devices.801 *802 * @returns Pointer to the head of the sorted doubly linked list.803 * @param aDevices Head pointer (can be both singly and doubly linked list).804 */805 static PUSBDEVICE sortDevices(PUSBDEVICE pDevices)806 {807 PUSBDEVICE pHead = NULL;808 PUSBDEVICE pTail = NULL;809 while (pDevices)810 {811 /* unlink head */812 PUSBDEVICE pDev = pDevices;813 pDevices = pDev->pNext;814 if (pDevices)815 pDevices->pPrev = NULL;816 817 /* find location. */818 PUSBDEVICE pCur = pTail;819 while ( pCur820 && HostUSBDevice::i_compare(pCur, pDev) > 0)821 pCur = pCur->pPrev;822 823 /* insert (after pCur) */824 pDev->pPrev = pCur;825 if (pCur)826 {827 pDev->pNext = pCur->pNext;828 pCur->pNext = pDev;829 if (pDev->pNext)830 pDev->pNext->pPrev = pDev;831 else832 pTail = pDev;833 }834 else835 {836 pDev->pNext = pHead;837 if (pHead)838 pHead->pPrev = pDev;839 else840 pTail = pDev;841 pHead = pDev;842 }843 }844 845 LogFlowFuncLeave();846 return pHead;847 }848 849 850 /**851 * Process any relevant changes in the attached USB devices.852 *853 * Except for the first call, this is always running on the service thread.854 */855 void USBProxyService::processChanges(void)856 {857 LogFlowThisFunc(("\n"));858 859 /*860 * Get the sorted list of USB devices.861 */862 PUSBDEVICE pDevices = getDevices();863 pDevices = sortDevices(pDevices);864 865 // get a list of all running machines while we're outside the lock866 // (getOpenedMachines requests higher priority locks)867 SessionMachinesList llOpenedMachines;868 mHost->i_parent()->i_getOpenedMachines(llOpenedMachines);869 870 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);871 872 /*873 * Compare previous list with the new list of devices874 * and merge in any changes while notifying Host.875 */876 HostUSBDeviceList::iterator it = this->mDevices.begin();877 while ( it != mDevices.end()878 || pDevices)879 {880 ComObjPtr<HostUSBDevice> pHostDevice;881 882 if (it != mDevices.end())883 pHostDevice = *it;884 885 /*886 * Assert that the object is still alive (we still reference it in887 * the collection and we're the only one who calls uninit() on it.888 */889 AutoCaller devCaller(pHostDevice.isNull() ? NULL : pHostDevice);890 AssertComRC(devCaller.rc());891 892 /*893 * Lock the device object since we will read/write its894 * properties. All Host callbacks also imply the object is locked.895 */896 AutoWriteLock devLock(pHostDevice.isNull() ? NULL : pHostDevice897 COMMA_LOCKVAL_SRC_POS);898 899 /*900 * Compare.901 */902 int iDiff;903 if (pHostDevice.isNull())904 iDiff = 1;905 else906 {907 if (!pDevices)908 iDiff = -1;909 else910 iDiff = pHostDevice->i_compare(pDevices);911 }912 if (!iDiff)913 {914 /*915 * The device still there, update the state and move on. The PUSBDEVICE916 * structure is eaten by updateDeviceState / HostUSBDevice::updateState().917 */918 PUSBDEVICE pCur = pDevices;919 pDevices = pDevices->pNext;920 pCur->pPrev = pCur->pNext = NULL;921 922 bool fRunFilters = false;923 SessionMachine *pIgnoreMachine = NULL;924 devLock.release();925 alock.release();926 if (updateDeviceState(pHostDevice, pCur, &fRunFilters, &pIgnoreMachine))927 deviceChanged(pHostDevice,928 (fRunFilters ? &llOpenedMachines : NULL),929 pIgnoreMachine);930 alock.acquire();931 ++it;932 }933 else934 {935 if (iDiff > 0)936 {937 /*938 * Head of pDevices was attached.939 */940 PUSBDEVICE pNew = pDevices;941 pDevices = pDevices->pNext;942 pNew->pPrev = pNew->pNext = NULL;943 944 ComObjPtr<HostUSBDevice> NewObj;945 NewObj.createObject();946 NewObj->init(pNew, this);947 Log(("USBProxyService::processChanges: attached %p {%s} %s / %p:{.idVendor=%#06x, .idProduct=%#06x, .pszProduct=\"%s\", .pszManufacturer=\"%s\"}\n",948 (HostUSBDevice *)NewObj,949 NewObj->i_getName().c_str(),950 NewObj->i_getStateName(),951 pNew,952 pNew->idVendor,953 pNew->idProduct,954 pNew->pszProduct,955 pNew->pszManufacturer));956 957 mDevices.insert(it, NewObj);958 959 devLock.release();960 alock.release();961 deviceAdded(NewObj, llOpenedMachines, pNew);962 alock.acquire();963 }964 else965 {966 /*967 * Check if the device was actually detached or logically detached968 * as the result of a re-enumeration.969 */970 if (!pHostDevice->i_wasActuallyDetached())971 ++it;972 else973 {974 it = mDevices.erase(it);975 devLock.release();976 alock.release();977 deviceRemoved(pHostDevice);978 Log(("USBProxyService::processChanges: detached %p {%s}\n",979 (HostUSBDevice *)pHostDevice,980 pHostDevice->i_getName().c_str()));981 982 /* from now on, the object is no more valid,983 * uninitialize to avoid abuse */984 devCaller.release();985 pHostDevice->uninit();986 alock.acquire();987 }988 }989 }990 } /* while */991 992 LogFlowThisFunc(("returns void\n"));993 }994 995 996 /**997 519 * Get a list of USB device currently attached to the host. 998 520 * 999 * The default implementation in USBProxy Servicejust a dummy stub.521 * The default implementation in USBProxyBackend just a dummy stub. 1000 522 * 1001 523 * @returns Pointer to a list of USB devices. 1002 524 * The list nodes are freed individually by calling freeDevice(). 1003 525 */ 1004 PUSBDEVICE USBProxy Service::getDevices(void)526 PUSBDEVICE USBProxyBackend::getDevices(void) 1005 527 { 1006 528 return NULL; … … 1017 539 * @param aUSBDevice The USB device structure. 1018 540 */ 1019 void USBProxy Service::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice,541 void USBProxyBackend::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, 1020 542 SessionMachinesList &llOpenedMachines, 1021 543 PUSBDEVICE aUSBDevice) … … 1054 576 * @param aDevice The device in question. 1055 577 */ 1056 void USBProxy Service::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice)578 void USBProxyBackend::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice) 1057 579 { 1058 580 /* … … 1085 607 * @param aRunFilters Whether or not to run filters. 1086 608 */ 1087 bool USBProxy Service::updateDeviceStateFake(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters,609 bool USBProxyBackend::updateDeviceStateFake(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, 1088 610 SessionMachine **aIgnoreMachine) 1089 611 { … … 1111 633 * @param aIgnoreMachine Machine to ignore when running filters. 1112 634 */ 1113 bool USBProxy Service::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters,635 bool USBProxyBackend::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, 1114 636 SessionMachine **aIgnoreMachine) 1115 637 { … … 1131 653 * @param aIgnoreMachine Machine to ignore when running filters. 1132 654 */ 1133 void USBProxy Service::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines,655 void USBProxyBackend::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines, 1134 656 SessionMachine *aIgnoreMachine) 1135 657 { … … 1167 689 */ 1168 690 /*static*/ void 1169 USBProxy Service::freeDeviceMembers(PUSBDEVICE pDevice)691 USBProxyBackend::freeDeviceMembers(PUSBDEVICE pDevice) 1170 692 { 1171 693 RTStrFree((char *)pDevice->pszManufacturer); … … 1178 700 RTStrFree((char *)pDevice->pszAddress); 1179 701 pDevice->pszAddress = NULL; 702 RTStrFree((char *)pDevice->pszBackend); 703 pDevice->pszBackend = NULL; 1180 704 #ifdef RT_OS_WINDOWS 1181 705 RTStrFree(pDevice->pszAltAddress); … … 1196 720 */ 1197 721 /*static*/ void 1198 USBProxy Service::freeDevice(PUSBDEVICE pDevice)722 USBProxyBackend::freeDevice(PUSBDEVICE pDevice) 1199 723 { 1200 724 freeDeviceMembers(pDevice); … … 1210 734 */ 1211 735 /*static*/ void 1212 USBProxy Service::initFilterFromDevice(PUSBFILTER aFilter, HostUSBDevice *aDevice)1213 { 1214 PCUSBDEVICE pDev = aDevice-> mUsb;736 USBProxyBackend::initFilterFromDevice(PUSBFILTER aFilter, HostUSBDevice *aDevice) 737 { 738 PCUSBDEVICE pDev = aDevice->i_getUsbData(); 1215 739 int vrc; 1216 740 … … 1241 765 1242 766 1243 /**1244 * Searches the list of devices (mDevices) for the given device.1245 *1246 *1247 * @returns Smart pointer to the device on success, NULL otherwise.1248 * @param aId The UUID of the device we're looking for.1249 */1250 ComObjPtr<HostUSBDevice> USBProxyService::findDeviceById(IN_GUID aId)1251 {1252 Guid Id(aId);1253 ComObjPtr<HostUSBDevice> Dev;1254 for (HostUSBDeviceList::iterator it = mDevices.begin();1255 it != mDevices.end();1256 ++it)1257 if ((*it)->i_getId() == Id)1258 {1259 Dev = (*it);1260 break;1261 }1262 1263 return Dev;1264 }1265 1266 767 /*static*/ 1267 HRESULT USBProxy Service::setError(HRESULT aResultCode, const char *aText, ...)768 HRESULT USBProxyBackend::setError(HRESULT aResultCode, const char *aText, ...) 1268 769 { 1269 770 va_list va; … … 1271 772 HRESULT rc = VirtualBoxBase::setErrorInternal(aResultCode, 1272 773 COM_IIDOF(IHost), 1273 "USBProxy Service",774 "USBProxyBackend", 1274 775 Utf8StrFmt(aText, va), 1275 776 false /* aWarning*/, -
trunk/src/VBox/Main/src-server/USBProxyService.cpp
r58170 r59117 33 33 #include <iprt/string.h> 34 34 35 /** Pair of a USB proxy backend and the opaque filter data assigned by the backend. */ 36 typedef std::pair<USBProxyBackend *, void *> USBFilterPair; 37 /** List of USB filter pairs. */ 38 typedef std::list<USBFilterPair> USBFilterList; 39 40 /** 41 * Data for a USB device filter. 42 */ 43 struct USBFilterData 44 { 45 USBFilterData() 46 : llUsbFilters() 47 { } 48 49 USBFilterList llUsbFilters; 50 }; 35 51 36 52 /** … … 38 54 */ 39 55 USBProxyService::USBProxyService(Host *aHost) 40 : mHost(aHost), m Thread(NIL_RTTHREAD), mTerminate(false), mLastError(VINF_SUCCESS), mDevices()56 : mHost(aHost), mDevices(), mBackends() 41 57 { 42 58 LogFlowThisFunc(("aHost=%p\n", aHost)); … … 49 65 HRESULT USBProxyService::init(void) 50 66 { 67 USBProxyBackend *pUsbProxyBackendHost; 68 # if defined(RT_OS_DARWIN) 69 pUsbProxyBackendHost = new USBProxyBackendDarwin(this); 70 # elif defined(RT_OS_LINUX) 71 pUsbProxyBackendHost = new USBProxyBackendLinux(this); 72 # elif defined(RT_OS_OS2) 73 pUsbProxyBackendHost = new USBProxyBackendOs2(this); 74 # elif defined(RT_OS_SOLARIS) 75 pUsbProxyBackendHost = new USBProxyBackendSolaris(this); 76 # elif defined(RT_OS_WINDOWS) 77 pUsbProxyBackendHost = new USBProxyBackendWindows(this); 78 # elif defined(RT_OS_FREEBSD) 79 pUsbProxyBackendHost = new USBProxyBackendFreeBSD(this); 80 # else 81 pUsbProxyBackendHost = new USBProxyBackend(this); 82 # endif 83 int vrc = pUsbProxyBackendHost->init(); 84 if (RT_FAILURE(vrc)) 85 { 86 delete pUsbProxyBackendHost; 87 mLastError = vrc; 88 } 89 else 90 mBackends.push_back(pUsbProxyBackendHost); 91 92 #if 0 /** @todo: Pass in the config. */ 93 pUsbProxyBackendHost = new USBProxyBackendUsbIp(this); 94 hrc = pUsbProxyBackendHost->init(); 95 if (FAILED(hrc)) 96 { 97 delete pUsbProxyBackendHost; 98 return hrc; 99 } 100 #endif 101 102 mBackends.push_back(pUsbProxyBackendHost); 51 103 return S_OK; 52 104 } … … 59 111 { 60 112 LogFlowThisFunc(("\n")); 61 Assert(mThread == NIL_RTTHREAD);62 113 mDevices.clear(); 63 m Terminate = true;114 mBackends.clear(); 64 115 mHost = NULL; 65 116 } … … 74 125 bool USBProxyService::isActive(void) 75 126 { 76 return m Thread != NIL_RTTHREAD;127 return mBackends.size() > 0; 77 128 } 78 129 … … 87 138 { 88 139 return mLastError; 89 }90 91 92 /**93 * Get last error message.94 * Can be used to check why the proxy !isActive() upon construction as an95 * extension to getLastError(). May return a NULL error.96 *97 * @param98 * @returns VBox status code.99 */100 HRESULT USBProxyService::getLastErrorMessage(BSTR *aError)101 {102 AssertPtrReturn(aError, E_POINTER);103 mLastErrorMessage.cloneTo(aError);104 return S_OK;105 140 } 106 141 … … 120 155 } 121 156 157 158 void *USBProxyService::insertFilter(PCUSBFILTER aFilter) 159 { 160 USBFilterData *pFilterData = new USBFilterData(); 161 162 for (USBProxyBackendList::iterator it = mBackends.begin(); 163 it != mBackends.end(); 164 ++it) 165 { 166 USBProxyBackend *pUsbProxyBackend = *it; 167 void *pvId = pUsbProxyBackend->insertFilter(aFilter); 168 169 pFilterData->llUsbFilters.push_back(USBFilterPair(pUsbProxyBackend, pvId)); 170 } 171 172 return pFilterData; 173 } 174 175 void USBProxyService::removeFilter(void *aId) 176 { 177 USBFilterData *pFilterData = (USBFilterData *)aId; 178 179 for (USBFilterList::iterator it = pFilterData->llUsbFilters.begin(); 180 it != pFilterData->llUsbFilters.end(); 181 ++it) 182 { 183 USBProxyBackend *pUsbProxyBackend = it->first; 184 pUsbProxyBackend->removeFilter(it->second); 185 } 186 187 pFilterData->llUsbFilters.clear(); 188 delete pFilterData; 189 } 122 190 123 191 /** … … 241 309 && fRunFilters) 242 310 { 311 USBProxyBackend *pUsbProxyBackend = pHostDevice->i_getUsbProxyBackend(); 243 312 Assert(aDone && pHostDevice->i_getUnistate() == kHostUSBDeviceState_HeldByProxy && pHostDevice->i_getMachine().isNull()); 244 313 devLock.release(); 245 314 alock.release(); 246 HRESULT hrc2 = runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine);315 HRESULT hrc2 = pUsbProxyBackend->runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine); 247 316 ComAssertComRC(hrc2); 248 317 } … … 289 358 ++it) 290 359 { 291 ComObjPtr<HostUSBDevice> device = *it; 292 AutoReadLock devLock(device COMMA_LOCKVAL_SRC_POS); 293 if ( device->i_getUnistate() == kHostUSBDeviceState_HeldByProxy 294 || device->i_getUnistate() == kHostUSBDeviceState_Unused 295 || device->i_getUnistate() == kHostUSBDeviceState_Capturable) 296 { 360 ComObjPtr<HostUSBDevice> pHostDevice = *it; 361 AutoReadLock devLock(pHostDevice COMMA_LOCKVAL_SRC_POS); 362 if ( pHostDevice->i_getUnistate() == kHostUSBDeviceState_HeldByProxy 363 || pHostDevice->i_getUnistate() == kHostUSBDeviceState_Unused 364 || pHostDevice->i_getUnistate() == kHostUSBDeviceState_Capturable) 365 { 366 USBProxyBackend *pUsbProxyBackend = pHostDevice->i_getUsbProxyBackend(); 297 367 devLock.release(); 298 runMachineFilters(aMachine, device);368 pUsbProxyBackend->runMachineFilters(aMachine, pHostDevice); 299 369 } 300 370 } … … 357 427 && fRunFilters) 358 428 { 429 USBProxyBackend *pUsbProxyBackend = pHostDevice->i_getUsbProxyBackend(); 359 430 Assert( aDone 360 431 && pHostDevice->i_getUnistate() == kHostUSBDeviceState_HeldByProxy … … 362 433 devLock.release(); 363 434 alock.release(); 364 HRESULT hrc2 = runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine);435 HRESULT hrc2 = pUsbProxyBackend->runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine); 365 436 ComAssertComRC(hrc2); 366 437 alock.acquire(); … … 373 444 374 445 375 /**376 * Runs all the filters on the specified device.377 *378 * All filters mean global and active VM, with the exception of those379 * belonging to \a aMachine. If a global ignore filter matched or if380 * none of the filters matched, the device will be released back to381 * the host.382 *383 * The device calling us here will be in the HeldByProxy, Unused, or384 * Capturable state. The caller is aware that locks held might have385 * to be abandond because of IPC and that the device might be in386 * almost any state upon return.387 *388 *389 * @returns COM status code (only parameter & state checks will fail).390 * @param aDevice The USB device to apply filters to.391 * @param aIgnoreMachine The machine to ignore filters from (we've just392 * detached the device from this machine).393 *394 * @note The caller is expected to own no locks.395 */396 HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice,397 SessionMachinesList &llOpenedMachines,398 SessionMachine *aIgnoreMachine)399 {400 LogFlowThisFunc(("{%s} ignoring=%p\n", aDevice->i_getName().c_str(), aIgnoreMachine));401 402 /*403 * Verify preconditions.404 */405 AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);406 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), E_FAIL);407 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);408 AutoWriteLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);409 AssertMsgReturn(aDevice->i_isCapturableOrHeld(), ("{%s} %s\n", aDevice->i_getName().c_str(),410 aDevice->i_getStateName()), E_FAIL);411 412 /*413 * Get the lists we'll iterate.414 */415 Host::USBDeviceFilterList globalFilters;416 417 mHost->i_getUSBFilters(&globalFilters);418 419 /*420 * Run global filters filters first.421 */422 bool fHoldIt = false;423 for (Host::USBDeviceFilterList::const_iterator it = globalFilters.begin();424 it != globalFilters.end();425 ++it)426 {427 AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS);428 const HostUSBDeviceFilter::Data &data = (*it)->i_getData();429 if (aDevice->i_isMatch(data))430 {431 USBDeviceFilterAction_T action = USBDeviceFilterAction_Null;432 (*it)->COMGETTER(Action)(&action);433 if (action == USBDeviceFilterAction_Ignore)434 {435 /*436 * Release the device to the host and we're done.437 */438 filterLock.release();439 devLock.release();440 alock.release();441 aDevice->i_requestReleaseToHost();442 return S_OK;443 }444 if (action == USBDeviceFilterAction_Hold)445 {446 /*447 * A device held by the proxy needs to be subjected448 * to the machine filters.449 */450 fHoldIt = true;451 break;452 }453 AssertMsgFailed(("action=%d\n", action));454 }455 }456 globalFilters.clear();457 458 /*459 * Run the per-machine filters.460 */461 for (SessionMachinesList::const_iterator it = llOpenedMachines.begin();462 it != llOpenedMachines.end();463 ++it)464 {465 ComObjPtr<SessionMachine> pMachine = *it;466 467 /* Skip the machine the device was just detached from. */468 if ( aIgnoreMachine469 && pMachine == aIgnoreMachine)470 continue;471 472 /* runMachineFilters takes care of checking the machine state. */473 devLock.release();474 alock.release();475 if (runMachineFilters(pMachine, aDevice))476 {477 LogFlowThisFunc(("{%s} attached to %p\n", aDevice->i_getName().c_str(), (void *)pMachine));478 return S_OK;479 }480 alock.acquire();481 devLock.acquire();482 }483 484 /*485 * No matching machine, so request hold or release depending486 * on global filter match.487 */488 devLock.release();489 alock.release();490 if (fHoldIt)491 aDevice->i_requestHold();492 else493 aDevice->i_requestReleaseToHost();494 return S_OK;495 }496 497 498 /**499 * Runs the USB filters of the machine on the device.500 *501 * If a match is found we will request capture for VM. This may cause502 * us to temporary abandon locks while doing IPC.503 *504 * @param aMachine Machine whose filters are to be run.505 * @param aDevice The USB device in question.506 * @returns @c true if the device has been or is being attached to the VM, @c false otherwise.507 *508 * @note Locks several objects temporarily for reading or writing.509 */510 bool USBProxyService::runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice)511 {512 LogFlowThisFunc(("{%s} aMachine=%p \n", aDevice->i_getName().c_str(), aMachine));513 514 /*515 * Validate preconditions.516 */517 AssertReturn(aMachine, false);518 AssertReturn(!isWriteLockOnCurrentThread(), false);519 AssertReturn(!aMachine->isWriteLockOnCurrentThread(), false);520 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);521 /* Let HostUSBDevice::requestCaptureToVM() validate the state. */522 523 /*524 * Do the job.525 */526 ULONG ulMaskedIfs;527 if (aMachine->i_hasMatchingUSBFilter(aDevice, &ulMaskedIfs))528 {529 /* try to capture the device */530 HRESULT hrc = aDevice->i_requestCaptureForVM(aMachine, false /* aSetError */, Utf8Str(), ulMaskedIfs);531 return SUCCEEDED(hrc)532 || hrc == E_UNEXPECTED /* bad device state, give up */;533 }534 535 return false;536 }537 538 539 /**540 * A filter was inserted / loaded.541 *542 * @param aFilter Pointer to the inserted filter.543 * @return ID of the inserted filter544 */545 void *USBProxyService::insertFilter(PCUSBFILTER aFilter)546 {547 // return non-NULL to fake success.548 NOREF(aFilter);549 return (void *)1;550 }551 552 553 /**554 * A filter was removed.555 *556 * @param aId ID of the filter to remove557 */558 void USBProxyService::removeFilter(void *aId)559 {560 NOREF(aId);561 }562 563 564 /**565 * A VM is trying to capture a device, do necessary preparations.566 *567 * @returns VBox status code.568 * @param aDevice The device in question.569 */570 int USBProxyService::captureDevice(HostUSBDevice *aDevice)571 {572 NOREF(aDevice);573 return VERR_NOT_IMPLEMENTED;574 }575 576 577 /**578 * Notification that an async captureDevice() operation completed.579 *580 * This is used by the proxy to release temporary filters.581 *582 * @returns VBox status code.583 * @param aDevice The device in question.584 * @param aSuccess Whether it succeeded or failed.585 */586 void USBProxyService::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)587 {588 NOREF(aDevice);589 NOREF(aSuccess);590 }591 592 593 /**594 * The device is going to be detached from a VM.595 *596 * @param aDevice The device in question.597 *598 * @todo unused599 */600 void USBProxyService::detachingDevice(HostUSBDevice *aDevice)601 {602 NOREF(aDevice);603 }604 605 606 /**607 * A VM is releasing a device back to the host.608 *609 * @returns VBox status code.610 * @param aDevice The device in question.611 */612 int USBProxyService::releaseDevice(HostUSBDevice *aDevice)613 {614 NOREF(aDevice);615 return VERR_NOT_IMPLEMENTED;616 }617 618 619 /**620 * Notification that an async releaseDevice() operation completed.621 *622 * This is used by the proxy to release temporary filters.623 *624 * @returns VBox status code.625 * @param aDevice The device in question.626 * @param aSuccess Whether it succeeded or failed.627 */628 void USBProxyService::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)629 {630 NOREF(aDevice);631 NOREF(aSuccess);632 }633 634 635 446 // Internals 636 447 ///////////////////////////////////////////////////////////////////////////// 637 638 639 /**640 * Starts the service.641 *642 * @returns VBox status code.643 */644 int USBProxyService::start(void)645 {646 int rc = VINF_SUCCESS;647 if (mThread == NIL_RTTHREAD)648 {649 /*650 * Force update before starting the poller thread.651 */652 rc = wait(0);653 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED || RT_SUCCESS(rc))654 {655 processChanges();656 657 /*658 * Create the poller thread which will look for changes.659 */660 mTerminate = false;661 rc = RTThreadCreate(&mThread, USBProxyService::serviceThread, this,662 0, RTTHREADTYPE_INFREQUENT_POLLER, RTTHREADFLAGS_WAITABLE, "USBPROXY");663 AssertRC(rc);664 if (RT_SUCCESS(rc))665 LogFlowThisFunc(("started mThread=%RTthrd\n", mThread));666 else667 mThread = NIL_RTTHREAD;668 }669 mLastError = rc;670 }671 else672 LogFlowThisFunc(("already running, mThread=%RTthrd\n", mThread));673 return rc;674 }675 676 677 /**678 * Stops the service.679 *680 * @returns VBox status code.681 */682 int USBProxyService::stop(void)683 {684 int rc = VINF_SUCCESS;685 if (mThread != NIL_RTTHREAD)686 {687 /*688 * Mark the thread for termination and kick it.689 */690 ASMAtomicXchgSize(&mTerminate, true);691 rc = interruptWait();692 AssertRC(rc);693 694 /*695 * Wait for the thread to finish and then update the state.696 */697 rc = RTThreadWait(mThread, 60000, NULL);698 if (rc == VERR_INVALID_HANDLE)699 rc = VINF_SUCCESS;700 if (RT_SUCCESS(rc))701 {702 LogFlowThisFunc(("stopped mThread=%RTthrd\n", mThread));703 mThread = NIL_RTTHREAD;704 mTerminate = false;705 }706 else707 {708 AssertRC(rc);709 mLastError = rc;710 }711 }712 else713 LogFlowThisFunc(("not active\n"));714 715 return rc;716 }717 718 719 /**720 * The service thread created by start().721 *722 * @param Thread The thread handle.723 * @param pvUser Pointer to the USBProxyService instance.724 */725 /*static*/ DECLCALLBACK(int) USBProxyService::serviceThread(RTTHREAD /* Thread */, void *pvUser)726 {727 USBProxyService *pThis = (USBProxyService *)pvUser;728 LogFlowFunc(("pThis=%p\n", pThis));729 pThis->serviceThreadInit();730 int rc = VINF_SUCCESS;731 732 /*733 * Processing loop.734 */735 for (;;)736 {737 rc = pThis->wait(RT_INDEFINITE_WAIT);738 if (RT_FAILURE(rc) && rc != VERR_INTERRUPTED && rc != VERR_TIMEOUT)739 break;740 if (pThis->mTerminate)741 break;742 pThis->processChanges();743 }744 745 pThis->serviceThreadTerm();746 LogFlowFunc(("returns %Rrc\n", rc));747 return rc;748 }749 750 751 /**752 * First call made on the service thread, use it to do753 * thread initialization.754 *755 * The default implementation in USBProxyService just a dummy stub.756 */757 void USBProxyService::serviceThreadInit(void)758 {759 }760 761 762 /**763 * Last call made on the service thread, use it to do764 * thread termination.765 */766 void USBProxyService::serviceThreadTerm(void)767 {768 }769 770 771 /**772 * Wait for a change in the USB devices attached to the host.773 *774 * The default implementation in USBProxyService just a dummy stub.775 *776 * @returns VBox status code. VERR_INTERRUPTED and VERR_TIMEOUT are considered777 * harmless, while all other error status are fatal.778 * @param aMillies Number of milliseconds to wait.779 */780 int USBProxyService::wait(RTMSINTERVAL aMillies)781 {782 return RTThreadSleep(RT_MIN(aMillies, 250));783 }784 785 786 /**787 * Interrupt any wait() call in progress.788 *789 * The default implementation in USBProxyService just a dummy stub.790 *791 * @returns VBox status code.792 */793 int USBProxyService::interruptWait(void)794 {795 return VERR_NOT_IMPLEMENTED;796 }797 448 798 449 … … 851 502 * Process any relevant changes in the attached USB devices. 852 503 * 853 * Except for the first call, this is always running on the service thread. 854 */ 855 void USBProxyService::processChanges(void) 504 * This is called from any available USB proxy backends service thread when they discover 505 * a change. 506 */ 507 void USBProxyService::i_updateDeviceList(USBProxyBackend *pUsbProxyBackend, PUSBDEVICE pDevices) 856 508 { 857 509 LogFlowThisFunc(("\n")); 858 510 859 /*860 * Get the sorted list of USB devices.861 */862 PUSBDEVICE pDevices = getDevices();863 511 pDevices = sortDevices(pDevices); 864 512 … … 897 545 COMMA_LOCKVAL_SRC_POS); 898 546 547 /* Skip all devices not belonging to the same backend. */ 548 if ( !pHostDevice.isNull() 549 && pHostDevice->i_getUsbProxyBackend() != pUsbProxyBackend) 550 { 551 ++it; 552 continue; 553 } 554 899 555 /* 900 556 * Compare. … … 924 580 devLock.release(); 925 581 alock.release(); 926 if ( updateDeviceState(pHostDevice, pCur, &fRunFilters, &pIgnoreMachine))927 deviceChanged(pHostDevice,928 (fRunFilters ? &llOpenedMachines : NULL),929 pIgnoreMachine);582 if (pUsbProxyBackend->updateDeviceState(pHostDevice, pCur, &fRunFilters, &pIgnoreMachine)) 583 pUsbProxyBackend->deviceChanged(pHostDevice, 584 (fRunFilters ? &llOpenedMachines : NULL), 585 pIgnoreMachine); 930 586 alock.acquire(); 931 587 ++it; … … 944 600 ComObjPtr<HostUSBDevice> NewObj; 945 601 NewObj.createObject(); 946 NewObj->init(pNew, this);602 NewObj->init(pNew, pUsbProxyBackend); 947 603 Log(("USBProxyService::processChanges: attached %p {%s} %s / %p:{.idVendor=%#06x, .idProduct=%#06x, .pszProduct=\"%s\", .pszManufacturer=\"%s\"}\n", 948 604 (HostUSBDevice *)NewObj, … … 959 615 devLock.release(); 960 616 alock.release(); 961 deviceAdded(NewObj, llOpenedMachines, pNew);617 pUsbProxyBackend->deviceAdded(NewObj, llOpenedMachines, pNew); 962 618 alock.acquire(); 963 619 } … … 975 631 devLock.release(); 976 632 alock.release(); 977 deviceRemoved(pHostDevice);633 pUsbProxyBackend->deviceRemoved(pHostDevice); 978 634 Log(("USBProxyService::processChanges: detached %p {%s}\n", 979 635 (HostUSBDevice *)pHostDevice, … … 995 651 996 652 /** 997 * Get a list of USB device currently attached to the host. 998 * 999 * The default implementation in USBProxyService just a dummy stub. 1000 * 1001 * @returns Pointer to a list of USB devices. 1002 * The list nodes are freed individually by calling freeDevice(). 1003 */ 1004 PUSBDEVICE USBProxyService::getDevices(void) 1005 { 1006 return NULL; 1007 } 1008 1009 1010 /** 1011 * Performs the required actions when a device has been added. 1012 * 1013 * This means things like running filters and subsequent capturing and 1014 * VM attaching. This may result in IPC and temporary lock abandonment. 1015 * 1016 * @param aDevice The device in question. 1017 * @param aUSBDevice The USB device structure. 1018 */ 1019 void USBProxyService::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, 1020 SessionMachinesList &llOpenedMachines, 1021 PUSBDEVICE aUSBDevice) 1022 { 1023 /* 1024 * Validate preconditions. 1025 */ 1026 AssertReturnVoid(!isWriteLockOnCurrentThread()); 1027 AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread()); 1028 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS); 1029 LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid}\n", 1030 (HostUSBDevice *)aDevice, 1031 aDevice->i_getName().c_str(), 1032 aDevice->i_getStateName(), 1033 aDevice->i_getId().raw())); 1034 1035 /* 1036 * Run filters on the device. 1037 */ 1038 if (aDevice->i_isCapturableOrHeld()) 1039 { 1040 devLock.release(); 1041 HRESULT rc = runAllFiltersOnDevice(aDevice, llOpenedMachines, NULL /* aIgnoreMachine */); 1042 AssertComRC(rc); 1043 } 1044 1045 NOREF(aUSBDevice); 1046 } 1047 1048 1049 /** 1050 * Remove device notification hook for the OS specific code. 1051 * 1052 * This is means things like 1053 * 1054 * @param aDevice The device in question. 1055 */ 1056 void USBProxyService::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice) 1057 { 1058 /* 1059 * Validate preconditions. 1060 */ 1061 AssertReturnVoid(!isWriteLockOnCurrentThread()); 1062 AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread()); 1063 AutoWriteLock devLock(aDevice COMMA_LOCKVAL_SRC_POS); 1064 LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid}\n", 1065 (HostUSBDevice *)aDevice, 1066 aDevice->i_getName().c_str(), 1067 aDevice->i_getStateName(), 1068 aDevice->i_getId().raw())); 1069 1070 /* 1071 * Detach the device from any machine currently using it, 1072 * reset all data and uninitialize the device object. 1073 */ 1074 devLock.release(); 1075 aDevice->i_onPhysicalDetached(); 1076 } 1077 1078 1079 /** 1080 * Implement fake capture, ++. 1081 * 1082 * @returns true if there is a state change. 1083 * @param pDevice The device in question. 1084 * @param pUSBDevice The USB device structure for the last enumeration. 1085 * @param aRunFilters Whether or not to run filters. 1086 */ 1087 bool USBProxyService::updateDeviceStateFake(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, 1088 SessionMachine **aIgnoreMachine) 1089 { 1090 *aRunFilters = false; 1091 *aIgnoreMachine = NULL; 1092 AssertReturn(aDevice, false); 1093 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false); 1094 1095 /* 1096 * Just hand it to the device, it knows best what needs to be done. 1097 */ 1098 return aDevice->i_updateStateFake(aUSBDevice, aRunFilters, aIgnoreMachine); 1099 } 1100 1101 1102 /** 1103 * Updates the device state. 1104 * 1105 * This is responsible for calling HostUSBDevice::updateState(). 1106 * 1107 * @returns true if there is a state change. 1108 * @param aDevice The device in question. 1109 * @param aUSBDevice The USB device structure for the last enumeration. 1110 * @param aRunFilters Whether or not to run filters. 1111 * @param aIgnoreMachine Machine to ignore when running filters. 1112 */ 1113 bool USBProxyService::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, 1114 SessionMachine **aIgnoreMachine) 1115 { 1116 AssertReturn(aDevice, false); 1117 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false); 1118 1119 return aDevice->i_updateState(aUSBDevice, aRunFilters, aIgnoreMachine); 1120 } 1121 1122 1123 /** 1124 * Handle a device which state changed in some significant way. 1125 * 1126 * This means things like running filters and subsequent capturing and 1127 * VM attaching. This may result in IPC and temporary lock abandonment. 1128 * 1129 * @param aDevice The device. 1130 * @param pllOpenedMachines list of running session machines (VirtualBox::getOpenedMachines()); if NULL, we don't run filters 1131 * @param aIgnoreMachine Machine to ignore when running filters. 1132 */ 1133 void USBProxyService::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList *pllOpenedMachines, 1134 SessionMachine *aIgnoreMachine) 1135 { 1136 /* 1137 * Validate preconditions. 1138 */ 1139 AssertReturnVoid(!isWriteLockOnCurrentThread()); 1140 AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread()); 1141 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS); 1142 LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid} aRunFilters=%RTbool aIgnoreMachine=%p\n", 1143 (HostUSBDevice *)aDevice, 1144 aDevice->i_getName().c_str(), 1145 aDevice->i_getStateName(), 1146 aDevice->i_getId().raw(), 1147 (pllOpenedMachines != NULL), // used to be "bool aRunFilters" 1148 aIgnoreMachine)); 1149 devLock.release(); 1150 1151 /* 1152 * Run filters if requested to do so. 1153 */ 1154 if (pllOpenedMachines) 1155 { 1156 HRESULT rc = runAllFiltersOnDevice(aDevice, *pllOpenedMachines, aIgnoreMachine); 1157 AssertComRC(rc); 1158 } 1159 } 1160 1161 1162 1163 /** 1164 * Free all the members of a USB device returned by getDevice(). 1165 * 1166 * @param pDevice Pointer to the device. 1167 */ 1168 /*static*/ void 1169 USBProxyService::freeDeviceMembers(PUSBDEVICE pDevice) 1170 { 1171 RTStrFree((char *)pDevice->pszManufacturer); 1172 pDevice->pszManufacturer = NULL; 1173 RTStrFree((char *)pDevice->pszProduct); 1174 pDevice->pszProduct = NULL; 1175 RTStrFree((char *)pDevice->pszSerialNumber); 1176 pDevice->pszSerialNumber = NULL; 1177 1178 RTStrFree((char *)pDevice->pszAddress); 1179 pDevice->pszAddress = NULL; 1180 #ifdef RT_OS_WINDOWS 1181 RTStrFree(pDevice->pszAltAddress); 1182 pDevice->pszAltAddress = NULL; 1183 RTStrFree(pDevice->pszHubName); 1184 pDevice->pszHubName = NULL; 1185 #elif defined(RT_OS_SOLARIS) 1186 RTStrFree(pDevice->pszDevicePath); 1187 pDevice->pszDevicePath = NULL; 1188 #endif 1189 } 1190 1191 1192 /** 1193 * Free one USB device returned by getDevice(). 1194 * 1195 * @param pDevice Pointer to the device. 1196 */ 1197 /*static*/ void 1198 USBProxyService::freeDevice(PUSBDEVICE pDevice) 1199 { 1200 freeDeviceMembers(pDevice); 1201 RTMemFree(pDevice); 1202 } 1203 1204 1205 /** 1206 * Initializes a filter with the data from the specified device. 1207 * 1208 * @param aFilter The filter to fill. 1209 * @param aDevice The device to fill it with. 1210 */ 1211 /*static*/ void 1212 USBProxyService::initFilterFromDevice(PUSBFILTER aFilter, HostUSBDevice *aDevice) 1213 { 1214 PCUSBDEVICE pDev = aDevice->mUsb; 1215 int vrc; 1216 1217 vrc = USBFilterSetNumExact(aFilter, USBFILTERIDX_VENDOR_ID, pDev->idVendor, true); AssertRC(vrc); 1218 vrc = USBFilterSetNumExact(aFilter, USBFILTERIDX_PRODUCT_ID, pDev->idProduct, true); AssertRC(vrc); 1219 vrc = USBFilterSetNumExact(aFilter, USBFILTERIDX_DEVICE_REV, pDev->bcdDevice, true); AssertRC(vrc); 1220 vrc = USBFilterSetNumExact(aFilter, USBFILTERIDX_DEVICE_CLASS, pDev->bDeviceClass, true); AssertRC(vrc); 1221 vrc = USBFilterSetNumExact(aFilter, USBFILTERIDX_DEVICE_SUB_CLASS, pDev->bDeviceSubClass, true); AssertRC(vrc); 1222 vrc = USBFilterSetNumExact(aFilter, USBFILTERIDX_DEVICE_PROTOCOL, pDev->bDeviceProtocol, true); AssertRC(vrc); 1223 vrc = USBFilterSetNumExact(aFilter, USBFILTERIDX_PORT, pDev->bPort, false); AssertRC(vrc); 1224 vrc = USBFilterSetNumExact(aFilter, USBFILTERIDX_BUS, pDev->bBus, false); AssertRC(vrc); 1225 if (pDev->pszSerialNumber) 1226 { 1227 vrc = USBFilterSetStringExact(aFilter, USBFILTERIDX_SERIAL_NUMBER_STR, pDev->pszSerialNumber, true); 1228 AssertRC(vrc); 1229 } 1230 if (pDev->pszProduct) 1231 { 1232 vrc = USBFilterSetStringExact(aFilter, USBFILTERIDX_PRODUCT_STR, pDev->pszProduct, true); 1233 AssertRC(vrc); 1234 } 1235 if (pDev->pszManufacturer) 1236 { 1237 vrc = USBFilterSetStringExact(aFilter, USBFILTERIDX_MANUFACTURER_STR, pDev->pszManufacturer, true); 1238 AssertRC(vrc); 1239 } 653 * Returns the global USB filter list stored in the Host object. 654 * 655 * @returns nothing. 656 * @param pGlobalFilters Where to store the global filter list on success. 657 */ 658 void USBProxyService::i_getUSBFilters(USBDeviceFilterList *pGlobalFilters) 659 { 660 mHost->i_getUSBFilters(pGlobalFilters); 1240 661 } 1241 662 -
trunk/src/VBox/Main/src-server/darwin/USBProxyBackendDarwin.cpp
r59116 r59117 49 49 * Initializes the object (called right after construction). 50 50 * 51 * @returns S_OK on success and non-fatal failures, some COM error otherwise.52 */ 53 HRESULTUSBProxyServiceDarwin::init(void)51 * @returns VBox status code. 52 */ 53 int USBProxyServiceDarwin::init(void) 54 54 { 55 55 /* … … 58 58 int rc = USBLibInit(); 59 59 if (RT_FAILURE(rc)) 60 { 61 mLastError = rc; 62 return S_OK; 63 } 60 return rc; 61 64 62 mUSBLibInitialized = true; 65 63 … … 68 66 */ 69 67 start(); 70 return S_OK;68 return VINF_SUCCESS; 71 69 } 72 70 … … 135 133 int rc = DarwinReEnumerateUSBDevice(aDevice->mUsb); 136 134 if (RT_SUCCESS(rc)) 137 aDevice-> mOneShotId = pvId;135 aDevice->i_setBackendUserData(pvId); 138 136 else 139 137 { … … 153 151 * Remove the one-shot filter if necessary. 154 152 */ 155 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice-> mOneShotId));156 if (!aSuccess && aDevice-> mOneShotId)157 USBLibRemoveFilter(aDevice-> mOneShotId);158 aDevice-> mOneShotId = NULL;153 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice->i_getBackendUserData())); 154 if (!aSuccess && aDevice->i_getBackendUserData()) 155 USBLibRemoveFilter(aDevice->i_getBackendUserData()); 156 aDevice->i_setBackendUserData(NULL); 159 157 } 160 158 … … 189 187 int rc = DarwinReEnumerateUSBDevice(aDevice->mUsb); 190 188 if (RT_SUCCESS(rc)) 191 aDevice-> mOneShotId = pvId;189 aDevice->i_setBackendUserData(pvId); 192 190 else 193 191 { … … 207 205 * Remove the one-shot filter if necessary. 208 206 */ 209 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice-> mOneShotId));210 if (!aSuccess && aDevice-> mOneShotId)211 USBLibRemoveFilter(aDevice-> mOneShotId);212 aDevice-> mOneShotId = NULL;207 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice->i_getBackendUserData())); 208 if (!aSuccess && aDevice->i_getBackendUserData()) 209 USBLibRemoveFilter(aDevice->i_getBackendUserData()); 210 aDevice->i_setBackendUserData(NULL); 213 211 } 214 212 -
trunk/src/VBox/Main/src-server/freebsd/USBProxyBackendFreeBSD.cpp
r59116 r59117 72 72 * @returns S_OK on success and non-fatal failures, some COM error otherwise. 73 73 */ 74 HRESULTUSBProxyServiceFreeBSD::init(void)74 int USBProxyServiceFreeBSD::init(void) 75 75 { 76 76 /* … … 79 79 int rc = RTSemEventCreate(&mNotifyEventSem); 80 80 if (RT_FAILURE(rc)) 81 { 82 mLastError = rc; 83 return E_FAIL; 84 } 81 return rc; 85 82 86 83 /* … … 88 85 */ 89 86 start(); 90 return S_OK;87 return VINF_SUCCESS; 91 88 } 92 89 -
trunk/src/VBox/Main/src-server/generic/USBProxyBackendUsbIp.cpp
r59043 r59117 1 1 /* $Id$ */ 2 2 /** @file 3 * VirtualBox USB Proxy Service, Linux Specialization.3 * VirtualBox USB Proxy Backend, USB/IP. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 20 05-2012Oracle Corporation7 * Copyright (C) 2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 32 32 #include <iprt/assert.h> 33 33 #include <iprt/ctype.h> 34 #include <iprt/ dir.h>34 #include <iprt/tcp.h> 35 35 #include <iprt/env.h> 36 #include <iprt/file.h>37 36 #include <iprt/err.h> 38 37 #include <iprt/mem.h> 39 #include <iprt/param.h>40 #include <iprt/path.h>41 38 #include <iprt/pipe.h> 42 #include <iprt/stream.h> 43 #include <iprt/linux/sysfs.h> 44 45 #include <stdlib.h> 46 #include <string.h> 47 #include <stdio.h> 48 #include <errno.h> 49 #include <fcntl.h> 50 #include <unistd.h> 51 #include <sys/statfs.h> 52 #include <sys/poll.h> 53 #ifdef VBOX_WITH_LINUX_COMPILER_H 54 # include <linux/compiler.h> 55 #endif 56 #include <linux/usbdevice_fs.h> 57 39 #include <iprt/asm.h> 40 #include <iprt/cdefs.h> 41 42 /** The USB/IP default port to connect to. */ 43 #define USBIP_PORT_DEFAULT 3240 44 /** The USB version number used for the protocol. */ 45 #define USBIP_VERSION UINT16_C(0x0111) 46 /** Request indicator in the command code. */ 47 #define USBIP_INDICATOR_REQ RT_BIT(15) 48 49 /** Command/Reply code for OP_REQ/RET_DEVLIST. */ 50 #define USBIP_REQ_RET_DEVLIST UINT16_C(5) 51 52 /** @todo: Duplicate code in USBProxyDevice-usbip.cpp */ 53 /** 54 * Exported device entry in the OP_RET_DEVLIST reply. 55 */ 56 #pragma pack(1) 57 typedef struct UsbIpExportedDevice 58 { 59 /** Path of the device, zero terminated string. */ 60 char szPath[256]; 61 /** Bus ID of the exported device, zero terminated string. */ 62 char szBusId[32]; 63 /** Bus number. */ 64 uint32_t u32BusNum; 65 /** Device number. */ 66 uint32_t u32DevNum; 67 /** Speed indicator of the device. */ 68 uint32_t u32Speed; 69 /** Vendor ID of the device. */ 70 uint16_t u16VendorId; 71 /** Product ID of the device. */ 72 uint16_t u16ProductId; 73 /** Device release number. */ 74 uint16_t u16BcdDevice; 75 /** Device class. */ 76 uint8_t bDeviceClass; 77 /** Device Subclass. */ 78 uint8_t bDeviceSubClass; 79 /** Device protocol. */ 80 uint8_t bDeviceProtocol; 81 /** Configuration value. */ 82 uint8_t bConfigurationValue; 83 /** Current configuration value of the device. */ 84 uint8_t bNumConfigurations; 85 /** Number of interfaces for the device. */ 86 uint8_t bNumInterfaces; 87 } UsbIpExportedDevice; 88 /** Pointer to a exported device entry. */ 89 typedef UsbIpExportedDevice *PUsbIpExportedDevice; 90 #pragma pack() 91 AssertCompileSize(UsbIpExportedDevice, 312); 92 93 /** 94 * Interface descriptor entry for an exported device. 95 */ 96 #pragma pack(1) 97 typedef struct UsbIpDeviceInterface 98 { 99 /** Intefrace class. */ 100 uint8_t bInterfaceClass; 101 /** Interface sub class. */ 102 uint8_t bInterfaceSubClass; 103 /** Interface protocol identifier. */ 104 uint8_t bInterfaceProtocol; 105 /** Padding byte for alignment. */ 106 uint8_t bPadding; 107 } UsbIpDeviceInterface; 108 /** Pointer to an interface descriptor entry. */ 109 typedef UsbIpDeviceInterface *PUsbIpDeviceInterface; 110 #pragma pack() 111 112 /** 113 * USB/IP device list request. 114 */ 115 #pragma pack(1) 116 typedef struct UsbIpReqDevList 117 { 118 /** Protocol version number. */ 119 uint16_t u16Version; 120 /** Command code. */ 121 uint16_t u16Cmd; 122 /** Status field, unused. */ 123 int32_t u32Status; 124 } UsbIpReqDevList; 125 /** Pointer to a device list request. */ 126 typedef UsbIpReqDevList *PUsbIpReqDevList; 127 #pragma pack() 128 129 /** 130 * USB/IP Import reply. 131 * 132 * This is only the header, for successful 133 * requests the device details are sent to as 134 * defined in UsbIpExportedDevice. 135 */ 136 #pragma pack(1) 137 typedef struct UsbIpRetDevList 138 { 139 /** Protocol version number. */ 140 uint16_t u16Version; 141 /** Command code. */ 142 uint16_t u16Cmd; 143 /** Status field, unused. */ 144 int32_t u32Status; 145 /** Number of exported devices. */ 146 uint32_t u32DevicesExported; 147 } UsbIpRetDevList; 148 /** Pointer to a import reply. */ 149 typedef UsbIpRetDevList *PUsbIpRetDevList; 150 #pragma pack() 151 152 /** Pollset id of the socket. */ 153 #define USBIP_POLL_ID_SOCKET 0 154 /** Pollset id of the pipe. */ 155 #define USBIP_POLL_ID_PIPE 1 156 157 /** @name USB/IP error codes. 158 * @{ */ 159 /** Success indicator. */ 160 #define USBIP_STATUS_SUCCESS INT32_C(0) 161 /** @} */ 162 163 /** @name USB/IP device speeds. 164 * @{ */ 165 /** Unknown speed. */ 166 #define USBIP_SPEED_UNKNOWN 0 167 /** Low (1.0) speed. */ 168 #define USBIP_SPEED_LOW 1 169 /** Full (1.1) speed. */ 170 #define USBIP_SPEED_FULL 2 171 /** High (2.0) speed. */ 172 #define USBIP_SPEED_HIGH 3 173 /** Variable (CWUSB) speed. */ 174 #define USBIP_SPEED_WIRELESS 4 175 /** Super (3.0) speed. */ 176 #define USBIP_SPEED_SUPER 5 177 /** @} */ 178 179 /** 180 * Private USB/IP proxy backend data. 181 */ 182 struct USBProxyBackendUsbIp::Data 183 { 184 Data() 185 : hSocket(NIL_RTSOCKET), 186 hWakeupPipeR(NIL_RTPIPE), 187 hWakeupPipeW(NIL_RTPIPE), 188 hPollSet(NIL_RTPOLLSET), 189 uPort(USBIP_PORT_DEFAULT), 190 pszHost(NULL), 191 hMtxDevices(NIL_RTSEMFASTMUTEX), 192 cUsbDevicesCur(0), 193 pUsbDevicesCur(NULL), 194 enmRecvState(kUsbIpRecvState_Invalid), 195 cbResidualRecv(0), 196 pbRecvBuf(NULL), 197 cDevicesLeft(0), 198 pHead(NULL), 199 ppNext(&pHead) 200 { } 201 202 /** Socket handle to the server. */ 203 RTSOCKET hSocket; 204 /** Pipe used to interrupt wait(), the read end. */ 205 RTPIPE hWakeupPipeR; 206 /** Pipe used to interrupt wait(), the write end. */ 207 RTPIPE hWakeupPipeW; 208 /** Pollset for the socket and wakeup pipe. */ 209 RTPOLLSET hPollSet; 210 /** Port of the USB/IP host to connect to. */ 211 uint32_t uPort; 212 /** USB/IP host address. */ 213 char *pszHost; 214 /** Mutex protecting the device list against concurrent access. */ 215 RTSEMFASTMUTEX hMtxDevices; 216 /** Number of devices in the list. */ 217 uint32_t cUsbDevicesCur; 218 /** The current list of devices to compare with. */ 219 PUSBDEVICE pUsbDevicesCur; 220 /** Current receive state. */ 221 USBIPRECVSTATE enmRecvState; 222 /** Scratch space for holding the data until it was completely received. 223 * Which one to access is based on the current receive state. */ 224 union 225 { 226 UsbIpRetDevList RetDevList; 227 UsbIpExportedDevice ExportedDevice; 228 UsbIpDeviceInterface DeviceInterface; 229 /** Byte view. */ 230 uint8_t abRecv[1]; 231 } Scratch; 232 /** Residual number of bytes to receive before we can work with the data. */ 233 size_t cbResidualRecv; 234 /** Current pointer into the scratch buffer. */ 235 uint8_t *pbRecvBuf; 236 /** Number of devices left to receive for the current request. */ 237 uint32_t cDevicesLeft; 238 /** Number of interfaces to skip during receive. */ 239 uint32_t cInterfacesLeft; 240 /** The current head pointer for the new device list. */ 241 PUSBDEVICE pHead; 242 /** The next pointer to add a device to. */ 243 PUSBDEVICE *ppNext; 244 /** Current amount of devices in the list. */ 245 uint32_t cDevicesCur; 246 }; 247 248 /** 249 * Convert the given exported device structure from host to network byte order. 250 * 251 * @returns nothing. 252 * @param pDevice The device structure to convert. 253 */ 254 DECLINLINE(void) usbProxyBackendUsbIpExportedDeviceN2H(PUsbIpExportedDevice pDevice) 255 { 256 pDevice->u32BusNum = RT_N2H_U32(pDevice->u32BusNum); 257 pDevice->u32DevNum = RT_N2H_U32(pDevice->u32DevNum); 258 pDevice->u32Speed = RT_N2H_U16(pDevice->u32Speed); 259 pDevice->u16VendorId = RT_N2H_U16(pDevice->u16VendorId); 260 pDevice->u16ProductId = RT_N2H_U16(pDevice->u16ProductId); 261 pDevice->u16BcdDevice = RT_N2H_U16(pDevice->u16BcdDevice); 262 } 58 263 59 264 /** 60 265 * Initialize data members. 61 266 */ 62 USBProxyServiceLinux::USBProxyServiceLinux(Host *aHost) 63 : USBProxyService(aHost), mhFile(NIL_RTFILE), mhWakeupPipeR(NIL_RTPIPE), 64 mhWakeupPipeW(NIL_RTPIPE), mUsingUsbfsDevices(true /* see init */), 65 mUdevPolls(0), mpWaiter(NULL) 66 { 67 LogFlowThisFunc(("aHost=%p\n", aHost)); 267 USBProxyBackendUsbIp::USBProxyBackendUsbIp(USBProxyService *aUsbProxyService) 268 : USBProxyBackend(aUsbProxyService) 269 { 270 LogFlowThisFunc(("aUsbProxyService=%p\n", aUsbProxyService)); 68 271 } 69 272 … … 73 276 * @returns S_OK on success and non-fatal failures, some COM error otherwise. 74 277 */ 75 HRESULT USBProxyServiceLinux::init(void) 76 { 77 const char *pcszDevicesRoot; 78 int rc = USBProxyLinuxChooseMethod(&mUsingUsbfsDevices, &pcszDevicesRoot); 278 int USBProxyBackendUsbIp::init(void) 279 { 280 int rc = VINF_SUCCESS; 281 282 m = new Data; 283 284 /** @todo: Pass in some config like host and port to connect to. */ 285 286 /* Setup wakeup pipe and poll set first. */ 287 rc = RTSemFastMutexCreate(&m->hMtxDevices); 79 288 if (RT_SUCCESS(rc)) 80 289 { 81 mDevicesRoot = pcszDevicesRoot; 82 rc = mUsingUsbfsDevices ? initUsbfs() : initSysfs(); 83 /* For the day when we have VBoxSVC release logging... */ 84 LogRel((RT_SUCCESS(rc) ? "Successfully initialised host USB using %s\n" 85 : "Failed to initialise host USB using %s\n", 86 mUsingUsbfsDevices ? "USBFS" : "sysfs")); 87 } 88 mLastError = rc; 89 return S_OK; 90 } 91 92 /** 93 * Initialization routine for the usbfs based operation. 94 * 95 * @returns iprt status code. 96 */ 97 int USBProxyServiceLinux::initUsbfs(void) 98 { 99 Assert(mUsingUsbfsDevices); 100 101 /* 102 * Open the devices file. 103 */ 104 int rc; 105 char *pszDevices = RTPathJoinA(mDevicesRoot.c_str(), "devices"); 106 if (pszDevices) 107 { 108 rc = RTFileOpen(&mhFile, pszDevices, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 290 rc = RTPipeCreate(&m->hWakeupPipeR, &m->hWakeupPipeW, 0); 109 291 if (RT_SUCCESS(rc)) 110 292 { 111 rc = RTP ipeCreate(&mhWakeupPipeR, &mhWakeupPipeW, 0 /*fFlags*/);293 rc = RTPollSetCreate(&m->hPollSet); 112 294 if (RT_SUCCESS(rc)) 113 295 { 114 /* 115 * Start the poller thread. 116 */ 117 rc = start(); 296 rc = RTPollSetAddPipe(m->hPollSet, m->hWakeupPipeR, 297 RTPOLL_EVT_READ, USBIP_POLL_ID_PIPE); 118 298 if (RT_SUCCESS(rc)) 119 299 { 120 RTStrFree(pszDevices); 121 LogFlowThisFunc(("returns successfully\n")); 122 return VINF_SUCCESS; 300 /* Connect to the USB/IP host. */ 301 rc = reconnect(); 302 if (RT_SUCCESS(rc)) 303 rc = start(); /* Start service thread. */ 123 304 } 124 305 125 RTPipeClose(mhWakeupPipeR); 126 RTPipeClose(mhWakeupPipeW); 127 mhWakeupPipeW = mhWakeupPipeR = NIL_RTPIPE; 306 if (RT_FAILURE(rc)) 307 { 308 RTPollSetRemove(m->hPollSet, USBIP_POLL_ID_PIPE); 309 int rc2 = RTPollSetDestroy(m->hPollSet); 310 AssertRC(rc2); 311 } 128 312 } 129 else 130 Log(("USBProxyServiceLinux::USBProxyServiceLinux: RTFilePipe failed with rc=%Rrc\n", rc)); 131 RTFileClose(mhFile); 132 } 133 134 RTStrFree(pszDevices); 135 } 136 else 137 { 138 rc = VERR_NO_MEMORY; 139 Log(("USBProxyServiceLinux::USBProxyServiceLinux: out of memory!\n")); 140 } 141 142 LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc)); 313 314 if (RT_FAILURE(rc)) 315 { 316 int rc2 = RTPipeClose(m->hWakeupPipeR); 317 AssertRC(rc2); 318 rc2 = RTPipeClose(m->hWakeupPipeW); 319 AssertRC(rc2); 320 } 321 } 322 if (RT_FAILURE(rc)) 323 RTSemFastMutexDestroy(m->hMtxDevices); 324 } 325 143 326 return rc; 144 327 } 145 328 146 147 /**148 * Initialization routine for the sysfs based operation.149 *150 * @returns iprt status code151 */152 int USBProxyServiceLinux::initSysfs(void)153 {154 Assert(!mUsingUsbfsDevices);155 156 #ifdef VBOX_USB_WITH_SYSFS157 try158 {159 mpWaiter = new VBoxMainHotplugWaiter(mDevicesRoot.c_str());160 }161 catch(std::bad_alloc &e)162 {163 return VERR_NO_MEMORY;164 }165 int rc = mpWaiter->getStatus();166 if (RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_TRY_AGAIN)167 rc = start();168 else if (rc == VERR_NOT_SUPPORTED)169 /* This can legitimately happen if hal or DBus are not running, but of170 * course we can't start in this case. */171 rc = VINF_SUCCESS;172 return rc;173 174 #else /* !VBOX_USB_WITH_SYSFS */175 return VERR_NOT_IMPLEMENTED;176 #endif /* !VBOX_USB_WITH_SYSFS */177 }178 179 180 329 /** 181 330 * Stop all service threads and free the device chain. 182 331 */ 183 USBProxy ServiceLinux::~USBProxyServiceLinux()332 USBProxyBackendUsbIp::~USBProxyBackendUsbIp() 184 333 { 185 334 LogFlowThisFunc(("\n")); … … 194 343 * Free resources. 195 344 */ 196 doUsbfsCleanupAsNeeded(); 197 #ifdef VBOX_USB_WITH_SYSFS 198 if (mpWaiter) 199 delete mpWaiter; 200 #endif 201 } 202 203 204 /** 205 * If any Usbfs-related resources are currently allocated, then free them 206 * and mark them as freed. 207 */ 208 void USBProxyServiceLinux::doUsbfsCleanupAsNeeded() 209 { 210 /* 211 * Free resources. 212 */ 213 RTFileClose(mhFile); 214 mhFile = NIL_RTFILE; 215 216 RTPipeClose(mhWakeupPipeR); 217 RTPipeClose(mhWakeupPipeW); 218 mhWakeupPipeW = mhWakeupPipeR = NIL_RTPIPE; 219 } 220 221 222 int USBProxyServiceLinux::captureDevice(HostUSBDevice *aDevice) 345 if (m->hPollSet != NIL_RTPOLLSET) 346 { 347 disconnect(); 348 349 int rc = RTPollSetRemove(m->hPollSet, USBIP_POLL_ID_PIPE); 350 AssertRC(rc); 351 rc = RTPollSetDestroy(m->hPollSet); 352 AssertRC(rc); 353 rc = RTPipeClose(m->hWakeupPipeR); 354 AssertRC(rc); 355 rc = RTPipeClose(m->hWakeupPipeW); 356 AssertRC(rc); 357 } 358 359 if (m->pszHost) 360 RTStrFree(m->pszHost); 361 if (m->hMtxDevices != NIL_RTSEMFASTMUTEX) 362 RTSemFastMutexDestroy(m->hMtxDevices); 363 364 delete m; 365 } 366 367 368 int USBProxyBackendUsbIp::captureDevice(HostUSBDevice *aDevice) 223 369 { 224 370 AssertReturn(aDevice, VERR_GENERAL_FAILURE); … … 229 375 230 376 /* 231 * Don't think weneed to do anything when the device is held... fake it.377 * We don't need to do anything when the device is held... fake it. 232 378 */ 233 379 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_Capturing); … … 239 385 240 386 241 int USBProxy ServiceLinux::releaseDevice(HostUSBDevice *aDevice)387 int USBProxyBackendUsbIp::releaseDevice(HostUSBDevice *aDevice) 242 388 { 243 389 AssertReturn(aDevice, VERR_GENERAL_FAILURE); … … 258 404 259 405 260 bool USBProxy ServiceLinux::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters,406 bool USBProxyBackendUsbIp::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, 261 407 SessionMachine **aIgnoreMachine) 262 408 { … … 265 411 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS); 266 412 if ( aUSBDevice->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE 267 && aDevice-> mUsb->enmState == USBDEVICESTATE_USED_BY_HOST)413 && aDevice->i_getUsbData()->enmState == USBDEVICESTATE_USED_BY_HOST) 268 414 LogRel(("USBProxy: Device %04x:%04x (%s) has become accessible.\n", 269 415 aUSBDevice->idVendor, aUSBDevice->idProduct, aUSBDevice->pszAddress)); … … 273 419 274 420 275 /** 276 * A device was added, we need to adjust mUdevPolls. 277 * 278 * See USBProxyService::deviceAdded for details. 279 */ 280 void USBProxyServiceLinux::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, 281 PUSBDEVICE aUSBDevice) 282 { 283 AssertReturnVoid(aDevice); 284 AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread()); 285 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS); 286 if (aUSBDevice->enmState == USBDEVICESTATE_USED_BY_HOST) 287 { 288 LogRel(("USBProxy: Device %04x:%04x (%s) isn't accessible. giving udev a few seconds to fix this...\n", 289 aUSBDevice->idVendor, aUSBDevice->idProduct, aUSBDevice->pszAddress)); 290 mUdevPolls = 10; /* (10 * 500ms = 5s) */ 291 } 292 293 devLock.release(); 294 USBProxyService::deviceAdded(aDevice, llOpenedMachines, aUSBDevice); 295 } 296 297 298 int USBProxyServiceLinux::wait(RTMSINTERVAL aMillies) 299 { 300 int rc; 301 if (mUsingUsbfsDevices) 302 rc = waitUsbfs(aMillies); 303 else 304 rc = waitSysfs(aMillies); 421 int USBProxyBackendUsbIp::wait(RTMSINTERVAL aMillies) 422 { 423 int rc = VINF_SUCCESS; 424 bool fDeviceListChangedOrWokenUp = false; 425 426 /* Try to reconnect once when we enter if we lost the connection earlier. */ 427 if (m->hSocket == NIL_RTSOCKET) 428 rc = reconnect(); 429 430 /* Query a new device list upon entering. */ 431 if (m->enmRecvState == kUsbIpRecvState_None) 432 { 433 rc = startListExportedDevicesReq(); 434 if (RT_FAILURE(rc)) 435 disconnect(); 436 } 437 438 /* 439 * Because the USB/IP protocol doesn't specify a way to get notified about 440 * new or removed exported devices we have to poll the host periodically for 441 * a new device list and compare it with the previous one notifying the proxy 442 * service about changes. 443 */ 444 while ( !fDeviceListChangedOrWokenUp 445 && (aMillies == RT_INDEFINITE_WAIT || aMillies > 0) 446 && RT_SUCCESS(rc)) 447 { 448 RTMSINTERVAL msWait = aMillies; 449 uint64_t msPollStart = RTTimeMilliTS(); 450 uint32_t uIdReady = 0; 451 uint32_t fEventsRecv = 0; 452 453 /* Limit the waiting time to 1sec so we can either reconnect or get a new device list. */ 454 if (m->hSocket == NIL_RTSOCKET || m->enmRecvState == kUsbIpRecvState_None) 455 msWait = RT_MIN(1000, aMillies); 456 457 rc = RTPoll(m->hPollSet, msWait, &fEventsRecv, &uIdReady); 458 if (RT_SUCCESS(rc)) 459 { 460 if (uIdReady == USBIP_POLL_ID_PIPE) 461 { 462 /* Drain the wakeup pipe. */ 463 char bRead = 0; 464 size_t cbRead = 0; 465 466 rc = RTPipeRead(m->hWakeupPipeR, &bRead, 1, &cbRead); 467 Assert(RT_SUCCESS(rc) && cbRead == 1); 468 fDeviceListChangedOrWokenUp = true; 469 } 470 else if (uIdReady == USBIP_POLL_ID_SOCKET) 471 { 472 if (fEventsRecv & RTPOLL_EVT_ERROR) 473 rc = VERR_NET_SHUTDOWN; 474 else 475 rc = receiveData(); 476 if (RT_SUCCESS(rc)) 477 { 478 /* 479 * If we are in the none state again we received the previous request 480 * and have a new device list to compare the old against. 481 */ 482 if (m->enmRecvState == kUsbIpRecvState_None) 483 { 484 if (hasDevListChanged(m->pHead)) 485 fDeviceListChangedOrWokenUp = true; 486 487 /* Update to the new list in any case now that we have it anyway. */ 488 RTSemFastMutexRequest(m->hMtxDevices); 489 freeDeviceList(m->pUsbDevicesCur); 490 m->cUsbDevicesCur = m->cDevicesCur; 491 m->pUsbDevicesCur = m->pHead; 492 RTSemFastMutexRelease(m->hMtxDevices); 493 494 m->pHead = NULL; 495 resetRecvState(); 496 } 497 } 498 else if (rc == VERR_NET_SHUTDOWN || rc == VERR_BROKEN_PIPE) 499 { 500 LogRelMax(10, ("USB/IP: Lost connection to host \"%s\", trying to reconnect...\n", m->pszHost)); 501 disconnect(); 502 rc = VINF_SUCCESS; 503 } 504 } 505 else 506 { 507 AssertMsgFailed(("Invalid poll ID returned\n")); 508 rc = VERR_INVALID_STATE; 509 } 510 aMillies -= (RTTimeMilliTS() - msPollStart); 511 } 512 else if (rc == VERR_TIMEOUT) 513 { 514 aMillies -= msWait; 515 if (aMillies) 516 { 517 /* Try to reconnect and start a new request if we lost the connection before. */ 518 if (m->hSocket == NIL_RTSOCKET) 519 rc = reconnect(); 520 521 if (RT_SUCCESS(rc)) 522 rc = startListExportedDevicesReq(); 523 } 524 } 525 } 526 305 527 return rc; 306 528 } 307 529 308 530 309 /** String written to the wakeup pipe. */ 310 #define WAKE_UP_STRING "WakeUp!" 311 /** Length of the string written. */ 312 #define WAKE_UP_STRING_LEN ( sizeof(WAKE_UP_STRING) - 1 ) 313 314 int USBProxyServiceLinux::waitUsbfs(RTMSINTERVAL aMillies) 315 { 316 struct pollfd PollFds[2]; 317 318 /* Cap the wait interval if we're polling for udevd changing device permissions. */ 319 if (aMillies > 500 && mUdevPolls > 0) 320 { 321 mUdevPolls--; 322 aMillies = 500; 323 } 324 325 RT_ZERO(PollFds); 326 PollFds[0].fd = RTFileToNative(mhFile); 327 PollFds[0].events = POLLIN; 328 PollFds[1].fd = RTPipeToNative(mhWakeupPipeR); 329 PollFds[1].events = POLLIN | POLLERR | POLLHUP; 330 331 int rc = poll(&PollFds[0], 2, aMillies); 332 if (rc == 0) 333 return VERR_TIMEOUT; 334 if (rc > 0) 335 { 336 /* drain the pipe */ 337 if (PollFds[1].revents & POLLIN) 338 { 339 char szBuf[WAKE_UP_STRING_LEN]; 340 rc = RTPipeReadBlocking(mhWakeupPipeR, szBuf, sizeof(szBuf), NULL); 341 AssertRC(rc); 342 } 343 return VINF_SUCCESS; 344 } 345 return RTErrConvertFromErrno(errno); 346 } 347 348 349 int USBProxyServiceLinux::waitSysfs(RTMSINTERVAL aMillies) 350 { 351 #ifdef VBOX_USB_WITH_SYSFS 352 int rc = mpWaiter->Wait(aMillies); 353 if (rc == VERR_TRY_AGAIN) 354 { 355 RTThreadYield(); 356 rc = VINF_SUCCESS; 357 } 358 return rc; 359 #else /* !VBOX_USB_WITH_SYSFS */ 360 return USBProxyService::wait(aMillies); 361 #endif /* !VBOX_USB_WITH_SYSFS */ 362 } 363 364 365 int USBProxyServiceLinux::interruptWait(void) 531 int USBProxyBackendUsbIp::interruptWait(void) 366 532 { 367 533 AssertReturn(!isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE); 368 534 369 535 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 370 #ifdef VBOX_USB_WITH_SYSFS 371 LogFlowFunc(("mUsingUsbfsDevices=%d\n", mUsingUsbfsDevices)); 372 if (!mUsingUsbfsDevices) 373 { 374 mpWaiter->Interrupt(); 375 LogFlowFunc(("Returning VINF_SUCCESS\n")); 376 return VINF_SUCCESS; 377 } 378 #endif /* VBOX_USB_WITH_SYSFS */ 379 int rc = RTPipeWriteBlocking(mhWakeupPipeW, WAKE_UP_STRING, WAKE_UP_STRING_LEN, NULL); 536 537 int rc = RTPipeWriteBlocking(m->hWakeupPipeW, "", 1, NULL); 380 538 if (RT_SUCCESS(rc)) 381 RTPipeFlush(m hWakeupPipeW);539 RTPipeFlush(m->hWakeupPipeW); 382 540 LogFlowFunc(("returning %Rrc\n", rc)); 383 541 return rc; … … 385 543 386 544 387 PUSBDEVICE USBProxyServiceLinux::getDevices(void) 388 { 389 return USBProxyLinuxGetDevices(mDevicesRoot.c_str(), !mUsingUsbfsDevices); 390 } 545 PUSBDEVICE USBProxyBackendUsbIp::getDevices(void) 546 { 547 PUSBDEVICE pFirst = NULL; 548 PUSBDEVICE *ppNext = &pFirst; 549 550 /* Create a deep copy of the device list. */ 551 RTSemFastMutexRequest(m->hMtxDevices); 552 PUSBDEVICE pCur = m->pUsbDevicesCur; 553 while (pCur) 554 { 555 PUSBDEVICE pNew = (PUSBDEVICE)RTMemAllocZ(sizeof(USBDEVICE)); 556 if (pNew) 557 { 558 pNew->pszManufacturer = RTStrDup(pCur->pszManufacturer); 559 pNew->pszProduct = RTStrDup(pCur->pszProduct); 560 if (pCur->pszSerialNumber) 561 pNew->pszSerialNumber = RTStrDup(pCur->pszSerialNumber); 562 pNew->pszBackend = RTStrDup(pCur->pszBackend); 563 pNew->pszAddress = RTStrDup(pCur->pszAddress); 564 565 pNew->idVendor = pCur->idVendor; 566 pNew->idProduct = pCur->idProduct; 567 pNew->bcdDevice = pCur->bcdDevice; 568 pNew->bcdUSB = pCur->bcdUSB; 569 pNew->bDeviceClass = pCur->bDeviceClass; 570 pNew->bDeviceSubClass = pCur->bDeviceSubClass; 571 pNew->bDeviceProtocol = pCur->bDeviceProtocol; 572 pNew->bNumConfigurations = pCur->bNumConfigurations; 573 pNew->enmState = pCur->enmState; 574 pNew->u64SerialHash = pCur->u64SerialHash; 575 pNew->bBus = pCur->bBus; 576 pNew->bPort = pCur->bPort; 577 pNew->enmSpeed = pCur->enmSpeed; 578 579 /* link it */ 580 pNew->pNext = NULL; 581 pNew->pPrev = *ppNext; 582 *ppNext = pNew; 583 ppNext = &pNew->pNext; 584 } 585 586 pCur = pCur->pNext; 587 } 588 RTSemFastMutexRelease(m->hMtxDevices); 589 590 return pFirst; 591 } 592 593 /** 594 * Frees a given device list. 595 * 596 * @returns nothing. 597 * @param pHead The head of the device list to free. 598 */ 599 void USBProxyBackendUsbIp::freeDeviceList(PUSBDEVICE pHead) 600 { 601 PUSBDEVICE pNext = pHead; 602 while (pNext) 603 { 604 PUSBDEVICE pFree = pNext; 605 pNext = pNext->pNext; 606 freeDevice(pFree); 607 } 608 } 609 610 /** 611 * Resets the receive state to the idle state. 612 * 613 * @returns nothing. 614 */ 615 void USBProxyBackendUsbIp::resetRecvState() 616 { 617 freeDeviceList(m->pHead); 618 m->pHead = NULL; 619 m->ppNext = &m->pHead; 620 m->cDevicesCur = 0; 621 m->enmRecvState = kUsbIpRecvState_None; 622 m->cbResidualRecv = 0; 623 m->pbRecvBuf = &m->Scratch.abRecv[0]; 624 m->cDevicesLeft = 0; 625 } 626 627 /** 628 * Disconnects from the host and resets the receive state. 629 * 630 * @returns nothing. 631 */ 632 void USBProxyBackendUsbIp::disconnect() 633 { 634 if (m->hSocket != NIL_RTSOCKET) 635 { 636 int rc = RTPollSetRemove(m->hPollSet, USBIP_POLL_ID_SOCKET); 637 Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND); 638 639 RTTcpClientCloseEx(m->hSocket, false /*fGracefulShutdown*/); 640 m->hSocket = NIL_RTSOCKET; 641 } 642 643 resetRecvState(); 644 } 645 646 /** 647 * Tries to reconnect to the USB/IP host. 648 * 649 * @returns VBox status code. 650 */ 651 int USBProxyBackendUsbIp::reconnect() 652 { 653 /* Make sure we are disconnected. */ 654 disconnect(); 655 656 /* Connect to the USB/IP host. */ 657 int rc = RTTcpClientConnect(m->pszHost, m->uPort, &m->hSocket); 658 if (RT_SUCCESS(rc)) 659 { 660 rc = RTTcpSetSendCoalescing(m->hSocket, false); 661 if (RT_FAILURE(rc)) 662 LogRel(("USB/IP: Disabling send coalescing failed (rc=%Rrc), continuing nevertheless but expect increased latency\n", rc)); 663 664 rc = RTPollSetAddSocket(m->hPollSet, m->hSocket, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 665 USBIP_POLL_ID_SOCKET); 666 if (RT_FAILURE(rc)) 667 { 668 RTTcpClientCloseEx(m->hSocket, false /*fGracefulShutdown*/); 669 m->hSocket = NIL_RTSOCKET; 670 } 671 } 672 673 return rc; 674 } 675 676 /** 677 * Initiates a new List Exported Devices request. 678 * 679 * @returns VBox status code. 680 */ 681 int USBProxyBackendUsbIp::startListExportedDevicesReq() 682 { 683 int rc = VINF_SUCCESS; 684 685 /* 686 * Reset the current state and reconnect in case we were called in the middle 687 * of another transfer (which should not happen). 688 */ 689 Assert(m->enmRecvState == kUsbIpRecvState_None); 690 if (m->enmRecvState != kUsbIpRecvState_None) 691 rc = reconnect(); 692 693 if (RT_SUCCESS(rc)) 694 { 695 /* Send of the request. */ 696 UsbIpReqDevList ReqDevList; 697 ReqDevList.u16Version = RT_H2N_U16(USBIP_VERSION); 698 ReqDevList.u16Cmd = RT_H2N_U16(USBIP_INDICATOR_REQ | USBIP_REQ_RET_DEVLIST); 699 ReqDevList.u32Status = RT_H2N_U32(0); 700 rc = RTTcpWrite(m->hSocket, &ReqDevList, sizeof(ReqDevList)); 701 if (RT_SUCCESS(rc)) 702 advanceState(kUsbIpRecvState_Hdr); 703 } 704 705 return rc; 706 } 707 708 /** 709 * Advances the state machine to the given state. 710 * 711 * @returns nothing. 712 * @param enmRecvState The new receive state. 713 */ 714 void USBProxyBackendUsbIp::advanceState(USBIPRECVSTATE enmRecvState) 715 { 716 switch (enmRecvState) 717 { 718 case kUsbIpRecvState_None: 719 break; 720 case kUsbIpRecvState_Hdr: 721 { 722 m->cbResidualRecv = sizeof(UsbIpRetDevList); 723 m->pbRecvBuf = (uint8_t *)&m->Scratch.RetDevList; 724 break; 725 } 726 case kUsbIpRecvState_ExportedDevice: 727 { 728 m->cbResidualRecv = sizeof(UsbIpExportedDevice); 729 m->pbRecvBuf = (uint8_t *)&m->Scratch.ExportedDevice; 730 break; 731 } 732 case kUsbIpRecvState_DeviceInterface: 733 { 734 m->cbResidualRecv = sizeof(UsbIpDeviceInterface); 735 m->pbRecvBuf = (uint8_t *)&m->Scratch.DeviceInterface; 736 break; 737 } 738 default: 739 AssertMsgFailed(("Invalid USB/IP receive state %d\n", enmRecvState)); 740 return; 741 } 742 743 m->enmRecvState = enmRecvState; 744 } 745 746 /** 747 * Receives data from the USB/IP host and processes it when everything for the current 748 * state was received. 749 * 750 * @returns VBox status code. 751 */ 752 int USBProxyBackendUsbIp::receiveData() 753 { 754 size_t cbRecvd = 0; 755 int rc = RTTcpReadNB(m->hSocket, m->pbRecvBuf, m->cbResidualRecv, &cbRecvd); 756 if (RT_SUCCESS(rc)) 757 { 758 m->cbResidualRecv -= cbRecvd; 759 m->pbRecvBuf += cbRecvd; 760 /* In case we received everything for the current state process the data. */ 761 if (!m->cbResidualRecv) 762 rc = processData(); 763 } 764 765 return rc; 766 } 767 768 /** 769 * Processes the data in the scratch buffer based on the current state. 770 * 771 * @returns VBox status code. 772 */ 773 int USBProxyBackendUsbIp::processData() 774 { 775 int rc = VINF_SUCCESS; 776 777 switch (m->enmRecvState) 778 { 779 case kUsbIpRecvState_Hdr: 780 { 781 /* Check that the reply matches our expectations. */ 782 if ( RT_N2H_U16(m->Scratch.RetDevList.u16Version) == USBIP_VERSION 783 && RT_N2H_U16(m->Scratch.RetDevList.u16Cmd) == USBIP_REQ_RET_DEVLIST 784 && RT_N2H_U32(m->Scratch.RetDevList.u32Status) == USBIP_STATUS_SUCCESS) 785 { 786 /* Populate the number of exported devices in the list and go to the next state. */ 787 m->cDevicesLeft = RT_N2H_U32(m->Scratch.RetDevList.u32DevicesExported); 788 if (m->cDevicesLeft) 789 advanceState(kUsbIpRecvState_ExportedDevice); 790 else 791 advanceState(kUsbIpRecvState_None); 792 } 793 else 794 { 795 LogRelMax(10, ("USB/IP: Host sent an invalid reply to the list exported device request (Version: %#x Cmd: %#x Status: %#x)\n", 796 RT_N2H_U16(m->Scratch.RetDevList.u16Version), RT_N2H_U16(m->Scratch.RetDevList.u16Cmd), 797 RT_N2H_U32(m->Scratch.RetDevList.u32Status))); 798 rc = VERR_INVALID_STATE; 799 } 800 break; 801 } 802 case kUsbIpRecvState_ExportedDevice: 803 { 804 /* Create a new device and add it to the list. */ 805 usbProxyBackendUsbIpExportedDeviceN2H(&m->Scratch.ExportedDevice); 806 rc = addDeviceToList(&m->Scratch.ExportedDevice); 807 if (RT_SUCCESS(rc)) 808 { 809 m->cInterfacesLeft = m->Scratch.ExportedDevice.bNumInterfaces; 810 if (m->cInterfacesLeft) 811 advanceState(kUsbIpRecvState_DeviceInterface); 812 else 813 { 814 m->cDevicesLeft--; 815 if (m->cDevicesLeft) 816 advanceState(kUsbIpRecvState_ExportedDevice); 817 else 818 advanceState(kUsbIpRecvState_None); 819 } 820 } 821 break; 822 } 823 case kUsbIpRecvState_DeviceInterface: 824 { 825 /* 826 * If all interfaces for the current device were received receive the next device 827 * if there is another one left, if not we are done with the current request. 828 */ 829 m->cInterfacesLeft--; 830 if (m->cInterfacesLeft) 831 advanceState(kUsbIpRecvState_DeviceInterface); 832 else 833 { 834 m->cDevicesLeft--; 835 if (m->cDevicesLeft) 836 advanceState(kUsbIpRecvState_ExportedDevice); 837 else 838 advanceState(kUsbIpRecvState_None); 839 } 840 break; 841 } 842 case kUsbIpRecvState_None: 843 default: 844 AssertMsgFailed(("Invalid USB/IP receive state %d\n", m->enmRecvState)); 845 return VERR_INVALID_STATE; 846 } 847 848 return rc; 849 } 850 851 /** 852 * Creates a new USB device and adds it to the list. 853 * 854 * @returns VBox status code. 855 * @param pDev Pointer to the USB/IP exported device structure to take 856 * the information for the new device from. 857 */ 858 int USBProxyBackendUsbIp::addDeviceToList(PUsbIpExportedDevice pDev) 859 { 860 PUSBDEVICE pNew = (PUSBDEVICE)RTMemAllocZ(sizeof(USBDEVICE)); 861 if (!pNew) 862 return VERR_NO_MEMORY; 863 864 pNew->pszManufacturer = RTStrDup(""); 865 pNew->pszProduct = RTStrDup(""); 866 pNew->pszSerialNumber = NULL; 867 pNew->pszBackend = RTStrDup("usbip"); 868 869 /* Make sure the Bus id is 0 terminated. */ 870 pDev->szBusId[31] = '\0'; 871 RTStrAPrintf((char **)&pNew->pszAddress, "usbip://%s:%u:%s", m->pszHost, m->uPort, &pDev->szBusId[0]); 872 873 pNew->idVendor = pDev->u16VendorId; 874 pNew->idProduct = pDev->u16ProductId; 875 pNew->bcdDevice = pDev->u16BcdDevice; 876 pNew->bDeviceClass = pDev->bDeviceClass; 877 pNew->bDeviceSubClass = pDev->bDeviceSubClass; 878 pNew->bDeviceProtocol = pDev->bDeviceProtocol; 879 pNew->bNumConfigurations = pDev->bNumConfigurations; 880 pNew->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; 881 pNew->u64SerialHash = 0; 882 pNew->bBus = (uint8_t)pDev->u32BusNum; 883 pNew->bPort = (uint8_t)pDev->u32DevNum; 884 885 switch (pDev->u32Speed) 886 { 887 case USBIP_SPEED_LOW: 888 pNew->enmSpeed = USBDEVICESPEED_LOW; 889 pNew->bcdUSB = 1 << 8; 890 break; 891 case USBIP_SPEED_FULL: 892 pNew->enmSpeed = USBDEVICESPEED_FULL; 893 pNew->bcdUSB = 1 << 8; 894 break; 895 case USBIP_SPEED_HIGH: 896 pNew->enmSpeed = USBDEVICESPEED_HIGH; 897 pNew->bcdUSB = 2 << 8; 898 break; 899 case USBIP_SPEED_WIRELESS: 900 pNew->enmSpeed = USBDEVICESPEED_VARIABLE; 901 pNew->bcdUSB = 1 << 8; 902 break; 903 case USBIP_SPEED_SUPER: 904 pNew->enmSpeed = USBDEVICESPEED_SUPER; 905 pNew->bcdUSB = 3 << 8; 906 break; 907 case USBIP_SPEED_UNKNOWN: 908 default: 909 pNew->bcdUSB = 1 << 8; 910 pNew->enmSpeed = USBDEVICESPEED_UNKNOWN; 911 } 912 913 /* link it */ 914 pNew->pNext = NULL; 915 pNew->pPrev = *m->ppNext; 916 *m->ppNext = pNew; 917 m->ppNext = &pNew->pNext; 918 m->cDevicesCur++; 919 920 return VINF_SUCCESS; 921 } 922 923 /** 924 * Compares the given device list with the current one and returns whether it has 925 * changed. 926 * 927 * @returns flag whether the device list has changed compared to the current one. 928 * @param pDevices The device list to compare the current one against. 929 */ 930 bool USBProxyBackendUsbIp::hasDevListChanged(PUSBDEVICE pDevices) 931 { 932 /** @todo */ 933 return true; 934 } 935 -
trunk/src/VBox/Main/src-server/linux/USBGetDevices.cpp
r58170 r59117 1352 1352 pInfo->mDevice); 1353 1353 Dev->pszAddress = pszAddress; 1354 Dev->pszBackend = RTStrDup("host"); 1354 1355 1355 1356 /* Work out from the data collected whether we can support this device. */ -
trunk/src/VBox/Main/src-server/linux/USBProxyBackendLinux.cpp
r59116 r59117 60 60 * Initialize data members. 61 61 */ 62 USBProxy ServiceLinux::USBProxyServiceLinux(Host *aHost)63 : USBProxy Service(aHost), mhFile(NIL_RTFILE), mhWakeupPipeR(NIL_RTPIPE),62 USBProxyBackendLinux::USBProxyBackendLinux(USBProxyService *aUsbProxyService) 63 : USBProxyBackend(aUsbProxyService), mhFile(NIL_RTFILE), mhWakeupPipeR(NIL_RTPIPE), 64 64 mhWakeupPipeW(NIL_RTPIPE), mUsingUsbfsDevices(true /* see init */), 65 65 mUdevPolls(0), mpWaiter(NULL) 66 66 { 67 LogFlowThisFunc(("a Host=%p\n", aHost));67 LogFlowThisFunc(("aUsbProxyService=%p\n", aUsbProxyService)); 68 68 } 69 69 … … 71 71 * Initializes the object (called right after construction). 72 72 * 73 * @returns S_OK on success and non-fatal failures, some COM error otherwise.74 */ 75 HRESULT USBProxyServiceLinux::init(void)73 * @returns VBox status code. 74 */ 75 int USBProxyBackendLinux::init(void) 76 76 { 77 77 const char *pcszDevicesRoot; … … 86 86 mUsingUsbfsDevices ? "USBFS" : "sysfs")); 87 87 } 88 mLastError = rc; 89 return S_OK;88 89 return rc; 90 90 } 91 91 … … 95 95 * @returns iprt status code. 96 96 */ 97 int USBProxy ServiceLinux::initUsbfs(void)97 int USBProxyBackendLinux::initUsbfs(void) 98 98 { 99 99 Assert(mUsingUsbfsDevices); … … 128 128 } 129 129 else 130 Log(("USBProxy ServiceLinux::USBProxyServiceLinux: RTFilePipe failed with rc=%Rrc\n", rc));130 Log(("USBProxyBackendLinux::USBProxyBackendLinux: RTFilePipe failed with rc=%Rrc\n", rc)); 131 131 RTFileClose(mhFile); 132 132 } … … 137 137 { 138 138 rc = VERR_NO_MEMORY; 139 Log(("USBProxy ServiceLinux::USBProxyServiceLinux: out of memory!\n"));139 Log(("USBProxyBackendLinux::USBProxyBackendLinux: out of memory!\n")); 140 140 } 141 141 … … 150 150 * @returns iprt status code 151 151 */ 152 int USBProxy ServiceLinux::initSysfs(void)152 int USBProxyBackendLinux::initSysfs(void) 153 153 { 154 154 Assert(!mUsingUsbfsDevices); … … 181 181 * Stop all service threads and free the device chain. 182 182 */ 183 USBProxy ServiceLinux::~USBProxyServiceLinux()183 USBProxyBackendLinux::~USBProxyBackendLinux() 184 184 { 185 185 LogFlowThisFunc(("\n")); … … 206 206 * and mark them as freed. 207 207 */ 208 void USBProxy ServiceLinux::doUsbfsCleanupAsNeeded()208 void USBProxyBackendLinux::doUsbfsCleanupAsNeeded() 209 209 { 210 210 /* … … 220 220 221 221 222 int USBProxy ServiceLinux::captureDevice(HostUSBDevice *aDevice)222 int USBProxyBackendLinux::captureDevice(HostUSBDevice *aDevice) 223 223 { 224 224 AssertReturn(aDevice, VERR_GENERAL_FAILURE); … … 239 239 240 240 241 int USBProxy ServiceLinux::releaseDevice(HostUSBDevice *aDevice)241 int USBProxyBackendLinux::releaseDevice(HostUSBDevice *aDevice) 242 242 { 243 243 AssertReturn(aDevice, VERR_GENERAL_FAILURE); … … 258 258 259 259 260 bool USBProxy ServiceLinux::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters,260 bool USBProxyBackendLinux::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, 261 261 SessionMachine **aIgnoreMachine) 262 262 { … … 265 265 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS); 266 266 if ( aUSBDevice->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE 267 && aDevice-> mUsb->enmState == USBDEVICESTATE_USED_BY_HOST)267 && aDevice->i_getUsbData()->enmState == USBDEVICESTATE_USED_BY_HOST) 268 268 LogRel(("USBProxy: Device %04x:%04x (%s) has become accessible.\n", 269 269 aUSBDevice->idVendor, aUSBDevice->idProduct, aUSBDevice->pszAddress)); … … 278 278 * See USBProxyService::deviceAdded for details. 279 279 */ 280 void USBProxy ServiceLinux::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines,280 void USBProxyBackendLinux::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, 281 281 PUSBDEVICE aUSBDevice) 282 282 { … … 292 292 293 293 devLock.release(); 294 USBProxy Service::deviceAdded(aDevice, llOpenedMachines, aUSBDevice);295 } 296 297 298 int USBProxy ServiceLinux::wait(RTMSINTERVAL aMillies)294 USBProxyBackend::deviceAdded(aDevice, llOpenedMachines, aUSBDevice); 295 } 296 297 298 int USBProxyBackendLinux::wait(RTMSINTERVAL aMillies) 299 299 { 300 300 int rc; … … 312 312 #define WAKE_UP_STRING_LEN ( sizeof(WAKE_UP_STRING) - 1 ) 313 313 314 int USBProxy ServiceLinux::waitUsbfs(RTMSINTERVAL aMillies)314 int USBProxyBackendLinux::waitUsbfs(RTMSINTERVAL aMillies) 315 315 { 316 316 struct pollfd PollFds[2]; … … 347 347 348 348 349 int USBProxy ServiceLinux::waitSysfs(RTMSINTERVAL aMillies)349 int USBProxyBackendLinux::waitSysfs(RTMSINTERVAL aMillies) 350 350 { 351 351 #ifdef VBOX_USB_WITH_SYSFS … … 363 363 364 364 365 int USBProxy ServiceLinux::interruptWait(void)365 int USBProxyBackendLinux::interruptWait(void) 366 366 { 367 367 AssertReturn(!isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE); … … 385 385 386 386 387 PUSBDEVICE USBProxy ServiceLinux::getDevices(void)387 PUSBDEVICE USBProxyBackendLinux::getDevices(void) 388 388 { 389 389 return USBProxyLinuxGetDevices(mDevicesRoot.c_str(), !mUsingUsbfsDevices); -
trunk/src/VBox/Main/src-server/solaris/USBProxyBackendSolaris.cpp
r59116 r59117 65 65 * Initializes the object (called right after construction). 66 66 * 67 * @returns S_OK on success and non-fatal failures, some COM error otherwise.68 */ 69 HRESULTUSBProxyServiceSolaris::init(void)67 * @returns VBox status code. 68 */ 69 int USBProxyServiceSolaris::init(void) 70 70 { 71 71 /* … … 74 74 int rc = RTSemEventCreate(&mNotifyEventSem); 75 75 if (RT_FAILURE(rc)) 76 { 77 mLastError = rc; 78 return E_FAIL; 79 } 76 return rc; 80 77 81 78 /* … … 85 82 if (RT_FAILURE(rc)) 86 83 { 87 mLastError = rc; 88 return S_OK; 89 } 84 RTSemEventDestroy(&mNotifyEventSem); 85 return rc; 86 } 87 90 88 mUSBLibInitialized = true; 91 89 … … 94 92 */ 95 93 start(); 96 return S_OK;94 return VINF_SUCCESS; 97 95 } 98 96 … … 342 340 343 341 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_Capturing); 344 AssertReturn(aDevice-> mUsb, VERR_INVALID_POINTER);342 AssertReturn(aDevice->i_getUsbData(), VERR_INVALID_POINTER); 345 343 346 344 /* … … 358 356 } 359 357 360 PUSBDEVICE pDev = aDevice-> mUsb;358 PUSBDEVICE pDev = aDevice->i_getUsbData(); 361 359 int rc = USBLibResetDevice(pDev->pszDevicePath, true); 362 360 if (RT_SUCCESS(rc)) 363 aDevice-> mOneShotId = pvId;361 aDevice->i_setBackendUserData(pvId); 364 362 else 365 363 { … … 378 376 * Remove the one-shot filter if necessary. 379 377 */ 380 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice-> mOneShotId));381 if (!aSuccess && aDevice-> mOneShotId)378 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice->i_getBackendUserData())); 379 if (!aSuccess && aDevice->i_getBackendUserData()) 382 380 USBLibRemoveFilter(aDevice->mOneShotId); 383 aDevice-> mOneShotId = NULL;381 aDevice->i_setBackendUserData(NULL); 384 382 } 385 383 … … 397 395 398 396 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_ReleasingToHost); 399 AssertReturn(aDevice-> mUsb, VERR_INVALID_POINTER);397 AssertReturn(aDevice->i_getUsbData(), VERR_INVALID_POINTER); 400 398 401 399 /* … … 413 411 } 414 412 415 PUSBDEVICE pDev = aDevice-> mUsb;413 PUSBDEVICE pDev = aDevice->i_getUsbData(); 416 414 int rc = USBLibResetDevice(pDev->pszDevicePath, true /* Re-attach */); 417 415 if (RT_SUCCESS(rc)) 418 aDevice-> mOneShotId = pvId;416 aDevice->i_setBackendUserData(pvId); 419 417 else 420 418 { … … 433 431 * Remove the one-shot filter if necessary. 434 432 */ 435 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice-> mOneShotId));436 if (!aSuccess && aDevice-> mOneShotId)437 USBLibRemoveFilter(aDevice-> mOneShotId);438 aDevice-> mOneShotId = NULL;433 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice->i_getBackendUserData())); 434 if (!aSuccess && aDevice->i_getBackendUserData()) 435 USBLibRemoveFilter(aDevice->i_getBackendUser()); 436 aDevice->i_setBackendUserData(NULL); 439 437 } 440 438 -
trunk/src/VBox/Main/src-server/win/USBProxyBackendWindows.cpp
r59116 r59117 50 50 * @returns S_OK on success and non-fatal failures, some COM error otherwise. 51 51 */ 52 HRESULTUSBProxyServiceWindows::init(void)52 int USBProxyServiceWindows::init(void) 53 53 { 54 54 /* … … 56 56 */ 57 57 mhEventInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL); 58 AssertReturn(mhEventInterrupt != INVALID_HANDLE_VALUE, E_FAIL);58 AssertReturn(mhEventInterrupt != INVALID_HANDLE_VALUE, VERR_OUT_OF_RESOURCES); 59 59 60 60 /* … … 71 71 { 72 72 LogFlowThisFunc(("returns successfully\n")); 73 return S_OK;73 return VINF_SUCCESS; 74 74 } 75 75 … … 81 81 82 82 LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc)); 83 mLastError = rc; 84 return S_OK; 83 return rc; 85 84 } 86 85 -
trunk/src/VBox/Main/testcase/Makefile.kmk
r56825 r59117 208 208 tstUSBProxyLinux_SOURCES = \ 209 209 tstUSBProxyLinux.cpp \ 210 ../src-server/linux/USBProxy ServiceLinux.cpp \210 ../src-server/linux/USBProxyBackendLinux.cpp \ 211 211 ../src-server/linux/USBGetDevices.cpp 212 212 tstUSBProxyLinux_INCS = \ -
trunk/src/VBox/Main/testcase/tstUSBProxyLinux.cpp
r57358 r59117 1 1 /* $Id$ */ 2 2 /** @file 3 * USBProxy ServiceLinux test case.3 * USBProxyBackendLinux test case. 4 4 */ 5 5 … … 21 21 *********************************************************************************************************************************/ 22 22 23 #include "USBProxy Service.h"23 #include "USBProxyBackend.h" 24 24 #include "USBGetDevices.h" 25 25 … … 32 32 /*** BEGIN STUBS ***/ 33 33 34 USBProxy Service::USBProxyService(Host*) {}35 USBProxy Service::~USBProxyService() {}36 HRESULT USBProxyService::init() { return S_OK; }37 int USBProxy Service::start() { return VINF_SUCCESS; }38 int USBProxy Service::stop() { return VINF_SUCCESS; }39 RWLockHandle *USBProxy Service::lockHandle() const { return NULL; }40 void *USBProxy Service::insertFilter(USBFILTER const*) { return NULL; }41 void USBProxy Service::removeFilter(void*) {}42 int USBProxy Service::captureDevice(HostUSBDevice*) { return VINF_SUCCESS; }43 void USBProxy Service::captureDeviceCompleted(HostUSBDevice*, bool) {}44 void USBProxy Service::detachingDevice(HostUSBDevice*) {}45 int USBProxy Service::releaseDevice(HostUSBDevice*) { return VINF_SUCCESS; }46 void USBProxy Service::releaseDeviceCompleted(HostUSBDevice*, bool) {}47 void USBProxy Service::serviceThreadInit() {}48 void USBProxy Service::serviceThreadTerm() {}49 int USBProxy Service::wait(unsigned int) { return VINF_SUCCESS; }50 int USBProxy Service::interruptWait() { return VINF_SUCCESS; }51 PUSBDEVICE USBProxy Service::getDevices() { return NULL; }52 void USBProxy Service::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice) {}53 void USBProxy Service::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice) {}54 void USBProxy Service::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList*, SessionMachine*) {}55 bool USBProxy Service::updateDeviceState(HostUSBDevice*, USBDEVICE*, bool*, SessionMachine**) { return true; }56 bool USBProxy Service::updateDeviceStateFake(HostUSBDevice*, USBDEVICE*, bool*, SessionMachine**) { return true; }57 bool USBProxy Service::isActive() { return true; }34 USBProxyBackend::USBProxyBackend(USBProxyService*) {} 35 USBProxyBackend::~USBProxyBackend() {} 36 int USBProxyBackend::init() { return VINF_SUCCESS; } 37 int USBProxyBackend::start() { return VINF_SUCCESS; } 38 int USBProxyBackend::stop() { return VINF_SUCCESS; } 39 RWLockHandle *USBProxyBackend::lockHandle() const { return NULL; } 40 void *USBProxyBackend::insertFilter(USBFILTER const*) { return NULL; } 41 void USBProxyBackend::removeFilter(void*) {} 42 int USBProxyBackend::captureDevice(HostUSBDevice*) { return VINF_SUCCESS; } 43 void USBProxyBackend::captureDeviceCompleted(HostUSBDevice*, bool) {} 44 void USBProxyBackend::detachingDevice(HostUSBDevice*) {} 45 int USBProxyBackend::releaseDevice(HostUSBDevice*) { return VINF_SUCCESS; } 46 void USBProxyBackend::releaseDeviceCompleted(HostUSBDevice*, bool) {} 47 void USBProxyBackend::serviceThreadInit() {} 48 void USBProxyBackend::serviceThreadTerm() {} 49 int USBProxyBackend::wait(unsigned int) { return VINF_SUCCESS; } 50 int USBProxyBackend::interruptWait() { return VINF_SUCCESS; } 51 PUSBDEVICE USBProxyBackend::getDevices() { return NULL; } 52 void USBProxyBackend::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice) {} 53 void USBProxyBackend::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice) {} 54 void USBProxyBackend::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList*, SessionMachine*) {} 55 bool USBProxyBackend::updateDeviceState(HostUSBDevice*, USBDEVICE*, bool*, SessionMachine**) { return true; } 56 bool USBProxyBackend::updateDeviceStateFake(HostUSBDevice*, USBDEVICE*, bool*, SessionMachine**) { return true; } 57 bool USBProxyBackend::isActive() { return true; } 58 58 59 59 VBoxMainHotplugWaiter::VBoxMainHotplugWaiter(char const*) {} … … 62 62 { 63 63 return Utf8Str(); 64 }65 66 int USBProxyService::getLastError(void)67 {68 return mLastError;69 64 } 70 65 -
trunk/src/VBox/VMM/VMMR3/PDMUsb.cpp
r58126 r59117 983 983 * @param pUVM The user mode VM handle. 984 984 * @param pUuid The UUID to be associated with the device. 985 * @param fRemote Whether it's a remove or local device.985 * @param pszBackend The proxy backend to use. 986 986 * @param pszAddress The address string. 987 987 * @param pvBackend Pointer to the backend. … … 990 990 * @param pszCaptureFilename Path to the file for USB traffic capturing, optional. 991 991 */ 992 VMMR3DECL(int) PDMR3UsbCreateProxyDevice(PUVM pUVM, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend,992 VMMR3DECL(int) PDMR3UsbCreateProxyDevice(PUVM pUVM, PCRTUUID pUuid, const char *pszBackend, const char *pszAddress, void *pvBackend, 993 993 uint32_t iUsbVersion, uint32_t fMaskedIfs, const char *pszCaptureFilename) 994 994 { … … 1040 1040 rc = RTUuidToStr(pUuid, &szUuid[0], sizeof(szUuid)); AssertRCBreak(rc); 1041 1041 rc = CFGMR3InsertString(pConfig, "UUID", szUuid); AssertRCBreak(rc); 1042 rc = CFGMR3Insert Integer(pConfig, "Remote", fRemote);AssertRCBreak(rc);1042 rc = CFGMR3InsertString(pConfig, "Backend", pszBackend); AssertRCBreak(rc); 1043 1043 rc = CFGMR3InsertInteger(pConfig, "USBVersion", iUsbVersion); AssertRCBreak(rc); 1044 1044 rc = CFGMR3InsertInteger(pConfig, "pvBackend", (uintptr_t)pvBackend); AssertRCBreak(rc);
Note:
See TracChangeset
for help on using the changeset viewer.