VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/darwin/testcase/tstOpenUSBDev.cpp@ 68033

Last change on this file since 68033 was 63495, checked in by vboxsync, 8 years ago

warnings (clang)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1/* $Id: tstOpenUSBDev.cpp 63495 2016-08-15 17:19:46Z vboxsync $ */
2/** @file
3 * Testcase that attempts to locate and open the specfied device.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <mach/mach.h>
23#include <Carbon/Carbon.h>
24#include <IOKit/IOKitLib.h>
25#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
26#include <IOKit/scsi/SCSITaskLib.h>
27#include <mach/mach_error.h>
28#include <IOKit/usb/IOUSBLib.h>
29#include <IOKit/IOCFPlugIn.h>
30
31#include <iprt/mem.h>
32#include <iprt/string.h>
33#include <iprt/process.h>
34#include <iprt/assert.h>
35#include <iprt/thread.h>
36#include <iprt/getopt.h>
37#include <iprt/initterm.h>
38#include <iprt/stream.h>
39
40/**
41 * Gets an unsigned 32-bit integer value.
42 *
43 * @returns Success indicator (true/false).
44 * @param DictRef The dictionary.
45 * @param KeyStrRef The key name.
46 * @param pu32 Where to store the key value.
47 */
48static bool tstDictGetU32(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint32_t *pu32)
49{
50 CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
51 if (ValRef)
52 {
53 if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt32Type, pu32))
54 return true;
55 }
56 *pu32 = 0;
57 return false;
58}
59
60
61/**
62 * Gets an unsigned 64-bit integer value.
63 *
64 * @returns Success indicator (true/false).
65 * @param DictRef The dictionary.
66 * @param KeyStrRef The key name.
67 * @param pu64 Where to store the key value.
68 */
69static bool tstDictGetU64(CFMutableDictionaryRef DictRef, CFStringRef KeyStrRef, uint64_t *pu64)
70{
71 CFTypeRef ValRef = CFDictionaryGetValue(DictRef, KeyStrRef);
72 if (ValRef)
73 {
74 if (CFNumberGetValue((CFNumberRef)ValRef, kCFNumberSInt64Type, pu64))
75 return true;
76 }
77 *pu64 = 0;
78 return false;
79}
80
81
82static int tstDoWork(io_object_t USBDevice, const char *argv0)
83{
84 /*
85 * Create a plugin interface for the device and query its IOUSBDeviceInterface.
86 */
87 int vrc = VINF_SUCCESS;
88 SInt32 Score = 0;
89 IOCFPlugInInterface **ppPlugInInterface = NULL;
90 IOReturn irc = IOCreatePlugInInterfaceForService(USBDevice, kIOUSBDeviceUserClientTypeID,
91 kIOCFPlugInInterfaceID, &ppPlugInInterface, &Score);
92 if (irc == kIOReturnSuccess)
93 {
94 IOUSBDeviceInterface245 **ppDevI = NULL;
95 HRESULT hrc = (*ppPlugInInterface)->QueryInterface(ppPlugInInterface,
96 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID245),
97 (LPVOID *)&ppDevI);
98 irc = IODestroyPlugInInterface(ppPlugInInterface); Assert(irc == kIOReturnSuccess);
99 ppPlugInInterface = NULL;
100 if (hrc == S_OK)
101 {
102 /*
103 * Try open the device for exclusive access.
104 */
105 irc = (*ppDevI)->USBDeviceOpenSeize(ppDevI);
106 if (irc == kIOReturnExclusiveAccess)
107 {
108 RTThreadSleep(20);
109 irc = (*ppDevI)->USBDeviceOpenSeize(ppDevI);
110 }
111 if (irc == kIOReturnSuccess)
112 {
113#if 0
114 /*
115 * Re-enumerate the device and bail out.
116 */
117 irc = (*ppDevI)->USBDeviceReEnumerate(ppDevI, 0);
118 if (irc != kIOReturnSuccess)
119 {
120 vrc = RTErrConvertFromDarwinIO(irc);
121 RTPrintf("%s: Failed to re-enumerate the device, irc=%#x (vrc=%Rrc).\n", argv0, irc, vrc);
122 }
123#endif
124
125 (*ppDevI)->USBDeviceClose(ppDevI);
126 }
127 else if (irc == kIOReturnExclusiveAccess)
128 {
129 vrc = VERR_SHARING_VIOLATION;
130 RTPrintf("%s: The device is being used by another process (irc=kIOReturnExclusiveAccess)\n", argv0);
131 }
132 else
133 {
134 vrc = VERR_OPEN_FAILED;
135 RTPrintf("%s: Failed to open the device, irc=%#x (vrc=%Rrc).\n", argv0, irc, vrc);
136 }
137 }
138 else
139 {
140 vrc = VERR_OPEN_FAILED;
141 RTPrintf("%s: Failed to create plugin interface for the device, hrc=%#x (vrc=%Rrc).\n", argv0, hrc, vrc);
142 }
143
144 (*ppDevI)->Release(ppDevI);
145 }
146 else
147 {
148 vrc = RTErrConvertFromDarwinIO(irc);
149 RTPrintf("%s: Failed to open the device, plug-in creation failed with irc=%#x (vrc=%Rrc).\n", argv0, irc, vrc);
150 }
151
152 return vrc;
153}
154
155
156static int tstSyntax(const char *argv0)
157{
158 RTPrintf("syntax: %s [criteria]\n"
159 "\n"
160 "Criteria:\n"
161 " -l <location>\n"
162 " -s <session>\n"
163 , argv0);
164 return 1;
165}
166
167
168int main(int argc, char **argv)
169{
170 RTR3InitExe(argc, &argv, 0);
171
172 /*
173 * Show help if not arguments.
174 */
175 if (argc <= 1)
176 return tstSyntax(argv[0]);
177
178 /*
179 * Parse arguments.
180 */
181 static const RTGETOPTDEF g_aOptions[] =
182 {
183 { "--location", 'l', RTGETOPT_REQ_UINT32 },
184 { "--session", 's', RTGETOPT_REQ_UINT64 },
185 };
186
187 kern_return_t krc;
188 uint64_t u64SessionId = 0;
189 uint32_t u32LocationId = 0;
190
191 int ch;
192 RTGETOPTUNION ValueUnion;
193 RTGETOPTSTATE GetState;
194 RTGetOptInit(&GetState, argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), 1, 0 /* fFlags */);
195 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
196 {
197 switch (ch)
198 {
199 case 'l':
200 u32LocationId = ValueUnion.u32;
201 break;
202 case 's':
203 u64SessionId = ValueUnion.u64;
204 break;
205 case 'h':
206 return tstSyntax(argv[0]);
207 case 'V':
208 RTPrintf("$Revision: 63495 $\n");
209 return 0;
210
211 default:
212 return RTGetOptPrintError(ch, &ValueUnion);
213 }
214 }
215
216 /*
217 * Open the master port.
218 */
219 mach_port_t MasterPort = MACH_PORT_NULL;
220 krc = IOMasterPort(MACH_PORT_NULL, &MasterPort);
221 if (krc != KERN_SUCCESS)
222 {
223 RTPrintf("%s: IOMasterPort -> %x\n", argv[0], krc);
224 return 1;
225 }
226
227 /*
228 * Iterate the USB devices and find all that matches.
229 */
230 CFMutableDictionaryRef RefMatchingDict = IOServiceMatching(kIOUSBDeviceClassName);
231 if (!RefMatchingDict)
232 {
233 RTPrintf("%s: IOServiceMatching failed\n", argv[0]);
234 return 1;
235 }
236
237 io_iterator_t USBDevices = IO_OBJECT_NULL;
238 IOReturn irc = IOServiceGetMatchingServices(MasterPort, RefMatchingDict, &USBDevices);
239 if (irc != kIOReturnSuccess)
240 {
241 RTPrintf("%s: IOServiceGetMatchingServices -> %#x\n", argv[0], irc);
242 return 1;
243 }
244 RefMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */
245
246 unsigned cDevices = 0;
247 unsigned cMatches = 0;
248 io_object_t USBDevice;
249 while ((USBDevice = IOIteratorNext(USBDevices)))
250 {
251 cDevices++;
252 CFMutableDictionaryRef PropsRef = 0;
253 krc = IORegistryEntryCreateCFProperties(USBDevice, &PropsRef, kCFAllocatorDefault, kNilOptions);
254 if (krc == KERN_SUCCESS)
255 {
256 uint64_t u64CurSessionId;
257 uint32_t u32CurLocationId;
258 if ( ( !u64SessionId
259 || ( tstDictGetU64(PropsRef, CFSTR("sessionID"), &u64CurSessionId)
260 && u64CurSessionId == u64SessionId))
261 && ( !u32LocationId
262 || ( tstDictGetU32(PropsRef, CFSTR(kUSBDevicePropertyLocationID), &u32CurLocationId)
263 && u32CurLocationId == u32LocationId))
264 )
265 {
266 cMatches++;
267 CFRelease(PropsRef);
268 tstDoWork(USBDevice, argv[0]);
269 }
270 else
271 CFRelease(PropsRef);
272 }
273 IOObjectRelease(USBDevice);
274 }
275 IOObjectRelease(USBDevices);
276
277 /*
278 * Bitch if we didn't find anything matching the criteria.
279 */
280 if (!cMatches)
281 RTPrintf("%s: No matching devices found from a total of %d.\n", argv[0], cDevices);
282 return !cMatches;
283}
284
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette