101e307bb33304d9dda53a7652510880e8228b13vboxsync/* $Id$ */
101e307bb33304d9dda53a7652510880e8228b13vboxsync/** @file
101e307bb33304d9dda53a7652510880e8228b13vboxsync *
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Emulated USB manager implementation.
101e307bb33304d9dda53a7652510880e8228b13vboxsync */
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync/*
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Copyright (C) 2013 Oracle Corporation
101e307bb33304d9dda53a7652510880e8228b13vboxsync *
101e307bb33304d9dda53a7652510880e8228b13vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
101e307bb33304d9dda53a7652510880e8228b13vboxsync * available from http://www.virtualbox.org. This file is free software;
101e307bb33304d9dda53a7652510880e8228b13vboxsync * you can redistribute it and/or modify it under the terms of the GNU
101e307bb33304d9dda53a7652510880e8228b13vboxsync * General Public License (GPL) as published by the Free Software
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
101e307bb33304d9dda53a7652510880e8228b13vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
101e307bb33304d9dda53a7652510880e8228b13vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
101e307bb33304d9dda53a7652510880e8228b13vboxsync */
101e307bb33304d9dda53a7652510880e8228b13vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync#define LOG_GROUP_MAIN_OVERRIDE LOG_GROUP_MAIN_EMULATEDUSB
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync#include "EmulatedUSBImpl.h"
101e307bb33304d9dda53a7652510880e8228b13vboxsync#include "ConsoleImpl.h"
101e307bb33304d9dda53a7652510880e8228b13vboxsync#include "Logging.h"
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync#include <VBox/vmm/pdmusb.h>
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync/*
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Emulated USB webcam device instance.
101e307bb33304d9dda53a7652510880e8228b13vboxsync */
101e307bb33304d9dda53a7652510880e8228b13vboxsynctypedef std::map <Utf8Str, Utf8Str> EUSBSettingsMap;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsynctypedef enum EUSBDEVICESTATUS
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBDEVICE_CREATED,
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBDEVICE_ATTACHING,
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBDEVICE_ATTACHED
101e307bb33304d9dda53a7652510880e8228b13vboxsync} EUSBDEVICESTATUS;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncclass EUSBWEBCAM /* : public EUSBDEVICE */
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync private:
101e307bb33304d9dda53a7652510880e8228b13vboxsync int32_t volatile mcRefs;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync EmulatedUSB *mpEmulatedUSB;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync RTUUID mUuid;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync char mszUuid[RTUUID_STR_LENGTH];
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync Utf8Str mPath;
101e307bb33304d9dda53a7652510880e8228b13vboxsync Utf8Str mSettings;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBSettingsMap mDevSettings;
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBSettingsMap mDrvSettings;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync void *mpvObject;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync static DECLCALLBACK(int) emulatedWebcamAttach(PUVM pUVM, EUSBWEBCAM *pThis, const char *pszDriver);
101e307bb33304d9dda53a7652510880e8228b13vboxsync static DECLCALLBACK(int) emulatedWebcamDetach(PUVM pUVM, EUSBWEBCAM *pThis);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT settingsParse(void);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync ~EUSBWEBCAM()
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync public:
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBWEBCAM()
101e307bb33304d9dda53a7652510880e8228b13vboxsync :
101e307bb33304d9dda53a7652510880e8228b13vboxsync mcRefs(1),
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync mpEmulatedUSB(NULL),
3e5224a1d5067b0e153420cfa3fa382164a1b1e1vboxsync mpvObject(NULL),
3e5224a1d5067b0e153420cfa3fa382164a1b1e1vboxsync enmStatus(EUSBDEVICE_CREATED)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync RT_ZERO(mUuid);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync RT_ZERO(mszUuid);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync int32_t AddRef(void)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync return ASMAtomicIncS32(&mcRefs);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync void Release(void)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync int32_t c = ASMAtomicDecS32(&mcRefs);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (c == 0)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync delete this;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT Initialize(Console *pConsole,
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync EmulatedUSB *pEmulatedUSB,
101e307bb33304d9dda53a7652510880e8228b13vboxsync const com::Utf8Str *aPath,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync const com::Utf8Str *aSettings,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync void *pvObject);
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT Attach(Console *pConsole,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync PUVM pUVM,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync const char *pszDriver);
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT Detach(Console *pConsole,
101e307bb33304d9dda53a7652510880e8228b13vboxsync PUVM pUVM);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync bool HasId(const char *pszId) { return RTStrCmp(pszId, mszUuid) == 0;}
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBDEVICESTATUS enmStatus;
101e307bb33304d9dda53a7652510880e8228b13vboxsync};
101e307bb33304d9dda53a7652510880e8228b13vboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsyncstatic int emulatedWebcamInsertSettings(PCFGMNODE pConfig, EUSBSettingsMap *pSettings)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync int rc = VINF_SUCCESS;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBSettingsMap::const_iterator it;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync for (it = pSettings->begin(); it != pSettings->end(); ++it)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync /* Convert some well known settings for backward compatibility. */
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if ( RTStrCmp(it->first.c_str(), "MaxPayloadTransferSize") == 0
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync || RTStrCmp(it->first.c_str(), "MaxFramerate") == 0)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync uint32_t u32 = 0;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync rc = RTStrToUInt32Full(it->second.c_str(), 10, &u32);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (rc == VINF_SUCCESS)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync rc = CFGMR3InsertInteger(pConfig, it->first.c_str(), u32);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync else
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (RT_SUCCESS(rc)) /* VWRN_* */
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync rc = VERR_INVALID_PARAMETER;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync else
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync rc = CFGMR3InsertString(pConfig, it->first.c_str(), it->second.c_str());
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (RT_FAILURE(rc))
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync break;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync return rc;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync}
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync/* static */ DECLCALLBACK(int) EUSBWEBCAM::emulatedWebcamAttach(PUVM pUVM, EUSBWEBCAM *pThis, const char *pszDriver)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync PCFGMNODE pInstance = CFGMR3CreateTree(pUVM);
101e307bb33304d9dda53a7652510880e8228b13vboxsync PCFGMNODE pConfig;
101e307bb33304d9dda53a7652510880e8228b13vboxsync CFGMR3InsertNode(pInstance, "Config", &pConfig);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync int rc = emulatedWebcamInsertSettings(pConfig, &pThis->mDevSettings);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (RT_FAILURE(rc))
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync return rc;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync PCFGMNODE pEUSB;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync CFGMR3InsertNode(pConfig, "EmulatedUSB", &pEUSB);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync CFGMR3InsertString(pEUSB, "Id", pThis->mszUuid);
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync CFGMR3InsertInteger(pEUSB, "pfnCallback", (uintptr_t)EmulatedUSB::i_eusbCallback);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync CFGMR3InsertInteger(pEUSB, "pvCallback", (uintptr_t)pThis->mpEmulatedUSB);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync PCFGMNODE pLunL0;
101e307bb33304d9dda53a7652510880e8228b13vboxsync CFGMR3InsertNode(pInstance, "LUN#0", &pLunL0);
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync CFGMR3InsertString(pLunL0, "Driver", pszDriver);
101e307bb33304d9dda53a7652510880e8228b13vboxsync CFGMR3InsertNode(pLunL0, "Config", &pConfig);
101e307bb33304d9dda53a7652510880e8228b13vboxsync CFGMR3InsertString(pConfig, "DevicePath", pThis->mPath.c_str());
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync CFGMR3InsertInteger(pConfig, "Object", (uintptr_t)pThis->mpvObject);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync rc = emulatedWebcamInsertSettings(pConfig, &pThis->mDrvSettings);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (RT_FAILURE(rc))
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync return rc;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
49266c3495090afba8c49601c1c14b6521f23b66vboxsync /* pInstance will be used by PDM and deallocated on error. */
dcc837f3a6f10996beb8aa7965f67f7f6c273fb4vboxsync rc = PDMR3UsbCreateEmulatedDevice(pUVM, "Webcam", pInstance, &pThis->mUuid, NULL);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync LogRelFlowFunc(("PDMR3UsbCreateEmulatedDevice %Rrc\n", rc));
101e307bb33304d9dda53a7652510880e8228b13vboxsync return rc;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync/* static */ DECLCALLBACK(int) EUSBWEBCAM::emulatedWebcamDetach(PUVM pUVM, EUSBWEBCAM *pThis)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync return PDMR3UsbDetachDevice(pUVM, &pThis->mUuid);
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EUSBWEBCAM::Initialize(Console *pConsole,
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync EmulatedUSB *pEmulatedUSB,
101e307bb33304d9dda53a7652510880e8228b13vboxsync const com::Utf8Str *aPath,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync const com::Utf8Str *aSettings,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync void *pvObject)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT hrc = S_OK;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync int vrc = RTUuidCreate(&mUuid);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (RT_SUCCESS(vrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync RTStrPrintf(mszUuid, sizeof(mszUuid), "%RTuuid", &mUuid);
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = mPath.assignEx(*aPath);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = mSettings.assignEx(*aSettings);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = settingsParse();
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (SUCCEEDED(hrc))
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync mpEmulatedUSB = pEmulatedUSB;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync mpvObject = pvObject;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc) && RT_FAILURE(vrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync LogFlowThisFunc(("%Rrc\n", vrc));
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = pConsole->setError(VBOX_E_IPRT_ERROR,
101e307bb33304d9dda53a7652510880e8228b13vboxsync "Init emulated USB webcam (%Rrc)", vrc);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync return hrc;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EUSBWEBCAM::settingsParse(void)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync HRESULT hr = S_OK;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync /* Parse mSettings string:
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync * "[dev:|drv:]Name1=Value1;[dev:|drv:]Name2=Value2"
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync */
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync char *pszSrc = mSettings.mutableRaw();
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (pszSrc)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync while (*pszSrc)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync /* Does the setting belong to device of driver. Default is both. */
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync bool fDev = true;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync bool fDrv = true;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (RTStrNICmp(pszSrc, "drv:", strlen("drv:")) == 0)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync pszSrc += strlen("drv:");
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync fDev = false;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync else if (RTStrNICmp(pszSrc, "dev:", strlen("dev:")) == 0)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync pszSrc += strlen("dev:");
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync fDrv = false;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync char *pszEq = RTStrStr(pszSrc, "=");
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (!pszEq)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync hr = E_INVALIDARG;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync break;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync char *pszEnd = RTStrStr(pszEq, ";");
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (!pszEnd)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync pszEnd = pszEq + strlen(pszEq);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync *pszEq = 0;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync char chEnd = *pszEnd;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync *pszEnd = 0;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync /* Empty strings not allowed. */
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (*pszSrc != 0 && pszEq[1] != 0)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (fDev)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync mDevSettings[pszSrc] = &pszEq[1];
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (fDrv)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync mDrvSettings[pszSrc] = &pszEq[1];
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync *pszEq = '=';
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync *pszEnd = chEnd;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync pszSrc = pszEnd;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (*pszSrc == ';')
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync pszSrc++;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (SUCCEEDED(hr))
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync {
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync EUSBSettingsMap::const_iterator it;
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync for (it = mDevSettings.begin(); it != mDevSettings.end(); ++it)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync LogRelFlowFunc(("[dev:%s] = [%s]\n", it->first.c_str(), it->second.c_str()));
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync for (it = mDrvSettings.begin(); it != mDrvSettings.end(); ++it)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync LogRelFlowFunc(("[drv:%s] = [%s]\n", it->first.c_str(), it->second.c_str()));
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync }
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync return hr;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EUSBWEBCAM::Attach(Console *pConsole,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync PUVM pUVM,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync const char *pszDriver)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT hrc = S_OK;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync int vrc = VMR3ReqCallWaitU(pUVM, 0 /* idDstCpu (saved state, see #6232) */,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync (PFNRT)emulatedWebcamAttach, 3,
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync pUVM, this, pszDriver);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc) && RT_FAILURE(vrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync LogFlowThisFunc(("%Rrc\n", vrc));
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = pConsole->setError(VBOX_E_IPRT_ERROR,
101e307bb33304d9dda53a7652510880e8228b13vboxsync "Attach emulated USB webcam (%Rrc)", vrc);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync return hrc;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EUSBWEBCAM::Detach(Console *pConsole,
101e307bb33304d9dda53a7652510880e8228b13vboxsync PUVM pUVM)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT hrc = S_OK;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync int vrc = VMR3ReqCallWaitU(pUVM, 0 /* idDstCpu (saved state, see #6232) */,
101e307bb33304d9dda53a7652510880e8228b13vboxsync (PFNRT)emulatedWebcamDetach, 2,
101e307bb33304d9dda53a7652510880e8228b13vboxsync pUVM, this);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc) && RT_FAILURE(vrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync LogFlowThisFunc(("%Rrc\n", vrc));
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = pConsole->setError(VBOX_E_IPRT_ERROR,
101e307bb33304d9dda53a7652510880e8228b13vboxsync "Detach emulated USB webcam (%Rrc)", vrc);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync return hrc;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync/*
101e307bb33304d9dda53a7652510880e8228b13vboxsync * EmulatedUSB implementation.
101e307bb33304d9dda53a7652510880e8228b13vboxsync */
101e307bb33304d9dda53a7652510880e8228b13vboxsyncDEFINE_EMPTY_CTOR_DTOR(EmulatedUSB)
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::FinalConstruct()
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync return BaseFinalConstruct();
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncvoid EmulatedUSB::FinalRelease()
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync uninit();
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync BaseFinalRelease();
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync/*
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Initializes the instance.
101e307bb33304d9dda53a7652510880e8228b13vboxsync *
101e307bb33304d9dda53a7652510880e8228b13vboxsync * @param pConsole The owner.
101e307bb33304d9dda53a7652510880e8228b13vboxsync */
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::init(ComObjPtr<Console> pConsole)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
3aaa225258168480a1464324666cb1fbc2aedb58vboxsync LogFlowThisFunc(("\n"));
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync ComAssertRet(!pConsole.isNull(), E_INVALIDARG);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync /* Enclose the state transition NotReady->InInit->Ready */
101e307bb33304d9dda53a7652510880e8228b13vboxsync AutoInitSpan autoInitSpan(this);
101e307bb33304d9dda53a7652510880e8228b13vboxsync AssertReturn(autoInitSpan.isOk(), E_FAIL);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync m.pConsole = pConsole;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync /* Confirm a successful initialization */
101e307bb33304d9dda53a7652510880e8228b13vboxsync autoInitSpan.setSucceeded();
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync return S_OK;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync/*
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Uninitializes the instance.
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
101e307bb33304d9dda53a7652510880e8228b13vboxsync */
101e307bb33304d9dda53a7652510880e8228b13vboxsyncvoid EmulatedUSB::uninit()
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync LogFlowThisFunc(("\n"));
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync m.pConsole.setNull();
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
101e307bb33304d9dda53a7652510880e8228b13vboxsync WebcamsMap::iterator it = m.webcams.begin();
101e307bb33304d9dda53a7652510880e8228b13vboxsync while (it != m.webcams.end())
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBWEBCAM *p = it->second;
67a6db19d55bc91c9d010f2e954163dbefc0e139vboxsync m.webcams.erase(it++);
101e307bb33304d9dda53a7652510880e8228b13vboxsync p->Release();
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync alock.release();
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
101e307bb33304d9dda53a7652510880e8228b13vboxsync AutoUninitSpan autoUninitSpan(this);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (autoUninitSpan.uninitDone())
101e307bb33304d9dda53a7652510880e8228b13vboxsync return;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::getWebcams(std::vector<com::Utf8Str> &aWebcams)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT hrc = S_OK;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync try
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync aWebcams.resize(m.webcams.size());
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync catch (std::bad_alloc &)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = E_OUTOFMEMORY;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync catch (...)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = E_FAIL;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync size_t i;
101e307bb33304d9dda53a7652510880e8228b13vboxsync WebcamsMap::const_iterator it;
101e307bb33304d9dda53a7652510880e8228b13vboxsync for (i = 0, it = m.webcams.begin(); it != m.webcams.end(); ++it)
101e307bb33304d9dda53a7652510880e8228b13vboxsync aWebcams[i++] = it->first;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync return hrc;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncstatic const Utf8Str s_pathDefault(".0");
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::webcamAttach(const com::Utf8Str &aPath,
101e307bb33304d9dda53a7652510880e8228b13vboxsync const com::Utf8Str &aSettings)
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync{
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync return i_webcamAttachInternal(aPath, aSettings, "HostWebcam", NULL);
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync}
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync
5d8f180802bc04caa5104a9db780e21e5220df30vboxsyncHRESULT EmulatedUSB::i_webcamAttachInternal(const com::Utf8Str &aPath,
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync const com::Utf8Str &aSettings,
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync const char *pszDriver,
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync void *pvObject)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT hrc = S_OK;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync const Utf8Str &path = aPath.isEmpty() || aPath == "."? s_pathDefault: aPath;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync Console::SafeVMPtr ptrVM(m.pConsole);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (ptrVM.isOk())
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBWEBCAM *p = new EUSBWEBCAM();
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (p)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync hrc = p->Initialize(m.pConsole, this, &path, &aSettings, pvObject);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
101e307bb33304d9dda53a7652510880e8228b13vboxsync WebcamsMap::const_iterator it = m.webcams.find(path);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (it == m.webcams.end())
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync p->AddRef();
101e307bb33304d9dda53a7652510880e8228b13vboxsync try
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync m.webcams[path] = p;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync catch (std::bad_alloc &)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = E_OUTOFMEMORY;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync catch (...)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = E_FAIL;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync p->enmStatus = EUSBDEVICE_ATTACHING;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync else
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = E_FAIL;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync hrc = p->Attach(m.pConsole, ptrVM.rawUVM(), pszDriver);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (SUCCEEDED(hrc))
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync p->enmStatus = EUSBDEVICE_ATTACHED;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync else
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (p->enmStatus != EUSBDEVICE_CREATED)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync m.webcams.erase(path);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync alock.release();
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync p->Release();
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync else
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = E_OUTOFMEMORY;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync else
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = VBOX_E_INVALID_VM_STATE;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync return hrc;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::webcamDetach(const com::Utf8Str &aPath)
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync{
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync return i_webcamDetachInternal(aPath);
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync}
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync
5d8f180802bc04caa5104a9db780e21e5220df30vboxsyncHRESULT EmulatedUSB::i_webcamDetachInternal(const com::Utf8Str &aPath)
101e307bb33304d9dda53a7652510880e8228b13vboxsync{
101e307bb33304d9dda53a7652510880e8228b13vboxsync HRESULT hrc = S_OK;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync const Utf8Str &path = aPath.isEmpty() || aPath == "."? s_pathDefault: aPath;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync Console::SafeVMPtr ptrVM(m.pConsole);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (ptrVM.isOk())
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync EUSBWEBCAM *p = NULL;
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
101e307bb33304d9dda53a7652510880e8228b13vboxsync WebcamsMap::iterator it = m.webcams.find(path);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (it != m.webcams.end())
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (it->second->enmStatus == EUSBDEVICE_ATTACHED)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync p = it->second;
101e307bb33304d9dda53a7652510880e8228b13vboxsync m.webcams.erase(it);
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync alock.release();
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (p)
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = p->Detach(m.pConsole, ptrVM.rawUVM());
101e307bb33304d9dda53a7652510880e8228b13vboxsync p->Release();
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
67a6db19d55bc91c9d010f2e954163dbefc0e139vboxsync else
67a6db19d55bc91c9d010f2e954163dbefc0e139vboxsync {
67a6db19d55bc91c9d010f2e954163dbefc0e139vboxsync hrc = E_INVALIDARG;
67a6db19d55bc91c9d010f2e954163dbefc0e139vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync else
101e307bb33304d9dda53a7652510880e8228b13vboxsync {
101e307bb33304d9dda53a7652510880e8228b13vboxsync hrc = VBOX_E_INVALID_VM_STATE;
101e307bb33304d9dda53a7652510880e8228b13vboxsync }
101e307bb33304d9dda53a7652510880e8228b13vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync return hrc;
101e307bb33304d9dda53a7652510880e8228b13vboxsync}
101e307bb33304d9dda53a7652510880e8228b13vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync/* static */ DECLCALLBACK(int) EmulatedUSB::eusbCallbackEMT(EmulatedUSB *pThis, char *pszId, uint32_t iEvent,
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync void *pvData, uint32_t cbData)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync{
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync LogRelFlowFunc(("id %s event %d, data %p %d\n", pszId, iEvent, pvData, cbData));
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync NOREF(cbData);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync int rc = VINF_SUCCESS;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (iEvent == 0)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync com::Utf8Str path;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync HRESULT hr = pThis->webcamPathFromId(&path, pszId);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (SUCCEEDED(hr))
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync hr = pThis->webcamDetach(path);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (FAILED(hr))
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync rc = VERR_INVALID_STATE;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync else
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync rc = VERR_NOT_FOUND;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync else
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync rc = VERR_INVALID_PARAMETER;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync RTMemFree(pszId);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync RTMemFree(pvData);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync LogRelFlowFunc(("rc %Rrc\n", rc));
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync return rc;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync}
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync/* static */ DECLCALLBACK(int) EmulatedUSB::i_eusbCallback(void *pv, const char *pszId, uint32_t iEvent,
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync const void *pvData, uint32_t cbData)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync{
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync /* Make a copy of parameters, forward to EMT and leave the callback to not hold any lock in the device. */
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync int rc = VINF_SUCCESS;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync void *pvIdCopy = NULL;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync void *pvDataCopy = NULL;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (cbData > 0)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync pvDataCopy = RTMemDup(pvData, cbData);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (!pvDataCopy)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync rc = VERR_NO_MEMORY;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (RT_SUCCESS(rc))
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync pvIdCopy = RTMemDup(pszId, strlen(pszId) + 1);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (!pvIdCopy)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync rc = VERR_NO_MEMORY;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (RT_SUCCESS(rc))
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync EmulatedUSB *pThis = (EmulatedUSB *)pv;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync Console::SafeVMPtr ptrVM(pThis->m.pConsole);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (ptrVM.isOk())
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync /* No wait. */
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync rc = VMR3ReqCallNoWaitU(ptrVM.rawUVM(), 0 /* idDstCpu */,
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync (PFNRT)EmulatedUSB::eusbCallbackEMT, 5,
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync pThis, pvIdCopy, iEvent, pvDataCopy, cbData);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync else
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync rc = VERR_INVALID_STATE;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (RT_FAILURE(rc))
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync RTMemFree(pvIdCopy);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync RTMemFree(pvDataCopy);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync return rc;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync}
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsyncHRESULT EmulatedUSB::webcamPathFromId(com::Utf8Str *pPath, const char *pszId)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync{
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync HRESULT hr = S_OK;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync Console::SafeVMPtr ptrVM(m.pConsole);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (ptrVM.isOk())
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync WebcamsMap::const_iterator it;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync for (it = m.webcams.begin(); it != m.webcams.end(); ++it)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync EUSBWEBCAM *p = it->second;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (p->HasId(pszId))
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync *pPath = it->first;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync break;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync if (it == m.webcams.end())
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync hr = E_FAIL;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync alock.release();
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync else
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync {
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync hr = VBOX_E_INVALID_VM_STATE;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync }
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync return hr;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync}
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync
101e307bb33304d9dda53a7652510880e8228b13vboxsync/* vi: set tabstop=4 shiftwidth=4 expandtab: */