VirtualBox

source: vbox/trunk/src/VBox/Main/solaris/USBProxyServiceSolaris.cpp@ 31891

Last change on this file since 31891 was 31891, checked in by vboxsync, 15 years ago

Main: export USBProxyService and USBFilter to OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.9 KB
Line 
1/* $Id: USBProxyServiceSolaris.cpp 31891 2010-08-24 07:58:48Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Service, Solaris Specialization.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * Oracle Corporation confidential
10 * All rights reserved
11 */
12
13
14/*******************************************************************************
15* Header Files *
16*******************************************************************************/
17#include "USBProxyService.h"
18#include "Logging.h"
19
20#include <VBox/usb.h>
21#include <VBox/usblib.h>
22#include <VBox/err.h>
23#include <iprt/semaphore.h>
24#include <iprt/path.h>
25
26#include <sys/usb/usba.h>
27#include <syslog.h>
28
29/*******************************************************************************
30* Internal Functions *
31*******************************************************************************/
32static int solarisWalkDeviceNode(di_node_t Node, void *pvArg);
33static void solarisFreeUSBDevice(PUSBDEVICE pDevice);
34static USBDEVICESTATE solarisDetermineUSBDeviceState(PUSBDEVICE pDevice, di_node_t Node);
35
36
37/*******************************************************************************
38* Structures and Typedefs *
39*******************************************************************************/
40typedef struct USBDEVICELIST
41{
42 PUSBDEVICE pHead;
43 PUSBDEVICE pTail;
44} USBDEVICELIST;
45typedef USBDEVICELIST *PUSBDEVICELIST;
46
47
48/**
49 * Initialize data members.
50 */
51USBProxyServiceSolaris::USBProxyServiceSolaris (Host *aHost)
52 : USBProxyService (aHost), mUSBLibInitialized(false)
53{
54 LogFlowThisFunc(("aHost=%p\n", aHost));
55}
56
57
58/**
59 * Initializes the object (called right after construction).
60 *
61 * @returns S_OK on success and non-fatal failures, some COM error otherwise.
62 */
63HRESULT USBProxyServiceSolaris::init(void)
64{
65 /*
66 * Call the superclass method first.
67 */
68 HRESULT hrc = USBProxyService::init();
69 AssertComRCReturn(hrc, hrc);
70
71 /*
72 * Create semaphore.
73 */
74 int rc = RTSemEventCreate(&mNotifyEventSem);
75 if (RT_FAILURE(rc))
76 {
77 mLastError = rc;
78 return E_FAIL;
79 }
80
81 /*
82 * Initialize the USB library.
83 */
84 rc = USBLibInit();
85 if (RT_FAILURE(rc))
86 {
87 mLastError = rc;
88 return S_OK;
89 }
90 mUSBLibInitialized = true;
91
92 /*
93 * Start the poller thread.
94 */
95 start();
96 return S_OK;
97}
98
99
100/**
101 * Stop all service threads and free the device chain.
102 */
103USBProxyServiceSolaris::~USBProxyServiceSolaris()
104{
105 LogFlowThisFunc(("destruct\n"));
106
107 /*
108 * Stop the service.
109 */
110 if (isActive())
111 stop();
112
113 /*
114 * Terminate the USB library
115 */
116 if (mUSBLibInitialized)
117 {
118 USBLibTerm();
119 mUSBLibInitialized = false;
120 }
121
122 RTSemEventDestroy(mNotifyEventSem);
123 mNotifyEventSem = NULL;
124}
125
126
127void *USBProxyServiceSolaris::insertFilter(PCUSBFILTER aFilter)
128{
129 return USBLibAddFilter(aFilter);
130}
131
132
133void USBProxyServiceSolaris::removeFilter(void *pvID)
134{
135 USBLibRemoveFilter(pvID);
136}
137
138
139int USBProxyServiceSolaris::wait(RTMSINTERVAL aMillies)
140{
141 return RTSemEventWait(mNotifyEventSem, aMillies < 1000 ? 1000 : RT_MIN(aMillies, 5000));
142}
143
144
145int USBProxyServiceSolaris::interruptWait(void)
146{
147 return RTSemEventSignal(mNotifyEventSem);
148}
149
150
151PUSBDEVICE USBProxyServiceSolaris::getDevices(void)
152{
153 USBDEVICELIST DevList;
154 DevList.pHead = NULL;
155 DevList.pTail = NULL;
156 di_node_t RootNode = di_init("/", DINFOCPYALL);
157 if (RootNode != DI_NODE_NIL)
158 di_walk_node(RootNode, DI_WALK_CLDFIRST, &DevList, solarisWalkDeviceNode);
159
160 di_fini(RootNode);
161 return DevList.pHead;
162}
163
164#if 0
165static int solarisWalkMinor(di_node_t Node, di_minor_t Minor, void *pvArg)
166{
167 char *pszDevFsPath = di_devfs_path(Node);
168 char *pszMinorName = di_minor_name(Minor);
169 PUSBDEVICE pDev = (PUSBDEVICE)pvArg;
170
171 AssertRelease(pDev);
172
173 if (!pszDevFsPath || !pszMinorName)
174 return DI_WALK_CONTINUE;
175
176 RTStrAPrintf(&pDev->pszApId, "/devices%s:%s", pszDevFsPath, pszMinorName);
177 di_devfs_path_free(pszDevFsPath);
178
179 syslog(LOG_ERR, "VBoxUsbApId:%s\n", pDev->pszApId);
180 return DI_WALK_TERMINATE;
181}
182
183static bool solarisGetApId(PUSBDEVICE pDev, char *pszDevicePath, di_node_t RootNode)
184{
185 pDev->pszApId = NULL;
186
187 /* Skip "/devices" prefix if any */
188 char achDevicesDir[] = "/devices/";
189 if (strncmp(pszDevicePath, achDevicesDir, sizeof(achDevicesDir)) == 0)
190 pszDevicePath += sizeof(achDevicesDir);
191
192 char *pszPhysical = RTStrDup(pszDevicePath);
193 char *pszTmp = NULL;
194
195 /* Remove dynamic component "::" if any */
196 if ((pszTmp = strstr(pszPhysical, "::")) != NULL)
197 *pszTmp = '\0';
198
199 /* Remove minor name if any */
200 if ((pszTmp = strrchr(pszPhysical, ':')) != NULL)
201 *pszTmp = '\0';
202
203 /* Walk device tree */
204// di_node_t RootNode = di_init("/", DINFOCPYALL);
205// if (RootNode != DI_NODE_NIL)
206// {
207// di_node_t MinorNode = di_lookup_node(RootNode, pszPhysical);
208// if (MinorNode != DI_NODE_NIL)
209 {
210 di_walk_minor(RootNode, NULL, DI_CHECK_ALIAS | DI_CHECK_INTERNAL_PATH, pDev, solarisWalkMinor);
211 return true;
212 }
213// di_fini(RootNode);
214// }
215
216 return false;
217}
218#endif
219
220static int solarisWalkDeviceNode(di_node_t Node, void *pvArg)
221{
222 PUSBDEVICELIST pList = (PUSBDEVICELIST)pvArg;
223 AssertPtrReturn(pList, DI_WALK_TERMINATE);
224
225 /*
226 * Check if it's a USB device in the first place.
227 */
228 bool fUSBDevice = false;
229 char *pszCompatNames = NULL;
230 int cCompatNames = di_compatible_names(Node, &pszCompatNames);
231 for (int i = 0; i < cCompatNames; i++, pszCompatNames += strlen(pszCompatNames) + 1)
232 if (!strncmp(pszCompatNames, "usb", 3))
233 {
234 fUSBDevice = true;
235 break;
236 }
237
238 if (!fUSBDevice)
239 return DI_WALK_CONTINUE;
240
241 /*
242 * Check if it's a device node or interface.
243 */
244 int *pInt = NULL;
245 char *pStr = NULL;
246 int rc = DI_WALK_CONTINUE;
247 if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "interface", &pInt) < 0)
248 {
249 /* It's a device node. */
250 char *pszDevicePath = di_devfs_path(Node);
251 PUSBDEVICE pCur = (PUSBDEVICE)RTMemAllocZ(sizeof(*pCur));
252 if (!pCur)
253 {
254 LogRel(("USBService: failed to allocate %d bytes for PUSBDEVICE.\n", sizeof(*pCur)));
255 return DI_WALK_TERMINATE;
256 }
257
258 bool fValidDevice = false;
259 do
260 {
261 AssertBreak(pszDevicePath);
262
263 char *pszDriverName = di_driver_name(Node);
264
265 /*
266 * Skip hubs
267 */
268 if ( pszDriverName
269 && !strcmp(pszDriverName, "hubd"))
270 {
271 break;
272 }
273
274 /*
275 * Mandatory.
276 * snv_85 and above have usb-dev-descriptor node properties, but older one's do not.
277 * So if we cannot obtain the entire device descriptor, we try falling back to the
278 * invidividual properties (those must not fail, if it does we drop the device).
279 */
280 uchar_t *pDevData = NULL;
281 int cbProp = di_prop_lookup_bytes(DDI_DEV_T_ANY, Node, "usb-dev-descriptor", &pDevData);
282 if ( cbProp > 0
283 && pDevData)
284 {
285 usb_dev_descr_t *pDeviceDescriptor = (usb_dev_descr_t *)pDevData;
286 pCur->bDeviceClass = pDeviceDescriptor->bDeviceClass;
287 pCur->bDeviceSubClass = pDeviceDescriptor->bDeviceSubClass;
288 pCur->bDeviceProtocol = pDeviceDescriptor->bDeviceProtocol;
289 pCur->idVendor = pDeviceDescriptor->idVendor;
290 pCur->idProduct = pDeviceDescriptor->idProduct;
291 pCur->bcdDevice = pDeviceDescriptor->bcdDevice;
292 pCur->bcdUSB = pDeviceDescriptor->bcdUSB;
293 pCur->bNumConfigurations = pDeviceDescriptor->bNumConfigurations;
294 pCur->fPartialDescriptor = false;
295 }
296 else
297 {
298 AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-vendor-id", &pInt) > 0);
299 pCur->idVendor = (uint16_t)*pInt;
300
301 AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-product-id", &pInt) > 0);
302 pCur->idProduct = (uint16_t)*pInt;
303
304 AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-revision-id", &pInt) > 0);
305 pCur->bcdDevice = (uint16_t)*pInt;
306
307 AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-release", &pInt) > 0);
308 pCur->bcdUSB = (uint16_t)*pInt;
309
310 pCur->fPartialDescriptor = true;
311 }
312
313 char *pszPortAddr = di_bus_addr(Node);
314 if (pszPortAddr)
315 pCur->bPort = RTStrToUInt8(pszPortAddr); /* Bus & Port are mixed up (kernel driver/userland) */
316 else
317 pCur->bPort = 0;
318
319#if 0
320 /*
321 * Obtain the dev_t of the device.
322 */
323 di_minor_t Minor = di_minor_next(Node, DI_MINOR_NIL);
324 AssertBreak(Minor != DI_MINOR_NIL);
325 dev_t DeviceNum = di_minor_devt(Minor);
326
327 int DevInstance = 0;
328 rc = solarisUSBGetInstance(pszDevicePath, &DevInstance);
329
330 char szAddress[PATH_MAX + 128];
331 RTStrPrintf(szAddress, sizeof(szAddress), "/dev/usb/%x.%x|%s", pCur->idVendor, pCur->idProduct, pszDevicePath);
332 /* @todo after binding ugen we need to append the instance number to the address. Not yet sure how we can update PUSBDEVICE at that time. */
333
334 pCur->pszAddress = RTStrDup(szAddress);
335 AssertBreak(pCur->pszAddress);
336#endif
337
338#ifdef VBOX_WITH_NEW_USB_CODE_ON_SOLARIS
339 char pathBuf[PATH_MAX];
340 RTStrPrintf(pathBuf, sizeof(pathBuf), "%s", pszDevicePath);
341 RTPathStripFilename(pathBuf);
342
343 char szBuf[PATH_MAX + 48];
344 RTStrPrintf(szBuf, sizeof(szBuf), "%#x:%#x:%d:%s", pCur->idVendor, pCur->idProduct, pCur->bcdDevice, pathBuf);
345#else
346 char szBuf[2 * PATH_MAX];
347 RTStrPrintf(szBuf, sizeof(szBuf), "/dev/usb/%x.%x/%d|%s", pCur->idVendor, pCur->idProduct, 0, pszDevicePath);
348#endif
349 pCur->pszAddress = RTStrDup(szBuf);
350
351 pCur->pszDevicePath = RTStrDup(pszDevicePath);
352 AssertBreak(pCur->pszDevicePath);
353
354 /*
355 * Optional (some devices don't have all these)
356 */
357 if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-product-name", &pStr) > 0)
358 pCur->pszProduct = RTStrDup(pStr);
359
360 if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-vendor-name", &pStr) > 0)
361 pCur->pszManufacturer = RTStrDup(pStr);
362
363 if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-serialno", &pStr) > 0)
364 pCur->pszSerialNumber = RTStrDup(pStr);
365
366 if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "low-speed", &pInt) >= 0)
367 pCur->enmSpeed = USBDEVICESPEED_LOW;
368 else if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "high-speed", &pInt) >= 0)
369 pCur->enmSpeed = USBDEVICESPEED_HIGH;
370 else
371 pCur->enmSpeed = USBDEVICESPEED_FULL;
372
373 /* Determine state of the USB device. */
374 pCur->enmState = solarisDetermineUSBDeviceState(pCur, Node);
375
376// fValidDevice = solarisGetApId(pCur, pszDevicePath, Node);
377 fValidDevice = true;
378
379 /*
380 * Valid device, add it to the list.
381 */
382 if (fValidDevice)
383 {
384 pCur->pPrev = pList->pTail;
385 if (pList->pTail)
386 pList->pTail = pList->pTail->pNext = pCur;
387 else
388 pList->pTail = pList->pHead = pCur;
389 }
390 rc = DI_WALK_CONTINUE;
391 } while(0);
392
393 di_devfs_path_free(pszDevicePath);
394 if (!fValidDevice)
395 solarisFreeUSBDevice(pCur);
396 }
397 return rc;
398}
399
400
401static USBDEVICESTATE solarisDetermineUSBDeviceState(PUSBDEVICE pDevice, di_node_t Node)
402{
403 char *pszDriverName = di_driver_name(Node);
404
405 /* Not possible unless a user explicitly unbinds the default driver. */
406 if (!pszDriverName)
407 return USBDEVICESTATE_UNUSED;
408
409#ifdef VBOX_WITH_NEW_USB_CODE_ON_SOLARIS
410 if (!strncmp(pszDriverName, VBOXUSB_DRIVER_NAME, sizeof(VBOXUSB_DRIVER_NAME) - 1))
411 return USBDEVICESTATE_HELD_BY_PROXY;
412
413 NOREF(pDevice);
414 return USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
415#else
416
417 USBDEVICESTATE enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
418
419 /* Filter out keyboards, mouse */
420 if (!pDevice->fPartialDescriptor)
421 {
422 /*
423 * Here we have a fully valid device descriptor, so we fine
424 * tune what's usable and what's not.
425 */
426 if ( pDevice->bDeviceClass == 3 /* HID */
427 && ( pDevice->bDeviceProtocol == 1 /* Mouse */
428 || pDevice->bDeviceProtocol == 2)) /* Keyboard */
429 {
430 return USBDEVICESTATE_USED_BY_HOST;
431 }
432 }
433 else
434 {
435 /*
436 * Old Nevadas don't give full device descriptor in ring-3.
437 * So those Nevadas we just filter out all HIDs as unusable.
438 */
439 if (!strcmp(pszDriverName, "hid"))
440 return USBDEVICESTATE_USED_BY_HOST;
441 }
442
443 return enmState;
444#endif
445}
446
447
448int USBProxyServiceSolaris::captureDevice(HostUSBDevice *aDevice)
449{
450 /*
451 * Check preconditions.
452 */
453 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
454 LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
455 AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
456 Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
457 AssertReturn(aDevice->mUsb, VERR_INVALID_POINTER);
458
459#ifdef VBOX_WITH_NEW_USB_CODE_ON_SOLARIS
460 /*
461 * Create a one-shot capture filter for the device and reset the device.
462 */
463 USBFILTER Filter;
464 USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_CAPTURE);
465 initFilterFromDevice(&Filter, aDevice);
466
467 void *pvId = USBLibAddFilter(&Filter);
468 if (!pvId)
469 {
470 LogRel(("USBService: failed to add filter\n"));
471 return VERR_GENERAL_FAILURE;
472 }
473
474 PUSBDEVICE pDev = aDevice->mUsb;
475 int rc = USBLibResetDevice(pDev->pszDevicePath, true);
476 if (RT_SUCCESS(rc))
477 aDevice->mOneShotId = pvId;
478 else
479 {
480 USBLibRemoveFilter(pvId);
481 pvId = NULL;
482 }
483 LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
484 return rc;
485
486#else
487
488 /*
489 * Add the driver alias for binding the USB device to our driver.
490 */
491 PUSBDEVICE pDev = aDevice->mUsb;
492 int rc = USBLibAddDeviceAlias(pDev);
493 if (RT_SUCCESS(rc))
494 {
495 /*
496 * Reconnect and configure the device into an 'online' state because hard reset via
497 * usb_reset_device(9F) leaves the devices in an indeterminent state sometimes.
498 * In case of errors here, ignore them and prod further...
499 */
500 rc = USBLibResetDevice(pDev->pszDevicePath, true);
501 if (rc)
502 LogRel(("USBService: USBLibResetDevice failed. device=%s rc=%d\n", pDev->pszDevicePath, rc));
503
504 /*
505 * Get device driver instance number.
506 */
507 int iInstance;
508 rc = USBLibDeviceInstance(pDev->pszDevicePath, &iInstance);
509 if (RT_SUCCESS(rc))
510 {
511 /*
512 * Check device node to verify driver binding.
513 */
514 char szDevNode[PATH_MAX];
515 RTStrPrintf(szDevNode, sizeof(szDevNode), "/dev/usb/%x.%x/%d", pDev->idVendor, pDev->idProduct, 0);
516
517 /*
518 * Wait for the driver to export the device nodes with a timeout of ~5 seconds.
519 */
520 unsigned cTimeout = 0;
521 bool fExportedNodes = false;
522 while (cTimeout < 5000)
523 {
524 if (RTPathExists(szDevNode))
525 {
526 fExportedNodes = true;
527 break;
528 }
529 RTThreadSleep(500);
530 cTimeout += 500;
531 }
532 if (fExportedNodes)
533 {
534#if 0
535 /*
536 * This does not work. ProxyDevice somehow still gets the old values.
537 * Update our device with the node path as well as the device tree path.
538 */
539 RTStrFree((char *)pDev->pszAddress);
540 RTStrAPrintf(const_cast<char **>(&pDev->pszAddress), "%s|/devices%s", szDevNode, pDev->pszDevicePath);
541#endif
542
543 /*
544 * We don't need the system alias for this device anymore now that we've captured it.
545 * This will also ensure that in case VirtualBox crashes at a later point with
546 * a captured device it will not affect the user's USB devices.
547 */
548 USBLibRemoveDeviceAlias(pDev);
549 syslog(LOG_ERR, "USBPService: Success captured %s\n", aDevice->getName().c_str());
550 return VINF_SUCCESS;
551 }
552 else
553 {
554 rc = VERR_PATH_NOT_FOUND;
555 LogRel(("USBService: failed to stat %s for device.\n", szDevNode));
556 syslog(LOG_ERR, "USBService: failed to stat %s for device.\n", szDevNode);
557 }
558 }
559 else
560 LogRel(("USBService: failed to obtain device instance number for %s rc=%Rrc\n", aDevice->getName().c_str(), rc));
561 }
562 else
563 LogRel(("USBService: failed to add alias for device %s devicepath=%s rc=%Rrc\n", aDevice->getName().c_str(), pDev->pszDevicePath, rc));
564
565 USBLibRemoveDeviceAlias(pDev);
566 syslog(LOG_ERR, "USBPService: failed to capture device %s.\n", aDevice->getName().c_str());
567 return VERR_OPEN_FAILED;
568
569#endif
570
571}
572
573
574void USBProxyServiceSolaris::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
575{
576#ifdef VBOX_WITH_NEW_USB_CODE_ON_SOLARIS
577 /*
578 * Remove the one-shot filter if necessary.
579 */
580 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->getName().c_str(), aSuccess, aDevice->mOneShotId));
581 if (!aSuccess && aDevice->mOneShotId)
582 USBLibRemoveFilter(aDevice->mOneShotId);
583 aDevice->mOneShotId = NULL;
584#endif
585}
586
587
588int USBProxyServiceSolaris::releaseDevice(HostUSBDevice *aDevice)
589{
590 /*
591 * Check preconditions.
592 */
593 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
594 LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
595 AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
596 Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
597 AssertReturn(aDevice->mUsb, VERR_INVALID_POINTER);
598
599#ifdef VBOX_WITH_NEW_USB_CODE_ON_SOLARIS
600
601 /*
602 * Create a one-shot ignore filter for the device and reset it.
603 */
604 USBFILTER Filter;
605 USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_IGNORE);
606 initFilterFromDevice(&Filter, aDevice);
607
608 void *pvId = USBLibAddFilter(&Filter);
609 if (!pvId)
610 {
611 LogRel(("USBService: Adding ignore filter failed!\n"));
612 return VERR_GENERAL_FAILURE;
613 }
614
615 PUSBDEVICE pDev = aDevice->mUsb;
616 int rc = USBLibResetDevice(pDev->pszDevicePath, true /* Re-attach */);
617 if (RT_SUCCESS(rc))
618 aDevice->mOneShotId = pvId;
619 else
620 {
621 USBLibRemoveFilter(pvId);
622 pvId = NULL;
623 }
624 LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
625 return rc;
626
627#else
628
629 /*
630 * Though may not be strictly remove the driver alias for releasing the USB device
631 * from our driver, ignore errors here as we usually remove the alias immediately after capturing.
632 */
633 PUSBDEVICE pDev = aDevice->mUsb;
634 int rc = USBLibRemoveDeviceAlias(pDev);
635 Assert(pDev->pszDevicePath);
636 rc = USBLibResetDevice(pDev->pszDevicePath, true /* Re-attach */);
637 if (RT_SUCCESS(rc))
638 return VINF_SUCCESS;
639
640 /* The Solaris specifics are free'd in USBProxyService::freeDeviceMembers */
641
642 LogRel(("USBService: failed to reset device %s devicepath=%s rc=%Rrc\n", aDevice->getName().c_str(), pDev->pszDevicePath, rc));
643 return rc;
644
645#endif
646
647}
648
649
650void USBProxyServiceSolaris::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
651{
652#ifdef VBOX_WITH_NEW_USB_CODE_ON_SOLARIS
653 /*
654 * Remove the one-shot filter if necessary.
655 */
656 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->getName().c_str(), aSuccess, aDevice->mOneShotId));
657 if (!aSuccess && aDevice->mOneShotId)
658 USBLibRemoveFilter(aDevice->mOneShotId);
659 aDevice->mOneShotId = NULL;
660#endif
661}
662
663
664bool USBProxyServiceSolaris::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
665{
666#ifdef VBOX_WITH_NEW_USB_CODE_ON_SOLARIS
667 return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
668#else
669 return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
670#endif
671}
672
673/**
674 * Wrapper called by walkDeviceNode.
675 *
676 * @param pDevice The USB device to free.
677 */
678void solarisFreeUSBDevice(PUSBDEVICE pDevice)
679{
680 USBProxyService::freeDevice(pDevice);
681}
682
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