-
Notifications
You must be signed in to change notification settings - Fork 3
/
listing2.html
executable file
·466 lines (390 loc) · 20.6 KB
/
listing2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<!-- BEGIN META TAG INFO -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="home" href="http://developer.apple.com/">
<link rel="find" href="http://developer.apple.com/search/">
<link rel="stylesheet" type="text/css" href="../../documentation/css/adcstyle.css" title="fonts">
<script language="JavaScript" src="../../documentation/js/adc.js" type="text/javascript"></script>
<!-- END META TAG INFO -->
<!-- BEGIN TITLE -->
<title>USBPrivateDataSample - /USBPrivateDataSample.c</title>
<!-- END TITLE -->
<script language="JavaScript">
function JumpToNewPage() {
window.location=document.scpopupmenu.gotop.value;
return true;
}
</script>
</head>
<!-- BEGIN BODY OPEN -->
<body>
<!--END BODY OPEN -->
<!-- START CENTER OPEN -->
<center>
<!-- END CENTER OPEN -->
<!-- BEGIN LOGO AND SEARCH -->
<!--#include virtual="/includes/adcnavbar"-->
<!-- END LOGO AND SEARCH -->
<!-- START BREADCRUMB -->
<div id="breadcrumb">
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td scope="row"><img width="340" height="10" src="images/1dot.gif" alt=""></td>
<td><img width="340" height="10" src="images/1dot.gif" alt=""></td>
</tr>
<tr valign="middle">
<td align="left" colspan="2">
<a href="http://developer.apple.com/">ADC Home</a> > <a href="../../referencelibrary/index.html">Reference Library</a> > <a href="../../samplecode/index.html">Sample Code</a> > <a href="../../samplecode/HardwareDrivers/index.html">Hardware & Drivers</a> > <a href="../../samplecode/HardwareDrivers/idxUSB-date.html">USB</a> > <A HREF="javascript:location.replace('index.html');">USBPrivateDataSample</A> >
</td>
</tr>
<tr>
<td colspan="2" scope="row"><img width="680" height="35" src="images/1dot.gif" alt=""></td>
</tr>
</table>
</div>
<!-- END BREADCRUMB -->
<!-- START MAIN CONTENT -->
<!-- START TITLE GRAPHIC AND INTRO-->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td><h1><div id="pagehead">USBPrivateDataSample</div></h1></td>
</tr>
</table>
<!-- END TITLE GRAPHIC AND INTRO -->
<!-- START WIDE COLUMN -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td id="scdetails">
<h2>/USBPrivateDataSample.c</h2>
<form name="scpopupmenu" onSubmit="return false;" method=post>
<p><strong>View Source Code:</strong>
<select name="gotop" onChange="JumpToNewPage();" style="width:340px"><option selected value="ingnore">Select File</option>
<option value="listing1.html">/Read Me.txt</option>
<option value="listing2.html">/USBPrivateDataSample.c</option></select>
</p>
</form>
<p><strong><a href="USBPrivateDataSample.zip">Download Sample</a></strong> (“USBPrivateDataSample.zip”, 19.9K)<BR>
<strong><a href="USBPrivateDataSample.dmg">Download Sample</a></strong> (“USBPrivateDataSample.dmg”, 79.7K)</p>
<!--
<p><strong><a href="#">Download Sample</a></strong> (“filename.sit”, 500K)</p>
-->
</td>
</tr>
<tr>
<td scope="row"><img width="680" height="10" src="images/1dot.gif" alt=""><br>
<img height="1" width="680" src="images/1dot_919699.gif" alt=""><br>
<img width="680" height="20" src="images/1dot.gif" alt=""></td>
</tr>
<tr>
<td scope="row">
<!--googleon: index -->
<pre class="sourcecodebox">/*
File: USBPrivateDataSample.c
Description: This sample demonstrates how to use IOKitLib and IOUSBLib to set up asynchronous
callbacks when a USB device is attached to or removed from the system.
It also shows how to associate arbitrary data with each device instance.
Copyright: © Copyright 2001-2006 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under Apple's
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Change History (most recent first):
1.2 10/04/2006 Updated to produce a universal binary. Now requires Xcode 2.2.1 or
later to build. Modernized and incorporated bug fixes.
1.1 04/24/2002 Added comments, release of interface object, use of USB location ID
1.0 10/30/2001 New sample.
*/
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
// Change these two constants to match your device's idVendor and idProduct.
// Or, just pass your idVendor and idProduct as command line arguments when running this sample.
#define kMyVendorID 1351
#define kMyProductID 8193
typedef struct MyPrivateData {
io_object_t notification;
IOUSBDeviceInterface **deviceInterface;
CFStringRef deviceName;
UInt32 locationID;
} MyPrivateData;
static IONotificationPortRef gNotifyPort;
static io_iterator_t gAddedIter;
static CFRunLoopRef gRunLoop;
//================================================================================================
//
// DeviceNotification
//
// This routine will get called whenever any kIOGeneralInterest notification happens. We are
// interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other
// messages are defined in IOMessage.h.
//
//================================================================================================
void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
{
kern_return_t kr;
MyPrivateData *privateDataRef = (MyPrivateData *) refCon;
if (messageType == kIOMessageServiceIsTerminated) {
fprintf(stderr, "Device removed.\n");
// Dump our private data to stderr just to see what it looks like.
fprintf(stderr, "privateDataRef->deviceName: ");
CFShow(privateDataRef->deviceName);
fprintf(stderr, "privateDataRef->locationID: 0x%lx.\n\n", privateDataRef->locationID);
// Free the data we're no longer using now that the device is going away
CFRelease(privateDataRef->deviceName);
if (privateDataRef->deviceInterface) {
kr = (*privateDataRef->deviceInterface)->Release(privateDataRef->deviceInterface);
}
kr = IOObjectRelease(privateDataRef->notification);
free(privateDataRef);
}
}
//================================================================================================
//
// DeviceAdded
//
// This routine is the callback for our IOServiceAddMatchingNotification. When we get called
// we will look at all the devices that were added and we will:
//
// 1. Create some private data to relate to each device (in this case we use the service's name
// and the location ID of the device
// 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device,
// using the refCon field to store a pointer to our private data. When we get called with
// this interest notification, we can grab the refCon and access our private data.
//
//================================================================================================
void DeviceAdded(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t usbDevice;
IOCFPlugInInterface **plugInInterface = NULL;
SInt32 score;
HRESULT res;
while ((usbDevice = IOIteratorNext(iterator))) {
io_name_t deviceName;
CFStringRef deviceNameAsCFString;
MyPrivateData *privateDataRef = NULL;
UInt32 locationID;
printf("Device added.\n");
// Add some app-specific information about this device.
// Create a buffer to hold the data.
privateDataRef = malloc(sizeof(MyPrivateData));
bzero(privateDataRef, sizeof(MyPrivateData));
// Get the USB device's name.
kr = IORegistryEntryGetName(usbDevice, deviceName);
if (KERN_SUCCESS != kr) {
deviceName[0] = '\0';
}
deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName,
kCFStringEncodingASCII);
// Dump our data to stderr just to see what it looks like.
fprintf(stderr, "deviceName: ");
CFShow(deviceNameAsCFString);
// Save the device's name to our private data.
privateDataRef->deviceName = deviceNameAsCFString;
// Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface
// for our device. This will create the necessary connections between our userland application and the
// kernel object for the USB Device.
kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
&plugInInterface, &score);
if ((kIOReturnSuccess != kr) || !plugInInterface) {
fprintf(stderr, "IOCreatePlugInInterfaceForService returned 0x%08x.\n", kr);
continue;
}
// Use the plugin interface to retrieve the device interface.
res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
(LPVOID*) &privateDataRef->deviceInterface);
// Now done with the plugin interface.
(*plugInInterface)->Release(plugInInterface);
if (res || privateDataRef->deviceInterface == NULL) {
fprintf(stderr, "QueryInterface returned %d.\n", (int) res);
continue;
}
// Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h.
// In this case, fetch the locationID. The locationID uniquely identifies the device
// and will remain the same, even across reboots, so long as the bus topology doesn't change.
kr = (*privateDataRef->deviceInterface)->GetLocationID(privateDataRef->deviceInterface, &locationID);
if (KERN_SUCCESS != kr) {
fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr);
continue;
}
else {
fprintf(stderr, "Location ID: 0x%lx\n\n", locationID);
}
privateDataRef->locationID = locationID;
// Register for an interest notification of this device being removed. Use a reference to our
// private data as the refCon which will be passed to the notification callback.
kr = IOServiceAddInterestNotification(gNotifyPort, // notifyPort
usbDevice, // service
kIOGeneralInterest, // interestType
DeviceNotification, // callback
privateDataRef, // refCon
&(privateDataRef->notification) // notification
);
if (KERN_SUCCESS != kr) {
printf("IOServiceAddInterestNotification returned 0x%08x.\n", kr);
}
// Done with this USB device; release the reference added by IOIteratorNext
kr = IOObjectRelease(usbDevice);
}
}
//================================================================================================
//
// SignalHandler
//
// This routine will get called when we interrupt the program (usually with a Ctrl-C from the
// command line).
//
//================================================================================================
void SignalHandler(int sigraised)
{
fprintf(stderr, "\nInterrupted.\n");
exit(0);
}
//================================================================================================
// main
//================================================================================================
int main(int argc, const char *argv[])
{
CFMutableDictionaryRef matchingDict;
CFRunLoopSourceRef runLoopSource;
CFNumberRef numberRef;
kern_return_t kr;
long usbVendor = kMyVendorID;
long usbProduct = kMyProductID;
sig_t oldHandler;
// pick up command line arguments
if (argc > 1) {
usbVendor = atoi(argv[1]);
}
if (argc > 2) {
usbProduct = atoi(argv[2]);
}
// Set up a signal handler so we can clean up when we're interrupted from the command line
// Otherwise we stay in our run loop forever.
oldHandler = signal(SIGINT, SignalHandler);
if (oldHandler == SIG_ERR) {
fprintf(stderr, "Could not establish new signal handler.");
}
fprintf(stderr, "Looking for devices matching vendor ID=%ld and product ID=%ld.\n", usbVendor, usbProduct);
// Set up the matching criteria for the devices we're interested in. The matching criteria needs to follow
// the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7.
// See also Technical Q&A QA1076 "Tips on USB driver matching on Mac OS X"
// <http://developer.apple.com/qa/qa2001/qa1076.html>.
// One exception is that you can use the matching dictionary "as is", i.e. without adding any matching
// criteria to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will
// consume this dictionary reference, so there is no need to release it later on.
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
// IOUSBDevice and its subclasses
if (matchingDict == NULL) {
fprintf(stderr, "IOServiceMatching returned NULL.\n");
return -1;
}
// We are interested in all USB devices (as opposed to USB interfaces). The Common Class Specification
// tells us that we need to specify the idVendor, idProduct, and bcdDevice fields, or, if we're not interested
// in particular bcdDevices, just the idVendor and idProduct. Note that if we were trying to match an
// IOUSBInterface, we would need to set more values in the matching dictionary (e.g. idVendor, idProduct,
// bInterfaceNumber and bConfigurationValue.
// Create a CFNumber for the idVendor and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBVendorID),
numberRef);
CFRelease(numberRef);
// Create a CFNumber for the idProduct and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBProductID),
numberRef);
CFRelease(numberRef);
numberRef = NULL;
// Create a notification port and add its run loop event source to our run loop
// This is how async notifications get set up.
gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
gRunLoop = CFRunLoopGetCurrent();
CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode);
// Now set up a notification to be called when a device is first matched by I/O Kit.
kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort
kIOFirstMatchNotification, // notificationType
matchingDict, // matching
DeviceAdded, // callback
NULL, // refCon
&gAddedIter // notification
);
// Iterate once to get already-present devices and arm the notification
DeviceAdded(NULL, gAddedIter);
// Start the run loop. Now we'll receive notifications.
fprintf(stderr, "Starting run loop.\n\n");
CFRunLoopRun();
// We should never get here
fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n");
return 0;
}
</pre>
<!--googleoff: index -->
</td>
</tr>
</table>
<!-- END WIDE COLUMN -->
<!-- END MAIN CONTENT -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td><div style="width: 100%; height: 1px; background-color: #919699; margin-top: 5px; margin-bottom: 15px"></div></td>
</tr>
<tr>
<td align="center"><br/>
<table border="0" cellpadding="0" cellspacing="0" class="graybox">
<tr>
<th>Did this document help you?</th>
</tr>
<tr>
<td>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=1&url=/samplecode/USBPrivateDataSample/listing2.html%3Fid%3DDTS10000456-1.1&media=dvd" target=_new>Yes</a>: Tell us what works for you.</div>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=2&url=/samplecode/USBPrivateDataSample/listing2.html%3Fid%3DDTS10000456-1.1&media=dvd" target=_new>It’s good, but:</a> Report typos, inaccuracies, and so forth.</div>
<div><a href="http://developer.apple.com/feedback/?v=3&url=/samplecode/USBPrivateDataSample/listing2.html%3Fid%3DDTS10000456-1.1&media=dvd" target=_new>It wasn’t helpful</a>: Tell us what would have helped.</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- START BOTTOM APPLE NAVIGATION -->
<!--#include virtual="/includes/footer"-->
<!-- END BOTTOM APPLE NAVIGATION -->
<!-- START CENTER CLOSE -->
</center>
<!-- END CENTER CLOSE -->
</body>
</html>