VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxBFE/HostUSBImpl.cpp@ 8207

Last change on this file since 8207 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: 9.8 KB
Line 
1/** @file
2 *
3 * VBox frontends: Basic Frontend (BFE):
4 * Implementation of HostUSB
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/* r=michael: I have removed almost all functionality from the Main
24 * version of this file, but left the structure as similar
25 * as I could in case we do need some of it some day. */
26
27#include <string>
28
29#ifdef RT_OS_LINUX
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <unistd.h>
33#include <sys/ioctl.h>
34#include <fcntl.h>
35#include <mntent.h>
36/* bird: This is a hack to work around conflicts between these linux kernel headers
37 * and the GLIBC tcpip headers. They have different declarations of the 4
38 * standard byte order functions. */
39#define _LINUX_BYTEORDER_GENERIC_H
40#include <linux/cdrom.h>
41#include <errno.h>
42#endif /* RT_OS_LINUX */
43
44#include "HostUSBImpl.h"
45#include "HostUSBDeviceImpl.h"
46#include "USBProxyService.h"
47#include "Logging.h"
48
49#include <VBox/pdm.h>
50#include <VBox/vusb.h>
51#include <VBox/usb.h>
52#include <VBox/err.h>
53#include <iprt/string.h>
54#include <iprt/system.h>
55#include <iprt/time.h>
56#include <stdio.h>
57
58#include <algorithm>
59
60// destructor
61/////////////////////////////////////////////////////////////////////////////
62
63HostUSB::~HostUSB()
64{
65 if (isReady())
66 uninit();
67}
68
69// public initializer/uninitializer for internal purposes only
70/////////////////////////////////////////////////////////////////////////////
71
72/**
73 * Initializes the host USB object.
74 *
75 * @returns COM result indicator
76 * @param parent handle of our parent object
77 */
78HRESULT HostUSB::init(PVM pVM)
79{
80 LogFlowMember(("HostUSB::init(): isReady=%d\n", isReady()));
81
82 ComAssertRet (!isReady(), E_UNEXPECTED);
83
84 /* Save pointer to the VM */
85 mpVM = pVM;
86
87/*
88#ifdef RT_OS_LINUX
89 mUSBProxyService = new USBProxyServiceLinux (this);
90#elif defined RT_OS_WINDOWS
91 mUSBProxyService = new USBProxyServiceWin32 (this);
92*/
93#ifdef RT_OS_L4
94 mUSBProxyService = new USBProxyServiceLinux (this);
95#else
96 mUSBProxyService = new USBProxyService (this);
97#endif
98 /** @todo handle !mUSBProxySerivce->isActive() and mUSBProxyService->getLastError()
99 * and somehow report or whatever that the proxy failed to startup.
100 * Also, there might be init order issues... */
101
102 setReady(true);
103 return S_OK;
104}
105
106/**
107 * Uninitializes the host object and sets the ready flag to FALSE.
108 * Called either from FinalRelease() or by the parent when it gets destroyed.
109 */
110void HostUSB::uninit()
111{
112 LogFlowMember(("HostUSB::uninit(): isReady=%d\n", isReady()));
113
114 AssertReturn (isReady(), (void) 0);
115
116 delete mUSBProxyService;
117 mUSBProxyService = NULL;
118
119 mUSBDevices.clear();
120
121 setReady (FALSE);
122}
123
124// private methods
125////////////////////////////////////////////////////////////////////////////////
126
127/**
128 * Called by USB proxy service when a new device is physically attached
129 * to the host.
130 *
131 * @param aDevice Pointer to the device which has been attached.
132 */
133void HostUSB::onUSBDeviceAttached (HostUSBDevice *aDevice)
134{
135 LogFlowMember (("HostUSB::onUSBDeviceAttached: aDevice=%p\n",
136 aDevice));
137 HostUSB::AutoLock alock (this);
138
139 // add to the collecion
140 mUSBDevices.push_back (aDevice);
141
142 // apply all filters (no need to lock the device, nobody can access it yet)
143 HRESULT rc = AttachUSBDevice(aDevice);
144 AssertComRC (rc);
145}
146
147/**
148 * Called by USB proxy service (?) when the device is physically detached
149 * from the host.
150 *
151 * @param aDevice Pointer to the device which has been detached.
152 */
153void HostUSB::onUSBDeviceDetached (HostUSBDevice *aDevice)
154{
155 LogFlowMember (("HostUSB::onUSBDeviceDetached: aDevice=%p\n",
156 &aDevice));
157 HostUSB::AutoLock alock (this);
158
159 RTUUID id = aDevice->id();
160
161 HostUSBDevice *device = 0;
162 HostUSB::USBDeviceList::iterator it = mUSBDevices.begin();
163 while (it != mUSBDevices.end())
164 {
165 if (RTUuidCompare(&(*it)->id(), &id) == 0)
166 {
167 device = (*it);
168 break;
169 }
170 ++ it;
171 }
172
173 AssertReturn (!!device, (void) 0);
174
175 // remove from the collecion
176 mUSBDevices.erase (it);
177
178 if (device->isCaptured())
179 {
180 // the device is captured, release it
181 alock.unlock();
182 HRESULT rc = DetachUSBDevice (device);
183 AssertComRC (rc);
184 }
185}
186
187/**
188 * Called by USB proxy service when the state of the host-driven device
189 * has changed because of non proxy interaction.
190 *
191 * @param aDevice The device in question.
192 */
193void HostUSB::onUSBDeviceStateChanged (HostUSBDevice *aDevice)
194{
195 LogFlowMember (("HostUSB::onUSBDeviceStateChanged: \n"));
196 HostUSB::AutoLock alock (this);
197
198 /** @todo dmik, is there anything we should do here? For instance if the device now is available? */
199}
200
201STDMETHODIMP HostUSB::AttachUSBDevice (HostUSBDevice *hostDevice)
202{
203 AutoLock alock (this);
204 /* This originally checked that the console object was ready.
205 * Unfortunately, this method now belongs to HostUSB, and can get
206 * called during construction - so before we are "ready". */
207// CHECK_READY();
208
209 /*
210 * Don't proceed unless we've found the usb controller.
211 */
212 if (!mpVM)
213 return setError (E_FAIL, tr ("VM is not powered up"));
214 PPDMIBASE pBase;
215 int vrc = PDMR3QueryLun (mpVM, "usb-ohci", 0, 0, &pBase);
216 if (VBOX_FAILURE (vrc))
217 return setError (E_FAIL, tr ("VM doesn't have a USB controller"));
218 /*
219 * Make sure that the device is in a captureable state
220 */
221 USBDeviceState_T eState = hostDevice->state();
222 if (eState != USBDeviceState_Busy &&
223 eState != USBDeviceState_Available &&
224 eState != USBDeviceState_Held)
225 return setError (E_FAIL,
226 tr ("Device is not in a capturable state"));
227 PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG)pBase->pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG);
228 AssertReturn (pRhConfig, E_FAIL);
229
230 /*
231 * Get the address and the Uuid, and call the pfnCreateProxyDevice roothub method in EMT.
232 */
233 std::string Address;
234 STDMETHODIMP hrc = hostDevice->COMGETTER (Address) (&Address);
235 AssertComRC (hrc);
236
237 RTUUID Uuid;
238 hrc = hostDevice->COMGETTER (Id) (Uuid);
239 AssertComRC (hrc);
240
241 /* No remote devices for now */
242 BOOL fRemote = FALSE;
243 void *pvRemote = NULL;
244
245 LogFlowMember (("Console::AttachUSBDevice: Proxying USB device '%s' %Vuuid...\n", Address.c_str(), &Uuid));
246 PVMREQ pReq;
247 vrc = VMR3ReqCall (mpVM, &pReq, RT_INDEFINITE_WAIT,
248 (PFNRT)pRhConfig->pfnCreateProxyDevice,
249 5, pRhConfig, &Uuid, fRemote,
250 Address.c_str(), pvRemote);
251 if (VBOX_SUCCESS (vrc))
252 vrc = pReq->iStatus;
253 VMR3ReqFree (pReq);
254 if (VBOX_SUCCESS (vrc))
255 hostDevice->setCaptured();
256 else
257 {
258 Log (("Console::AttachUSBDevice: Failed to create proxy device for '%s' %Vuuid, vrc=%Vrc\n", Address.c_str(),
259 &Uuid, vrc));
260 AssertRC (vrc);
261 /* michael: I presume this is not needed. */
262/* hrc = mControl->ReleaseUSBDevice (Uuid);
263 AssertComRC (hrc); */
264 switch (vrc)
265 {
266 case VERR_VUSB_NO_PORTS:
267 hrc = setError (E_FAIL, tr ("No available ports on the USB controller"));
268 break;
269 case VERR_VUSB_USBFS_PERMISSION:
270 hrc = setError (E_FAIL, tr ("Not permitted to open the USB device, check usbfs options"));
271 break;
272 default:
273 hrc = setError (E_FAIL, tr ("Failed to create USB proxy device: %Vrc"), vrc);
274 break;
275 }
276 return hrc;
277 }
278
279 return S_OK;
280}
281
282STDMETHODIMP HostUSB::DetachUSBDevice (HostUSBDevice *aDevice)
283{
284 AutoLock alock (this);
285 /* This originally checked that the console object was ready.
286 * Unfortunately, this method now belongs to HostUSB, and can get
287 * called during construction - so before we are "ready". */
288// CHECK_READY();
289
290 /*
291 * Detach the device from the VM
292 */
293 int vrc = VERR_PDM_DEVICE_NOT_FOUND;
294 if (mpVM)
295 {
296 PPDMIBASE pBase;
297 vrc = PDMR3QueryLun (mpVM, "usb-ohci", 0, 0, &pBase);
298 if (VBOX_SUCCESS (vrc))
299 {
300 PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG)pBase->pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG);
301 Assert (pRhConfig);
302
303 RTUUID Uuid = aDevice->id();
304 LogFlowMember (("Console::DetachUSBDevice: Detaching USB proxy device %Vuuid...\n", &Uuid));
305 PVMREQ pReq;
306 vrc = VMR3ReqCall (mpVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)pRhConfig->pfnDestroyProxyDevice,
307 2, pRhConfig, &Uuid);
308 if (VBOX_SUCCESS (vrc))
309 vrc = pReq->iStatus;
310 VMR3ReqFree (pReq);
311 }
312 }
313 if ( vrc == VERR_PDM_DEVICE_NOT_FOUND
314 || vrc == VERR_PDM_DEVICE_INSTANCE_NOT_FOUND)
315 {
316 Log (("Console::DetachUSBDevice: USB isn't enabled.\n"));
317 vrc = VINF_SUCCESS;
318 }
319 if (VBOX_SUCCESS (vrc))
320 return S_OK;
321 Log (("Console::AttachUSBDevice: Failed to detach the device from the USB controller, vrc=%Vrc.\n", vrc));
322 return(setError (E_UNEXPECTED, tr ("Failed to destroy the USB proxy device: %Vrc"), vrc));
323}
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