VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxBFE/HostUSBDeviceImpl.cpp@ 5965

Last change on this file since 5965 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.2 KB
Line 
1/** @file
2 *
3 * VBox frontends: Basic Frontend (BFE):
4 * Implementation of HostUSBDevice
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.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 as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "HostUSBDeviceImpl.h"
20#include "USBProxyService.h"
21#include "Logging.h"
22
23#include <VBox/err.h>
24
25
26// constructor / destructor
27/////////////////////////////////////////////////////////////////////////////
28
29HostUSBDevice::HostUSBDevice()
30 : mUSBProxyService (NULL), m_pUsb (NULL)
31{
32}
33
34HostUSBDevice::~HostUSBDevice()
35{
36 if (m_pUsb)
37 {
38 USBProxyService::freeDevice (m_pUsb);
39 m_pUsb = NULL;
40 }
41}
42
43// public initializer/uninitializer for internal purposes only
44/////////////////////////////////////////////////////////////////////////////
45
46/**
47 * Initializes the USB device object.
48 *
49 * @returns COM result indicator
50 * @param aUsb Pointer to the usb device structure for which the object is to be a wrapper.
51 * This structure is now fully owned by the HostUSBDevice object and will be
52 * freed when it is destructed.
53 * @param aUSBProxyService Pointer to the USB Proxy Service object.
54 */
55HRESULT HostUSBDevice::init(PUSBDEVICE aUsb, USBProxyService *aUSBProxyService)
56{
57 ComAssertRet (aUsb, E_INVALIDARG);
58
59 AutoLock alock (this);
60
61 /*
62 * We need a unique ID for this VBoxSVC session.
63 * The UUID isn't stored anywhere.
64 */
65 RTUuidCreate(&mId);
66
67 /*
68 * Convert from USBDEVICESTATE to USBDeviceState.
69 *
70 * Note that not all proxy backend can detect the HELD_BY_PROXY
71 * and USED_BY_GUEST states. But that shouldn't matter much.
72 */
73 switch (aUsb->enmState)
74 {
75 default:
76 AssertMsgFailed(("aUsb->enmState=%d\n", aUsb->enmState));
77 case USBDEVICESTATE_UNSUPPORTED:
78 mState = USBDeviceState_USBDeviceNotSupported;
79 break;
80 case USBDEVICESTATE_USED_BY_HOST:
81 mState = USBDeviceState_USBDeviceUnavailable;
82 break;
83 case USBDEVICESTATE_USED_BY_HOST_CAPTURABLE:
84 mState = USBDeviceState_USBDeviceBusy;
85 break;
86 case USBDEVICESTATE_UNUSED:
87 mState = USBDeviceState_USBDeviceAvailable;
88 break;
89 case USBDEVICESTATE_HELD_BY_PROXY:
90 mState = USBDeviceState_USBDeviceHeld;
91 break;
92 case USBDEVICESTATE_USED_BY_GUEST:
93 mState = USBDeviceState_USBDeviceCaptured;
94 break;
95 }
96
97 /*
98 * Other data members.
99 */
100 mIgnored = false;
101 mUSBProxyService = aUSBProxyService;
102 m_pUsb = aUsb;
103
104 setReady (true);
105 return S_OK;
106}
107
108// IUSBDevice properties
109/////////////////////////////////////////////////////////////////////////////
110
111/**
112 * Returns the GUID.
113 *
114 * @returns COM status code
115 * @param aId Address of result variable.
116 */
117STDMETHODIMP HostUSBDevice::COMGETTER(Id)(RTUUID &aId)
118{
119/* AutoLock alock (this); */
120 CHECK_READY();
121
122 aId = mId;
123 return S_OK;
124}
125
126
127/**
128 * Returns the vendor Id.
129 *
130 * @returns COM status code
131 * @param aVendorId Where to store the vendor id.
132 */
133STDMETHODIMP HostUSBDevice::COMGETTER(VendorId)(USHORT *aVendorId)
134{
135 if (!aVendorId)
136 return E_INVALIDARG;
137
138 AutoLock alock (this);
139 CHECK_READY();
140
141 *aVendorId = m_pUsb->idVendor;
142 return S_OK;
143}
144
145
146/**
147 * Returns the product Id.
148 *
149 * @returns COM status code
150 * @param aProductId Where to store the product id.
151 */
152STDMETHODIMP HostUSBDevice::COMGETTER(ProductId)(USHORT *aProductId)
153{
154 if (!aProductId)
155 return E_INVALIDARG;
156
157 AutoLock alock (this);
158 CHECK_READY();
159
160 *aProductId = m_pUsb->idProduct;
161 return S_OK;
162}
163
164
165/**
166 * Returns the revision BCD.
167 *
168 * @returns COM status code
169 * @param aRevision Where to store the revision BCD.
170 */
171STDMETHODIMP HostUSBDevice::COMGETTER(Revision)(USHORT *aRevision)
172{
173 if (!aRevision)
174 return E_INVALIDARG;
175
176 AutoLock alock (this);
177 CHECK_READY();
178
179 *aRevision = m_pUsb->bcdDevice;
180 return S_OK;
181}
182
183/**
184 * Returns the manufacturer string.
185 *
186 * @returns COM status code
187 * @param aManufacturer Where to put the return string.
188 */
189STDMETHODIMP HostUSBDevice::COMGETTER(Manufacturer)
190 (std::string *aManufacturer)
191{
192 if (!aManufacturer)
193 return E_INVALIDARG;
194
195 AutoLock alock (this);
196 CHECK_READY();
197
198 *aManufacturer = m_pUsb->pszManufacturer;
199 return S_OK;
200}
201
202
203/**
204 * Returns the product string.
205 *
206 * @returns COM status code
207 * @param aProduct Where to put the return string.
208 */
209STDMETHODIMP HostUSBDevice::COMGETTER(Product)(std::string *aProduct)
210{
211 if (!aProduct)
212 return E_INVALIDARG;
213
214 AutoLock alock (this);
215 CHECK_READY();
216
217 *aProduct = m_pUsb->pszProduct;
218 return S_OK;
219}
220
221
222/**
223 * Returns the serial number string.
224 *
225 * @returns COM status code
226 * @param aSerialNumber Where to put the return string.
227 */
228STDMETHODIMP HostUSBDevice::COMGETTER(SerialNumber)
229 (std::string *aSerialNumber)
230{
231 if (!aSerialNumber)
232 return E_INVALIDARG;
233
234 AutoLock alock (this);
235 CHECK_READY();
236
237 *aSerialNumber = m_pUsb->pszSerialNumber;
238 return S_OK;
239}
240
241/**
242 * Returns the device address string.
243 *
244 * @returns COM status code
245 * @param aAddress Where to put the returned string.
246 */
247STDMETHODIMP HostUSBDevice::COMGETTER(Address)(std::string *aAddress)
248{
249 if (!aAddress)
250 return E_INVALIDARG;
251
252 AutoLock alock (this);
253 CHECK_READY();
254
255 *aAddress = m_pUsb->pszAddress;
256 return S_OK;
257}
258
259STDMETHODIMP HostUSBDevice::COMGETTER(Port)(USHORT *aPort)
260{
261 if (!aPort)
262 return E_INVALIDARG;
263
264 AutoLock alock (this);
265 CHECK_READY();
266
267 ///@todo implement
268 aPort = 0;
269 return S_OK;
270}
271
272STDMETHODIMP HostUSBDevice::COMGETTER(Remote)(BOOL *aRemote)
273{
274 if (!aRemote)
275 return E_INVALIDARG;
276
277 AutoLock alock (this);
278 CHECK_READY();
279
280 *aRemote = FALSE;
281 return S_OK;
282}
283
284// IHostUSBDevice properties
285/////////////////////////////////////////////////////////////////////////////
286
287STDMETHODIMP HostUSBDevice::COMGETTER(State) (USBDeviceState_T *aState)
288{
289 if (!aState)
290 return E_POINTER;
291
292 AutoLock lock (this);
293 CHECK_READY();
294
295 *aState = mState;
296 return S_OK;
297}
298
299
300// public methods only for internal purposes
301////////////////////////////////////////////////////////////////////////////////
302
303/** Sets the ignored flag and returns the device to the host */
304void HostUSBDevice::setIgnored()
305{
306 AutoLock alock (this);
307 AssertReturn (isReady(), (void) 0);
308
309 AssertReturn (!mIgnored, (void) 0);
310
311 mIgnored = false;
312 setHostDriven();
313}
314
315/** Requests the capture */
316void HostUSBDevice::setCaptured ()
317{
318 AutoLock alock (this);
319 Assert (isReady());
320
321 Assert (
322 mState == USBDeviceState_USBDeviceBusy ||
323 mState == USBDeviceState_USBDeviceAvailable ||
324 mState == USBDeviceState_USBDeviceHeld);
325
326 mUSBProxyService->captureDevice (this);
327
328 mState = USBDeviceState_USBDeviceCaptured;
329}
330
331/**
332 * Returns the device back to the host
333 *
334 * @returns VBox status code.
335 */
336int HostUSBDevice::setHostDriven()
337{
338 AutoLock alock (this);
339 AssertReturn (isReady(), VERR_INVALID_PARAMETER);
340
341 AssertReturn (mState == USBDeviceState_USBDeviceHeld, VERR_INVALID_PARAMETER);
342
343 mState = USBDeviceState_USBDeviceAvailable;
344
345 return mUSBProxyService->releaseDevice (this);
346}
347
348/**
349 * Resets the device as if it were just attached to the host
350 *
351 * @returns VBox status code.
352 */
353int HostUSBDevice::reset()
354{
355 AutoLock alock (this);
356 AssertReturn (isReady(), VERR_INVALID_PARAMETER);
357
358 mState = USBDeviceState_USBDeviceHeld;
359 mIgnored = false;
360
361 /** @todo this operation might fail and cause the device to the reattached with a different address and all that. */
362 return mUSBProxyService->resetDevice (this);
363}
364
365/**
366 * Sets the state of the device, as it was reported by the host.
367 * This method applicable only for devices currently controlled by the host.
368 *
369 * @param aState new state
370 */
371void HostUSBDevice::setHostState (USBDeviceState_T aState)
372{
373 AssertReturn (
374 aState == USBDeviceState_USBDeviceUnavailable ||
375 aState == USBDeviceState_USBDeviceBusy ||
376 aState == USBDeviceState_USBDeviceAvailable,
377 (void) 0);
378
379 AssertReturn (
380 mState == USBDeviceState_USBDeviceNotSupported || /* initial state */
381 mState == USBDeviceState_USBDeviceUnavailable ||
382 mState == USBDeviceState_USBDeviceBusy ||
383 mState == USBDeviceState_USBDeviceAvailable,
384 (void) 0);
385
386 if (mState != aState)
387 {
388 mState = aState;
389 }
390}
391
392
393/**
394 * Compares this device with a USBDEVICE and decides which comes first.
395 *
396 * @returns < 0 if this should come before pDev2.
397 * @returns 0 if this and pDev2 are equal.
398 * @returns > 0 if this should come after pDev2.
399 *
400 * @param pDev2 Device 2.
401 */
402int HostUSBDevice::compare (PCUSBDEVICE pDev2)
403{
404 return compare (m_pUsb, pDev2);
405}
406
407
408/**
409 * Compares two USB devices and decides which comes first.
410 *
411 * @returns < 0 if pDev1 should come before pDev2.
412 * @returns 0 if pDev1 and pDev2 are equal.
413 * @returns > 0 if pDev1 should come after pDev2.
414 *
415 * @param pDev1 Device 1.
416 * @param pDev2 Device 2.
417 */
418/*static*/ int HostUSBDevice::compare (PCUSBDEVICE pDev1, PCUSBDEVICE pDev2)
419{
420 int iDiff = pDev1->idVendor - pDev2->idVendor;
421 if (iDiff)
422 return iDiff;
423
424 iDiff = pDev1->idProduct - pDev2->idProduct;
425 if (iDiff)
426 return iDiff;
427
428 /** @todo Sander, will this work on windows as well? Linux won't reuse an address for quite a while. */
429 return strcmp(pDev1->pszAddress, pDev2->pszAddress);
430}
431
432/**
433 * Updates the state of the device.
434 *
435 * @returns true if the state has actually changed.
436 * @returns false if the stat didn't change, or the change might have been cause by VBox.
437 *
438 * @param aDev The current device state as seen by the proxy backend.
439 */
440bool HostUSBDevice::updateState (PCUSBDEVICE aDev)
441{
442 AutoLock alock (this);
443
444 /*
445 * We have to be pretty conservative here because the proxy backend
446 * doesn't necessarily know everything that's going on. So, rather
447 * be overly careful than changing the state once when we shouldn't!
448 */
449 switch (aDev->enmState)
450 {
451 default:
452 AssertMsgFailed (("aDev->enmState=%d\n", aDev->enmState));
453 case USBDEVICESTATE_UNSUPPORTED:
454 Assert (mState == USBDeviceState_USBDeviceNotSupported);
455 return false;
456
457 case USBDEVICESTATE_USED_BY_HOST:
458 switch (mState)
459 {
460 case USBDeviceState_USBDeviceUnavailable:
461 /* the proxy may confuse following states with unavailable */
462 case USBDeviceState_USBDeviceHeld:
463 case USBDeviceState_USBDeviceCaptured:
464 return false;
465 default:
466 LogFlowMember ((" HostUSBDevice::updateState: %d -> %d\n",
467 mState, USBDeviceState_USBDeviceUnavailable));
468 mState = USBDeviceState_USBDeviceUnavailable;
469 return true;
470 }
471 break;
472
473 case USBDEVICESTATE_USED_BY_HOST_CAPTURABLE:
474 switch (mState)
475 {
476 case USBDeviceState_USBDeviceBusy:
477 /* the proxy may confuse following states with capturable */
478 case USBDeviceState_USBDeviceHeld:
479 case USBDeviceState_USBDeviceCaptured:
480 return false;
481 default:
482 LogFlowMember ((" HostUSBDevice::updateState: %d -> %d\n",
483 mState, USBDeviceState_USBDeviceBusy));
484 mState = USBDeviceState_USBDeviceBusy;
485 return true;
486 }
487 break;
488
489 case USBDEVICESTATE_UNUSED:
490 switch (mState)
491 {
492 case USBDeviceState_USBDeviceAvailable:
493 /* the proxy may confuse following state(s) with available */
494 case USBDeviceState_USBDeviceHeld:
495 case USBDeviceState_USBDeviceCaptured:
496 return false;
497 default:
498 LogFlowMember ((" HostUSBDevice::updateState: %d -> %d\n",
499 mState, USBDeviceState_USBDeviceAvailable));
500 mState = USBDeviceState_USBDeviceAvailable;
501 return true;
502 }
503 break;
504
505 case USBDEVICESTATE_HELD_BY_PROXY:
506 switch (mState)
507 {
508 case USBDeviceState_USBDeviceHeld:
509 /* the proxy may confuse following state(s) with held */
510 case USBDeviceState_USBDeviceAvailable:
511 case USBDeviceState_USBDeviceBusy:
512 case USBDeviceState_USBDeviceCaptured:
513 return false;
514 default:
515 LogFlowMember ((" HostUSBDevice::updateState: %d -> %d\n",
516 mState, USBDeviceState_USBDeviceHeld));
517 mState = USBDeviceState_USBDeviceHeld;
518 return true;
519 }
520 break;
521
522 case USBDEVICESTATE_USED_BY_GUEST:
523 switch (mState)
524 {
525 case USBDeviceState_USBDeviceCaptured:
526 /* the proxy may confuse following state(s) with captured */
527 case USBDeviceState_USBDeviceHeld:
528 case USBDeviceState_USBDeviceAvailable:
529 case USBDeviceState_USBDeviceBusy:
530 return false;
531 default:
532 LogFlowMember ((" HostUSBDevice::updateState: %d -> %d\n",
533 mState, USBDeviceState_USBDeviceHeld));
534 mState = USBDeviceState_USBDeviceHeld;
535 return true;
536 }
537 break;
538 }
539}
540
Note: See TracBrowser for help on using the repository browser.

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