VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/darwin/VBoxUSB.cpp@ 51139

Last change on this file since 51139 was 51139, checked in by vboxsync, 11 years ago

Mac OS X host: more logging for VBoxUSB.kext.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 78.4 KB
Line 
1/* $Id: VBoxUSB.cpp 51139 2014-04-24 18:48:08Z vboxsync $ */
2/** @file
3 * VirtualBox USB driver for Darwin.
4 *
5 * This driver is responsible for hijacking USB devices when any of the
6 * VBoxSVC daemons requests it. It is also responsible for arbitrating
7 * access to hijacked USB devices.
8 */
9
10/*
11 * Copyright (C) 2006-2013 Oracle Corporation
12 *
13 * This file is part of VirtualBox Open Source Edition (OSE), as
14 * available from http://www.virtualbox.org. This file is free software;
15 * you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License (GPL) as published by the Free Software
17 * Foundation, in version 2 as it comes in the "COPYING" file of the
18 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_USB_DRV
27/* Deal with conflicts first.
28 * (This is mess inherited from BSD. The *BSDs has clean this up long ago.) */
29#include <sys/param.h>
30#undef PVM
31#include <IOKit/IOLib.h> /* Assert as function */
32
33#include "VBoxUSBInterface.h"
34#include "VBoxUSBFilterMgr.h"
35#include <VBox/version.h>
36#include <VBox/usblib-darwin.h>
37#include <VBox/log.h>
38#include <iprt/types.h>
39#include <iprt/initterm.h>
40#include <iprt/assert.h>
41#include <iprt/semaphore.h>
42#include <iprt/process.h>
43#include <iprt/alloc.h>
44#include <iprt/err.h>
45#include <iprt/asm.h>
46
47#include <mach/kmod.h>
48#include <miscfs/devfs/devfs.h>
49#include <sys/conf.h>
50#include <sys/errno.h>
51#include <sys/ioccom.h>
52#include <sys/malloc.h>
53#include <sys/proc.h>
54#include <kern/task.h>
55#include <IOKit/IOService.h>
56#include <IOKit/IOUserClient.h>
57#include <IOKit/IOKitKeys.h>
58#include <IOKit/usb/USB.h>
59#include <IOKit/usb/IOUSBDevice.h>
60#include <IOKit/usb/IOUSBInterface.h>
61#include <IOKit/usb/IOUSBUserClient.h>
62
63/* private: */
64RT_C_DECLS_BEGIN
65extern void *get_bsdtask_info(task_t);
66RT_C_DECLS_END
67
68/* Temporary: Extra logging */
69#ifdef Log
70# undef Log
71#endif
72#define Log LogRel
73#ifdef Log2
74# undef Log2
75#endif
76#define Log2 LogRel
77/* Temporary: needed for extra debug info */
78#define VBOX_PROC_SELFNAME_LEN (20)
79#define VBOX_RETRIEVE_CUR_PROC_NAME(_name) char _name[VBOX_PROC_SELFNAME_LEN]; \
80 proc_selfname(pszProcName, VBOX_PROC_SELFNAME_LEN)
81
82
83/*******************************************************************************
84* Defined Constants And Macros *
85*******************************************************************************/
86/** Locks the lists. */
87#define VBOXUSB_LOCK() do { int rc = RTSemFastMutexRequest(g_Mtx); AssertRC(rc); } while (0)
88/** Unlocks the lists. */
89#define VBOXUSB_UNLOCK() do { int rc = RTSemFastMutexRelease(g_Mtx); AssertRC(rc); } while (0)
90
91
92/*******************************************************************************
93* Internal Functions *
94*******************************************************************************/
95RT_C_DECLS_BEGIN
96static kern_return_t VBoxUSBStart(struct kmod_info *pKModInfo, void *pvData);
97static kern_return_t VBoxUSBStop(struct kmod_info *pKModInfo, void *pvData);
98RT_C_DECLS_END
99
100
101/*******************************************************************************
102* Structures and Typedefs *
103*******************************************************************************/
104/**
105 * The service class.
106 *
107 * This is the management service that VBoxSVC and the VMs speak to.
108 *
109 * @remark The method prototypes are ordered somewhat after their order of
110 * invocation, while the implementation is ordered by pair.
111 */
112class org_virtualbox_VBoxUSB : public IOService
113{
114 OSDeclareDefaultStructors(org_virtualbox_VBoxUSB);
115
116public:
117 /** @name IOService
118 * @{ */
119 virtual bool init(OSDictionary *pDictionary = 0);
120 virtual bool start(IOService *pProvider);
121 virtual bool open(IOService *pForClient, IOOptionBits fOptions = 0, void *pvArg = 0);
122 virtual bool terminate(IOOptionBits fOptions);
123 virtual void close(IOService *pForClient, IOOptionBits fOptions = 0);
124 virtual void stop(IOService *pProvider);
125 virtual void free();
126
127 virtual bool terminateClient(IOService *pClient, IOOptionBits fOptions);
128 virtual bool finalize(IOOptionBits fOptions);
129 virtual void retain() const;
130 virtual void release(int freeWhen) const;
131 virtual void taggedRetain(const void *pTag=0) const;
132 virtual void taggedRelease(const void *pTag, const int freeWhen) const;
133 /** @} */
134};
135OSDefineMetaClassAndStructors(org_virtualbox_VBoxUSB, IOService);
136
137
138
139
140/**
141 * The user client class that pairs up with org_virtualbox_VBoxUSB.
142 */
143class org_virtualbox_VBoxUSBClient : public IOUserClient
144{
145 OSDeclareDefaultStructors(org_virtualbox_VBoxUSBClient);
146
147public:
148 /** @name IOService & IOUserClient
149 * @{ */
150 virtual bool initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type);
151 virtual bool start(IOService *pProvider);
152 virtual IOReturn clientClose(void);
153 virtual IOReturn clientDied(void);
154 virtual bool terminate(IOOptionBits fOptions = 0);
155 virtual bool finalize(IOOptionBits fOptions);
156 virtual void stop(IOService *pProvider);
157 virtual void free();
158 virtual void retain() const;
159 virtual void release(int freeWhen) const;
160 virtual void taggedRetain(const void *pTag=0) const;
161 virtual void taggedRelease(const void *pTag, const int freeWhen) const;
162 virtual IOExternalMethod *getTargetAndMethodForIndex(IOService **ppService, UInt32 iMethod);
163 /** @} */
164
165 /** @name User client methods
166 * @{ */
167 IOReturn addFilter(PUSBFILTER pFilter, PVBOXUSBADDFILTEROUT pOut, IOByteCount cbFilter, IOByteCount *pcbOut);
168 IOReturn removeFilter(uintptr_t *puId, int *prc, IOByteCount cbIn, IOByteCount *pcbOut);
169 /** @} */
170
171 static bool isClientTask(task_t ClientTask);
172
173private:
174 /** The service provider. */
175 org_virtualbox_VBoxUSB *m_pProvider;
176 /** The client task. */
177 task_t m_Task;
178 /** The client process. */
179 RTPROCESS m_Process;
180 /** Pointer to the next user client. */
181 org_virtualbox_VBoxUSBClient * volatile m_pNext;
182 /** List of user clients. Protected by g_Mtx. */
183 static org_virtualbox_VBoxUSBClient * volatile s_pHead;
184};
185OSDefineMetaClassAndStructors(org_virtualbox_VBoxUSBClient, IOUserClient);
186
187
188/**
189 * The IOUSBDevice driver class.
190 *
191 * The main purpose of this is hijack devices matching current filters.
192 *
193 * @remarks This is derived from IOUSBUserClientInit instead of IOService because we must make
194 * sure IOUSBUserClientInit::start() gets invoked for this provider. The problem is that
195 * there is some kind of magic that prevents this from happening if we boost the probe
196 * score to high. With the result that we don't have the required plugin entry for
197 * user land and consequently cannot open it.
198 *
199 * So, to avoid having to write a lot of code we just inherit from IOUSBUserClientInit
200 * and make some possibly bold assumptions about it not changing. This just means
201 * we'll have to keep an eye on the source apple releases or only call
202 * IOUSBUserClientInit::start() and hand the rest of the super calls to IOService. For
203 * now we're doing it by the C++ book.
204 */
205class org_virtualbox_VBoxUSBDevice : public IOUSBUserClientInit
206{
207 OSDeclareDefaultStructors(org_virtualbox_VBoxUSBDevice);
208
209public:
210 /** @name IOService
211 * @{ */
212 virtual bool init(OSDictionary *pDictionary = 0);
213 virtual IOService *probe(IOService *pProvider, SInt32 *pi32Score);
214 virtual bool start(IOService *pProvider);
215 virtual bool terminate(IOOptionBits fOptions = 0);
216 virtual void stop(IOService *pProvider);
217 virtual void free();
218 virtual IOReturn message(UInt32 enmMsg, IOService *pProvider, void *pvArg = 0);
219
220 virtual bool open(IOService *pForClient, IOOptionBits fOptions = 0, void *pvArg = 0);
221 virtual void close(IOService *pForClient, IOOptionBits fOptions = 0);
222 virtual bool terminateClient(IOService *pClient, IOOptionBits fOptions);
223 virtual bool finalize(IOOptionBits fOptions);
224
225 virtual void retain() const;
226 virtual void release(int freeWhen) const;
227 virtual void taggedRetain(const void *pTag=0) const;
228 virtual void taggedRelease(const void *pTag, const int freeWhen) const;
229
230 /** @} */
231
232 static void scheduleReleaseByOwner(RTPROCESS Owner);
233private:
234 /** The interface we're driving (aka. the provider). */
235 IOUSBDevice *m_pDevice;
236 /** The owner process, meaning the VBoxSVC process. */
237 RTPROCESS volatile m_Owner;
238 /** The client process, meaning the VM process. */
239 RTPROCESS volatile m_Client;
240 /** The ID of the matching filter. */
241 uintptr_t m_uId;
242 /** Have we opened the device or not? */
243 bool volatile m_fOpen;
244 /** Should be open the device on the next close notification message? */
245 bool volatile m_fOpenOnWasClosed;
246 /** Whether to re-enumerate this device when the client closes it.
247 * This is something we'll do when the filter owner dies. */
248 bool volatile m_fReleaseOnClose;
249 /** Whether we're being unloaded or not.
250 * Only valid in stop(). */
251 bool m_fBeingUnloaded;
252 /** Pointer to the next device in the list. */
253 org_virtualbox_VBoxUSBDevice * volatile m_pNext;
254 /** Pointer to the list head. Protected by g_Mtx. */
255 static org_virtualbox_VBoxUSBDevice * volatile s_pHead;
256
257#ifdef DEBUG
258 /** The interest notifier. */
259 IONotifier *m_pNotifier;
260
261 static IOReturn MyInterestHandler(void *pvTarget, void *pvRefCon, UInt32 enmMsgType,
262 IOService *pProvider, void * pvMsgArg, vm_size_t cbMsgArg);
263#endif
264};
265OSDefineMetaClassAndStructors(org_virtualbox_VBoxUSBDevice, IOUSBUserClientInit);
266
267
268/**
269 * The IOUSBInterface driver class.
270 *
271 * The main purpose of this is hijack interfaces which device is driven
272 * by org_virtualbox_VBoxUSBDevice.
273 *
274 * @remarks See org_virtualbox_VBoxUSBDevice for why we use IOUSBUserClientInit.
275 */
276class org_virtualbox_VBoxUSBInterface : public IOUSBUserClientInit
277{
278 OSDeclareDefaultStructors(org_virtualbox_VBoxUSBInterface);
279
280public:
281 /** @name IOService
282 * @{ */
283 virtual bool init(OSDictionary *pDictionary = 0);
284 virtual IOService *probe(IOService *pProvider, SInt32 *pi32Score);
285 virtual bool start(IOService *pProvider);
286 virtual bool terminate(IOOptionBits fOptions = 0);
287 virtual void stop(IOService *pProvider);
288 virtual void free();
289 virtual IOReturn message(UInt32 enmMsg, IOService *pProvider, void *pvArg = 0);
290
291 virtual bool open(IOService *pForClient, IOOptionBits fOptions = 0, void *pvArg = 0);
292 virtual void close(IOService *pForClient, IOOptionBits fOptions = 0);
293 virtual bool terminateClient(IOService *pClient, IOOptionBits fOptions);
294 virtual bool finalize(IOOptionBits fOptions);
295
296
297 virtual void retain() const;
298 virtual void release(int freeWhen) const;
299 virtual void taggedRetain(const void *pTag=0) const;
300 virtual void taggedRelease(const void *pTag, const int freeWhen) const;
301
302 /** @} */
303
304private:
305 /** The interface we're driving (aka. the provider). */
306 IOUSBInterface *m_pInterface;
307 /** Have we opened the device or not? */
308 bool volatile m_fOpen;
309 /** Should be open the device on the next close notification message? */
310 bool volatile m_fOpenOnWasClosed;
311};
312OSDefineMetaClassAndStructors(org_virtualbox_VBoxUSBInterface, IOUSBUserClientInit);
313
314
315
316
317
318/*******************************************************************************
319* Global Variables *
320*******************************************************************************/
321/*
322 * Declare the module stuff.
323 */
324RT_C_DECLS_BEGIN
325extern kern_return_t _start(struct kmod_info *pKModInfo, void *pvData);
326extern kern_return_t _stop(struct kmod_info *pKModInfo, void *pvData);
327
328KMOD_EXPLICIT_DECL(VBoxDrv, VBOX_VERSION_STRING, _start, _stop)
329DECLHIDDEN(kmod_start_func_t *) _realmain = VBoxUSBStart;
330DECLHIDDEN(kmod_stop_func_t *) _antimain = VBoxUSBStop;
331DECLHIDDEN(int) _kext_apple_cc = __APPLE_CC__;
332RT_C_DECLS_END
333
334/** Mutex protecting the lists. */
335static RTSEMFASTMUTEX g_Mtx = NIL_RTSEMFASTMUTEX;
336org_virtualbox_VBoxUSBClient * volatile org_virtualbox_VBoxUSBClient::s_pHead = NULL;
337org_virtualbox_VBoxUSBDevice * volatile org_virtualbox_VBoxUSBDevice::s_pHead = NULL;
338
339/** Global instance count - just for checking proving that everything is destroyed correctly. */
340static volatile uint32_t g_cInstances = 0;
341
342
343/**
344 * Start the kernel module.
345 */
346static kern_return_t VBoxUSBStart(struct kmod_info *pKModInfo, void *pvData)
347{
348 int rc;
349 Log(("VBoxUSBStart\n"));
350
351 /*
352 * Initialize IPRT.
353 */
354 rc = RTR0Init(0);
355 if (RT_SUCCESS(rc))
356 {
357 /*
358 * Create the spinlock.
359 */
360 rc = RTSemFastMutexCreate(&g_Mtx);
361 if (RT_SUCCESS(rc))
362 {
363 rc = VBoxUSBFilterInit();
364 if (RT_SUCCESS(rc))
365 {
366#if 0 /* testing */
367 USBFILTER Flt;
368 USBFilterInit(&Flt, USBFILTERTYPE_CAPTURE);
369 USBFilterSetNumExact(&Flt, USBFILTERIDX_VENDOR_ID, 0x096e, true);
370 uintptr_t uId;
371 rc = VBoxUSBFilterAdd(&Flt, 1, &uId);
372 printf("VBoxUSB: VBoxUSBFilterAdd #1 -> %d + %p\n", rc, uId);
373
374 USBFilterInit(&Flt, USBFILTERTYPE_CAPTURE);
375 USBFilterSetStringPattern(&Flt, USBFILTERIDX_PRODUCT_STR, "*DISK*", true);
376 rc = VBoxUSBFilterAdd(&Flt, 2, &uId);
377 printf("VBoxUSB: VBoxUSBFilterAdd #2 -> %d + %p\n", rc, uId);
378#endif
379 return KMOD_RETURN_SUCCESS;
380 }
381 printf("VBoxUSB: VBoxUSBFilterInit failed (rc=%d)\n", rc);
382 RTSemFastMutexDestroy(g_Mtx);
383 g_Mtx = NIL_RTSEMFASTMUTEX;
384 }
385 else
386 printf("VBoxUSB: RTSemFastMutexCreate failed (rc=%d)\n", rc);
387 RTR0Term();
388 }
389 else
390 printf("VBoxUSB: failed to initialize IPRT (rc=%d)\n", rc);
391
392 return KMOD_RETURN_FAILURE;
393}
394
395
396/**
397 * Stop the kernel module.
398 */
399static kern_return_t VBoxUSBStop(struct kmod_info *pKModInfo, void *pvData)
400{
401 int rc;
402 Log(("VBoxUSBStop: g_cInstances=%d\n", g_cInstances));
403
404 /** @todo Fix problem with crashing when unloading a driver that's in use. */
405
406 /*
407 * Undo the work done during start (in reverse order).
408 */
409 VBoxUSBFilterTerm();
410
411 rc = RTSemFastMutexDestroy(g_Mtx);
412 AssertRC(rc);
413 g_Mtx = NIL_RTSEMFASTMUTEX;
414
415 RTR0Term();
416
417 Log(("VBoxUSBStop - done\n"));
418 return KMOD_RETURN_SUCCESS;
419}
420
421
422
423
424
425
426/**
427 * Gets the name of a IOKit message.
428 *
429 * @returns Message name (read only).
430 * @param enmMsg The message.
431 */
432DECLINLINE(const char *) DbgGetIOKitMessageName(UInt32 enmMsg)
433{
434#ifdef DEBUG
435 switch (enmMsg)
436 {
437#define MY_CASE(enm) case enm: return #enm; break
438 MY_CASE(kIOMessageServiceIsTerminated);
439 MY_CASE(kIOMessageServiceIsSuspended);
440 MY_CASE(kIOMessageServiceIsResumed);
441 MY_CASE(kIOMessageServiceIsRequestingClose);
442 MY_CASE(kIOMessageServiceIsAttemptingOpen);
443 MY_CASE(kIOMessageServiceWasClosed);
444 MY_CASE(kIOMessageServiceBusyStateChange);
445 MY_CASE(kIOMessageServicePropertyChange);
446 MY_CASE(kIOMessageCanDevicePowerOff);
447 MY_CASE(kIOMessageDeviceWillPowerOff);
448 MY_CASE(kIOMessageDeviceWillNotPowerOff);
449 MY_CASE(kIOMessageDeviceHasPoweredOn);
450 MY_CASE(kIOMessageCanSystemPowerOff);
451 MY_CASE(kIOMessageSystemWillPowerOff);
452 MY_CASE(kIOMessageSystemWillNotPowerOff);
453 MY_CASE(kIOMessageCanSystemSleep);
454 MY_CASE(kIOMessageSystemWillSleep);
455 MY_CASE(kIOMessageSystemWillNotSleep);
456 MY_CASE(kIOMessageSystemHasPoweredOn);
457 MY_CASE(kIOMessageSystemWillRestart);
458 MY_CASE(kIOMessageSystemWillPowerOn);
459 MY_CASE(kIOUSBMessageHubResetPort);
460 MY_CASE(kIOUSBMessageHubSuspendPort);
461 MY_CASE(kIOUSBMessageHubResumePort);
462 MY_CASE(kIOUSBMessageHubIsDeviceConnected);
463 MY_CASE(kIOUSBMessageHubIsPortEnabled);
464 MY_CASE(kIOUSBMessageHubReEnumeratePort);
465 MY_CASE(kIOUSBMessagePortHasBeenReset);
466 MY_CASE(kIOUSBMessagePortHasBeenResumed);
467 MY_CASE(kIOUSBMessageHubPortClearTT);
468 MY_CASE(kIOUSBMessagePortHasBeenSuspended);
469 MY_CASE(kIOUSBMessageFromThirdParty);
470 MY_CASE(kIOUSBMessagePortWasNotSuspended);
471 MY_CASE(kIOUSBMessageExpressCardCantWake);
472// MY_CASE(kIOUSBMessageCompositeDriverReconfigured);
473#undef MY_CASE
474 }
475#endif /* DEBUG */
476 return "unknown";
477}
478
479
480
481
482
483/*
484 *
485 * org_virtualbox_VBoxUSB
486 *
487 */
488
489
490/**
491 * Initialize the object.
492 * @remark Only for logging.
493 */
494bool
495org_virtualbox_VBoxUSB::init(OSDictionary *pDictionary)
496{
497 uint32_t cInstances = ASMAtomicIncU32(&g_cInstances);
498 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
499 Log(("VBoxUSB::init([%p], %p) new g_cInstances=%d pszProcName=[%s] [retain count: %d]\n", this, pDictionary, cInstances, pszProcName, getRetainCount()));
500 if (IOService::init(pDictionary))
501 {
502 /* init members. */
503 Log(("VBoxUSB::init([%p], %p) returns true pszProcName=[%s] [retain count: %d]\n", this, pDictionary, pszProcName, getRetainCount()));
504 return true;
505 }
506 ASMAtomicDecU32(&g_cInstances);
507 Log(("VBoxUSB::init([%p], %p) returns false pszProcName=[%s] [retain count: %d]\n", this, pDictionary, pszProcName, getRetainCount()));
508 return false;
509}
510
511
512/**
513 * Free the object.
514 * @remark Only for logging.
515 */
516void
517org_virtualbox_VBoxUSB::free()
518{
519 uint32_t cInstances = ASMAtomicDecU32(&g_cInstances); NOREF(cInstances);
520 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
521 Log(("VBoxUSB::free([%p]) new g_cInstances=%d pszProcName=[%s] [retain count: %d]\n", this, cInstances, pszProcName, getRetainCount()));
522 IOService::free();
523}
524
525
526/**
527 * Start this service.
528 */
529bool
530org_virtualbox_VBoxUSB::start(IOService *pProvider)
531{
532 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
533 Log(("VBoxUSB::start([%p], %p {%s}) pszProcName=[%s] [retain count: %d]\n", this, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
534
535 if (IOService::start(pProvider))
536 {
537 /* register the service. */
538 registerService();
539 Log(("VBoxUSB::start([%p], %p {%s}) pszProcName=[%s] returns true [retain count: %d]\n", this, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
540 return true;
541 }
542
543 Log(("VBoxUSB::start([%p], %p {%s}) pszProcName=[%s] returns false [retain count: %d]\n", this, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
544 return false;
545}
546
547
548/**
549 * Stop this service.
550 * @remark Only for logging.
551 */
552void
553org_virtualbox_VBoxUSB::stop(IOService *pProvider)
554{
555 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
556 Log(("VBoxUSB::stop([%p], %p (%s)) (1) pszProcName=[%s] [retain count: %d]\n", this, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
557 IOService::stop(pProvider);
558 Log(("VBoxUSB::stop([%p], %p (%s)) (2) pszProcName=[%s] [retain count: %d]\n", this, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
559}
560
561
562/**
563 * Stop this service.
564 * @remark Only for logging.
565 */
566bool
567org_virtualbox_VBoxUSB::open(IOService *pForClient, IOOptionBits fOptions/* = 0*/, void *pvArg/* = 0*/)
568{
569 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
570 Log(("VBoxUSB::open([%p], %p, %#x, %p) pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pvArg, pszProcName, getRetainCount()));
571 bool fRc = IOService::open(pForClient, fOptions, pvArg);
572 Log(("VBoxUSB::open([%p], %p, %#x, %p) -> %d pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pvArg, fRc, pszProcName, getRetainCount()));
573 return fRc;
574}
575
576
577/**
578 * Stop this service.
579 * @remark Only for logging.
580 */
581void
582org_virtualbox_VBoxUSB::close(IOService *pForClient, IOOptionBits fOptions/* = 0*/)
583{
584 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
585 IOService::close(pForClient, fOptions);
586 Log(("VBoxUSB::close([%p], %p, %#x) pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pszProcName, getRetainCount()));
587}
588
589
590/**
591 * Terminate request.
592 * @remark Only for logging.
593 */
594bool
595org_virtualbox_VBoxUSB::terminate(IOOptionBits fOptions)
596{
597 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
598 Log(("VBoxUSB::terminate([%p], %#x): pszProcName=[%s] g_cInstances=%d [retain count: %d]\n", this, fOptions, pszProcName, g_cInstances, getRetainCount()));
599 bool fRc = IOService::terminate(fOptions);
600 Log(("VBoxUSB::terminate([%p], %#x): pszProcName=[%s] returns %d [retain count: %d]\n", this, fOptions, pszProcName, fRc, getRetainCount()));
601 return fRc;
602}
603
604
605bool
606org_virtualbox_VBoxUSB::terminateClient(IOService *pClient, IOOptionBits fOptions)
607{
608 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
609 Log(("VBoxUSB::terminateClient([%p], pClient=%p, fOptions=%#x) pszProcName=[%s] [retain count: %d]\n", this, pClient, fOptions, pszProcName, getRetainCount()));
610 bool fRc = IOService::terminateClient(pClient, fOptions);
611 Log(("VBoxUSB::terminateClient([%p], pClient=%p, fOptions=%#x) returns %d pszProcName=[%s] [retain count: %d]\n", this, pClient, fOptions, fRc, pszProcName, getRetainCount()));
612 return fRc;
613}
614
615
616bool
617org_virtualbox_VBoxUSB::finalize(IOOptionBits fOptions)
618{
619 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
620 Log(("VBoxUSB::finalize([%p], fOptions=%#x) pszProcName=[%s] [retain count: %d]\n", this, fOptions, pszProcName, getRetainCount()));
621 bool fRc = IOService::finalize(fOptions);
622 Log(("VBoxUSB::finalize([%p], fOptions=%#x) returns %d pszProcName=[%s] [retain count: %d]\n", this, fOptions, fRc, pszProcName, getRetainCount()));
623 return fRc;
624}
625
626
627void
628org_virtualbox_VBoxUSB::retain() const
629{
630 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
631 Log(("VBoxUSB::retain([%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
632 IOService::retain();
633 Log(("VBoxUSB::retain([%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
634}
635
636
637void
638org_virtualbox_VBoxUSB::release(int freeWhen) const
639{
640 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
641 Log(("VBoxUSB::release([%p], freeWhen=[%d]) pszProcName=[%s] [retain count: %d]\n", this, freeWhen, pszProcName, getRetainCount()));
642 IOService::release(freeWhen);
643}
644
645
646void
647org_virtualbox_VBoxUSB::taggedRetain(const void *pTag) const
648{
649 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
650 Log(("VBoxUSB::taggedRetain([%p], pTag=[%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pTag, pszProcName, getRetainCount()));
651 IOService::taggedRetain(pTag);
652 Log(("VBoxUSB::taggedRetain([%p], pTag=[%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pTag, pszProcName, getRetainCount()));
653}
654
655
656void
657org_virtualbox_VBoxUSB::taggedRelease(const void *pTag, const int freeWhen) const
658{
659 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
660 Log(("VBoxUSB::taggedRelease([%p], pTag=[%p], freeWhen=[%d]) pszProcName=[%s] [retain count: %d]\n", this, pTag, freeWhen, pszProcName, getRetainCount()));
661 IOService::taggedRelease(pTag, freeWhen);
662}
663
664
665
666
667
668
669
670
671
672
673/*
674 *
675 * org_virtualbox_VBoxUSBClient
676 *
677 */
678
679
680/**
681 * Initializer called when the client opens the service.
682 */
683bool
684org_virtualbox_VBoxUSBClient::initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type)
685{
686 if (!OwningTask)
687 {
688 Log(("VBoxUSBClient::initWithTask([%p], %p, %p, %#x) -> false (no task) [retain count: %d]\n", this, OwningTask, pvSecurityId, u32Type, getRetainCount()));
689 return false;
690 }
691
692 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
693
694 proc_t pProc = (proc_t)get_bsdtask_info(OwningTask); /* we need the pid */
695 Log(("VBoxUSBClient::initWithTask([%p], %p(->%p:{.pid=%d (%s)}, %p, %#x) [retain count: %d]\n",
696 this, OwningTask, pProc, pProc ? proc_pid(pProc) : -1, pszProcName, pvSecurityId, u32Type, getRetainCount()));
697
698 if (IOUserClient::initWithTask(OwningTask, pvSecurityId , u32Type))
699 {
700 m_pProvider = NULL;
701 m_Task = OwningTask;
702 m_Process = pProc ? proc_pid(pProc) : NIL_RTPROCESS;
703 m_pNext = NULL;
704
705 uint32_t cInstances = ASMAtomicIncU32(&g_cInstances);
706 Log(("VBoxUSBClient::initWithTask([%p], %p(->%p:{.pid=%d (%s)}, %p, %#x) -> true; new g_cInstances=%d [retain count: %d]\n",
707 this, OwningTask, pProc, pProc ? proc_pid(pProc) : -1, pszProcName, pvSecurityId, u32Type, cInstances, getRetainCount()));
708 return true;
709 }
710
711 Log(("VBoxUSBClient::initWithTask([%p], %p(->%p:{.pid=%d (%s)}, %p, %#x) -> false [retain count: %d]\n",
712 this, OwningTask, pProc, pProc ? proc_pid(pProc) : -1, pszProcName, pvSecurityId, u32Type, getRetainCount()));
713 return false;
714}
715
716
717/**
718 * Free the object.
719 * @remark Only for logging.
720 */
721void
722org_virtualbox_VBoxUSBClient::free()
723{
724 uint32_t cInstances = ASMAtomicDecU32(&g_cInstances); NOREF(cInstances);
725 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
726 Log(("VBoxUSBClient::free([%p]) new g_cInstances=%d pszProcName=[%s] [retain count: %d]\n", this, cInstances, pszProcName, getRetainCount()));
727 IOUserClient::free();
728}
729
730
731/**
732 * Retain the object.
733 * @remark Only for logging.
734 */
735void
736org_virtualbox_VBoxUSBClient::retain() const
737{
738 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
739
740 Log(("VBoxUSBClient::retain([%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
741 IOUserClient::retain();
742 Log(("VBoxUSBClient::retain([%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
743}
744
745
746/**
747 * Release the object.
748 * @remark Only for logging.
749 */
750void
751org_virtualbox_VBoxUSBClient::release(int freeWhen) const
752{
753 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
754
755 Log(("VBoxUSBClient::release([%p], freeWhen=%d) pszProcName=[%s] [retain count: %d]\n", this, freeWhen, pszProcName, getRetainCount()));
756 IOUserClient::release(freeWhen);
757}
758
759
760/**
761 * Tagged retain the object.
762 * @remark Only for logging.
763 */
764void
765org_virtualbox_VBoxUSBClient::taggedRetain(const void *pTag) const
766{
767 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
768
769 Log(("VBoxUSBClient::taggedRetain([%p], [pTag=%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pTag, pszProcName, getRetainCount()));
770 IOUserClient::taggedRetain(pTag);
771 Log(("VBoxUSBClient::taggedRetain([%p], [pTag=%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pTag, pszProcName, getRetainCount()));
772}
773
774
775/**
776 * Tagged release the object.
777 * @remark Only for logging.
778 */
779void
780org_virtualbox_VBoxUSBClient::taggedRelease(const void *pTag, const int freeWhen) const
781{
782 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
783
784 Log(("VBoxUSBClient::taggedRelease([%p], [pTag=%p], [freeWhen=%d]) pszProcName=[%s] [retain count: %d]\n", this, pTag, freeWhen, pszProcName, getRetainCount()));
785 IOUserClient::taggedRelease(pTag, freeWhen);
786}
787
788
789/**
790 * Start the client service.
791 */
792bool
793org_virtualbox_VBoxUSBClient::start(IOService *pProvider)
794{
795 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
796
797 Log(("VBoxUSBClient::start([%p], %p) pszProcName=[%s] [retain count: %d]\n", this, pProvider, pszProcName, getRetainCount()));
798 if (IOUserClient::start(pProvider))
799 {
800 m_pProvider = OSDynamicCast(org_virtualbox_VBoxUSB, pProvider);
801 if (m_pProvider)
802 {
803 /*
804 * Add ourselves to the list of user clients.
805 */
806 VBOXUSB_LOCK();
807
808 m_pNext = s_pHead;
809 s_pHead = this;
810
811 VBOXUSB_UNLOCK();
812
813 Log(("VBoxUSBClient::start([%p]): returns true pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
814 return true;
815 }
816 Log(("VBoxUSBClient::start: %p isn't org_virtualbox_VBoxUSB pszProcName=[%s] [retain count: %d]\n", pProvider, pszProcName, getRetainCount()));
817 }
818
819 Log(("VBoxUSBClient::start([%p]): returns false pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
820 return false;
821}
822
823
824/**
825 * Client exits normally.
826 */
827IOReturn
828org_virtualbox_VBoxUSBClient::clientClose(void)
829{
830 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
831
832 Log(("VBoxUSBClient::clientClose([%p:{.m_Process=%d}]) pszProcName=[%s] [retain count: %d]\n", this, (int)m_Process, pszProcName, getRetainCount()));
833
834 /*
835 * Remove this process from the client list.
836 */
837 VBOXUSB_LOCK();
838
839 org_virtualbox_VBoxUSBClient *pPrev = NULL;
840 for (org_virtualbox_VBoxUSBClient *pCur = s_pHead; pCur; pCur = pCur->m_pNext)
841 {
842 if (pCur == this)
843 {
844 if (pPrev)
845 pPrev->m_pNext = m_pNext;
846 else
847 s_pHead = m_pNext;
848 m_pNext = NULL;
849 break;
850 }
851 pPrev = pCur;
852 }
853
854 VBOXUSB_UNLOCK();
855
856 /*
857 * Drop all filters owned by this client.
858 */
859 if (m_Process != NIL_RTPROCESS)
860 VBoxUSBFilterRemoveOwner(m_Process);
861
862 /*
863 * Schedule all devices owned (filtered) by this process for
864 * immediate release or release upon close.
865 */
866 if (m_Process != NIL_RTPROCESS)
867 org_virtualbox_VBoxUSBDevice::scheduleReleaseByOwner(m_Process);
868
869 /*
870 * Initiate termination.
871 */
872 m_pProvider = NULL;
873 terminate();
874
875 Log(("VBoxUSBClient::clientClose([%p:{.m_Process=%d}]) return kIOReturnSuccess pszProcName=[%s] [retain count: %d]\n", this, (int)m_Process, pszProcName, getRetainCount()));
876
877 return kIOReturnSuccess;
878}
879
880
881/**
882 * The client exits abnormally / forgets to do cleanups.
883 * @remark Only for logging.
884 */
885IOReturn
886org_virtualbox_VBoxUSBClient::clientDied(void)
887{
888 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
889
890 Log(("VBoxUSBClient::clientDied([%p]) m_Task=%p R0Process=%p Process=%d pszProcName=[%s] [retain count: %d]\n",
891 this, m_Task, RTR0ProcHandleSelf(), RTProcSelf(), pszProcName, getRetainCount()));
892 /* IOUserClient::clientDied() calls clientClose... */
893 bool fRc = IOUserClient::clientDied();
894 Log(("VBoxUSBClient::clientDied([%p]): returns %d pszProcName=[%s] [retain count: %d]\n", this, fRc, pszProcName, getRetainCount()));
895 return fRc;
896}
897
898
899/**
900 * Terminate the service (initiate the destruction).
901 * @remark Only for logging.
902 */
903bool
904org_virtualbox_VBoxUSBClient::terminate(IOOptionBits fOptions)
905{
906 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
907 /* kIOServiceRecursing, kIOServiceRequired, kIOServiceTerminate, kIOServiceSynchronous - interesting option bits */
908 Log(("VBoxUSBClient::terminate([%p], %#x) pszProcName=[%s] [retain count: %d]\n", this, fOptions, pszProcName, getRetainCount()));
909 bool fRc = IOUserClient::terminate(fOptions);
910 Log(("VBoxUSBClient::terminate([%p]): returns %d pszProcName=[%s] [retain count: %d]\n", this, fRc, pszProcName, getRetainCount()));
911 return fRc;
912}
913
914
915/**
916 * The final stage of the client service destruction.
917 * @remark Only for logging.
918 */
919bool
920org_virtualbox_VBoxUSBClient::finalize(IOOptionBits fOptions)
921{
922 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
923 Log(("VBoxUSBClient::finalize([%p], %#x) pszProcName=[%s] [retain count: %d]\n", this, fOptions, pszProcName, getRetainCount()));
924 bool fRc = IOUserClient::finalize(fOptions);
925 Log(("VBoxUSBClient::finalize([%p]): returns %d pszProcName=[%s] [retain count: %d]\n", this, fRc, pszProcName, getRetainCount()));
926 return fRc;
927}
928
929
930/**
931 * Stop the client service.
932 */
933void
934org_virtualbox_VBoxUSBClient::stop(IOService *pProvider)
935{
936 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
937 Log(("VBoxUSBClient::stop([%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
938 IOUserClient::stop(pProvider);
939 Log(("VBoxUSBClient::stop([%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
940
941 /*
942 * Paranoia.
943 */
944 VBOXUSB_LOCK();
945
946 org_virtualbox_VBoxUSBClient *pPrev = NULL;
947 for (org_virtualbox_VBoxUSBClient *pCur = s_pHead; pCur; pCur = pCur->m_pNext)
948 {
949 if (pCur == this)
950 {
951 if (pPrev)
952 pPrev->m_pNext = m_pNext;
953 else
954 s_pHead = m_pNext;
955 m_pNext = NULL;
956 break;
957 }
958 pPrev = pCur;
959 }
960
961 VBOXUSB_UNLOCK();
962}
963
964
965/**
966 * Translate a user method index into a service object and an external method structure.
967 *
968 * @returns Pointer to external method structure descripting the method.
969 * NULL if the index isn't valid.
970 * @param ppService Where to store the service object on success.
971 * @param iMethod The method index.
972 */
973IOExternalMethod *
974org_virtualbox_VBoxUSBClient::getTargetAndMethodForIndex(IOService **ppService, UInt32 iMethod)
975{
976 static IOExternalMethod s_aMethods[VBOXUSBMETHOD_END] =
977 {
978 /*[VBOXUSBMETHOD_ADD_FILTER] = */
979 {
980 (IOService *)0, /* object */
981 (IOMethod)&org_virtualbox_VBoxUSBClient::addFilter, /* func */
982 kIOUCStructIStructO, /* flags - struct input (count0) and struct output (count1) */
983 sizeof(USBFILTER), /* count0 - size of the input struct. */
984 sizeof(VBOXUSBADDFILTEROUT) /* count1 - size of the return struct. */
985 },
986 /* [VBOXUSBMETHOD_FILTER_REMOVE] = */
987 {
988 (IOService *)0, /* object */
989 (IOMethod)&org_virtualbox_VBoxUSBClient::removeFilter, /* func */
990 kIOUCStructIStructO, /* flags - struct input (count0) and struct output (count1) */
991 sizeof(uintptr_t), /* count0 - size of the input (id) */
992 sizeof(int) /* count1 - size of the output (rc) */
993 },
994 };
995
996 if (RT_UNLIKELY(iMethod >= RT_ELEMENTS(s_aMethods)))
997 return NULL;
998
999 *ppService = this;
1000 return &s_aMethods[iMethod];
1001}
1002
1003
1004/**
1005 * Add filter user request.
1006 *
1007 * @returns IOKit status code.
1008 * @param pFilter The filter to add.
1009 * @param pOut Pointer to the output structure.
1010 * @param cbFilter Size of the filter structure.
1011 * @param pcbOut In/Out - sizeof(*pOut).
1012 */
1013IOReturn
1014org_virtualbox_VBoxUSBClient::addFilter(PUSBFILTER pFilter, PVBOXUSBADDFILTEROUT pOut, IOByteCount cbFilter, IOByteCount *pcbOut)
1015{
1016 Log(("VBoxUSBClient::addFilter: [%p:{.m_Process=%d}] pFilter=%p pOut=%p\n", this, (int)m_Process, pFilter, pOut));
1017
1018 /*
1019 * Validate input.
1020 */
1021 if (RT_UNLIKELY( cbFilter != sizeof(*pFilter)
1022 || *pcbOut != sizeof(*pOut)))
1023 {
1024 printf("VBoxUSBClient::addFilter: cbFilter=%#x expected %#x; *pcbOut=%#x expected %#x\n",
1025 (int)cbFilter, (int)sizeof(*pFilter), (int)*pcbOut, (int)sizeof(*pOut));
1026 return kIOReturnBadArgument;
1027 }
1028
1029 /*
1030 * Log the filter details.
1031 */
1032#ifdef DEBUG
1033 Log2(("VBoxUSBClient::addFilter: idVendor=%#x idProduct=%#x bcdDevice=%#x bDeviceClass=%#x bDeviceSubClass=%#x bDeviceProtocol=%#x bBus=%#x bPort=%#x\n",
1034 USBFilterGetNum(pFilter, USBFILTERIDX_VENDOR_ID),
1035 USBFilterGetNum(pFilter, USBFILTERIDX_PRODUCT_ID),
1036 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_REV),
1037 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_CLASS),
1038 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_SUB_CLASS),
1039 USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_PROTOCOL),
1040 USBFilterGetNum(pFilter, USBFILTERIDX_BUS),
1041 USBFilterGetNum(pFilter, USBFILTERIDX_PORT)));
1042 Log2(("VBoxUSBClient::addFilter: Manufacturer=%s Product=%s Serial=%s\n",
1043 USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) : "<null>",
1044 USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) : "<null>",
1045 USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) : "<null>"));
1046#endif
1047
1048 /*
1049 * Since we cannot query the bus number, make sure the filter
1050 * isn't requiring that field to be present.
1051 */
1052 int rc = USBFilterSetMustBePresent(pFilter, USBFILTERIDX_BUS, false /* fMustBePresent */); AssertRC(rc);
1053
1054 /*
1055 * Add the filter.
1056 */
1057 pOut->uId = 0;
1058 pOut->rc = VBoxUSBFilterAdd(pFilter, m_Process, &pOut->uId);
1059
1060 Log(("VBoxUSBClient::addFilter: returns *pOut={.rc=%d, .uId=%p}\n", pOut->rc, (void *)pOut->uId));
1061 return kIOReturnSuccess;
1062}
1063
1064
1065/**
1066 * Removes filter user request.
1067 *
1068 * @returns IOKit status code.
1069 * @param puId Where to get the filter ID.
1070 * @param prc Where to store the return code.
1071 * @param cbIn sizeof(*puId).
1072 * @param pcbOut In/Out - sizeof(*prc).
1073 */
1074IOReturn
1075org_virtualbox_VBoxUSBClient::removeFilter(uintptr_t *puId, int *prc, IOByteCount cbIn, IOByteCount *pcbOut)
1076{
1077 Log(("VBoxUSBClient::removeFilter: [%p:{.m_Process=%d}] *puId=%p m_Proc\n", this, (int)m_Process, *puId));
1078
1079 /*
1080 * Validate input.
1081 */
1082 if (RT_UNLIKELY( cbIn != sizeof(*puId)
1083 || *pcbOut != sizeof(*prc)))
1084 {
1085 printf("VBoxUSBClient::removeFilter: cbIn=%#x expected %#x; *pcbOut=%#x expected %#x\n",
1086 (int)cbIn, (int)sizeof(*puId), (int)*pcbOut, (int)sizeof(*prc));
1087 return kIOReturnBadArgument;
1088 }
1089
1090 /*
1091 * Remove the filter.
1092 */
1093 *prc = VBoxUSBFilterRemove(m_Process, *puId);
1094
1095 Log(("VBoxUSBClient::removeFilter: returns *prc=%d\n", *prc));
1096 return kIOReturnSuccess;
1097}
1098
1099
1100/**
1101 * Checks whether the specified task is a VBoxUSB client task or not.
1102 *
1103 * This is used to validate clients trying to open any of the device
1104 * or interfaces that we've hijacked.
1105 *
1106 * @returns true / false.
1107 * @param ClientTask The task.
1108 *
1109 * @remark This protecting against other user clients is not currently implemented
1110 * as it turned out to be more bothersome than first imagined.
1111 */
1112/* static*/ bool
1113org_virtualbox_VBoxUSBClient::isClientTask(task_t ClientTask)
1114{
1115 VBOXUSB_LOCK();
1116
1117 for (org_virtualbox_VBoxUSBClient *pCur = s_pHead; pCur; pCur = pCur->m_pNext)
1118 if (pCur->m_Task == ClientTask)
1119 {
1120 VBOXUSB_UNLOCK();
1121 return true;
1122 }
1123
1124 VBOXUSB_UNLOCK();
1125 return false;
1126}
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141/*
1142 *
1143 * org_virtualbox_VBoxUSBDevice
1144 *
1145 */
1146
1147/**
1148 * Initialize instance data.
1149 *
1150 * @returns Success indicator.
1151 * @param pDictionary The dictionary that will become the registry entry's
1152 * property table, or NULL. Hand it up to our parents.
1153 */
1154bool
1155org_virtualbox_VBoxUSBDevice::init(OSDictionary *pDictionary)
1156{
1157 uint32_t cInstances = ASMAtomicIncU32(&g_cInstances);
1158
1159 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1160 Log(("VBoxUSBDevice::init([%p], %p) new g_cInstances=%d pszProcName=[%s] [retain count: %d]\n", this, pDictionary, cInstances, pszProcName, getRetainCount()));
1161
1162 m_pDevice = NULL;
1163 m_Owner = NIL_RTPROCESS;
1164 m_Client = NIL_RTPROCESS;
1165 m_uId = ~(uintptr_t)0;
1166 m_fOpen = false;
1167 m_fOpenOnWasClosed = false;
1168 m_fReleaseOnClose = false;
1169 m_fBeingUnloaded = false;
1170 m_pNext = NULL;
1171#ifdef DEBUG
1172 m_pNotifier = NULL;
1173#endif
1174
1175 return IOUSBUserClientInit::init(pDictionary);
1176}
1177
1178/**
1179 * Free the object.
1180 * @remark Only for logging.
1181 */
1182void
1183org_virtualbox_VBoxUSBDevice::free()
1184{
1185 uint32_t cInstances = ASMAtomicDecU32(&g_cInstances); NOREF(cInstances);
1186 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1187
1188 Log(("VBoxUSBDevice::free([%p]) new g_cInstances=%d pszProcName=[%s] [retain count: %d]\n", this, cInstances, pszProcName, getRetainCount()));
1189 IOUSBUserClientInit::free();
1190}
1191
1192
1193/**
1194 * The device/driver probing.
1195 *
1196 * I/O Kit will iterate all device drivers suitable for this kind of device
1197 * (this is something it figures out from the property file) and call their
1198 * probe() method in order to try determine which is the best match for the
1199 * device. We will match the device against the registered filters and set
1200 * a ridiculously high score if we find it, thus making it extremely likely
1201 * that we'll be the first driver to be started. We'll also set a couple of
1202 * attributes so that it's not necessary to do a rematch in init to find
1203 * the appropriate filter (might not be necessary..., see todo).
1204 *
1205 * @returns Service instance to be started and *pi32Score if matching.
1206 * NULL if not a device suitable for this driver.
1207 *
1208 * @param pProvider The provider instance.
1209 * @param pi32Score Where to store the probe score.
1210 */
1211IOService *
1212org_virtualbox_VBoxUSBDevice::probe(IOService *pProvider, SInt32 *pi32Score)
1213{
1214 Log(("VBoxUSBDevice::probe([%p], %p {%s}, %p={%d})\n", this,
1215 pProvider, pProvider->getName(), pi32Score, pi32Score ? *pi32Score : 0));
1216
1217 /*
1218 * Check against filters.
1219 */
1220 USBFILTER Device;
1221 USBFilterInit(&Device, USBFILTERTYPE_CAPTURE);
1222
1223 static const struct
1224 {
1225 const char *pszName;
1226 USBFILTERIDX enmIdx;
1227 bool fNumeric;
1228 } s_aProps[] =
1229 {
1230 { kUSBVendorID, USBFILTERIDX_VENDOR_ID, true },
1231 { kUSBProductID, USBFILTERIDX_PRODUCT_ID, true },
1232 { kUSBDeviceReleaseNumber, USBFILTERIDX_DEVICE_REV, true },
1233 { kUSBDeviceClass, USBFILTERIDX_DEVICE_CLASS, true },
1234 { kUSBDeviceSubClass, USBFILTERIDX_DEVICE_SUB_CLASS, true },
1235 { kUSBDeviceProtocol, USBFILTERIDX_DEVICE_PROTOCOL, true },
1236 { "PortNum", USBFILTERIDX_PORT, true },
1237 /// @todo { , USBFILTERIDX_BUS, true }, - must be derived :-/
1238 /// Seems to be the upper byte of locationID and our "grand parent" has a USBBusNumber prop.
1239 { "USB Vendor Name", USBFILTERIDX_MANUFACTURER_STR, false },
1240 { "USB Product Name", USBFILTERIDX_PRODUCT_STR, false },
1241 { "USB Serial Number", USBFILTERIDX_SERIAL_NUMBER_STR, false },
1242 };
1243 for (unsigned i = 0; i < RT_ELEMENTS(s_aProps); i++)
1244 {
1245 OSObject *pObj = pProvider->getProperty(s_aProps[i].pszName);
1246 if (!pObj)
1247 continue;
1248 if (s_aProps[i].fNumeric)
1249 {
1250 OSNumber *pNum = OSDynamicCast(OSNumber, pObj);
1251 if (pNum)
1252 {
1253 uint16_t u16 = pNum->unsigned16BitValue();
1254 Log2(("VBoxUSBDevice::probe: %d/%s - %#x (32bit=%#x)\n", i, s_aProps[i].pszName, u16, pNum->unsigned32BitValue()));
1255 int vrc = USBFilterSetNumExact(&Device, s_aProps[i].enmIdx, u16, true);
1256 if (RT_FAILURE(vrc))
1257 Log(("VBoxUSBDevice::probe: pObj=%p pNum=%p - %d/%s - rc=%d!\n", pObj, pNum, i, s_aProps[i].pszName, vrc));
1258 }
1259 else
1260 Log(("VBoxUSBDevice::probe: pObj=%p pNum=%p - %d/%s!\n", pObj, pNum, i, s_aProps[i].pszName));
1261 }
1262 else
1263 {
1264 OSString *pStr = OSDynamicCast(OSString, pObj);
1265 if (pStr)
1266 {
1267 Log2(("VBoxUSBDevice::probe: %d/%s - %s\n", i, s_aProps[i].pszName, pStr->getCStringNoCopy()));
1268 int vrc = USBFilterSetStringExact(&Device, s_aProps[i].enmIdx, pStr->getCStringNoCopy(), true);
1269 if (RT_FAILURE(vrc))
1270 Log(("VBoxUSBDevice::probe: pObj=%p pStr=%p - %d/%s - rc=%d!\n", pObj, pStr, i, s_aProps[i].pszName, vrc));
1271 }
1272 else
1273 Log(("VBoxUSBDevice::probe: pObj=%p pStr=%p - %d/%s\n", pObj, pStr, i, s_aProps[i].pszName));
1274 }
1275 }
1276 /** @todo try figure the blasted bus number */
1277
1278 /*
1279 * Run filters on it.
1280 */
1281 uintptr_t uId = 0;
1282 RTPROCESS Owner = VBoxUSBFilterMatch(&Device, &uId);
1283 USBFilterDelete(&Device);
1284 if (Owner == NIL_RTPROCESS)
1285 {
1286 Log(("VBoxUSBDevice::probe: returns NULL uId=%d\n", uId));
1287 return NULL;
1288 }
1289
1290 /*
1291 * It matched. Save the owner in the provider registry (hope that works).
1292 */
1293 IOService *pRet = IOUSBUserClientInit::probe(pProvider, pi32Score);
1294 Assert(pRet == this);
1295 m_Owner = Owner;
1296 m_uId = uId;
1297 Log(("%p: m_Owner=%d m_uId=%d\n", this, (int)m_Owner, (int)m_uId));
1298 *pi32Score = _1G;
1299 Log(("VBoxUSBDevice::probe: returns %p and *pi32Score=%d\n", pRet, *pi32Score));
1300 return pRet;
1301}
1302
1303
1304/**
1305 * Try start the device driver.
1306 *
1307 * We will do device linking, copy the filter and owner properties from the provider,
1308 * set the client property, retain the device, and try open (seize) the device.
1309 *
1310 * @returns Success indicator.
1311 * @param pProvider The provider instance.
1312 */
1313bool
1314org_virtualbox_VBoxUSBDevice::start(IOService *pProvider)
1315{
1316 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1317 Log(("VBoxUSBDevice::start([%p:{.m_Owner=%d, .m_uId=%p}], %p {%s}) pszProcName=[%s] [retain count: %d]\n",
1318 this, m_Owner, m_uId, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
1319
1320 m_pDevice = OSDynamicCast(IOUSBDevice, pProvider);
1321 if (!m_pDevice)
1322 {
1323 printf("VBoxUSBDevice::start([%p], %p {%s}): failed!\n", this, pProvider, pProvider->getName());
1324 return false;
1325 }
1326
1327#ifdef DEBUG
1328 /* for some extra log messages */
1329 m_pNotifier = pProvider->registerInterest(gIOGeneralInterest,
1330 &org_virtualbox_VBoxUSBDevice::MyInterestHandler,
1331 this, /* pvTarget */
1332 NULL); /* pvRefCon */
1333#endif
1334
1335 /*
1336 * Exploit IOUSBUserClientInit to process IOProviderMergeProperties.
1337 */
1338 IOUSBUserClientInit::start(pProvider); /* returns false */
1339
1340 /*
1341 * Link ourselves into the list of hijacked device.
1342 */
1343 VBOXUSB_LOCK();
1344
1345 m_pNext = s_pHead;
1346 s_pHead = this;
1347
1348 VBOXUSB_UNLOCK();
1349
1350 /*
1351 * Set the VBoxUSB properties.
1352 */
1353 if (!setProperty(VBOXUSB_OWNER_KEY, (unsigned long long)m_Owner, sizeof(m_Owner) * 8 /* bits */))
1354 Log(("VBoxUSBDevice::start: failed to set the '" VBOXUSB_OWNER_KEY "' property!\n"));
1355 if (!setProperty(VBOXUSB_CLIENT_KEY, (unsigned long long)m_Client, sizeof(m_Client) * 8 /* bits */))
1356 Log(("VBoxUSBDevice::start: failed to set the '" VBOXUSB_CLIENT_KEY "' property!\n"));
1357 if (!setProperty(VBOXUSB_FILTER_KEY, (unsigned long long)m_uId, sizeof(m_uId) * 8 /* bits */))
1358 Log(("VBoxUSBDevice::start: failed to set the '" VBOXUSB_FILTER_KEY "' property!\n"));
1359
1360 /*
1361 * Retain and open the device.
1362 */
1363 m_pDevice->retain();
1364 m_fOpen = m_pDevice->open(this, kIOServiceSeize, 0);
1365 if (!m_fOpen)
1366 Log(("VBoxUSBDevice::start: failed to open the device!\n"));
1367 m_fOpenOnWasClosed = !m_fOpen;
1368
1369 Log(("VBoxUSBDevice::start: returns %d\n", true));
1370 return true;
1371}
1372
1373
1374/**
1375 * Stop the device driver.
1376 *
1377 * We'll unlink the device, start device re-enumeration and close it. And call
1378 * the parent stop method of course.
1379 *
1380 * @param pProvider The provider instance.
1381 */
1382void
1383org_virtualbox_VBoxUSBDevice::stop(IOService *pProvider)
1384{
1385 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1386 Log(("VBoxUSBDevice::stop([%p], %p {%s}) pszProcName=[%s] [retain count: %d]\n", this, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
1387
1388 /*
1389 * Remove ourselves from the list of device.
1390 */
1391 VBOXUSB_LOCK();
1392
1393 org_virtualbox_VBoxUSBDevice *pPrev = NULL;
1394 for (org_virtualbox_VBoxUSBDevice *pCur = s_pHead; pCur; pCur = pCur->m_pNext)
1395 {
1396 if (pCur == this)
1397 {
1398 if (pPrev)
1399 pPrev->m_pNext = m_pNext;
1400 else
1401 s_pHead = m_pNext;
1402 m_pNext = NULL;
1403 break;
1404 }
1405 pPrev = pCur;
1406 }
1407
1408 VBOXUSB_UNLOCK();
1409
1410 /*
1411 * Should we release the device?
1412 */
1413 if (m_fBeingUnloaded)
1414 {
1415 if (m_pDevice)
1416 {
1417 IOReturn irc = m_pDevice->ReEnumerateDevice(0); NOREF(irc);
1418 Log(("VBoxUSBDevice::stop([%p], %p {%s}): m_pDevice=%p unload & ReEnumerateDevice -> %#x\n",
1419 this, pProvider, pProvider->getName(), m_pDevice, irc));
1420 }
1421 else
1422 {
1423 IOUSBDevice *pDevice = OSDynamicCast(IOUSBDevice, pProvider);
1424 if (pDevice)
1425 {
1426 IOReturn irc = pDevice->ReEnumerateDevice(0); NOREF(irc);
1427 Log(("VBoxUSBDevice::stop([%p], %p {%s}): pDevice=%p unload & ReEnumerateDevice -> %#x\n",
1428 this, pProvider, pProvider->getName(), pDevice, irc));
1429 }
1430 else
1431 Log(("VBoxUSBDevice::stop([%p], %p {%s}): failed to cast provider to IOUSBDevice\n",
1432 this, pProvider, pProvider->getName()));
1433 }
1434 }
1435 else if (m_fReleaseOnClose)
1436 {
1437 ASMAtomicWriteBool(&m_fReleaseOnClose, false);
1438 if (m_pDevice)
1439 {
1440 IOReturn irc = m_pDevice->ReEnumerateDevice(0); NOREF(irc);
1441 Log(("VBoxUSBDevice::stop([%p], %p {%s}): m_pDevice=%p close & ReEnumerateDevice -> %#x\n",
1442 this, pProvider, pProvider->getName(), m_pDevice, irc));
1443 }
1444 }
1445
1446 /*
1447 * Close and release the IOUSBDevice if didn't do that already in message().
1448 */
1449 if (m_pDevice)
1450 {
1451 /* close it */
1452 if (m_fOpen)
1453 {
1454 m_fOpenOnWasClosed = false;
1455 m_fOpen = false;
1456 m_pDevice->close(this, 0);
1457 }
1458
1459 /* release it (see start()) */
1460 m_pDevice->release();
1461 m_pDevice = NULL;
1462 }
1463
1464#ifdef DEBUG
1465 /* avoid crashing on unload. */
1466 if (m_pNotifier)
1467 {
1468 m_pNotifier->release();
1469 m_pNotifier = NULL;
1470 }
1471#endif
1472
1473 IOUSBUserClientInit::stop(pProvider);
1474 Log(("VBoxUSBDevice::stop: returns void\n"));
1475}
1476
1477
1478/**
1479 * Terminate the service (initiate the destruction).
1480 * @remark Only for logging.
1481 */
1482bool
1483org_virtualbox_VBoxUSBDevice::terminate(IOOptionBits fOptions)
1484{
1485 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1486
1487 /* kIOServiceRecursing, kIOServiceRequired, kIOServiceTerminate, kIOServiceSynchronous - interesting option bits */
1488 Log(("VBoxUSBDevice::terminate([%p], %#x) pszProcName=[%s] [retain count: %d]\n", this, fOptions, pszProcName, getRetainCount()));
1489
1490 /*
1491 * There aren't too many reasons why we gets terminated.
1492 * The most common one is that the device is being unplugged. Another is
1493 * that we've triggered reenumeration. In both cases we'll get a
1494 * kIOMessageServiceIsTerminated message before we're stopped.
1495 *
1496 * But, when we're unloaded the provider service isn't terminated, and
1497 * for some funny reason we're frequently causing kernel panics when the
1498 * device is detached (after we're unloaded). So, for now, let's try
1499 * re-enumerate it in stop.
1500 *
1501 * To avoid creating unnecessary trouble we'll try guess if we're being
1502 * unloaded from the option bit mask. (kIOServiceRecursing is private btw.)
1503 */
1504 /** @todo would be nice if there was a documented way of doing the unload detection this, or
1505 * figure out what exactly we're doing wrong in the unload scenario. */
1506 if ((fOptions & 0xffff) == (kIOServiceRequired | kIOServiceSynchronous))
1507 m_fBeingUnloaded = true;
1508
1509 bool fRc = IOUSBUserClientInit::terminate(fOptions);
1510 Log(("VBoxUSBDevice::terminate([%p]): returns %d\n", this, fRc));
1511 return fRc;
1512}
1513
1514
1515/**
1516 * Intercept open requests and only let Mr. Right (the VM process) open the device.
1517 * This is where it all gets a bit complicated...
1518 *
1519 * @return Status code.
1520 *
1521 * @param enmMsg The message number.
1522 * @param pProvider Pointer to the provider instance.
1523 * @param pvArg Message argument.
1524 */
1525IOReturn
1526org_virtualbox_VBoxUSBDevice::message(UInt32 enmMsg, IOService *pProvider, void *pvArg)
1527{
1528 Log(("VBoxUSBDevice::message([%p], %#x {%s}, %p {%s}, %p) - pid=%d\n",
1529 this, enmMsg, DbgGetIOKitMessageName(enmMsg), pProvider, pProvider->getName(), pvArg, RTProcSelf()));
1530
1531 IOReturn irc;
1532 switch (enmMsg)
1533 {
1534 /*
1535 * This message is send to the current IOService client from IOService::handleOpen(),
1536 * expecting it to call pProvider->close() if it agrees to the other party seizing
1537 * the service. It is also called in IOService::didTerminate() and perhaps some other
1538 * odd places. The way to find out is to examin the pvArg, which would be including
1539 * kIOServiceSeize if it's the handleOpen case.
1540 *
1541 * How to validate that the other end is actually our VM process? Well, IOKit doesn't
1542 * provide any clue about the new client really. But fortunately, it seems like the
1543 * calling task/process context when the VM tries to open the device is the VM process.
1544 * We'll ASSUME this'll remain like this for now...
1545 */
1546 case kIOMessageServiceIsRequestingClose:
1547 irc = kIOReturnExclusiveAccess;
1548 /* If it's not a seize request, assume it's didTerminate and pray that it isn't a rouge driver.
1549 ... weird, doesn't seem to match for the post has-terminated messages. */
1550 if (!((uintptr_t)pvArg & kIOServiceSeize))
1551 {
1552 Log(("VBoxUSBDevice::message([%p],%p {%s}, %p) - pid=%d: not seize - closing...\n",
1553 this, pProvider, pProvider->getName(), pvArg, RTProcSelf()));
1554 m_fOpen = false;
1555 m_fOpenOnWasClosed = false;
1556 if (m_pDevice)
1557 m_pDevice->close(this, 0);
1558 m_Client = NIL_RTPROCESS;
1559 irc = kIOReturnSuccess;
1560 }
1561 else
1562 {
1563 if (org_virtualbox_VBoxUSBClient::isClientTask(current_task()))
1564 {
1565 Log(("VBoxUSBDevice::message([%p],%p {%s}, %p) - pid=%d task=%p: client process, closing.\n",
1566 this, pProvider, pProvider->getName(), pvArg, RTProcSelf(), current_task()));
1567 m_fOpen = false;
1568 m_fOpenOnWasClosed = false;
1569 if (m_pDevice)
1570 m_pDevice->close(this, 0);
1571 m_fOpenOnWasClosed = true;
1572 m_Client = RTProcSelf();
1573 irc = kIOReturnSuccess;
1574 }
1575 else
1576 Log(("VBoxUSBDevice::message([%p],%p {%s}, %p) - pid=%d task=%p: not client process!\n",
1577 this, pProvider, pProvider->getName(), pvArg, RTProcSelf(), current_task()));
1578 }
1579 if (!setProperty(VBOXUSB_CLIENT_KEY, (unsigned long long)m_Client, sizeof(m_Client) * 8 /* bits */))
1580 Log(("VBoxUSBDevice::message: failed to set the '" VBOXUSB_CLIENT_KEY "' property!\n"));
1581 break;
1582
1583 /*
1584 * The service was closed by the current client.
1585 * Update the client property, check for scheduled re-enumeration and re-open.
1586 *
1587 * Note that we will not be called if we're doing the closing. (Even if we was
1588 * called in that case, the code should be able to handle it.)
1589 */
1590 case kIOMessageServiceWasClosed:
1591 /*
1592 * Update the client property value.
1593 */
1594 if (m_Client != NIL_RTPROCESS)
1595 {
1596 m_Client = NIL_RTPROCESS;
1597 if (!setProperty(VBOXUSB_CLIENT_KEY, (unsigned long long)m_Client, sizeof(m_Client) * 8 /* bits */))
1598 Log(("VBoxUSBDevice::message: failed to set the '" VBOXUSB_CLIENT_KEY "' property!\n"));
1599 }
1600
1601 if (m_pDevice)
1602 {
1603 /*
1604 * Should we release the device?
1605 */
1606 if (ASMAtomicXchgBool(&m_fReleaseOnClose, false))
1607 {
1608 m_fOpenOnWasClosed = false;
1609 irc = m_pDevice->ReEnumerateDevice(0);
1610 Log(("VBoxUSBDevice::message([%p], %p {%s}) - ReEnumerateDevice() -> %#x\n",
1611 this, pProvider, pProvider->getName(), irc));
1612 }
1613 /*
1614 * Should we attempt to re-open the device?
1615 */
1616 else if (m_fOpenOnWasClosed)
1617 {
1618 Log(("VBoxUSBDevice::message: attempting to re-open the device...\n"));
1619 m_fOpenOnWasClosed = false;
1620 m_fOpen = m_pDevice->open(this, kIOServiceSeize, 0);
1621 if (!m_fOpen)
1622 Log(("VBoxUSBDevice::message: failed to open the device!\n"));
1623 m_fOpenOnWasClosed = !m_fOpen;
1624 }
1625 }
1626
1627 irc = IOUSBUserClientInit::message(enmMsg, pProvider, pvArg);
1628 break;
1629
1630 /*
1631 * The IOUSBDevice is shutting down, so close it if we've opened it.
1632 */
1633 case kIOMessageServiceIsTerminated:
1634 m_fBeingUnloaded = false;
1635 ASMAtomicWriteBool(&m_fReleaseOnClose, false);
1636 if (m_pDevice)
1637 {
1638 /* close it */
1639 if (m_fOpen)
1640 {
1641 m_fOpen = false;
1642 m_fOpenOnWasClosed = false;
1643 Log(("VBoxUSBDevice::message: closing the device (%p)...\n", m_pDevice));
1644 m_pDevice->close(this, 0);
1645 }
1646
1647 /* release it (see start()) */
1648 Log(("VBoxUSBDevice::message: releasing the device (%p)...\n", m_pDevice));
1649 m_pDevice->release();
1650 m_pDevice = NULL;
1651 }
1652
1653 irc = IOUSBUserClientInit::message(enmMsg, pProvider, pvArg);
1654 break;
1655
1656 default:
1657 irc = IOUSBUserClientInit::message(enmMsg, pProvider, pvArg);
1658 break;
1659 }
1660
1661 Log(("VBoxUSBDevice::message([%p], %#x {%s}, %p {%s}, %p) -> %#x\n",
1662 this, enmMsg, DbgGetIOKitMessageName(enmMsg), pProvider, pProvider->getName(), pvArg, irc));
1663 return irc;
1664}
1665
1666
1667/**
1668 * Schedule all devices belonging to the specified process for release.
1669 *
1670 * Devices that aren't currently in use will be released immediately.
1671 *
1672 * @param Owner The owner process.
1673 */
1674/* static */ void
1675org_virtualbox_VBoxUSBDevice::scheduleReleaseByOwner(RTPROCESS Owner)
1676{
1677 Log2(("VBoxUSBDevice::scheduleReleaseByOwner: Owner=%d\n", Owner));
1678 AssertReturnVoid(Owner && Owner != NIL_RTPROCESS);
1679
1680 /*
1681 * Walk the list of devices looking for device belonging to this process.
1682 *
1683 * If we release a device, we have to lave the spinlock and will therefore
1684 * have to restart the search.
1685 */
1686 VBOXUSB_LOCK();
1687
1688 org_virtualbox_VBoxUSBDevice *pCur;
1689 do
1690 {
1691 for (pCur = s_pHead; pCur; pCur = pCur->m_pNext)
1692 {
1693 Log2(("VBoxUSBDevice::scheduleReleaseByOwner: pCur=%p m_Owner=%d (%s) m_fReleaseOnClose=%d\n",
1694 pCur, pCur->m_Owner, pCur->m_Owner == Owner ? "match" : "mismatch", pCur->m_fReleaseOnClose));
1695 if (pCur->m_Owner == Owner)
1696 {
1697 /* make sure we won't hit it again. */
1698 pCur->m_Owner = NIL_RTPROCESS;
1699 IOUSBDevice *pDevice = pCur->m_pDevice;
1700 if ( pDevice
1701 && !pCur->m_fReleaseOnClose)
1702 {
1703 pCur->m_fOpenOnWasClosed = false;
1704 if (pCur->m_Client != NIL_RTPROCESS)
1705 {
1706 /* It's currently open, so just schedule it for re-enumeration on close. */
1707 ASMAtomicWriteBool(&pCur->m_fReleaseOnClose, true);
1708 Log(("VBoxUSBDevice::scheduleReleaseByOwner: %p {%s} - used by %d\n",
1709 pDevice, pDevice->getName(), pCur->m_Client));
1710 }
1711 else
1712 {
1713 /*
1714 * Get the USBDevice object and do the re-enumeration now.
1715 * Retain the device so we don't run into any trouble.
1716 */
1717 pDevice->retain();
1718 VBOXUSB_UNLOCK();
1719
1720 IOReturn irc = pDevice->ReEnumerateDevice(0); NOREF(irc);
1721 Log(("VBoxUSBDevice::scheduleReleaseByOwner: %p {%s} - ReEnumerateDevice -> %#x\n",
1722 pDevice, pDevice->getName(), irc));
1723
1724 pDevice->release();
1725 VBOXUSB_LOCK();
1726 break;
1727 }
1728 }
1729 }
1730 }
1731 } while (pCur);
1732
1733 VBOXUSB_UNLOCK();
1734}
1735
1736
1737#ifdef DEBUG
1738/*static*/ IOReturn
1739org_virtualbox_VBoxUSBDevice::MyInterestHandler(void *pvTarget, void *pvRefCon, UInt32 enmMsgType,
1740 IOService *pProvider, void * pvMsgArg, vm_size_t cbMsgArg)
1741{
1742 org_virtualbox_VBoxUSBDevice *pThis = (org_virtualbox_VBoxUSBDevice *)pvTarget;
1743 if (!pThis)
1744 return kIOReturnError;
1745
1746 switch (enmMsgType)
1747 {
1748 case kIOMessageServiceIsAttemptingOpen:
1749 /* pvMsgArg == the open() fOptions, so we could check for kIOServiceSeize if we care.
1750 We'll also get a kIIOServiceRequestingClose message() for that... */
1751 Log(("VBoxUSBDevice::MyInterestHandler: kIOMessageServiceIsAttemptingOpen - pvRefCon=%p pProvider=%p pvMsgArg=%p cbMsgArg=%d\n",
1752 pvRefCon, pProvider, pvMsgArg, cbMsgArg));
1753 break;
1754
1755 case kIOMessageServiceWasClosed:
1756 Log(("VBoxUSBDevice::MyInterestHandler: kIOMessageServiceWasClosed - pvRefCon=%p pProvider=%p pvMsgArg=%p cbMsgArg=%d\n",
1757 pvRefCon, pProvider, pvMsgArg, cbMsgArg));
1758 break;
1759
1760 case kIOMessageServiceIsTerminated:
1761 Log(("VBoxUSBDevice::MyInterestHandler: kIOMessageServiceIsTerminated - pvRefCon=%p pProvider=%p pvMsgArg=%p cbMsgArg=%d\n",
1762 pvRefCon, pProvider, pvMsgArg, cbMsgArg));
1763 break;
1764
1765 case kIOUSBMessagePortHasBeenReset:
1766 Log(("VBoxUSBDevice::MyInterestHandler: kIOUSBMessagePortHasBeenReset - pvRefCon=%p pProvider=%p pvMsgArg=%p cbMsgArg=%d\n",
1767 pvRefCon, pProvider, pvMsgArg, cbMsgArg));
1768 break;
1769
1770 default:
1771 Log(("VBoxUSBDevice::MyInterestHandler: %#x (%s) - pvRefCon=%p pProvider=%p pvMsgArg=%p cbMsgArg=%d\n",
1772 enmMsgType, DbgGetIOKitMessageName(enmMsgType), pvRefCon, pProvider, pvMsgArg, cbMsgArg));
1773 break;
1774 }
1775
1776 return kIOReturnSuccess;
1777}
1778#endif /* DEBUG */
1779
1780
1781bool
1782org_virtualbox_VBoxUSBDevice::open(IOService *pForClient, IOOptionBits fOptions, void *pvArg)
1783{
1784 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1785 Log(("VBoxUSBDevice::open([%p], pForClient=%p, fOptions=%#x, pvArg=%p) (1) pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pvArg, pszProcName, getRetainCount()));
1786 bool fRc = IOUSBUserClientInit::open(pForClient, fOptions, pvArg);
1787 Log(("VBoxUSBDevice::open([%p], pForClient=%p, fOptions=%#x, pvArg=%p) (2) returns %d pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pvArg, fRc, pszProcName, getRetainCount()));
1788 return fRc;
1789}
1790
1791void
1792org_virtualbox_VBoxUSBDevice::close(IOService *pForClient, IOOptionBits fOptions)
1793{
1794 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1795 Log(("VBoxUSBDevice::close([%p], pForClient=%p, fOptions=%#x) (1) pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pszProcName, getRetainCount()));
1796 IOUSBUserClientInit::close(pForClient, fOptions);
1797 Log(("VBoxUSBDevice::close([%p], pForClient=%p, fOptions=%#x) (2) pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pszProcName, getRetainCount()));
1798}
1799
1800bool
1801org_virtualbox_VBoxUSBDevice::terminateClient(IOService *pClient, IOOptionBits fOptions)
1802{
1803 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1804 Log(("VBoxUSBDevice::terminateClient([%p], pClient=%p, fOptions=%#x) (1) pszProcName=[%s] [retain count: %d]\n", this, pClient, fOptions, pszProcName, getRetainCount()));
1805 bool fRc = IOUSBUserClientInit::terminateClient(pClient, fOptions);
1806 Log(("VBoxUSBDevice::terminateClient([%p], pClient=%p, fOptions=%#x) (2) returns %d pszProcName=[%s] [retain count: %d]\n", this, pClient, fOptions, fRc, pszProcName, getRetainCount()));
1807 return fRc;
1808}
1809
1810
1811bool
1812org_virtualbox_VBoxUSBDevice::finalize(IOOptionBits fOptions)
1813{
1814 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1815 Log(("VBoxUSBDevice::finalize([%p], fOptions=%#x) (1) pszProcName=[%s] [retain count: %d]\n", this, fOptions, pszProcName, getRetainCount()));
1816 bool fRc = IOUSBUserClientInit::finalize(fOptions);
1817 Log(("VBoxUSBDevice::finalize([%p], fOptions=%#x) (2) returns %d pszProcName=[%s] [retain count: %d]\n", this, fOptions, fRc, pszProcName, getRetainCount()));
1818 return fRc;
1819}
1820
1821
1822void
1823org_virtualbox_VBoxUSBDevice::retain() const
1824{
1825 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1826 Log(("VBoxUSBDevice::retain([%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
1827 IOUSBUserClientInit::retain();
1828 Log(("VBoxUSBDevice::retain([%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
1829}
1830
1831
1832void
1833org_virtualbox_VBoxUSBDevice::release(int freeWhen) const
1834{
1835 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1836 Log(("VBoxUSBDevice::release([%p], freeWhen=[%d]) pszProcName=[%s] [retain count: %d]\n", this, freeWhen, pszProcName, getRetainCount()));
1837 IOUSBUserClientInit::release(freeWhen);
1838}
1839
1840
1841void
1842org_virtualbox_VBoxUSBDevice::taggedRetain(const void *pTag) const
1843{
1844 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1845 Log(("VBoxUSBDevice::taggedRetain([%p], pTag=[%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pTag, pszProcName, getRetainCount()));
1846 IOUSBUserClientInit::taggedRetain(pTag);
1847 Log(("VBoxUSBDevice::taggedRetain([%p], pTag=[%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pTag, pszProcName, getRetainCount()));
1848}
1849
1850
1851void
1852org_virtualbox_VBoxUSBDevice::taggedRelease(const void *pTag, const int freeWhen) const
1853{
1854 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1855 Log(("VBoxUSBDevice::taggedRelease([%p], pTag=[%p], freeWhen=[%d]) pszProcName=[%s] [retain count: %d]\n", this, pTag, freeWhen, pszProcName, getRetainCount()));
1856 IOUSBUserClientInit::taggedRelease(pTag, freeWhen);
1857}
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870/*
1871 *
1872 * org_virtualbox_VBoxUSBInterface
1873 *
1874 */
1875
1876/**
1877 * Initialize our data members.
1878 */
1879bool
1880org_virtualbox_VBoxUSBInterface::init(OSDictionary *pDictionary)
1881{
1882 uint32_t cInstances = ASMAtomicIncU32(&g_cInstances);
1883 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1884
1885 Log(("VBoxUSBInterface::init([%p], %p) new g_cInstances=%d pszProcName=[%s] [retain count: %d]\n", this, pDictionary, cInstances, pszProcName, getRetainCount()));
1886
1887 m_pInterface = NULL;
1888 m_fOpen = false;
1889 m_fOpenOnWasClosed = false;
1890
1891 return IOUSBUserClientInit::init(pDictionary);
1892}
1893
1894
1895/**
1896 * Free the object.
1897 * @remark Only for logging.
1898 */
1899void
1900org_virtualbox_VBoxUSBInterface::free()
1901{
1902 uint32_t cInstances = ASMAtomicDecU32(&g_cInstances); NOREF(cInstances);
1903 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1904 Log(("VBoxUSBInterfaces::free([%p]) new g_cInstances=%d pszProcName=[%s] [retain count: %d]\n", this, cInstances, pszProcName, getRetainCount()));
1905 IOUSBUserClientInit::free();
1906}
1907
1908
1909/**
1910 * Probe the interface to see if we're the right driver for it.
1911 *
1912 * We implement this similarly to org_virtualbox_VBoxUSBDevice, except that
1913 * we don't bother matching filters but instead just check if the parent is
1914 * handled by org_virtualbox_VBoxUSBDevice or not.
1915 */
1916IOService *
1917org_virtualbox_VBoxUSBInterface::probe(IOService *pProvider, SInt32 *pi32Score)
1918{
1919 Log(("VBoxUSBInterface::probe([%p], %p {%s}, %p={%d})\n", this,
1920 pProvider, pProvider->getName(), pi32Score, pi32Score ? *pi32Score : 0));
1921
1922 /*
1923 * Check if VBoxUSBDevice is the parent's driver.
1924 */
1925 bool fHijackIt = false;
1926 const IORegistryPlane *pServicePlane = getPlane(kIOServicePlane);
1927 IORegistryEntry *pParent = pProvider->getParentEntry(pServicePlane);
1928 if (pParent)
1929 {
1930 Log(("VBoxUSBInterface::probe: pParent=%p {%s}\n", pParent, pParent->getName()));
1931
1932 OSIterator *pSiblings = pParent->getChildIterator(pServicePlane);
1933 if (pSiblings)
1934 {
1935 IORegistryEntry *pSibling;
1936 while ( (pSibling = OSDynamicCast(IORegistryEntry, pSiblings->getNextObject())) )
1937 {
1938 const OSMetaClass *pMetaClass = pSibling->getMetaClass();
1939 Log2(("sibling: %p - %s - %s\n", pMetaClass, pSibling->getName(), pMetaClass->getClassName()));
1940 if (pMetaClass == &org_virtualbox_VBoxUSBDevice::gMetaClass)
1941 {
1942 fHijackIt = true;
1943 break;
1944 }
1945 }
1946 pSiblings->release();
1947 }
1948 }
1949 if (!fHijackIt)
1950 {
1951 Log(("VBoxUSBInterface::probe: returns NULL\n"));
1952 return NULL;
1953 }
1954
1955 IOService *pRet = IOUSBUserClientInit::probe(pProvider, pi32Score);
1956 *pi32Score = _1G;
1957 Log(("VBoxUSBInterface::probe: returns %p and *pi32Score=%d - hijack it.\n", pRet, *pi32Score));
1958 return pRet;
1959}
1960
1961
1962/**
1963 * Start the driver (this), retain and open the USB interface object (pProvider).
1964 */
1965bool
1966org_virtualbox_VBoxUSBInterface::start(IOService *pProvider)
1967{
1968 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
1969 Log(("VBoxUSBInterface::start([%p], %p {%s}) pszProcName=[%s] [retain count: %d]\n", this, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
1970
1971 /*
1972 * Exploit IOUSBUserClientInit to process IOProviderMergeProperties.
1973 */
1974 IOUSBUserClientInit::start(pProvider); /* returns false */
1975
1976 /*
1977 * Retain the and open the interface (stop() or message() cleans up).
1978 */
1979 bool fRc = true;
1980 m_pInterface = OSDynamicCast(IOUSBInterface, pProvider);
1981 if (m_pInterface)
1982 {
1983 m_pInterface->retain();
1984 m_fOpen = m_pInterface->open(this, kIOServiceSeize, 0);
1985 if (!m_fOpen)
1986 Log(("VBoxUSBInterface::start: failed to open the interface!\n"));
1987 m_fOpenOnWasClosed = !m_fOpen;
1988 }
1989 else
1990 {
1991 printf("VBoxUSBInterface::start([%p], %p {%s}): failed!\n", this, pProvider, pProvider->getName());
1992 fRc = false;
1993 }
1994
1995 Log(("VBoxUSBInterface::start: returns %d\n", fRc));
1996 return fRc;
1997}
1998
1999
2000/**
2001 * Close and release the USB interface object (pProvider) and stop the driver (this).
2002 */
2003void
2004org_virtualbox_VBoxUSBInterface::stop(IOService *pProvider)
2005{
2006 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2007 Log(("org_virtualbox_VBoxUSBInterface::stop([%p], %p {%s}) pszProcName=[%s] [retain count: %d]\\n", this, pProvider, pProvider->getName(), pszProcName, getRetainCount()));
2008
2009 /*
2010 * Close and release the IOUSBInterface if didn't do that already in message().
2011 */
2012 if (m_pInterface)
2013 {
2014 /* close it */
2015 if (m_fOpen)
2016 {
2017 m_fOpenOnWasClosed = false;
2018 m_fOpen = false;
2019 m_pInterface->close(this, 0);
2020 }
2021
2022 /* release it (see start()) */
2023 m_pInterface->release();
2024 m_pInterface = NULL;
2025 }
2026
2027 IOUSBUserClientInit::stop(pProvider);
2028 Log(("VBoxUSBInterface::stop: returns void\n"));
2029}
2030
2031
2032/**
2033 * Terminate the service (initiate the destruction).
2034 * @remark Only for logging.
2035 */
2036bool
2037org_virtualbox_VBoxUSBInterface::terminate(IOOptionBits fOptions)
2038{
2039 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2040 /* kIOServiceRecursing, kIOServiceRequired, kIOServiceTerminate, kIOServiceSynchronous - interesting option bits */
2041 Log(("VBoxUSBInterface::terminate([%p], %#x) pszProcName=[%s] [retain count: %d]\n", this, fOptions, pszProcName, getRetainCount()));
2042 bool fRc = IOUSBUserClientInit::terminate(fOptions);
2043 Log(("VBoxUSBInterface::terminate([%p]): returns %d\n", this, fRc));
2044 return fRc;
2045}
2046
2047
2048/**
2049 * @copydoc org_virtualbox_VBoxUSBDevice::message
2050 */
2051IOReturn
2052org_virtualbox_VBoxUSBInterface::message(UInt32 enmMsg, IOService *pProvider, void *pvArg)
2053{
2054 Log(("VBoxUSBInterface::message([%p], %#x {%s}, %p {%s}, %p)\n",
2055 this, enmMsg, DbgGetIOKitMessageName(enmMsg), pProvider, pProvider->getName(), pvArg));
2056
2057 IOReturn irc;
2058 switch (enmMsg)
2059 {
2060 /*
2061 * See explanation in org_virtualbox_VBoxUSBDevice::message.
2062 */
2063 case kIOMessageServiceIsRequestingClose:
2064 irc = kIOReturnExclusiveAccess;
2065 if (!((uintptr_t)pvArg & kIOServiceSeize))
2066 {
2067 Log(("VBoxUSBInterface::message([%p],%p {%s}, %p) - pid=%d: not seize - closing...\n",
2068 this, pProvider, pProvider->getName(), pvArg, RTProcSelf()));
2069 m_fOpen = false;
2070 m_fOpenOnWasClosed = false;
2071 if (m_pInterface)
2072 m_pInterface->close(this, 0);
2073 irc = kIOReturnSuccess;
2074 }
2075 else
2076 {
2077 if (org_virtualbox_VBoxUSBClient::isClientTask(current_task()))
2078 {
2079 Log(("VBoxUSBInterface::message([%p],%p {%s}, %p) - pid=%d task=%p: client process, closing.\n",
2080 this, pProvider, pProvider->getName(), pvArg, RTProcSelf(), current_task()));
2081 m_fOpen = false;
2082 m_fOpenOnWasClosed = false;
2083 if (m_pInterface)
2084 m_pInterface->close(this, 0);
2085 m_fOpenOnWasClosed = true;
2086 irc = kIOReturnSuccess;
2087 }
2088 else
2089 Log(("VBoxUSBInterface::message([%p],%p {%s}, %p) - pid=%d task=%p: not client process!\n",
2090 this, pProvider, pProvider->getName(), pvArg, RTProcSelf(), current_task()));
2091 }
2092 break;
2093
2094 /*
2095 * The service was closed by the current client, check for re-open.
2096 */
2097 case kIOMessageServiceWasClosed:
2098 if (m_pInterface && m_fOpenOnWasClosed)
2099 {
2100 Log(("VBoxUSBInterface::message: attempting to re-open the interface...\n"));
2101 m_fOpenOnWasClosed = false;
2102 m_fOpen = m_pInterface->open(this, kIOServiceSeize, 0);
2103 if (!m_fOpen)
2104 Log(("VBoxUSBInterface::message: failed to open the interface!\n"));
2105 m_fOpenOnWasClosed = !m_fOpen;
2106 }
2107
2108 irc = IOUSBUserClientInit::message(enmMsg, pProvider, pvArg);
2109 break;
2110
2111 /*
2112 * The IOUSBInterface/Device is shutting down, so close and release.
2113 */
2114 case kIOMessageServiceIsTerminated:
2115 if (m_pInterface)
2116 {
2117 /* close it */
2118 if (m_fOpen)
2119 {
2120 m_fOpen = false;
2121 m_fOpenOnWasClosed = false;
2122 m_pInterface->close(this, 0);
2123 }
2124
2125 /* release it (see start()) */
2126 m_pInterface->release();
2127 m_pInterface = NULL;
2128 }
2129
2130 irc = IOUSBUserClientInit::message(enmMsg, pProvider, pvArg);
2131 break;
2132
2133 default:
2134 irc = IOUSBUserClientInit::message(enmMsg, pProvider, pvArg);
2135 break;
2136 }
2137
2138 Log(("VBoxUSBInterface::message([%p], %#x {%s}, %p {%s}, %p) -> %#x\n",
2139 this, enmMsg, DbgGetIOKitMessageName(enmMsg), pProvider, pProvider->getName(), pvArg, irc));
2140 return irc;
2141}
2142
2143bool
2144org_virtualbox_VBoxUSBInterface::open(IOService *pForClient, IOOptionBits fOptions, void *pvArg)
2145{
2146 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2147 Log(("VBoxUSBInterface::open([%p], pForClient=%p, fOptions=%#x, pvArg=%p) (1) pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pvArg, pszProcName, getRetainCount()));
2148 bool fRc = IOUSBUserClientInit::open(pForClient, fOptions, pvArg);
2149 Log(("VBoxUSBInterface::open([%p], pForClient=%p, fOptions=%#x, pvArg=%p) (2) returns %d pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pvArg, fRc, pszProcName, getRetainCount()));
2150 return fRc;
2151}
2152
2153void
2154org_virtualbox_VBoxUSBInterface::close(IOService *pForClient, IOOptionBits fOptions)
2155{
2156 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2157 Log(("VBoxUSBInterface::close([%p], pForClient=%p, fOptions=%#x) (1) pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pszProcName, getRetainCount()));
2158 IOUSBUserClientInit::close(pForClient, fOptions);
2159 Log(("VBoxUSBInterface::close([%p], pForClient=%p, fOptions=%#x) (2) pszProcName=[%s] [retain count: %d]\n", this, pForClient, fOptions, pszProcName, getRetainCount()));
2160}
2161
2162bool
2163org_virtualbox_VBoxUSBInterface::terminateClient(IOService *pClient, IOOptionBits fOptions)
2164{
2165 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2166 Log(("VBoxUSBInterface::terminateClient([%p], pClient=%p, fOptions=%#x) (1) pszProcName=[%s] [retain count: %d]\n", this, pClient, fOptions, pszProcName, getRetainCount()));
2167 bool fRc = IOUSBUserClientInit::terminateClient(pClient, fOptions);
2168 Log(("VBoxUSBInterface::terminateClient([%p], pClient=%p, fOptions=%#x) (2) returns %d pszProcName=[%s] [retain count: %d]\n", this, pClient, fOptions, fRc, pszProcName, getRetainCount()));
2169 return fRc;
2170}
2171
2172
2173bool
2174org_virtualbox_VBoxUSBInterface::finalize(IOOptionBits fOptions)
2175{
2176 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2177 Log(("VBoxUSBInterface::finalize([%p], fOptions=%#x) (1) pszProcName=[%s] [retain count: %d]\n", this, fOptions, pszProcName, getRetainCount()));
2178 bool fRc = IOUSBUserClientInit::finalize(fOptions);
2179 Log(("VBoxUSBInterface::finalize([%p], fOptions=%#x) (2) returns %d pszProcName=[%s] [retain count: %d]\n", this, fOptions, fRc, pszProcName, getRetainCount()));
2180 return fRc;
2181}
2182
2183void
2184org_virtualbox_VBoxUSBInterface::retain() const
2185{
2186 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2187 Log(("VBoxUSBInterface::retain([%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
2188 IOUSBUserClientInit::retain();
2189 Log(("VBoxUSBInterface::retain([%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pszProcName, getRetainCount()));
2190}
2191
2192
2193void
2194org_virtualbox_VBoxUSBInterface::release(int freeWhen) const
2195{
2196 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2197 Log(("VBoxUSBInterface::release([%p], freeWhen=[%d]) pszProcName=[%s] [retain count: %d]\n", this, freeWhen, pszProcName, getRetainCount()));
2198 IOUSBUserClientInit::release(freeWhen);
2199}
2200
2201
2202void
2203org_virtualbox_VBoxUSBInterface::taggedRetain(const void *pTag) const
2204{
2205 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2206 Log(("VBoxUSBInterface::taggedRetain([%p], pTag=[%p]) (1) pszProcName=[%s] [retain count: %d]\n", this, pTag, pszProcName, getRetainCount()));
2207 IOUSBUserClientInit::taggedRetain(pTag);
2208 Log(("VBoxUSBInterface::taggedRetain([%p], pTag=[%p]) (2) pszProcName=[%s] [retain count: %d]\n", this, pTag, pszProcName, getRetainCount()));
2209}
2210
2211
2212void
2213org_virtualbox_VBoxUSBInterface::taggedRelease(const void *pTag, const int freeWhen) const
2214{
2215 VBOX_RETRIEVE_CUR_PROC_NAME(pszProcName);
2216 Log(("VBoxUSBInterface::taggedRelease([%p], pTag=[%p], freeWhen=[%d]) pszProcName=[%s] [retain count: %d]\n", this, pTag, freeWhen, pszProcName, getRetainCount()));
2217 IOUSBUserClientInit::taggedRelease(pTag, freeWhen);
2218}
2219
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