101e307bb33304d9dda53a7652510880e8228b13vboxsync * Emulated USB manager implementation.
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Copyright (C) 2013 Oracle Corporation
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.
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync#define LOG_GROUP_MAIN_OVERRIDE LOG_GROUP_MAIN_EMULATEDUSB
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Emulated USB webcam device instance.
101e307bb33304d9dda53a7652510880e8228b13vboxsynctypedef std::map <Utf8Str, Utf8Str> EUSBSettingsMap;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync static DECLCALLBACK(int) emulatedWebcamAttach(PUVM pUVM, EUSBWEBCAM *pThis, const char *pszDriver);
101e307bb33304d9dda53a7652510880e8228b13vboxsync static DECLCALLBACK(int) emulatedWebcamDetach(PUVM pUVM, EUSBWEBCAM *pThis);
101e307bb33304d9dda53a7652510880e8228b13vboxsync if (c == 0)
101e307bb33304d9dda53a7652510880e8228b13vboxsync delete this;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync const char *pszDriver);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync bool HasId(const char *pszId) { return RTStrCmp(pszId, mszUuid) == 0;}
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsyncstatic int emulatedWebcamInsertSettings(PCFGMNODE pConfig, EUSBSettingsMap *pSettings)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync for (it = pSettings->begin(); it != pSettings->end(); ++it)
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 rc = RTStrToUInt32Full(it->second.c_str(), 10, &u32);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync rc = CFGMR3InsertInteger(pConfig, it->first.c_str(), u32);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync rc = CFGMR3InsertString(pConfig, it->first.c_str(), it->second.c_str());
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync/* static */ DECLCALLBACK(int) EUSBWEBCAM::emulatedWebcamAttach(PUVM pUVM, EUSBWEBCAM *pThis, const char *pszDriver)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync int rc = emulatedWebcamInsertSettings(pConfig, &pThis->mDevSettings);
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync CFGMR3InsertInteger(pEUSB, "pfnCallback", (uintptr_t)EmulatedUSB::i_eusbCallback);
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync CFGMR3InsertInteger(pEUSB, "pvCallback", (uintptr_t)pThis->mpEmulatedUSB);
101e307bb33304d9dda53a7652510880e8228b13vboxsync CFGMR3InsertString(pConfig, "DevicePath", pThis->mPath.c_str());
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync CFGMR3InsertInteger(pConfig, "Object", (uintptr_t)pThis->mpvObject);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync rc = emulatedWebcamInsertSettings(pConfig, &pThis->mDrvSettings);
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/* static */ DECLCALLBACK(int) EUSBWEBCAM::emulatedWebcamDetach(PUVM pUVM, EUSBWEBCAM *pThis)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync RTStrPrintf(mszUuid, sizeof(mszUuid), "%RTuuid", &mUuid);
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync /* Parse mSettings string:
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync * "[dev:|drv:]Name1=Value1;[dev:|drv:]Name2=Value2"
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync /* Does the setting belong to device of driver. Default is both. */
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync if (RTStrNICmp(pszSrc, "drv:", strlen("drv:")) == 0)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync else if (RTStrNICmp(pszSrc, "dev:", strlen("dev:")) == 0)
d1ec055a27f5ad2bd1b9005d6ef1715a81689d6evboxsync /* Empty strings not allowed. */
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()));
101e307bb33304d9dda53a7652510880e8228b13vboxsync int vrc = VMR3ReqCallWaitU(pUVM, 0 /* idDstCpu (saved state, see #6232) */,
101e307bb33304d9dda53a7652510880e8228b13vboxsync int vrc = VMR3ReqCallWaitU(pUVM, 0 /* idDstCpu (saved state, see #6232) */,
101e307bb33304d9dda53a7652510880e8228b13vboxsync * EmulatedUSB implementation.
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Initializes the instance.
101e307bb33304d9dda53a7652510880e8228b13vboxsync * @param pConsole The owner.
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::init(ComObjPtr<Console> pConsole)
101e307bb33304d9dda53a7652510880e8228b13vboxsync /* Enclose the state transition NotReady->InInit->Ready */
101e307bb33304d9dda53a7652510880e8228b13vboxsync /* Confirm a successful initialization */
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Uninitializes the instance.
101e307bb33304d9dda53a7652510880e8228b13vboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
101e307bb33304d9dda53a7652510880e8228b13vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::getWebcams(std::vector<com::Utf8Str> &aWebcams)
101e307bb33304d9dda53a7652510880e8228b13vboxsync catch (...)
101e307bb33304d9dda53a7652510880e8228b13vboxsync for (i = 0, it = m.webcams.begin(); it != m.webcams.end(); ++it)
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::webcamAttach(const com::Utf8Str &aPath,
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync return i_webcamAttachInternal(aPath, aSettings, "HostWebcam", NULL);
5d8f180802bc04caa5104a9db780e21e5220df30vboxsyncHRESULT EmulatedUSB::i_webcamAttachInternal(const com::Utf8Str &aPath,
101e307bb33304d9dda53a7652510880e8228b13vboxsync const Utf8Str &path = aPath.isEmpty() || aPath == "."? s_pathDefault: aPath;
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync hrc = p->Initialize(m.pConsole, this, &path, &aSettings, pvObject);
101e307bb33304d9dda53a7652510880e8228b13vboxsync WebcamsMap::const_iterator it = m.webcams.find(path);
101e307bb33304d9dda53a7652510880e8228b13vboxsync catch (...)
3c8ad0020c82e3ff4f3daad0d8cf2ef39085cbcavboxsync hrc = p->Attach(m.pConsole, ptrVM.rawUVM(), pszDriver);
101e307bb33304d9dda53a7652510880e8228b13vboxsyncHRESULT EmulatedUSB::webcamDetach(const com::Utf8Str &aPath)
5d8f180802bc04caa5104a9db780e21e5220df30vboxsyncHRESULT EmulatedUSB::i_webcamDetachInternal(const com::Utf8Str &aPath)
101e307bb33304d9dda53a7652510880e8228b13vboxsync const Utf8Str &path = aPath.isEmpty() || aPath == "."? s_pathDefault: aPath;
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync/* static */ DECLCALLBACK(int) EmulatedUSB::eusbCallbackEMT(EmulatedUSB *pThis, char *pszId, uint32_t iEvent,
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync LogRelFlowFunc(("id %s event %d, data %p %d\n", pszId, iEvent, pvData, cbData));
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync HRESULT hr = pThis->webcamPathFromId(&path, pszId);
5d8f180802bc04caa5104a9db780e21e5220df30vboxsync/* static */ DECLCALLBACK(int) EmulatedUSB::i_eusbCallback(void *pv, const char *pszId, uint32_t iEvent,
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync /* Make a copy of parameters, forward to EMT and leave the callback to not hold any lock in the device. */
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync /* No wait. */
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync rc = VMR3ReqCallNoWaitU(ptrVM.rawUVM(), 0 /* idDstCpu */,
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsyncHRESULT EmulatedUSB::webcamPathFromId(com::Utf8Str *pPath, const char *pszId)
9e06f22a5a8961cd7a7da569d683097b17f04dd1vboxsync for (it = m.webcams.begin(); it != m.webcams.end(); ++it)
101e307bb33304d9dda53a7652510880e8228b13vboxsync/* vi: set tabstop=4 shiftwidth=4 expandtab: */