/
main.c
217 lines (185 loc) · 7.22 KB
/
main.c
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
#define USE_ASYNC_IO
#define kOurVendorID 0x0582
#define kOurProductID 0x00ad
#define kOurProductIDBulkTest 4098
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <stdio.h>
#include <mach/mach.h>
#include <CoreFoundation/CoreFoundation.h>
//Global variables
static IONotificationPortRef gNotifyPort;
static io_iterator_t gRawAddedIter;
static io_iterator_t gRawRemovedIter;
static io_iterator_t gBulkTestAddedIter;
static io_iterator_t gBulkTestRemovedIter;
static char gBuffer[64];
IOReturn ConfigureDevice(IOUSBDeviceInterface **dev)
{
UInt8 numConfig;
IOReturn kr;
IOUSBConfigurationDescriptorPtr configDesc;
//Get the number of configurations. The sample code always chooses
//the first configuration (at index 0) but your code may need a
//different one
kr = (*dev)->GetNumberOfConfigurations(dev, &numConfig);
if (!numConfig)
return -1;
//Get the configuration descriptor for index 0
kr = (*dev)->GetConfigurationDescriptorPtr(dev, 0, &configDesc);
if (kr)
{
printf("Couldn’t get configuration descriptor for index %d (err = %08x)\n", 0, kr);
return -1;
}
//Set the device’s configuration. The configuration value is found in
//the bConfigurationValue field of the configuration descriptor
kr = (*dev)->SetConfiguration(dev, configDesc->bConfigurationValue);
if (kr)
{
printf("Couldn’t set configuration to value %d (err = %08x)\n", 0,
kr);
return -1;
}
return kIOReturnSuccess;
}
void RawDeviceAdded(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t usbDevice;
IOCFPlugInInterface **plugInInterface = NULL;
IOUSBDeviceInterface **dev = NULL;
HRESULT result;
SInt32 score;
UInt16 vendor;
UInt16 product;
UInt16 release;
while (usbDevice = IOIteratorNext(iterator))
{
//Create an intermediate plug-in
kr = IOCreatePlugInInterfaceForService(usbDevice,
kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
&plugInInterface, &score);
//Don’t need the device object after intermediate plug-in is created
kr = IOObjectRelease(usbDevice);
if ((kIOReturnSuccess != kr) || !plugInInterface)
{
printf("Unable to create a plug-in (%08x)\n", kr);
continue;
}
//Now create the device interface
result = (*plugInInterface)->QueryInterface(plugInInterface,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
(LPVOID *)&dev);
//Don’t need the intermediate plug-in after device interface
//is created
(*plugInInterface)->Release(plugInInterface);
if (result || !dev)
{
printf("Couldn’t create a device interface (%08x)\n",
(int) result);
continue;
}
//Check these values for confirmation
kr = (*dev)->GetDeviceVendor(dev, &vendor);
kr = (*dev)->GetDeviceProduct(dev, &product);
kr = (*dev)->GetDeviceReleaseNumber(dev, &release);
if ((vendor != kOurVendorID) || (product != kOurProductID) ||
(release != 1))
{
printf("Found unwanted device (vendor = %d, product = %d)\n",
vendor, product);
printf("(or the release was not equal to 1: release = %d)\n", release);
(void) (*dev)->Release(dev);
continue;
}
//Open the device to change its state
kr = (*dev)->USBDeviceOpen(dev);
if (kr != kIOReturnSuccess)
{
printf("Unable to open device: %08x\n", kr);
(void) (*dev)->Release(dev);
continue;
}
//Configure device
kr = ConfigureDevice(dev);
if (kr != kIOReturnSuccess)
{
printf("Unable to configure device: %08x\n", kr);
(void) (*dev)->USBDeviceClose(dev);
(void) (*dev)->Release(dev);
continue;
}
/*
//Download firmware to device
kr = DownloadToDevice(dev);
if (kr != kIOReturnSuccess)
{
printf("Unable to download firmware to device: %08x\n", kr);
(void) (*dev)->USBDeviceClose(dev);
(void) (*dev)->Release(dev);
continue;
}
*/
//Close this device and release object
kr = (*dev)->USBDeviceClose(dev);
kr = (*dev)->Release(dev);
}
}
int main (int argc, const char *argv[])
{
mach_port_t masterPort;
CFMutableDictionaryRef matchingDict;
CFRunLoopSourceRef runLoopSource;
kern_return_t kr;
SInt32 usbVendor = kOurVendorID;
SInt32 usbProduct = kOurProductID;
kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
if (kr || !masterPort)
{
printf("ERR: Couldn't create a master I/O Kit port(%08x)\n", kr);
return -1;
}
// Setup matching dictionary for class IOUSBDevice and its subclasses
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
if (!matchingDict)
{
printf("couldn't craete a usb matching dictionary :(\n");
mach_port_deallocate(mach_task_self(), masterPort);
return -1;
}
// add vendor and product Ids to dict
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorName),
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type, &usbVendor));
CFDictionarySetValue(matchingDict, CFSTR(kUSBProductName),
CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type, &usbProduct));
gNotifyPort = IONotificationPortCreate(masterPort);
runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
kCFRunLoopDefaultMode);
//Now set up two notifications: one to be called when a raw device
//is first matched by the I/O Kit and another to be called when the
//device is terminated
//Notification of first match:
kr = IOServiceAddMatchingNotification(gNotifyPort,
kIOFirstMatchNotification, matchingDict,
RawDeviceAdded, NULL, &gRawAddedIter);
//Iterate over set of matching devices to access already-present devices
//and to arm the notification
RawDeviceAdded(NULL, gRawAddedIter);
/*
//Notification of termination:
kr = IOServiceAddMatchingNotification(gNotifyPort,
kIOTerminatedNotification, matchingDict,
RawDeviceRemoved, NULL, &gRawRemovedIter);
//Iterate over set of matching devices to release each one and to
//arm the notification
RawDeviceRemoved(NULL, gRawRemovedIter);
*/
mach_port_deallocate(mach_task_self(), masterPort);
masterPort = 0;
CFRunLoopRun();
return 0;
}