VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/freebsd/USBProxyServiceFreeBSD.cpp@ 55567

Last change on this file since 55567 was 55095, checked in by vboxsync, 10 years ago

Assorted fixes for FreeBSD hosts, VBox compiles and runs again without further patches (tested on 10.1 amd64 )

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1/* $Id: USBProxyServiceFreeBSD.cpp 55095 2015-04-02 16:52:46Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Service, FreeBSD Specialization.
4 */
5
6/*
7 * Copyright (C) 2005-2012 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/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include "USBProxyService.h"
23#include "Logging.h"
24
25#include <VBox/usb.h>
26#include <VBox/usblib.h>
27#include <VBox/err.h>
28
29#include <iprt/string.h>
30#include <iprt/alloc.h>
31#include <iprt/assert.h>
32#include <iprt/file.h>
33#include <iprt/err.h>
34#include <iprt/mem.h>
35#include <iprt/param.h>
36#include <iprt/path.h>
37#include <iprt/semaphore.h>
38
39#include <stdlib.h>
40#include <string.h>
41#include <stdio.h>
42#include <errno.h>
43#include <unistd.h>
44#include <fcntl.h>
45#include <sys/poll.h>
46#include <dev/usb/usb.h>
47#include <dev/usb/usb_ioctl.h>
48
49/*******************************************************************************
50* Structures and Typedefs *
51*******************************************************************************/
52
53
54/*******************************************************************************
55* Global Variables *
56*******************************************************************************/
57
58/**
59 * Initialize data members.
60 */
61USBProxyServiceFreeBSD::USBProxyServiceFreeBSD(Host *aHost)
62 : USBProxyService(aHost)
63{
64 LogFlowThisFunc(("aHost=%p\n", aHost));
65}
66
67
68/**
69 * Initializes the object (called right after construction).
70 *
71 * @returns S_OK on success and non-fatal failures, some COM error otherwise.
72 */
73HRESULT USBProxyServiceFreeBSD::init(void)
74{
75 /*
76 * Create semaphore.
77 */
78 int rc = RTSemEventCreate(&mNotifyEventSem);
79 if (RT_FAILURE(rc))
80 {
81 mLastError = rc;
82 return E_FAIL;
83 }
84
85 /*
86 * Start the poller thread.
87 */
88 start();
89 return S_OK;
90}
91
92
93/**
94 * Stop all service threads and free the device chain.
95 */
96USBProxyServiceFreeBSD::~USBProxyServiceFreeBSD()
97{
98 LogFlowThisFunc(("\n"));
99
100 /*
101 * Stop the service.
102 */
103 if (isActive())
104 stop();
105
106 RTSemEventDestroy(mNotifyEventSem);
107 mNotifyEventSem = NULL;
108}
109
110
111int USBProxyServiceFreeBSD::captureDevice(HostUSBDevice *aDevice)
112{
113 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
114 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
115
116 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
117 LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));
118
119 /*
120 * Don't think we need to do anything when the device is held... fake it.
121 */
122 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_Capturing);
123 devLock.release();
124 interruptWait();
125
126 return VINF_SUCCESS;
127}
128
129
130int USBProxyServiceFreeBSD::releaseDevice(HostUSBDevice *aDevice)
131{
132 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
133 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
134
135 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
136 LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));
137
138 /*
139 * We're not really holding it atm., just fake it.
140 */
141 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_ReleasingToHost);
142 devLock.release();
143 interruptWait();
144
145 return VINF_SUCCESS;
146}
147
148
149bool USBProxyServiceFreeBSD::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters,
150 SessionMachine **aIgnoreMachine)
151{
152 AssertReturn(aDevice, false);
153 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
154
155 return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
156}
157
158
159/**
160 * A device was added
161 *
162 * See USBProxyService::deviceAdded for details.
163 */
164void USBProxyServiceFreeBSD::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines,
165 PUSBDEVICE aUSBDevice)
166{
167 USBProxyService::deviceAdded(aDevice, llOpenedMachines, aUSBDevice);
168}
169
170int USBProxyServiceFreeBSD::wait(RTMSINTERVAL aMillies)
171{
172 return RTSemEventWait(mNotifyEventSem, aMillies < 1000 ? 1000 : 5000);
173}
174
175
176int USBProxyServiceFreeBSD::interruptWait(void)
177{
178 return RTSemEventSignal(mNotifyEventSem);
179}
180
181
182/**
183 * Dumps a USBDEVICE structure to the log using LogLevel 3.
184 * @param pDev The structure to log.
185 * @todo This is really common code.
186 */
187DECLINLINE(void) usbLogDevice(PUSBDEVICE pDev)
188{
189 NOREF(pDev);
190
191 Log3(("USB device:\n"));
192 Log3(("Product: %s (%x)\n", pDev->pszProduct, pDev->idProduct));
193 Log3(("Manufacturer: %s (Vendor ID %x)\n", pDev->pszManufacturer, pDev->idVendor));
194 Log3(("Serial number: %s (%llx)\n", pDev->pszSerialNumber, pDev->u64SerialHash));
195 Log3(("Device revision: %d\n", pDev->bcdDevice));
196 Log3(("Device class: %x\n", pDev->bDeviceClass));
197 Log3(("Device subclass: %x\n", pDev->bDeviceSubClass));
198 Log3(("Device protocol: %x\n", pDev->bDeviceProtocol));
199 Log3(("USB version number: %d\n", pDev->bcdUSB));
200 Log3(("Device speed: %s\n",
201 pDev->enmSpeed == USBDEVICESPEED_UNKNOWN ? "unknown"
202 : pDev->enmSpeed == USBDEVICESPEED_LOW ? "1.5 MBit/s"
203 : pDev->enmSpeed == USBDEVICESPEED_FULL ? "12 MBit/s"
204 : pDev->enmSpeed == USBDEVICESPEED_HIGH ? "480 MBit/s"
205 : pDev->enmSpeed == USBDEVICESPEED_VARIABLE ? "variable"
206 : "invalid"));
207 Log3(("Number of configurations: %d\n", pDev->bNumConfigurations));
208 Log3(("Bus number: %d\n", pDev->bBus));
209 Log3(("Port number: %d\n", pDev->bPort));
210 Log3(("Device number: %d\n", pDev->bDevNum));
211 Log3(("Device state: %s\n",
212 pDev->enmState == USBDEVICESTATE_UNSUPPORTED ? "unsupported"
213 : pDev->enmState == USBDEVICESTATE_USED_BY_HOST ? "in use by host"
214 : pDev->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE ? "in use by host, possibly capturable"
215 : pDev->enmState == USBDEVICESTATE_UNUSED ? "not in use"
216 : pDev->enmState == USBDEVICESTATE_HELD_BY_PROXY ? "held by proxy"
217 : pDev->enmState == USBDEVICESTATE_USED_BY_GUEST ? "used by guest"
218 : "invalid"));
219 Log3(("OS device address: %s\n", pDev->pszAddress));
220}
221
222PUSBDEVICE USBProxyServiceFreeBSD::getDevices(void)
223{
224 PUSBDEVICE pDevices = NULL;
225 int FileUsb = 0;
226 int iBus = 0;
227 int iAddr = 1;
228 int rc = VINF_SUCCESS;
229 char *pszDevicePath = NULL;
230 uint32_t PlugTime = 0;
231
232 for (;;)
233 {
234 rc = RTStrAPrintf(&pszDevicePath, "/dev/%s%d.%d", USB_GENERIC_NAME, iBus, iAddr);
235 if (RT_FAILURE(rc))
236 {
237 mLastError = rc;
238 break;
239 }
240
241 LogFlowFunc((": Opening %s\n", pszDevicePath));
242
243 FileUsb = open(pszDevicePath, O_RDONLY);
244 if (FileUsb < 0)
245 {
246 if ( (errno != ENOENT)
247 && (errno != EACCES))
248 mLastError = RTErrConvertFromErrno(errno);
249
250 RTStrFree(pszDevicePath);
251
252 if ((errno == ENOENT) && (iAddr > 1))
253 {
254 iAddr = 1;
255 iBus++;
256 continue;
257 }
258 else if (errno == EACCES)
259 {
260 /* Skip devices without the right permission. */
261 iAddr++;
262 continue;
263 }
264 else
265 break;
266 }
267
268 LogFlowFunc((": %s opened successfully\n", pszDevicePath));
269
270 struct usb_device_info UsbDevInfo;
271 RT_ZERO(UsbDevInfo);
272
273 rc = ioctl(FileUsb, USB_GET_DEVICEINFO, &UsbDevInfo);
274 if (rc < 0)
275 {
276 LogFlowFunc((": Error querying device info rc=%Rrc\n", RTErrConvertFromErrno(errno)));
277 mLastError = RTErrConvertFromErrno(errno);
278 close(FileUsb);
279 RTStrFree(pszDevicePath);
280 break;
281 }
282
283 /* Filter out hubs */
284 if (UsbDevInfo.udi_class != 0x09)
285 {
286 PUSBDEVICE pDevice = (PUSBDEVICE)RTMemAllocZ(sizeof(USBDEVICE));
287 if (!pDevice)
288 {
289 mLastError = VERR_NO_MEMORY;
290 close(FileUsb);
291 RTStrFree(pszDevicePath);
292 break;
293 }
294
295 pDevice->enmState = USBDEVICESTATE_UNUSED;
296 pDevice->bBus = UsbDevInfo.udi_bus;
297 pDevice->bDeviceClass = UsbDevInfo.udi_class;
298 pDevice->bDeviceSubClass = UsbDevInfo.udi_subclass;
299 pDevice->bDeviceProtocol = UsbDevInfo.udi_protocol;
300 pDevice->bNumConfigurations = UsbDevInfo.udi_config_no;
301 pDevice->idVendor = UsbDevInfo.udi_vendorNo;
302 pDevice->idProduct = UsbDevInfo.udi_productNo;
303 pDevice->bDevNum = UsbDevInfo.udi_index;
304
305 switch (UsbDevInfo.udi_speed)
306 {
307 case USB_SPEED_LOW:
308 pDevice->enmSpeed = USBDEVICESPEED_LOW;
309 break;
310 case USB_SPEED_FULL:
311 pDevice->enmSpeed = USBDEVICESPEED_FULL;
312 break;
313 case USB_SPEED_HIGH:
314 pDevice->enmSpeed = USBDEVICESPEED_HIGH;
315 break;
316 case USB_SPEED_SUPER:
317 case USB_SPEED_VARIABLE:
318 default:
319 pDevice->enmSpeed = USBDEVICESPEED_UNKNOWN;
320 }
321
322 if (UsbDevInfo.udi_vendor[0] != '\0')
323 pDevice->pszManufacturer = RTStrDupN(UsbDevInfo.udi_vendor, sizeof(UsbDevInfo.udi_vendor));
324
325 if (UsbDevInfo.udi_product[0] != '\0')
326 pDevice->pszProduct = RTStrDupN(UsbDevInfo.udi_product, sizeof(UsbDevInfo.udi_product));
327
328 if (UsbDevInfo.udi_serial[0] != '\0')
329 {
330 pDevice->pszSerialNumber = RTStrDupN(UsbDevInfo.udi_serial, sizeof(UsbDevInfo.udi_serial));
331 pDevice->u64SerialHash = USBLibHashSerial(pDevice->pszSerialNumber);
332 }
333 rc = ioctl(FileUsb, USB_GET_PLUGTIME, &PlugTime);
334 if (rc == 0)
335 pDevice->u64SerialHash += PlugTime;
336
337 pDevice->pszAddress = RTStrDup(pszDevicePath);
338 pDevice->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
339
340 usbLogDevice(pDevice);
341
342 pDevice->pNext = pDevices;
343 if (pDevices)
344 pDevices->pPrev = pDevice;
345 pDevices = pDevice;
346 }
347 close(FileUsb);
348 RTStrFree(pszDevicePath);
349 iAddr++;
350 }
351
352 return pDevices;
353}
354
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