diff options
Diffstat (limited to 'fastboot/usb_osx.c')
-rw-r--r-- | fastboot/usb_osx.c | 538 |
1 files changed, 0 insertions, 538 deletions
diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c deleted file mode 100644 index d6a826094..000000000 --- a/fastboot/usb_osx.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <stdio.h> -#include <CoreFoundation/CoreFoundation.h> -#include <IOKit/IOKitLib.h> -#include <IOKit/IOCFPlugIn.h> -#include <IOKit/usb/IOUSBLib.h> -#include <IOKit/IOMessage.h> -#include <mach/mach_port.h> - -#include "usb.h" - - -/* - * Internal helper functions and associated definitions. - */ - -#if TRACE_USB -#define WARN(x...) fprintf(stderr, x) -#else -#define WARN(x...) -#endif - -#define ERR(x...) fprintf(stderr, "ERROR: " x) - -/** An open usb device */ -struct usb_handle -{ - int success; - ifc_match_func callback; - usb_ifc_info info; - - UInt8 bulkIn; - UInt8 bulkOut; - IOUSBInterfaceInterface190 **interface; - unsigned int zero_mask; -}; - -/** Try out all the interfaces and see if there's a match. Returns 0 on - * success, -1 on failure. */ -static int try_interfaces(IOUSBDeviceInterface **dev, usb_handle *handle) { - IOReturn kr; - IOUSBFindInterfaceRequest request; - io_iterator_t iterator; - io_service_t usbInterface; - IOCFPlugInInterface **plugInInterface; - IOUSBInterfaceInterface190 **interface = NULL; - HRESULT result; - SInt32 score; - UInt8 interfaceNumEndpoints; - UInt8 endpoint; - UInt8 configuration; - - // Placing the constant KIOUSBFindInterfaceDontCare into the following - // fields of the IOUSBFindInterfaceRequest structure will allow us to - // find all of the interfaces - request.bInterfaceClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - - // SetConfiguration will kill an existing UMS connection, so let's - // not do this if not necessary. - configuration = 0; - (*dev)->GetConfiguration(dev, &configuration); - if (configuration != 1) - (*dev)->SetConfiguration(dev, 1); - - // Get an iterator for the interfaces on the device - kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator); - - if (kr != 0) { - ERR("Couldn't create a device interface iterator: (%08x)\n", kr); - return -1; - } - - while ((usbInterface = IOIteratorNext(iterator))) { - // Create an intermediate plugin - kr = IOCreatePlugInInterfaceForService( - usbInterface, - kIOUSBInterfaceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugInInterface, - &score); - - // No longer need the usbInterface object now that we have the plugin - (void) IOObjectRelease(usbInterface); - - if ((kr != 0) || (!plugInInterface)) { - WARN("Unable to create plugin (%08x)\n", kr); - continue; - } - - // Now create the interface interface for the interface - result = (*plugInInterface)->QueryInterface( - plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), - (LPVOID) &interface); - - // No longer need the intermediate plugin - (*plugInInterface)->Release(plugInInterface); - - if (result || !interface) { - ERR("Couldn't create interface interface: (%08x)\n", - (unsigned int) result); - // continue so we can try the next interface - continue; - } - - /* - * Now open the interface. This will cause the pipes - * associated with the endpoints in the interface descriptor - * to be instantiated. - */ - - /* - * TODO: Earlier comments here indicated that it was a bad - * idea to just open any interface, because opening "mass - * storage endpoints" is bad. However, the only way to find - * out if an interface does bulk in or out is to open it, and - * the framework in this application wants to be told about - * bulk in / out before deciding whether it actually wants to - * use the interface. Maybe something needs to be done about - * this situation. - */ - - kr = (*interface)->USBInterfaceOpen(interface); - - if (kr != 0) { - WARN("Could not open interface: (%08x)\n", kr); - (void) (*interface)->Release(interface); - // continue so we can try the next interface - continue; - } - - // Get the number of endpoints associated with this interface. - kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); - - if (kr != 0) { - ERR("Unable to get number of endpoints: (%08x)\n", kr); - goto next_interface; - } - - // Get interface class, subclass and protocol - if ((*interface)->GetInterfaceClass(interface, &handle->info.ifc_class) != 0 || - (*interface)->GetInterfaceSubClass(interface, &handle->info.ifc_subclass) != 0 || - (*interface)->GetInterfaceProtocol(interface, &handle->info.ifc_protocol) != 0) - { - ERR("Unable to get interface class, subclass and protocol\n"); - goto next_interface; - } - - handle->info.has_bulk_in = 0; - handle->info.has_bulk_out = 0; - - // Iterate over the endpoints for this interface and see if there - // are any that do bulk in/out. - for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) { - UInt8 transferType; - UInt16 maxPacketSize; - UInt8 interval; - UInt8 number; - UInt8 direction; - - kr = (*interface)->GetPipeProperties(interface, endpoint, - &direction, - &number, &transferType, &maxPacketSize, &interval); - - if (kr == 0) { - if (transferType != kUSBBulk) { - continue; - } - - if (direction == kUSBIn) { - handle->info.has_bulk_in = 1; - handle->bulkIn = endpoint; - } else if (direction == kUSBOut) { - handle->info.has_bulk_out = 1; - handle->bulkOut = endpoint; - } - - if (handle->info.ifc_protocol == 0x01) { - handle->zero_mask = maxPacketSize - 1; - } - } else { - ERR("could not get pipe properties\n"); - } - - if (handle->info.has_bulk_in && handle->info.has_bulk_out) { - break; - } - } - - if (handle->callback(&handle->info) == 0) { - handle->interface = interface; - handle->success = 1; - - /* - * Clear both the endpoints, because it has been observed - * that the Mac may otherwise (incorrectly) start out with - * them in bad state. - */ - - if (handle->info.has_bulk_in) { - kr = (*interface)->ClearPipeStallBothEnds(interface, - handle->bulkIn); - if (kr != 0) { - ERR("could not clear input pipe; result %d", kr); - return -1; - } - } - - if (handle->info.has_bulk_out) { - kr = (*interface)->ClearPipeStallBothEnds(interface, - handle->bulkOut); - if (kr != 0) { - ERR("could not clear output pipe; result %d", kr); - return -1; - } - } - - return 0; - } - -next_interface: - (*interface)->USBInterfaceClose(interface); - (*interface)->Release(interface); - } - - return 0; -} - -/** Try out the given device and see if there's a match. Returns 0 on - * success, -1 on failure. - */ -static int try_device(io_service_t device, usb_handle *handle) { - kern_return_t kr; - IOCFPlugInInterface **plugin = NULL; - IOUSBDeviceInterface182 **dev = NULL; - SInt32 score; - HRESULT result; - UInt8 serialIndex; - - // Create an intermediate plugin. - kr = IOCreatePlugInInterfaceForService(device, - kIOUSBDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugin, &score); - - if ((kr != 0) || (plugin == NULL)) { - ERR("Unable to create a plug-in (%08x)\n", kr); - goto error; - } - - // Now create the device interface. - result = (*plugin)->QueryInterface(plugin, - CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev); - if ((result != 0) || (dev == NULL)) { - ERR("Couldn't create a device interface (%08x)\n", (int) result); - goto error; - } - - /* - * We don't need the intermediate interface after the device interface - * is created. - */ - IODestroyPlugInInterface(plugin); - - // So, we have a device, finally. Grab its vitals. - - kr = (*dev)->GetDeviceVendor(dev, &handle->info.dev_vendor); - if (kr != 0) { - ERR("GetDeviceVendor"); - goto error; - } - - kr = (*dev)->GetDeviceProduct(dev, &handle->info.dev_product); - if (kr != 0) { - ERR("GetDeviceProduct"); - goto error; - } - - kr = (*dev)->GetDeviceClass(dev, &handle->info.dev_class); - if (kr != 0) { - ERR("GetDeviceClass"); - goto error; - } - - kr = (*dev)->GetDeviceSubClass(dev, &handle->info.dev_subclass); - if (kr != 0) { - ERR("GetDeviceSubClass"); - goto error; - } - - kr = (*dev)->GetDeviceProtocol(dev, &handle->info.dev_protocol); - if (kr != 0) { - ERR("GetDeviceProtocol"); - goto error; - } - - kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); - - if (serialIndex > 0) { - IOUSBDevRequest req; - UInt16 buffer[256]; - - req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); - req.bRequest = kUSBRqGetDescriptor; - req.wValue = (kUSBStringDesc << 8) | serialIndex; - req.wIndex = 0; - req.pData = buffer; - req.wLength = sizeof(buffer); - kr = (*dev)->DeviceRequest(dev, &req); - - if (kr == kIOReturnSuccess && req.wLenDone > 0) { - int i, count; - - // skip first word, and copy the rest to the serial string, changing shorts to bytes. - count = (req.wLenDone - 1) / 2; - for (i = 0; i < count; i++) - handle->info.serial_number[i] = buffer[i + 1]; - handle->info.serial_number[i] = 0; - } - } else { - // device has no serial number - handle->info.serial_number[0] = 0; - } - - if (try_interfaces(dev, handle)) { - goto error; - } - - (*dev)->Release(dev); - return 0; - - error: - - if (dev != NULL) { - (*dev)->Release(dev); - } - - return -1; -} - - -/** Initializes the USB system. Returns 0 on success, -1 on error. */ -static int init_usb(ifc_match_func callback, usb_handle **handle) { - int ret = -1; - CFMutableDictionaryRef matchingDict; - kern_return_t result; - io_iterator_t iterator; - usb_handle h; - - h.success = 0; - h.callback = callback; - - /* - * Create our matching dictionary to find appropriate devices. - * IOServiceAddMatchingNotification consumes the reference, so we - * do not need to release it. - */ - matchingDict = IOServiceMatching(kIOUSBDeviceClassName); - - if (matchingDict == NULL) { - ERR("Couldn't create USB matching dictionary.\n"); - return -1; - } - - result = IOServiceGetMatchingServices( - kIOMasterPortDefault, matchingDict, &iterator); - - if (result != 0) { - ERR("Could not create iterator."); - return -1; - } - - for (;;) { - if (! IOIteratorIsValid(iterator)) { - /* - * Apple documentation advises resetting the iterator if - * it should become invalid during iteration. - */ - IOIteratorReset(iterator); - continue; - } - - io_service_t device = IOIteratorNext(iterator); - - if (device == 0) { - break; - } - - usb_ifc_info info; - - if (try_device(device, &h) != 0) { - IOObjectRelease(device); - ret = -1; - break; - } - - if (h.success) { - *handle = calloc(1, sizeof(usb_handle)); - memcpy(*handle, &h, sizeof(usb_handle)); - ret = 0; - break; - } - - IOObjectRelease(device); - } - - IOObjectRelease(iterator); - - return ret; -} - - - -/* - * Definitions of this file's public functions. - */ - -usb_handle *usb_open(ifc_match_func callback) { - usb_handle *handle = NULL; - - if (init_usb(callback, &handle) < 0) { - /* Something went wrong initializing USB. */ - return NULL; - } - - return handle; -} - -int usb_close(usb_handle *h) { - /* TODO: Something better here? */ - return 0; -} - -int usb_read(usb_handle *h, void *data, int len) { - IOReturn result; - UInt32 numBytes = len; - - if (len == 0) { - return 0; - } - - if (h == NULL) { - return -1; - } - - if (h->interface == NULL) { - ERR("usb_read interface was null\n"); - return -1; - } - - if (h->bulkIn == 0) { - ERR("bulkIn endpoint not assigned\n"); - return -1; - } - - result = (*h->interface)->ReadPipe( - h->interface, h->bulkIn, data, &numBytes); - - if (result == 0) { - return (int) numBytes; - } else { - ERR("usb_read failed with status %x\n", result); - } - - return -1; -} - -int usb_write(usb_handle *h, const void *data, int len) { - IOReturn result; - - if (len == 0) { - return 0; - } - - if (h == NULL) { - return -1; - } - - if (h->interface == NULL) { - ERR("usb_write interface was null\n"); - return -1; - } - - if (h->bulkOut == 0) { - ERR("bulkOut endpoint not assigned\n"); - return -1; - } - - result = (*h->interface)->WritePipe( - h->interface, h->bulkOut, (void *)data, len); - - #if 0 - if ((result == 0) && (h->zero_mask)) { - /* we need 0-markers and our transfer */ - if(!(len & h->zero_mask)) { - result = (*h->interface)->WritePipe( - h->interface, h->bulkOut, (void *)data, 0); - } - } - #endif - - if (result != 0) { - ERR("usb_write failed with status %x\n", result); - return -1; - } - - return len; -} |