VirtualBox

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

Last change on this file since 44337 was 44337, checked in by vboxsync, 12 years ago

update

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

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