VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/EmulatedUSBImpl.cpp@ 48406

最後變更 在這個檔案從48406是 48406,由 vboxsync 提交於 12 年 前

Main,VBoxManage: Implemented IConsole::EmulatedUSB. Removed IMachine::emulatedUSBWebcameraEnabled.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 9.9 KB
 
1/* $Id: EmulatedUSBImpl.cpp 48406 2013-09-10 12:53:50Z vboxsync $ */
2/** @file
3 *
4 * Emulated USB manager implementation.
5 */
6
7/*
8 * Copyright (C) 2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.alldomusa.eu.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "EmulatedUSBImpl.h"
20#include "ConsoleImpl.h"
21#include "Logging.h"
22
23#include <VBox/vmm/pdmusb.h>
24
25
26/*
27 * Emulated USB webcam device instance.
28 */
29typedef std::map <Utf8Str, Utf8Str> EUSBSettingsMap;
30
31typedef enum EUSBDEVICESTATUS
32{
33 EUSBDEVICE_CREATED,
34 EUSBDEVICE_ATTACHING,
35 EUSBDEVICE_ATTACHED
36} EUSBDEVICESTATUS;
37
38class EUSBWEBCAM /* : public EUSBDEVICE */
39{
40 private:
41 int32_t volatile mcRefs;
42
43 RTUUID mUuid;
44
45 Utf8Str mPath;
46 Utf8Str mSettings;
47
48 EUSBSettingsMap mDevSettings;
49 EUSBSettingsMap mDrvSettings;
50
51 static DECLCALLBACK(int) emulatedWebcamAttach(PUVM pUVM, EUSBWEBCAM *pThis);
52 static DECLCALLBACK(int) emulatedWebcamDetach(PUVM pUVM, EUSBWEBCAM *pThis);
53
54 HRESULT settingsParse(void);
55
56 ~EUSBWEBCAM()
57 {
58 }
59
60 public:
61 EUSBWEBCAM()
62 :
63 mcRefs(1),
64 enmStatus(EUSBDEVICE_CREATED)
65 {
66 RT_ZERO(mUuid);
67 }
68
69 int32_t AddRef(void)
70 {
71 return ASMAtomicIncS32(&mcRefs);
72 }
73
74 void Release(void)
75 {
76 int32_t c = ASMAtomicDecS32(&mcRefs);
77 if (c == 0)
78 {
79 delete this;
80 }
81 }
82
83 HRESULT Initialize(Console *pConsole,
84 const com::Utf8Str *aPath,
85 const com::Utf8Str *aSettings);
86 HRESULT Attach(Console *pConsole,
87 PUVM pUVM);
88 HRESULT Detach(Console *pConsole,
89 PUVM pUVM);
90
91 EUSBDEVICESTATUS enmStatus;
92};
93
94
95/* static */ DECLCALLBACK(int) EUSBWEBCAM::emulatedWebcamAttach(PUVM pUVM, EUSBWEBCAM *pThis)
96{
97 EUSBSettingsMap::const_iterator it;
98
99 PCFGMNODE pInstance = CFGMR3CreateTree(pUVM);
100 PCFGMNODE pConfig;
101 CFGMR3InsertNode(pInstance, "Config", &pConfig);
102 for (it = pThis->mDevSettings.begin(); it != pThis->mDevSettings.end(); ++it)
103 CFGMR3InsertString(pConfig, it->first.c_str(), it->second.c_str());
104
105 PCFGMNODE pLunL0;
106 CFGMR3InsertNode(pInstance, "LUN#0", &pLunL0);
107 CFGMR3InsertString(pLunL0, "Driver", "HostWebcam");
108 CFGMR3InsertNode(pLunL0, "Config", &pConfig);
109 CFGMR3InsertString(pConfig, "DevicePath", pThis->mPath.c_str());
110 for (it = pThis->mDrvSettings.begin(); it != pThis->mDrvSettings.end(); ++it)
111 CFGMR3InsertString(pConfig, it->first.c_str(), it->second.c_str());
112
113 int rc = PDMR3UsbCreateEmulatedDevice(pUVM, "Webcam", pInstance, &pThis->mUuid);
114 LogRel(("PDMR3UsbCreateEmulatedDevice %Rrc\n", rc));
115 if (RT_FAILURE(rc) && pInstance)
116 CFGMR3RemoveNode(pInstance);
117 return rc;
118}
119
120/* static */ DECLCALLBACK(int) EUSBWEBCAM::emulatedWebcamDetach(PUVM pUVM, EUSBWEBCAM *pThis)
121{
122 return PDMR3UsbDetachDevice(pUVM, &pThis->mUuid);
123}
124
125HRESULT EUSBWEBCAM::Initialize(Console *pConsole,
126 const com::Utf8Str *aPath,
127 const com::Utf8Str *aSettings)
128{
129 HRESULT hrc = S_OK;
130
131 int vrc = RTUuidCreate(&mUuid);
132 if (RT_SUCCESS(vrc))
133 {
134 hrc = mPath.assignEx(*aPath);
135 if (SUCCEEDED(hrc))
136 {
137 hrc = mSettings.assignEx(*aSettings);
138 }
139
140 if (SUCCEEDED(hrc))
141 {
142 hrc = settingsParse();
143 }
144 }
145
146 if (SUCCEEDED(hrc) && RT_FAILURE(vrc))
147 {
148 LogFlowThisFunc(("%Rrc\n", vrc));
149 hrc = pConsole->setError(VBOX_E_IPRT_ERROR,
150 "Init emulated USB webcam (%Rrc)", vrc);
151 }
152
153 return hrc;
154}
155
156HRESULT EUSBWEBCAM::settingsParse(void)
157{
158 HRESULT hrc = S_OK;
159
160 return hrc;
161}
162
163HRESULT EUSBWEBCAM::Attach(Console *pConsole,
164 PUVM pUVM)
165{
166 HRESULT hrc = S_OK;
167
168 int vrc = VMR3ReqCallWaitU(pUVM, 0 /* idDstCpu (saved state, see #6232) */,
169 (PFNRT)emulatedWebcamAttach, 2,
170 pUVM, this);
171
172 if (SUCCEEDED(hrc) && RT_FAILURE(vrc))
173 {
174 LogFlowThisFunc(("%Rrc\n", vrc));
175 hrc = pConsole->setError(VBOX_E_IPRT_ERROR,
176 "Attach emulated USB webcam (%Rrc)", vrc);
177 }
178
179 return hrc;
180}
181
182HRESULT EUSBWEBCAM::Detach(Console *pConsole,
183 PUVM pUVM)
184{
185 HRESULT hrc = S_OK;
186
187 int vrc = VMR3ReqCallWaitU(pUVM, 0 /* idDstCpu (saved state, see #6232) */,
188 (PFNRT)emulatedWebcamDetach, 2,
189 pUVM, this);
190
191 if (SUCCEEDED(hrc) && RT_FAILURE(vrc))
192 {
193 LogFlowThisFunc(("%Rrc\n", vrc));
194 hrc = pConsole->setError(VBOX_E_IPRT_ERROR,
195 "Detach emulated USB webcam (%Rrc)", vrc);
196 }
197
198 return hrc;
199}
200
201
202/*
203 * EmulatedUSB implementation.
204 */
205DEFINE_EMPTY_CTOR_DTOR(EmulatedUSB)
206
207HRESULT EmulatedUSB::FinalConstruct()
208{
209 return BaseFinalConstruct();
210}
211
212void EmulatedUSB::FinalRelease()
213{
214 uninit();
215
216 BaseFinalRelease();
217}
218
219/*
220 * Initializes the instance.
221 *
222 * @param pConsole The owner.
223 */
224HRESULT EmulatedUSB::init(ComObjPtr<Console> pConsole)
225{
226 LogFlowThisFunc(("pConsole=%p\n", pConsole));
227
228 ComAssertRet(!pConsole.isNull(), E_INVALIDARG);
229
230 /* Enclose the state transition NotReady->InInit->Ready */
231 AutoInitSpan autoInitSpan(this);
232 AssertReturn(autoInitSpan.isOk(), E_FAIL);
233
234 m.pConsole = pConsole;
235
236 /* Confirm a successful initialization */
237 autoInitSpan.setSucceeded();
238
239 return S_OK;
240}
241
242/*
243 * Uninitializes the instance.
244 * Called either from FinalRelease() or by the parent when it gets destroyed.
245 */
246void EmulatedUSB::uninit()
247{
248 LogFlowThisFunc(("\n"));
249
250 m.pConsole.setNull();
251
252 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
253 WebcamsMap::iterator it = m.webcams.begin();
254 while (it != m.webcams.end())
255 {
256 EUSBWEBCAM *p = it->second;
257 it = m.webcams.erase(it);
258 p->Release();
259 }
260 alock.release();
261
262 /* Enclose the state transition Ready->InUninit->NotReady */
263 AutoUninitSpan autoUninitSpan(this);
264 if (autoUninitSpan.uninitDone())
265 return;
266}
267
268HRESULT EmulatedUSB::getWebcams(std::vector<com::Utf8Str> &aWebcams)
269{
270 HRESULT hrc = S_OK;
271
272 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
273
274 try
275 {
276 aWebcams.resize(m.webcams.size());
277 }
278 catch (std::bad_alloc &)
279 {
280 hrc = E_OUTOFMEMORY;
281 }
282 catch (...)
283 {
284 hrc = E_FAIL;
285 }
286
287 if (SUCCEEDED(hrc))
288 {
289 size_t i;
290 WebcamsMap::const_iterator it;
291 for (i = 0, it = m.webcams.begin(); it != m.webcams.end(); ++it)
292 aWebcams[i++] = it->first;
293 }
294
295 return hrc;
296}
297
298static const Utf8Str s_pathDefault(".0");
299
300HRESULT EmulatedUSB::webcamAttach(const com::Utf8Str &aPath,
301 const com::Utf8Str &aSettings)
302{
303 HRESULT hrc = S_OK;
304
305 const Utf8Str &path = aPath.isEmpty() || aPath == "."? s_pathDefault: aPath;
306
307 Console::SafeVMPtr ptrVM(m.pConsole);
308 if (ptrVM.isOk())
309 {
310 EUSBWEBCAM *p = new EUSBWEBCAM();
311 if (p)
312 {
313 hrc = p->Initialize(m.pConsole, &path, &aSettings);
314 if (SUCCEEDED(hrc))
315 {
316 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
317 WebcamsMap::const_iterator it = m.webcams.find(path);
318 if (it == m.webcams.end())
319 {
320 p->AddRef();
321 try
322 {
323 m.webcams[path] = p;
324 }
325 catch (std::bad_alloc &)
326 {
327 hrc = E_OUTOFMEMORY;
328 }
329 catch (...)
330 {
331 hrc = E_FAIL;
332 }
333 p->enmStatus = EUSBDEVICE_ATTACHING;
334 }
335 else
336 {
337 hrc = E_FAIL;
338 }
339 }
340
341 if (SUCCEEDED(hrc))
342 {
343 hrc = p->Attach(m.pConsole, ptrVM.rawUVM());
344 }
345
346 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
347 if (SUCCEEDED(hrc))
348 {
349 p->enmStatus = EUSBDEVICE_ATTACHED;
350 }
351 else
352 {
353 if (p->enmStatus != EUSBDEVICE_CREATED)
354 {
355 m.webcams.erase(path);
356 }
357 }
358 alock.release();
359
360 p->Release();
361 }
362 else
363 {
364 hrc = E_OUTOFMEMORY;
365 }
366 }
367 else
368 {
369 hrc = VBOX_E_INVALID_VM_STATE;
370 }
371
372 return hrc;
373}
374
375HRESULT EmulatedUSB::webcamDetach(const com::Utf8Str &aPath)
376{
377 HRESULT hrc = S_OK;
378
379 const Utf8Str &path = aPath.isEmpty() || aPath == "."? s_pathDefault: aPath;
380
381 Console::SafeVMPtr ptrVM(m.pConsole);
382 if (ptrVM.isOk())
383 {
384 EUSBWEBCAM *p = NULL;
385
386 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
387 WebcamsMap::iterator it = m.webcams.find(path);
388 if (it != m.webcams.end())
389 {
390 if (it->second->enmStatus == EUSBDEVICE_ATTACHED)
391 {
392 p = it->second;
393 m.webcams.erase(it);
394 }
395 }
396 alock.release();
397
398 if (p)
399 {
400 hrc = p->Detach(m.pConsole, ptrVM.rawUVM());
401 p->Release();
402 }
403 }
404 else
405 {
406 hrc = VBOX_E_INVALID_VM_STATE;
407 }
408
409 return hrc;
410}
411
412/* vi: set tabstop=4 shiftwidth=4 expandtab: */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette