VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/UsbWebcamInterface.cpp@ 44281

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

export to OSE

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 10.4 KB
 
1/* $Id: UsbWebcamInterface.cpp 44281 2013-01-14 08:42:53Z vboxsync $ */
2/** @file
3 * UsbWebcamInterface - Driver Interface for USB Webcam emulation.
4 */
5
6/*
7 * Copyright (C) 2011-2013 Oracle Corporation
8 *
9 * Oracle Corporation confidential
10 * All rights reserved
11 */
12
13
14#define LOG_GROUP LOG_GROUP_USB_WEBCAM
15#include "UsbWebcamInterface.h"
16#include "ConsoleImpl.h"
17#include "ConsoleVRDPServer.h"
18
19#include <VBox/vmm/pdmwebcaminfs.h>
20
21
22typedef struct EMWEBCAMDRV *PEMWEBCAMDRV;
23
24struct EMWEBCAMDRV
25{
26 EmWebcam *pEmWebcam;
27 PDMIWEBCAMDOWN IWebcamDown;
28 PPDMIWEBCAMUP pIWebcamUp;
29
30};
31
32struct EMWEBCAMREMOTE
33{
34 EmWebcam *pEmWebcam;
35
36 /* The remote identifier. */
37 VRDEVIDEOINDEVICEHANDLE deviceHandle;
38
39 /* The device identifier for the PDM device.*/
40 uint64_t u64DeviceId;
41};
42
43typedef struct EMWEBCAMREQCTX
44{
45 EMWEBCAMREMOTE *pRemote;
46 void *pvUser;
47} EMWEBCAMREQCTX;
48
49
50static DECLCALLBACK(int) drvEmWebcamControl(PPDMIWEBCAMDOWN pInterface,
51 void *pvUser,
52 uint64_t u64DeviceId,
53 const PDMIWEBCAM_CTRLHDR *pCtrl,
54 uint32_t cbCtrl)
55{
56 LogFlowFunc(("pInterface:%p\n", pInterface));
57
58 PEMWEBCAMDRV pThis = RT_FROM_MEMBER(pInterface, EMWEBCAMDRV, IWebcamDown);
59
60 return pThis->pEmWebcam->SendControl(pThis, pvUser, u64DeviceId, (const VRDEVIDEOINCTRLHDR *)pCtrl, cbCtrl);
61}
62
63
64EmWebcam::EmWebcam(Console *console)
65 : mpDrv(NULL),
66 mParent(console),
67 mpRemote(NULL),
68 mu64DeviceIdSrc(0)
69{
70}
71
72EmWebcam::~EmWebcam()
73{
74 if (mpDrv)
75 {
76 mpDrv->pEmWebcam = NULL;
77 mpDrv = NULL;
78 }
79}
80
81void EmWebcam::EmWebcamDestruct(EMWEBCAMDRV *pDrv)
82{
83 AssertReturnVoid(pDrv == mpDrv);
84
85 if (mpRemote)
86 {
87 mParent->consoleVRDPServer()->VideoInDeviceDetach(&mpRemote->deviceHandle);
88 RTMemFree(mpRemote);
89 mpRemote = NULL;
90 }
91}
92
93void EmWebcam::EmWebcamCbNotify(uint32_t u32Id, const void *pvData, uint32_t cbData)
94{
95 int rc = VINF_SUCCESS;
96
97 switch (u32Id)
98 {
99 case VRDE_VIDEOIN_NOTIFY_ATTACH:
100 {
101 VRDEVIDEOINNOTIFYATTACH *p = (VRDEVIDEOINNOTIFYATTACH *)pvData;
102 Assert(cbData == sizeof(VRDEVIDEOINNOTIFYATTACH));
103
104 LogFlowFunc(("ATTACH[%d,%d]\n", p->deviceHandle.u32ClientId, p->deviceHandle.u32DeviceId));
105
106 /* Currently only one device is allowed. */
107 if (mpRemote)
108 {
109 AssertFailed();
110 rc = VERR_NOT_SUPPORTED;
111 break;
112 }
113
114 EMWEBCAMREMOTE *pRemote = (EMWEBCAMREMOTE *)RTMemAllocZ(sizeof(EMWEBCAMREMOTE));
115 if (pRemote == NULL)
116 {
117 rc = VERR_NO_MEMORY;
118 break;
119 }
120
121 pRemote->pEmWebcam = this;
122 pRemote->deviceHandle = p->deviceHandle;
123 pRemote->u64DeviceId = ASMAtomicIncU64(&mu64DeviceIdSrc);
124
125 mpRemote = pRemote;
126
127 /* Tell the server that this webcam will be used. */
128 rc = mParent->consoleVRDPServer()->VideoInDeviceAttach(&mpRemote->deviceHandle, mpRemote);
129 if (RT_FAILURE(rc))
130 {
131 RTMemFree(mpRemote);
132 mpRemote = NULL;
133 break;
134 }
135
136 /* Get the device description. */
137 rc = mParent->consoleVRDPServer()->VideoInGetDeviceDesc(NULL, &mpRemote->deviceHandle);
138
139 if (RT_FAILURE(rc))
140 {
141 mParent->consoleVRDPServer()->VideoInDeviceDetach(&mpRemote->deviceHandle);
142 RTMemFree(mpRemote);
143 mpRemote = NULL;
144 break;
145 }
146
147 LogFlowFunc(("sent DeviceDesc\n"));
148 } break;
149
150 case VRDE_VIDEOIN_NOTIFY_DETACH:
151 {
152 VRDEVIDEOINNOTIFYDETACH *p = (VRDEVIDEOINNOTIFYDETACH *)pvData;
153 Assert(cbData == sizeof(VRDEVIDEOINNOTIFYDETACH));
154
155 LogFlowFunc(("DETACH[%d,%d]\n", p->deviceHandle.u32ClientId, p->deviceHandle.u32DeviceId));
156
157 /* @todo */
158 if (mpRemote)
159 {
160 mpDrv->pIWebcamUp->pfnWebcamUpDetached(mpDrv->pIWebcamUp,
161 mpRemote->u64DeviceId);
162
163 /* No need to tell the server by calling VideoInDeviceDetach because the server is telling. */
164 RTMemFree(mpRemote);
165 mpRemote = NULL;
166 }
167 } break;
168
169 default:
170 rc = VERR_INVALID_PARAMETER;
171 AssertFailed();
172 break;
173 }
174
175 return;
176}
177
178void EmWebcam::EmWebcamCbDeviceDesc(int rcRequest, void *pDeviceCtx, void *pvUser,
179 const VRDEVIDEOINDEVICEDESC *pDeviceDesc, uint32_t cbDeviceDesc)
180{
181 EMWEBCAMREMOTE *pRemote = (EMWEBCAMREMOTE *)pDeviceCtx;
182 Assert(pRemote == mpRemote);
183
184 LogFlowFunc(("rcRequest %Rrc %p %p %p %d\n",
185 rcRequest, pDeviceCtx, pvUser, pDeviceDesc, cbDeviceDesc));
186
187 if (RT_SUCCESS(rcRequest))
188 {
189 mpDrv->pIWebcamUp->pfnWebcamUpAttached(mpDrv->pIWebcamUp,
190 pRemote->u64DeviceId,
191 (const PDMIWEBCAM_DEVICEDESC *)pDeviceDesc,
192 cbDeviceDesc);
193 }
194 else
195 {
196 mParent->consoleVRDPServer()->VideoInDeviceDetach(&mpRemote->deviceHandle);
197 RTMemFree(mpRemote);
198 mpRemote = NULL;
199 }
200}
201
202void EmWebcam::EmWebcamCbControl(int rcRequest, void *pDeviceCtx, void *pvUser,
203 const VRDEVIDEOINCTRLHDR *pControl, uint32_t cbControl)
204{
205 EMWEBCAMREMOTE *pRemote = (EMWEBCAMREMOTE *)pDeviceCtx;
206 Assert(pRemote == mpRemote);
207
208 LogFlowFunc(("rcRequest %Rrc %p %p %p %d\n",
209 rcRequest, pDeviceCtx, pvUser, pControl, cbControl));
210
211 bool fResponse = (pvUser != NULL);
212
213 mpDrv->pIWebcamUp->pfnWebcamUpControl(mpDrv->pIWebcamUp,
214 fResponse,
215 pvUser,
216 mpRemote->u64DeviceId,
217 (const PDMIWEBCAM_CTRLHDR *)pControl,
218 cbControl);
219
220 RTMemFree(pvUser);
221}
222
223void EmWebcam::EmWebcamCbFrame(int rcRequest, void *pDeviceCtx,
224 const VRDEVIDEOINPAYLOADHDR *pFrame, uint32_t cbFrame)
225{
226 LogFlowFunc(("rcRequest %Rrc %p %p %d\n",
227 rcRequest, pDeviceCtx, pFrame, cbFrame));
228
229 mpDrv->pIWebcamUp->pfnWebcamUpFrame(mpDrv->pIWebcamUp,
230 mpRemote->u64DeviceId,
231 (const uint8_t *)pFrame,
232 cbFrame);
233}
234
235int EmWebcam::SendControl(EMWEBCAMDRV *pDrv, void *pvUser, uint64_t u64DeviceId,
236 const VRDEVIDEOINCTRLHDR *pControl, uint32_t cbControl)
237{
238 AssertReturn(pDrv == mpDrv, VERR_NOT_SUPPORTED);
239
240 int rc = VINF_SUCCESS;
241
242 EMWEBCAMREQCTX *pCtx = NULL;
243
244 /* Verify that there is a remote device. */
245 if ( !mpRemote
246 || mpRemote->u64DeviceId != u64DeviceId)
247 {
248 rc = VERR_NOT_SUPPORTED;
249 }
250
251 if (RT_SUCCESS(rc))
252 {
253 pCtx = (EMWEBCAMREQCTX *)RTMemAlloc(sizeof(EMWEBCAMREQCTX));
254 if (!pCtx)
255 {
256 rc = VERR_NO_MEMORY;
257 }
258 }
259
260 if (RT_SUCCESS(rc))
261 {
262 pCtx->pRemote = mpRemote;
263 pCtx->pvUser = pvUser;
264
265 rc = mParent->consoleVRDPServer()->VideoInControl(pCtx, &mpRemote->deviceHandle, pControl, cbControl);
266
267 if (RT_FAILURE(rc))
268 {
269 RTMemFree(pCtx);
270 }
271 }
272
273 return rc;
274}
275
276/* static */ DECLCALLBACK(void *) EmWebcam::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
277{
278 LogFlowFunc(("pInterface:%p, pszIID:%s\n", __FUNCTION__, pInterface, pszIID));
279 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
280 PEMWEBCAMDRV pThis = PDMINS_2_DATA(pDrvIns, PEMWEBCAMDRV);
281
282 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
283 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIWEBCAMDOWN, &pThis->IWebcamDown);
284 return NULL;
285}
286
287/* static */ DECLCALLBACK(int) EmWebcam::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
288{
289 LogFlow(("%s: iInstance/#d, pCfg:%p, fFlags:%x\n", __FUNCTION__, pDrvIns->iInstance, pCfg, fFlags));
290
291 PEMWEBCAMDRV pThis = PDMINS_2_DATA(pDrvIns, PEMWEBCAMDRV);
292
293 if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
294 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
295
296 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
297 ("Configuration error: Not possible to attach anything to this driver!\n"),
298 VERR_PDM_DRVINS_NO_ATTACH);
299
300 void *pv = NULL;
301 int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
302 AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc);
303
304 pThis->pEmWebcam = (EmWebcam *)pv;
305 pThis->pEmWebcam->mpDrv = pThis;
306
307 pDrvIns->IBase.pfnQueryInterface = drvQueryInterface;
308
309 pThis->IWebcamDown.pfnWebcamDownControl = drvEmWebcamControl;
310
311 pThis->pIWebcamUp = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIWEBCAMUP);
312
313 AssertReturn(pThis->pIWebcamUp, VERR_PDM_MISSING_INTERFACE);
314
315 return VINF_SUCCESS;
316}
317
318/* static */ DECLCALLBACK(void) EmWebcam::drvDestruct(PPDMDRVINS pDrvIns)
319{
320 LogFlow(("%s: iInstance/#d\n", __FUNCTION__, pDrvIns->iInstance));
321 PEMWEBCAMDRV pThis = PDMINS_2_DATA(pDrvIns, PEMWEBCAMDRV);
322 if (pThis->pEmWebcam)
323 {
324 pThis->pEmWebcam->EmWebcamDestruct(pThis);
325 pThis->pEmWebcam = NULL;
326 }
327}
328
329/* static */ const PDMDRVREG EmWebcam::DrvReg =
330{
331 /* u32Version */
332 PDM_DRVREG_VERSION,
333 /* szName[32] */
334 "EmWebcam",
335 /* szRCMod[32] */
336 "",
337 /* szR0Mod[32] */
338 "",
339 /* pszDescription */
340 "Main Driver communicating with VRDE",
341 /* fFlags */
342 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
343 /* fClass */
344 PDM_DRVREG_CLASS_USB,
345 /* cMaxInstances */
346 1,
347 /* cbInstance */
348 sizeof(EMWEBCAMDRV),
349 /* pfnConstruct */
350 EmWebcam::drvConstruct,
351 /* pfnDestruct */
352 EmWebcam::drvDestruct,
353 /* pfnRelocate */
354 NULL,
355 /* pfnIOCtl */
356 NULL,
357 /* pfnPowerOn */
358 NULL,
359 /* pfnReset */
360 NULL,
361 /* pfnSuspend */
362 NULL,
363 /* pfnResume */
364 NULL,
365 /* pfnAttach */
366 NULL,
367 /* pfnDetach */
368 NULL,
369 /* pfnPowerOff */
370 NULL,
371 /* pfnSoftReset */
372 NULL,
373 /* u32VersionEnd */
374 PDM_DRVREG_VERSION
375};
376/* vi: set tabstop=4 shiftwidth=4 expandtab: */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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