1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define TRACE_TAG TRACE_USB
18
19#include "sysdeps.h"
20
21#include <CoreFoundation/CoreFoundation.h>
22
23#include <IOKit/IOKitLib.h>
24#include <IOKit/IOCFPlugIn.h>
25#include <IOKit/usb/IOUSBLib.h>
26#include <IOKit/IOMessage.h>
27#include <mach/mach_port.h>
28
29#include <inttypes.h>
30#include <stdio.h>
31
32#include "adb.h"
33#include "transport.h"
34
35#define  DBG   D
36
37static IONotificationPortRef    notificationPort = 0;
38static io_iterator_t            notificationIterator;
39
40struct usb_handle
41{
42    UInt8                     bulkIn;
43    UInt8                     bulkOut;
44    IOUSBInterfaceInterface   **interface;
45    io_object_t               usbNotification;
46    unsigned int              zero_mask;
47};
48
49static CFRunLoopRef currentRunLoop = 0;
50static pthread_mutex_t start_lock;
51static pthread_cond_t start_cond;
52
53
54static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator);
55static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator,
56                                   natural_t messageType,
57                                   void *messageArgument);
58static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface,
59                                  UInt16 vendor, UInt16 product);
60
61static int
62InitUSB()
63{
64    CFMutableDictionaryRef  matchingDict;
65    CFRunLoopSourceRef      runLoopSource;
66
67    //* To set up asynchronous notifications, create a notification port and
68    //* add its run loop event source to the program's run loop
69    notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
70    runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
71    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
72
73    //* Create our matching dictionary to find the Android device's
74    //* adb interface
75    //* IOServiceAddMatchingNotification consumes the reference, so we do
76    //* not need to release this
77    matchingDict = IOServiceMatching(kIOUSBInterfaceClassName);
78
79    if (!matchingDict) {
80        DBG("ERR: Couldn't create USB matching dictionary.\n");
81        return -1;
82    }
83
84    //* We have to get notifications for all potential candidates and test them
85    //* at connection time because the matching rules don't allow for a
86    //* USB interface class of 0xff for class+subclass+protocol matches
87    //* See https://developer.apple.com/library/mac/qa/qa1076/_index.html
88    IOServiceAddMatchingNotification(
89            notificationPort,
90            kIOFirstMatchNotification,
91            matchingDict,
92            AndroidInterfaceAdded,
93            NULL,
94            &notificationIterator);
95
96    //* Iterate over set of matching interfaces to access already-present
97    //* devices and to arm the notification
98    AndroidInterfaceAdded(NULL, notificationIterator);
99
100    return 0;
101}
102
103static void
104AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
105{
106    kern_return_t            kr;
107    io_service_t             usbDevice;
108    io_service_t             usbInterface;
109    IOCFPlugInInterface      **plugInInterface = NULL;
110    IOUSBInterfaceInterface220  **iface = NULL;
111    IOUSBDeviceInterface197  **dev = NULL;
112    HRESULT                  result;
113    SInt32                   score;
114    UInt32                   locationId;
115    UInt8                    if_class, subclass, protocol;
116    UInt16                   vendor;
117    UInt16                   product;
118    UInt8                    serialIndex;
119    char                     serial[256];
120    char                     devpathBuf[64];
121    char                     *devpath = NULL;
122
123    while ((usbInterface = IOIteratorNext(iterator))) {
124        //* Create an intermediate interface plugin
125        kr = IOCreatePlugInInterfaceForService(usbInterface,
126                                               kIOUSBInterfaceUserClientTypeID,
127                                               kIOCFPlugInInterfaceID,
128                                               &plugInInterface, &score);
129        IOObjectRelease(usbInterface);
130        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
131            DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
132            continue;
133        }
134
135        //* This gets us the interface object
136        result = (*plugInInterface)->QueryInterface(
137            plugInInterface,
138            CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID*)&iface);
139        //* We only needed the plugin to get the interface, so discard it
140        (*plugInInterface)->Release(plugInInterface);
141        if (result || !iface) {
142            DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
143            continue;
144        }
145
146        kr = (*iface)->GetInterfaceClass(iface, &if_class);
147        kr = (*iface)->GetInterfaceSubClass(iface, &subclass);
148        kr = (*iface)->GetInterfaceProtocol(iface, &protocol);
149        if(if_class != ADB_CLASS || subclass != ADB_SUBCLASS || protocol != ADB_PROTOCOL) {
150            // Ignore non-ADB devices.
151            DBG("Ignoring interface with incorrect class/subclass/protocol - %d, %d, %d\n", if_class, subclass, protocol);
152            (*iface)->Release(iface);
153            continue;
154        }
155
156        //* this gets us an ioservice, with which we will find the actual
157        //* device; after getting a plugin, and querying the interface, of
158        //* course.
159        //* Gotta love OS X
160        kr = (*iface)->GetDevice(iface, &usbDevice);
161        if (kIOReturnSuccess != kr || !usbDevice) {
162            DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
163            continue;
164        }
165
166        plugInInterface = NULL;
167        score = 0;
168        //* create an intermediate device plugin
169        kr = IOCreatePlugInInterfaceForService(usbDevice,
170                                               kIOUSBDeviceUserClientTypeID,
171                                               kIOCFPlugInInterfaceID,
172                                               &plugInInterface, &score);
173        //* only needed this to find the plugin
174        (void)IOObjectRelease(usbDevice);
175        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
176            DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
177            continue;
178        }
179
180        result = (*plugInInterface)->QueryInterface(plugInInterface,
181            CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*)&dev);
182        //* only needed this to query the plugin
183        (*plugInInterface)->Release(plugInInterface);
184        if (result || !dev) {
185            DBG("ERR: Couldn't create a device interface (%08x)\n",
186                (int) result);
187            continue;
188        }
189
190        //* Now after all that, we actually have a ref to the device and
191        //* the interface that matched our criteria
192        kr = (*dev)->GetDeviceVendor(dev, &vendor);
193        kr = (*dev)->GetDeviceProduct(dev, &product);
194        kr = (*dev)->GetLocationID(dev, &locationId);
195        if (kr == 0) {
196            snprintf(devpathBuf, sizeof(devpathBuf), "usb:%" PRIu32 "X",
197	             (unsigned int)locationId);
198            devpath = devpathBuf;
199        }
200        kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
201
202	if (serialIndex > 0) {
203		IOUSBDevRequest req;
204		UInt16          buffer[256];
205		UInt16          languages[128];
206
207		memset(languages, 0, sizeof(languages));
208
209		req.bmRequestType =
210			USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
211		req.bRequest = kUSBRqGetDescriptor;
212		req.wValue = (kUSBStringDesc << 8) | 0;
213		req.wIndex = 0;
214		req.pData = languages;
215		req.wLength = sizeof(languages);
216		kr = (*dev)->DeviceRequest(dev, &req);
217
218		if (kr == kIOReturnSuccess && req.wLenDone > 0) {
219
220			int langCount = (req.wLenDone - 2) / 2, lang;
221
222			for (lang = 1; lang <= langCount; lang++) {
223
224                                memset(buffer, 0, sizeof(buffer));
225                                memset(&req, 0, sizeof(req));
226
227				req.bmRequestType =
228					USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
229				req.bRequest = kUSBRqGetDescriptor;
230				req.wValue = (kUSBStringDesc << 8) | serialIndex;
231				req.wIndex = languages[lang];
232				req.pData = buffer;
233				req.wLength = sizeof(buffer);
234				kr = (*dev)->DeviceRequest(dev, &req);
235
236				if (kr == kIOReturnSuccess && req.wLenDone > 0) {
237					int i, count;
238
239					// skip first word, and copy the rest to the serial string,
240					// changing shorts to bytes.
241					count = (req.wLenDone - 1) / 2;
242					for (i = 0; i < count; i++)
243						serial[i] = buffer[i + 1];
244					serial[i] = 0;
245                                        break;
246				}
247			}
248		}
249	}
250        (*dev)->Release(dev);
251
252        DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
253            serial);
254
255        usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
256                                            vendor, product);
257        if (handle == NULL) {
258            DBG("ERR: Could not find device interface: %08x\n", kr);
259            (*iface)->Release(iface);
260            continue;
261        }
262
263        DBG("AndroidDeviceAdded calling register_usb_transport\n");
264        register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1);
265
266        // Register for an interest notification of this device being removed.
267        // Pass the reference to our private data as the refCon for the
268        // notification.
269        kr = IOServiceAddInterestNotification(notificationPort,
270                usbInterface,
271                kIOGeneralInterest,
272                AndroidInterfaceNotify,
273                handle,
274                &handle->usbNotification);
275
276        if (kIOReturnSuccess != kr) {
277            DBG("ERR: Unable to create interest notification (%08x)\n", kr);
278        }
279    }
280}
281
282static void
283AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
284{
285    usb_handle *handle = (usb_handle *)refCon;
286
287    if (messageType == kIOMessageServiceIsTerminated) {
288        if (!handle) {
289            DBG("ERR: NULL handle\n");
290            return;
291        }
292        DBG("AndroidInterfaceNotify\n");
293        IOObjectRelease(handle->usbNotification);
294        usb_kick(handle);
295    }
296}
297
298//* TODO: simplify this further since we only register to get ADB interface
299//* subclass+protocol events
300static usb_handle*
301CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product)
302{
303    usb_handle*                 handle = NULL;
304    IOReturn                    kr;
305    UInt8  interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
306    UInt8  endpoint;
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    if (kr != kIOReturnSuccess) {
313        DBG("ERR: Could not open interface: (%08x)\n", kr);
314        return NULL;
315    }
316
317    //* Get the number of endpoints associated with this interface
318    kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
319    if (kr != kIOReturnSuccess) {
320        DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
321        goto err_get_num_ep;
322    }
323
324    //* Get interface class, subclass and protocol
325    if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
326            (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
327            (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) {
328            DBG("ERR: Unable to get interface class, subclass and protocol\n");
329            goto err_get_interface_class;
330    }
331
332    //* check to make sure interface class, subclass and protocol match ADB
333    //* avoid opening mass storage endpoints
334    if (!is_adb_interface(vendor, product, interfaceClass,
335                interfaceSubClass, interfaceProtocol))
336        goto err_bad_adb_interface;
337
338    handle = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
339    if (handle == nullptr) goto err_bad_adb_interface;
340
341    //* Iterate over the endpoints for this interface and find the first
342    //* bulk in/out pipes available.  These will be our read/write pipes.
343    for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
344        UInt8   transferType;
345        UInt16  maxPacketSize;
346        UInt8   interval;
347        UInt8   number;
348        UInt8   direction;
349
350        kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
351                &number, &transferType, &maxPacketSize, &interval);
352
353        if (kIOReturnSuccess == kr) {
354            if (kUSBBulk != transferType)
355                continue;
356
357            if (kUSBIn == direction)
358                handle->bulkIn = endpoint;
359
360            if (kUSBOut == direction)
361                handle->bulkOut = endpoint;
362
363            handle->zero_mask = maxPacketSize - 1;
364        } else {
365            DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
366            goto err_get_pipe_props;
367        }
368    }
369
370    handle->interface = interface;
371    return handle;
372
373err_get_pipe_props:
374    free(handle);
375err_bad_adb_interface:
376err_get_interface_class:
377err_get_num_ep:
378    (*interface)->USBInterfaceClose(interface);
379    return NULL;
380}
381
382
383void* RunLoopThread(void* unused)
384{
385    InitUSB();
386
387    currentRunLoop = CFRunLoopGetCurrent();
388
389    // Signal the parent that we are running
390    adb_mutex_lock(&start_lock);
391    adb_cond_signal(&start_cond);
392    adb_mutex_unlock(&start_lock);
393
394    CFRunLoopRun();
395    currentRunLoop = 0;
396
397    IOObjectRelease(notificationIterator);
398    IONotificationPortDestroy(notificationPort);
399
400    DBG("RunLoopThread done\n");
401    return NULL;
402}
403
404
405static int initialized = 0;
406void usb_init()
407{
408    if (!initialized)
409    {
410        adb_thread_t    tid;
411
412        adb_mutex_init(&start_lock, NULL);
413        adb_cond_init(&start_cond, NULL);
414
415        if(adb_thread_create(&tid, RunLoopThread, NULL))
416            fatal_errno("cannot create input thread");
417
418        // Wait for initialization to finish
419        adb_mutex_lock(&start_lock);
420        adb_cond_wait(&start_cond, &start_lock);
421        adb_mutex_unlock(&start_lock);
422
423        adb_mutex_destroy(&start_lock);
424        adb_cond_destroy(&start_cond);
425
426        initialized = 1;
427    }
428}
429
430void usb_cleanup()
431{
432    DBG("usb_cleanup\n");
433    close_usb_devices();
434    if (currentRunLoop)
435        CFRunLoopStop(currentRunLoop);
436}
437
438int usb_write(usb_handle *handle, const void *buf, int len)
439{
440    IOReturn    result;
441
442    if (!len)
443        return 0;
444
445    if (!handle)
446        return -1;
447
448    if (NULL == handle->interface) {
449        DBG("ERR: usb_write interface was null\n");
450        return -1;
451    }
452
453    if (0 == handle->bulkOut) {
454        DBG("ERR: bulkOut endpoint not assigned\n");
455        return -1;
456    }
457
458    result =
459        (*handle->interface)->WritePipe(
460                              handle->interface, handle->bulkOut, (void *)buf, len);
461
462    if ((result == 0) && (handle->zero_mask)) {
463        /* we need 0-markers and our transfer */
464        if(!(len & handle->zero_mask)) {
465            result =
466                (*handle->interface)->WritePipe(
467                        handle->interface, handle->bulkOut, (void *)buf, 0);
468        }
469    }
470
471    if (0 == result)
472        return 0;
473
474    DBG("ERR: usb_write failed with status %d\n", result);
475    return -1;
476}
477
478int usb_read(usb_handle *handle, void *buf, int len)
479{
480    IOReturn result;
481    UInt32  numBytes = len;
482
483    if (!len) {
484        return 0;
485    }
486
487    if (!handle) {
488        return -1;
489    }
490
491    if (NULL == handle->interface) {
492        DBG("ERR: usb_read interface was null\n");
493        return -1;
494    }
495
496    if (0 == handle->bulkIn) {
497        DBG("ERR: bulkIn endpoint not assigned\n");
498        return -1;
499    }
500
501    result = (*handle->interface)->ReadPipe(handle->interface, handle->bulkIn, buf, &numBytes);
502
503    if (kIOUSBPipeStalled == result) {
504        DBG(" Pipe stalled, clearing stall.\n");
505        (*handle->interface)->ClearPipeStall(handle->interface, handle->bulkIn);
506        result = (*handle->interface)->ReadPipe(handle->interface, handle->bulkIn, buf, &numBytes);
507    }
508
509    if (kIOReturnSuccess == result)
510        return 0;
511    else {
512        DBG("ERR: usb_read failed with status %x\n", result);
513    }
514
515    return -1;
516}
517
518int usb_close(usb_handle *handle)
519{
520    return 0;
521}
522
523void usb_kick(usb_handle *handle)
524{
525    /* release the interface */
526    if (!handle)
527        return;
528
529    if (handle->interface)
530    {
531        (*handle->interface)->USBInterfaceClose(handle->interface);
532        (*handle->interface)->Release(handle->interface);
533        handle->interface = 0;
534    }
535}
536