system/corennnnn
Revision | 3fd82b8861aa410fab7785074941b459d92220c1 (tree) |
---|---|
Zeit | 2009-05-10 04:49:54 |
Autor | Dima Zavin <dima@andr...> |
Commiter | Dima Zavin |
adb: osx: Match devices based on interface subclass and protocol
Enumerating all vendor+product id combinations is not practical.
This modifies the matching algorithm to use the adb interface
subclass/protocol instead (0x42/0x1).
Signed-off-by: Dima Zavin <dima@android.com>
@@ -359,17 +359,10 @@ typedef enum { | ||
359 | 359 | |
360 | 360 | // Google's USB Vendor ID |
361 | 361 | #define VENDOR_ID_GOOGLE 0x18d1 |
362 | + | |
362 | 363 | // HTC's USB Vendor ID |
363 | 364 | #define VENDOR_ID_HTC 0x0bb4 |
364 | 365 | |
365 | -// products for VENDOR_ID_GOOGLE | |
366 | -#define PRODUCT_ID_SOONER 0xd00d // Sooner bootloader | |
367 | -#define PRODUCT_ID_SOONER_COMP 0xdeed // Sooner composite device | |
368 | - | |
369 | -// products for VENDOR_ID_HTC | |
370 | -#define PRODUCT_ID_DREAM 0x0c01 // Dream bootloader | |
371 | -#define PRODUCT_ID_DREAM_COMP 0x0c02 // Dream composite device | |
372 | - | |
373 | 366 | void local_init(); |
374 | 367 | int local_connect(int port); |
375 | 368 |
@@ -31,21 +31,17 @@ | ||
31 | 31 | |
32 | 32 | #define DBG D |
33 | 33 | |
34 | -typedef struct { | |
35 | - int vid; | |
36 | - int pid; | |
37 | -} VendorProduct; | |
38 | - | |
39 | -#define kSupportedDeviceCount 4 | |
40 | -VendorProduct kSupportedDevices[kSupportedDeviceCount] = { | |
41 | - { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER }, | |
42 | - { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER_COMP }, | |
43 | - { VENDOR_ID_HTC, PRODUCT_ID_DREAM }, | |
44 | - { VENDOR_ID_HTC, PRODUCT_ID_DREAM_COMP }, | |
34 | +#define ADB_SUBCLASS 0x42 | |
35 | +#define ADB_PROTOCOL 0x1 | |
36 | + | |
37 | +int vendorIds[] = { | |
38 | + VENDOR_ID_GOOGLE, | |
39 | + VENDOR_ID_HTC, | |
45 | 40 | }; |
41 | +#define NUM_VENDORS (sizeof(vendorIds)/sizeof(vendorIds[0])) | |
46 | 42 | |
47 | 43 | static IONotificationPortRef notificationPort = 0; |
48 | -static io_iterator_t notificationIterators[kSupportedDeviceCount]; | |
44 | +static io_iterator_t notificationIterators[NUM_VENDORS]; | |
49 | 45 | |
50 | 46 | struct usb_handle |
51 | 47 | { |
@@ -61,17 +57,20 @@ static pthread_mutex_t start_lock; | ||
61 | 57 | static pthread_cond_t start_cond; |
62 | 58 | |
63 | 59 | |
64 | -static void AndroidDeviceAdded(void *refCon, io_iterator_t iterator); | |
65 | -static void AndroidDeviceNotify(void *refCon, io_iterator_t iterator, natural_t messageType, void *messageArgument); | |
66 | -static usb_handle* FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product); | |
60 | +static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator); | |
61 | +static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator, | |
62 | + natural_t messageType, | |
63 | + void *messageArgument); | |
64 | +static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface, | |
65 | + UInt16 vendor, UInt16 product); | |
67 | 66 | |
68 | 67 | static int |
69 | 68 | InitUSB() |
70 | 69 | { |
71 | 70 | CFMutableDictionaryRef matchingDict; |
72 | 71 | CFRunLoopSourceRef runLoopSource; |
73 | - SInt32 vendor, product; | |
74 | - int i; | |
72 | + SInt32 vendor, if_subclass, if_protocol; | |
73 | + unsigned i; | |
75 | 74 | |
76 | 75 | //* To set up asynchronous notifications, create a notification port and |
77 | 76 | //* add its run loop event source to the program's run loop |
@@ -81,51 +80,57 @@ InitUSB() | ||
81 | 80 | |
82 | 81 | memset(notificationIterators, 0, sizeof(notificationIterators)); |
83 | 82 | |
84 | - //* loop through all supported vendor/product pairs | |
85 | - for (i = 0; i < kSupportedDeviceCount; i++) { | |
86 | - //* Create our matching dictionary to find the Android device | |
87 | - //* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this | |
88 | - matchingDict = IOServiceMatching(kIOUSBDeviceClassName); | |
83 | + //* loop through all supported vendors | |
84 | + for (i = 0; i < NUM_VENDORS; i++) { | |
85 | + //* Create our matching dictionary to find the Android device's | |
86 | + //* adb interface | |
87 | + //* IOServiceAddMatchingNotification consumes the reference, so we do | |
88 | + //* not need to release this | |
89 | + matchingDict = IOServiceMatching(kIOUSBInterfaceClassName); | |
89 | 90 | |
90 | 91 | if (!matchingDict) { |
91 | 92 | DBG("ERR: Couldn't create USB matching dictionary.\n"); |
92 | 93 | return -1; |
93 | 94 | } |
94 | 95 | |
95 | - //* Set up two matching dictionaries, one for each product ID we support. | |
96 | - //* This will cause the kernel to notify us only if the vendor and product IDs match. | |
97 | - vendor = kSupportedDevices[i].vid; | |
98 | - product = kSupportedDevices[i].pid; | |
99 | - CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor)); | |
100 | - CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product)); | |
101 | - | |
102 | - //* Now set up two notifications: one to be called when a raw device | |
103 | - //* is first matched by the I/O Kit and another to be called when the | |
104 | - //* device is terminated. | |
105 | - //* we need to do this with each matching dictionary. | |
96 | + //* Match based on vendor id, interface subclass and protocol | |
97 | + vendor = vendorIds[i]; | |
98 | + if_subclass = ADB_SUBCLASS; | |
99 | + if_protocol = ADB_PROTOCOL; | |
100 | + CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), | |
101 | + CFNumberCreate(kCFAllocatorDefault, | |
102 | + kCFNumberSInt32Type, &vendor)); | |
103 | + CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass), | |
104 | + CFNumberCreate(kCFAllocatorDefault, | |
105 | + kCFNumberSInt32Type, &if_subclass)); | |
106 | + CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol), | |
107 | + CFNumberCreate(kCFAllocatorDefault, | |
108 | + kCFNumberSInt32Type, &if_protocol)); | |
106 | 109 | IOServiceAddMatchingNotification( |
107 | 110 | notificationPort, |
108 | 111 | kIOFirstMatchNotification, |
109 | 112 | matchingDict, |
110 | - AndroidDeviceAdded, | |
113 | + AndroidInterfaceAdded, | |
111 | 114 | NULL, |
112 | 115 | ¬ificationIterators[i]); |
113 | 116 | |
114 | - //* Iterate over set of matching devices to access already-present devices | |
115 | - //* and to arm the notification | |
116 | - AndroidDeviceAdded(NULL, notificationIterators[i]); | |
117 | + //* Iterate over set of matching interfaces to access already-present | |
118 | + //* devices and to arm the notification | |
119 | + AndroidInterfaceAdded(NULL, notificationIterators[i]); | |
117 | 120 | } |
118 | 121 | |
119 | 122 | return 0; |
120 | 123 | } |
121 | 124 | |
122 | 125 | static void |
123 | -AndroidDeviceAdded(void *refCon, io_iterator_t iterator) | |
126 | +AndroidInterfaceAdded(void *refCon, io_iterator_t iterator) | |
124 | 127 | { |
125 | 128 | kern_return_t kr; |
126 | 129 | io_service_t usbDevice; |
130 | + io_service_t usbInterface; | |
127 | 131 | IOCFPlugInInterface **plugInInterface = NULL; |
128 | - IOUSBDeviceInterface182 **dev = NULL; | |
132 | + IOUSBInterfaceInterface220 **iface = NULL; | |
133 | + IOUSBDeviceInterface197 **dev = NULL; | |
129 | 134 | HRESULT result; |
130 | 135 | SInt32 score; |
131 | 136 | UInt16 vendor; |
@@ -133,28 +138,66 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator) | ||
133 | 138 | UInt8 serialIndex; |
134 | 139 | char serial[256]; |
135 | 140 | |
136 | - while ((usbDevice = IOIteratorNext(iterator))) { | |
137 | - //* Create an intermediate plugin | |
141 | + while ((usbInterface = IOIteratorNext(iterator))) { | |
142 | + //* Create an intermediate interface plugin | |
143 | + kr = IOCreatePlugInInterfaceForService(usbInterface, | |
144 | + kIOUSBInterfaceUserClientTypeID, | |
145 | + kIOCFPlugInInterfaceID, | |
146 | + &plugInInterface, &score); | |
147 | + IOObjectRelease(usbInterface); | |
148 | + if ((kIOReturnSuccess != kr) || (!plugInInterface)) { | |
149 | + DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr); | |
150 | + continue; | |
151 | + } | |
152 | + | |
153 | + //* This gets us the interface object | |
154 | + result = (*plugInInterface)->QueryInterface(plugInInterface, | |
155 | + CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID) | |
156 | + &iface); | |
157 | + //* We only needed the plugin to get the interface, so discard it | |
158 | + (*plugInInterface)->Release(plugInInterface); | |
159 | + if (result || !iface) { | |
160 | + DBG("ERR: Couldn't query the interface (%08x)\n", (int) result); | |
161 | + continue; | |
162 | + } | |
163 | + | |
164 | + //* this gets us an ioservice, with which we will find the actual | |
165 | + //* device; after getting a plugin, and querying the interface, of | |
166 | + //* course. | |
167 | + //* Gotta love OS X | |
168 | + kr = (*iface)->GetDevice(iface, &usbDevice); | |
169 | + if (kIOReturnSuccess != kr || !usbDevice) { | |
170 | + DBG("ERR: Couldn't grab device from interface (%08x)\n", kr); | |
171 | + continue; | |
172 | + } | |
173 | + | |
174 | + plugInInterface = NULL; | |
175 | + score = 0; | |
176 | + //* create an intermediate device plugin | |
138 | 177 | kr = IOCreatePlugInInterfaceForService(usbDevice, |
139 | 178 | kIOUSBDeviceUserClientTypeID, |
140 | 179 | kIOCFPlugInInterfaceID, |
141 | 180 | &plugInInterface, &score); |
142 | - | |
181 | + //* only needed this to find the plugin | |
182 | + (void)IOObjectRelease(usbDevice); | |
143 | 183 | if ((kIOReturnSuccess != kr) || (!plugInInterface)) { |
144 | - DBG("ERR: Unable to create a plug-in (%08x)\n", kr); | |
145 | - goto continue1; | |
184 | + DBG("ERR: Unable to create a device plug-in (%08x)\n", kr); | |
185 | + continue; | |
146 | 186 | } |
147 | 187 | |
148 | - //* Now create the device interface | |
149 | 188 | result = (*plugInInterface)->QueryInterface(plugInInterface, |
150 | 189 | CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev); |
151 | - | |
190 | + //* only needed this to query the plugin | |
191 | + (*plugInInterface)->Release(plugInInterface); | |
152 | 192 | if (result || !dev) { |
153 | - DBG("ERR: Couldn't create a device interface (%08x)\n", (int) result); | |
154 | - goto continue2; | |
193 | + DBG("ERR: Couldn't create a device interface (%08x)\n", | |
194 | + (int) result); | |
195 | + continue; | |
155 | 196 | } |
156 | 197 | |
157 | - //* Check the device to see if it's ours | |
198 | + //* Now after all that, we actually have a ref to the device and | |
199 | + //* the interface that matched our criteria | |
200 | + | |
158 | 201 | kr = (*dev)->GetDeviceVendor(dev, &vendor); |
159 | 202 | kr = (*dev)->GetDeviceProduct(dev, &product); |
160 | 203 | kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); |
@@ -163,7 +206,8 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator) | ||
163 | 206 | IOUSBDevRequest req; |
164 | 207 | UInt16 buffer[256]; |
165 | 208 | |
166 | - req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); | |
209 | + req.bmRequestType = | |
210 | + USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); | |
167 | 211 | req.bRequest = kUSBRqGetDescriptor; |
168 | 212 | req.wValue = (kUSBStringDesc << 8) | serialIndex; |
169 | 213 | req.wIndex = 0; |
@@ -174,219 +218,149 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator) | ||
174 | 218 | if (kr == kIOReturnSuccess && req.wLenDone > 0) { |
175 | 219 | int i, count; |
176 | 220 | |
177 | - // skip first word, and copy the rest to the serial string, changing shorts to bytes. | |
221 | + // skip first word, and copy the rest to the serial string, | |
222 | + // changing shorts to bytes. | |
178 | 223 | count = (req.wLenDone - 1) / 2; |
179 | 224 | for (i = 0; i < count; i++) |
180 | 225 | serial[i] = buffer[i + 1]; |
181 | 226 | serial[i] = 0; |
182 | 227 | } |
183 | 228 | } |
229 | + (*dev)->Release(dev); | |
184 | 230 | |
185 | - usb_handle* handle = NULL; | |
186 | - | |
187 | - //* Open the device | |
188 | - kr = (*dev)->USBDeviceOpen(dev); | |
189 | - | |
190 | - if (kr != kIOReturnSuccess) { | |
191 | - DBG("ERR: Could not open device: %08x\n", kr); | |
192 | - goto continue3; | |
193 | - } else { | |
194 | - //* Find an interface for the device | |
195 | - handle = FindDeviceInterface((IOUSBDeviceInterface**)dev, vendor, product); | |
196 | - } | |
231 | + DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product, | |
232 | + serial); | |
197 | 233 | |
234 | + usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface, | |
235 | + vendor, product); | |
198 | 236 | if (handle == NULL) { |
199 | 237 | DBG("ERR: Could not find device interface: %08x\n", kr); |
200 | - (*dev)->USBDeviceClose(dev); | |
201 | - goto continue3; | |
238 | + (*iface)->Release(iface); | |
239 | + continue; | |
202 | 240 | } |
203 | 241 | |
204 | 242 | DBG("AndroidDeviceAdded calling register_usb_transport\n"); |
205 | 243 | register_usb_transport(handle, (serial[0] ? serial : NULL)); |
206 | 244 | |
207 | - // Register for an interest notification of this device being removed. Pass the reference to our | |
208 | - // private data as the refCon for the notification. | |
245 | + // Register for an interest notification of this device being removed. | |
246 | + // Pass the reference to our private data as the refCon for the | |
247 | + // notification. | |
209 | 248 | kr = IOServiceAddInterestNotification(notificationPort, |
210 | - usbDevice, | |
249 | + usbInterface, | |
211 | 250 | kIOGeneralInterest, |
212 | - AndroidDeviceNotify, | |
251 | + AndroidInterfaceNotify, | |
213 | 252 | handle, |
214 | 253 | &handle->usbNotification); |
254 | + | |
215 | 255 | if (kIOReturnSuccess != kr) { |
216 | 256 | DBG("ERR: Unable to create interest notification (%08x)\n", kr); |
217 | 257 | } |
218 | - | |
219 | -continue3: | |
220 | - (void)(*dev)->Release(dev); | |
221 | -continue2: | |
222 | - IODestroyPlugInInterface(plugInInterface); | |
223 | -continue1: | |
224 | - IOObjectRelease(usbDevice); | |
225 | 258 | } |
226 | 259 | } |
227 | 260 | |
228 | 261 | static void |
229 | -AndroidDeviceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) | |
262 | +AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) | |
230 | 263 | { |
231 | 264 | usb_handle *handle = (usb_handle *)refCon; |
232 | 265 | |
233 | 266 | if (messageType == kIOMessageServiceIsTerminated) { |
234 | - DBG("AndroidDeviceNotify\n"); | |
267 | + if (!handle) { | |
268 | + DBG("ERR: NULL handle\n"); | |
269 | + return; | |
270 | + } | |
271 | + DBG("AndroidInterfaceNotify\n"); | |
235 | 272 | IOObjectRelease(handle->usbNotification); |
236 | 273 | usb_kick(handle); |
237 | 274 | } |
238 | 275 | } |
239 | 276 | |
277 | +//* TODO: simplify this further since we only register to get ADB interface | |
278 | +//* subclass+protocol events | |
240 | 279 | static usb_handle* |
241 | -FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product) | |
280 | +CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product) | |
242 | 281 | { |
243 | 282 | usb_handle* handle = NULL; |
244 | 283 | IOReturn kr; |
245 | - IOUSBFindInterfaceRequest request; | |
246 | - io_iterator_t iterator; | |
247 | - io_service_t usbInterface; | |
248 | - IOCFPlugInInterface **plugInInterface; | |
249 | - IOUSBInterfaceInterface **interface = NULL; | |
250 | - HRESULT result; | |
251 | - SInt32 score; | |
252 | 284 | UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol; |
253 | - UInt8 endpoint, configuration; | |
285 | + UInt8 endpoint; | |
254 | 286 | |
255 | - //* Placing the constant KIOUSBFindInterfaceDontCare into the following | |
256 | - //* fields of the IOUSBFindInterfaceRequest structure will allow us to | |
257 | - //* find all of the interfaces | |
258 | - request.bInterfaceClass = kIOUSBFindInterfaceDontCare; | |
259 | - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; | |
260 | - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; | |
261 | - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; | |
262 | - | |
263 | - //* SetConfiguration will kill an existing UMS connection, so let's not do this if not necessary. | |
264 | - configuration = 0; | |
265 | - (*dev)->GetConfiguration(dev, &configuration); | |
266 | - if (configuration != 1) | |
267 | - (*dev)->SetConfiguration(dev, 1); | |
268 | - | |
269 | - //* Get an iterator for the interfaces on the device | |
270 | - kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator); | |
271 | 287 | |
288 | + //* Now open the interface. This will cause the pipes associated with | |
289 | + //* the endpoints in the interface descriptor to be instantiated | |
290 | + kr = (*interface)->USBInterfaceOpen(interface); | |
272 | 291 | if (kr != kIOReturnSuccess) { |
273 | - DBG("ERR: Couldn't create a device interface iterator: (%08x)\n", kr); | |
292 | + DBG("ERR: Could not open interface: (%08x)\n", kr); | |
274 | 293 | return NULL; |
275 | 294 | } |
276 | 295 | |
277 | - while ((usbInterface = IOIteratorNext(iterator))) { | |
278 | - //* Create an intermediate plugin | |
279 | - kr = IOCreatePlugInInterfaceForService( | |
280 | - usbInterface, | |
281 | - kIOUSBInterfaceUserClientTypeID, | |
282 | - kIOCFPlugInInterfaceID, | |
283 | - &plugInInterface, | |
284 | - &score); | |
285 | - | |
286 | - //* No longer need the usbInterface object now that we have the plugin | |
287 | - (void) IOObjectRelease(usbInterface); | |
288 | - | |
289 | - if ((kr != kIOReturnSuccess) || (!plugInInterface)) { | |
290 | - DBG("ERR: Unable to create plugin (%08x)\n", kr); | |
291 | - break; | |
292 | - } | |
293 | - | |
294 | - //* Now create the interface interface for the interface | |
295 | - result = (*plugInInterface)->QueryInterface( | |
296 | - plugInInterface, | |
297 | - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), | |
298 | - (LPVOID) &interface); | |
299 | - | |
300 | - //* No longer need the intermediate plugin | |
301 | - (*plugInInterface)->Release(plugInInterface); | |
302 | - | |
303 | - if (result || !interface) { | |
304 | - DBG("ERR: Couldn't create interface interface: (%08x)\n", | |
305 | - (unsigned int) result); | |
306 | - break; | |
307 | - } | |
308 | - | |
309 | - //* Now open the interface. This will cause the pipes associated with | |
310 | - //* the endpoints in the interface descriptor to be instantiated | |
311 | - kr = (*interface)->USBInterfaceOpen(interface); | |
312 | - | |
313 | - if (kr != kIOReturnSuccess) | |
314 | - { | |
315 | - DBG("ERR: Could not open interface: (%08x)\n", kr); | |
316 | - (void) (*interface)->Release(interface); | |
317 | - //* continue so we can try the next interface | |
318 | - continue; | |
319 | - } | |
320 | - | |
321 | - //* Get the number of endpoints associated with this interface | |
322 | - kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); | |
323 | - | |
324 | - if (kr != kIOReturnSuccess) { | |
325 | - DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr); | |
326 | - goto next_interface; | |
327 | - } | |
296 | + //* Get the number of endpoints associated with this interface | |
297 | + kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); | |
298 | + if (kr != kIOReturnSuccess) { | |
299 | + DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr); | |
300 | + goto err_get_num_ep; | |
301 | + } | |
328 | 302 | |
329 | - //* Get interface class, subclass and protocol | |
330 | - if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess || | |
303 | + //* Get interface class, subclass and protocol | |
304 | + if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess || | |
331 | 305 | (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess || |
332 | - (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) | |
333 | - { | |
306 | + (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) { | |
334 | 307 | DBG("ERR: Unable to get interface class, subclass and protocol\n"); |
335 | - goto next_interface; | |
336 | - } | |
337 | - | |
338 | - //* check to make sure interface class, subclass and protocol match ADB | |
339 | - //* avoid opening mass storage endpoints | |
340 | - if (is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) { | |
341 | - handle = calloc(1, sizeof(usb_handle)); | |
308 | + goto err_get_interface_class; | |
309 | + } | |
342 | 310 | |
343 | - //* Iterate over the endpoints for this interface and find the first | |
344 | - //* bulk in/out pipes available. These will be our read/write pipes. | |
345 | - for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) { | |
346 | - UInt8 transferType; | |
347 | - UInt16 maxPacketSize; | |
348 | - UInt8 interval; | |
349 | - UInt8 number; | |
350 | - UInt8 direction; | |
311 | + //* check to make sure interface class, subclass and protocol match ADB | |
312 | + //* avoid opening mass storage endpoints | |
313 | + if (!is_adb_interface(vendor, product, interfaceClass, | |
314 | + interfaceSubClass, interfaceProtocol)) | |
315 | + goto err_bad_adb_interface; | |
351 | 316 | |
352 | - kr = (*interface)->GetPipeProperties(interface, endpoint, &direction, | |
353 | - &number, &transferType, &maxPacketSize, &interval); | |
317 | + handle = calloc(1, sizeof(usb_handle)); | |
354 | 318 | |
355 | - if (kIOReturnSuccess == kr) { | |
356 | - if (kUSBBulk != transferType) | |
357 | - continue; | |
319 | + //* Iterate over the endpoints for this interface and find the first | |
320 | + //* bulk in/out pipes available. These will be our read/write pipes. | |
321 | + for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) { | |
322 | + UInt8 transferType; | |
323 | + UInt16 maxPacketSize; | |
324 | + UInt8 interval; | |
325 | + UInt8 number; | |
326 | + UInt8 direction; | |
358 | 327 | |
359 | - if (kUSBIn == direction) | |
360 | - handle->bulkIn = endpoint; | |
328 | + kr = (*interface)->GetPipeProperties(interface, endpoint, &direction, | |
329 | + &number, &transferType, &maxPacketSize, &interval); | |
361 | 330 | |
362 | - if (kUSBOut == direction) | |
363 | - handle->bulkOut = endpoint; | |
331 | + if (kIOReturnSuccess == kr) { | |
332 | + if (kUSBBulk != transferType) | |
333 | + continue; | |
364 | 334 | |
365 | - if (interfaceProtocol == 0x01) { | |
366 | - handle->zero_mask = maxPacketSize - 1; | |
367 | - } | |
335 | + if (kUSBIn == direction) | |
336 | + handle->bulkIn = endpoint; | |
368 | 337 | |
369 | - } else { | |
370 | - DBG("ERR: FindDeviceInterface - could not get pipe properties\n"); | |
371 | - } | |
372 | - } | |
338 | + if (kUSBOut == direction) | |
339 | + handle->bulkOut = endpoint; | |
373 | 340 | |
374 | - handle->interface = interface; | |
375 | - break; | |
341 | + handle->zero_mask = maxPacketSize - 1; | |
342 | + } else { | |
343 | + DBG("ERR: FindDeviceInterface - could not get pipe properties\n"); | |
344 | + goto err_get_pipe_props; | |
376 | 345 | } |
377 | - | |
378 | -next_interface: | |
379 | - (*interface)->USBInterfaceClose(interface); | |
380 | - (*interface)->Release(interface); | |
381 | 346 | } |
382 | 347 | |
348 | + handle->interface = interface; | |
383 | 349 | return handle; |
350 | + | |
351 | +err_get_pipe_props: | |
352 | + free(handle); | |
353 | +err_bad_adb_interface: | |
354 | +err_get_interface_class: | |
355 | +err_get_num_ep: | |
356 | + (*interface)->USBInterfaceClose(interface); | |
357 | + return NULL; | |
384 | 358 | } |
385 | 359 | |
386 | 360 | |
387 | 361 | void* RunLoopThread(void* unused) |
388 | 362 | { |
389 | - int i; | |
363 | + unsigned i; | |
390 | 364 | |
391 | 365 | InitUSB(); |
392 | 366 |
@@ -400,7 +374,7 @@ void* RunLoopThread(void* unused) | ||
400 | 374 | CFRunLoopRun(); |
401 | 375 | currentRunLoop = 0; |
402 | 376 | |
403 | - for (i = 0; i < kSupportedDeviceCount; i++) { | |
377 | + for (i = 0; i < NUM_VENDORS; i++) { | |
404 | 378 | IOObjectRelease(notificationIterators[i]); |
405 | 379 | } |
406 | 380 | IONotificationPortDestroy(notificationPort); |
@@ -527,6 +501,9 @@ int usb_close(usb_handle *handle) | ||
527 | 501 | void usb_kick(usb_handle *handle) |
528 | 502 | { |
529 | 503 | /* release the interface */ |
504 | + if (!handle) | |
505 | + return; | |
506 | + | |
530 | 507 | if (handle->interface) |
531 | 508 | { |
532 | 509 | (*handle->interface)->USBInterfaceClose(handle->interface); |