VirtualBox

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

Last change on this file since 14976 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

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