1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/* -*- Mode: C; indent-tabs-mode:nil -*- */ 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * darwin backend for libusbx 1.0 4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net> 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This library is free software; you can redistribute it and/or 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modify it under the terms of the GNU Lesser General Public 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License as published by the Free Software Foundation; either 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * version 2.1 of the License, or (at your option) any later version. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This library is distributed in the hope that it will be useful, 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Lesser General Public License for more details. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You should have received a copy of the GNU Lesser General Public 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License along with this library; if not, write to the Free Software 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "config.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h> 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <fcntl.h> 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <libkern/OSAtomic.h> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mach/clock.h> 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mach/clock_types.h> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mach/mach_host.h> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mach/mach_port.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <AvailabilityMacros.h> 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #include <objc/objc-auto.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "darwin_usb.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* async event thread */ 46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER; 47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static clock_serv_t clock_realtime; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static clock_serv_t clock_monotonic; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic volatile int32_t initCount = 0; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER; 56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices}; 57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev)) 59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* async event thread */ 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pthread_t libusb_darwin_at; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_reset_device(struct libusb_device_handle *dev_handle); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int darwin_scan_devices(struct libusb_context *ctx); 70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int process_new_device (struct libusb_context *ctx, io_service_t service); 71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(ENABLE_LOGGING) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char *darwin_error_str (int result) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (result) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnSuccess: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "no error"; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnNotOpen: 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "device not opened for exclusive access"; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnNoDevice: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "no connection to an IOService"; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOUSBNoAsyncPortErr: 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "no async port has been opened for interface"; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnExclusiveAccess: 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "another process has device opened for exclusive access"; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOUSBPipeStalled: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "pipe is stalled"; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnError: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "could not establish a connection to the Darwin kernel"; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOUSBTransactionTimeout: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "transaction timed out"; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnBadArgument: 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "invalid argument"; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnAborted: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "transaction aborted"; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnNotResponding: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "device not responding"; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnOverrun: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "data overrun"; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnCannotWire: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "physical memory can not be wired down"; 101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case kIOReturnNoResources: 102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return "out of resources"; 103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case kIOUSBHighSpeedSplitError: 104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return "high speed split error"; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "unknown error"; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_to_libusb (int result) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (result) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnUnderrun: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnSuccess: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_SUCCESS; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnNotOpen: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnNoDevice: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NO_DEVICE; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnExclusiveAccess: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_ACCESS; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOUSBPipeStalled: 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_PIPE; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnBadArgument: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_INVALID_PARAM; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOUSBTransactionTimeout: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_TIMEOUT; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnNotResponding: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnAborted: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnError: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOUSBNoAsyncPortErr: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_OTHER; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/* this function must be called with the darwin_cached_devices_lock held */ 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) { 138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cached_dev->refcount--; 139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* free the device and remove it from the cache */ 140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (0 == cached_dev->refcount) { 141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch list_del(&cached_dev->list); 142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*(cached_dev->device))->Release(cached_dev->device); 144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch free (cached_dev); 145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) { 149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cached_dev->refcount++; 150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* current interface */ 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int8_t i, iface; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface = &priv->interfaces[iface]; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dev_handle->claimed_interfaces & (1 << iface)) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0 ; i < cInterface->num_endpoints ; i++) { 167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (cInterface->endpoint_addrs[i] == ep) { 168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *pipep = i + 1; 169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *ifcp = iface; 170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("pipe %d on interface %d matches", *pipep, *ifcp); 171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return 0; 172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* No pipe found with the correct endpoint address */ 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!matchingDict) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kIOReturnError; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (location) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFMutableDictionaryRef propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &kCFTypeDictionaryKeyCallBacks, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &kCFTypeDictionaryValueCallBacks); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (propertyMatchDict) { 195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* there are no unsigned CFNumber types so treat the value as signed. the os seems to do this 196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch internally (CFNumberType of locationID is 3) */ 197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* release our reference to the CFNumber (CFDictionarySetValue retains it) */ 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRelease (locationCF); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* release out reference to the CFMutableDictionaryRef (CFDictionarySetValue retains it) */ 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRelease (propertyMatchDict); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */ 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/* Returns 1 on success, 0 on failure. */ 214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) { 215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); 216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int ret = 0; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (cfNumber) { 219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) { 220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = CFNumberGetValue(cfNumber, type, p); 221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFRelease (cfNumber); 224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ret; 227ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic usb_device_t **darwin_device_from_service (io_service_t service) 230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_cf_plugin_ref_t *plugInInterface = NULL; 232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usb_device_t **device; 233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kern_return_t result; 234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SInt32 score; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, 237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kIOCFPlugInInterfaceID, &plugInInterface, 238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch &score); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kIOReturnSuccess != result || !plugInInterface) { 241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("could not set up plugin for service: %s\n", darwin_error_str (result)); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID), 246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (LPVOID)&device); 247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ 248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*plugInInterface)->Release (plugInInterface); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return device; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { 254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_context *ctx; 255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_service_t service; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_lock(&active_contexts_lock); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while ((service = IOIteratorNext(add_devices))) { 260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* add this device to each active context's device list */ 261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { 262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch process_new_device (ctx, service);; 263ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOObjectRelease(service); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_unlock(&active_contexts_lock); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { 272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device *dev = NULL; 273ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_context *ctx; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_service_t device; 276ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UInt64 session; 277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int ret; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((device = IOIteratorNext (rem_devices)) != 0) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* get the location from the i/o registry */ 281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObjectRelease (device); 283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!ret) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_lock(&active_contexts_lock); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { 289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("notifying context %p of device disconnect", ctx); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dev = usbi_get_device_by_session_id(ctx, (unsigned long) session); 292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (dev) { 293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* signal the core that this device has been disconnected. the core will tear down this device 294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch when the reference count reaches 0 */ 295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_disconnect_device(dev); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_unlock(&active_contexts_lock); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_clear_iterator (io_iterator_t iter) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_service_t device; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((device = IOIteratorNext (iter)) != 0) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObjectRelease (device); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void *darwin_event_thread_main (void *arg0) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_context *ctx = (struct libusb_context *)arg0; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRunLoopRef runloop; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* Set this thread's name, so it can be seen in the debugger 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch and crash reports. */ 317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pthread_setname_np ("org.libusb.device-hotplug"); 319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Tell the Objective-C garbage collector about this thread. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) This is required because, unlike NSThreads, pthreads are 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) not automatically registered. Although we don't use 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Objective-C, we use CoreFoundation, which does. */ 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) objc_registerThreadWithCollector(); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* hotplug (device arrival/removal) sources */ 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRunLoopSourceRef libusb_notification_cfsource; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_notification_port_t libusb_notification_port; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_iterator_t libusb_rem_device_iterator; 331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_iterator_t libusb_add_device_iterator; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("creating hotplug event source"); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runloop = CFRunLoopGetCurrent (); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRetain (runloop); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* add the notification port to the run loop */ 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port); 341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CFRunLoopAddSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* create notifications for removed devices */ 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification, 345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOServiceMatching(kIOUSBDeviceClassName), 346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (IOServiceMatchingCallback)darwin_devices_detached, 347ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void *)ctx, &libusb_rem_device_iterator); 348ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kresult != kIOReturnSuccess) { 350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); 351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pthread_exit (NULL); 353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* create notifications for attached devices */ 356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification, 357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOServiceMatching(kIOUSBDeviceClassName), 358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (IOServiceMatchingCallback)darwin_devices_attached, 359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void *)ctx, &libusb_add_device_iterator); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_exit (NULL); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* arm notifiers */ 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) darwin_clear_iterator (libusb_rem_device_iterator); 369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_clear_iterator (libusb_add_device_iterator); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("darwin event thread ready to receive events"); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 373ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* signal the main thread that the hotplug runloop has been created. */ 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_mutex_lock (&libusb_darwin_at_mutex); 375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch libusb_darwin_acfl = runloop; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_cond_signal (&libusb_darwin_at_cond); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_mutex_unlock (&libusb_darwin_at_mutex); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* run the runloop */ 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRunLoopRun(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("darwin event thread exiting"); 383ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 384ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* remove the notification cfsource */ 385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* delete notification port */ 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IONotificationPortDestroy (libusb_notification_port); 389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* delete iterators */ 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObjectRelease (libusb_rem_device_iterator); 392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOObjectRelease (libusb_add_device_iterator); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRelease (runloop); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) libusb_darwin_acfl = NULL; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_exit (NULL); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 401ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void _darwin_finalize(void) { 402ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dev, *next; 403ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_lock(&darwin_cached_devices_lock); 405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) { 406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_deref_cached_device(dev); 407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_unlock(&darwin_cached_devices_lock); 409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_init(struct libusb_context *ctx) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_name_port_t host_self; 413ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch static int initted = 0; 414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int rc; 415ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 416ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch rc = darwin_scan_devices (ctx); 417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (LIBUSB_SUCCESS != rc) { 418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return rc; 419ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (OSAtomicIncrement32Barrier(&initCount) == 1) { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* create the clocks that will be used */ 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!initted) { 425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch initted = 1; 426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch atexit(_darwin_finalize); 427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_self = mach_host_self(); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mach_port_deallocate(mach_task_self(), host_self); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, (void *)ctx); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_mutex_lock (&libusb_darwin_at_mutex); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!libusb_darwin_acfl) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_mutex_unlock (&libusb_darwin_at_mutex); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return rc; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_exit (void) { 446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (OSAtomicDecrement32Barrier(&initCount) == 0) { 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mach_port_deallocate(mach_task_self(), clock_realtime); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mach_port_deallocate(mach_task_self(), clock_monotonic); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* stop the event runloop and wait for the thread to terminate. */ 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRunLoopStop (libusb_darwin_acfl); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_join (libusb_darwin_at, NULL); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) { 457ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* return cached copy */ 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memmove (buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *host_endian = 0; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int get_configuration_index (struct libusb_device *dev, int config_value) { 468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt8 i, numConfig; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOUSBConfigurationDescriptorPtr desc; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* is there a simpler way to determine the index? */ 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(priv->device))->GetNumberOfConfigurations (priv->device, &numConfig); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0 ; i < numConfig ; i++) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*(priv->device))->GetConfigurationDescriptorPtr (priv->device, i, &desc); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (desc->bConfigurationValue == config_value) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* configuration not found */ 486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NOT_FOUND; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) { 490ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int config_index; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == priv->active_config) 494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NOT_FOUND; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_index = get_configuration_index (dev, priv->active_config); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (config_index < 0) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return config_index; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_get_config_descriptor (dev, config_index, buffer, len, host_endian); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) { 504ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOUSBConfigurationDescriptorPtr desc; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int ret; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 509ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!priv || !priv->device) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_OTHER; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kresult = (*priv->device)->GetConfigurationDescriptorPtr (priv->device, config_index, &desc); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult == kIOReturnSuccess) { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* copy descriptor */ 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (libusb_le16_to_cpu(desc->wTotalLength) < len) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = libusb_le16_to_cpu(desc->wTotalLength); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memmove (buffer, desc, len); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* GetConfigurationDescriptorPtr returns the descriptor in USB bus order */ 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *host_endian = 0; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = darwin_to_libusb (kresult); 525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (ret != LIBUSB_SUCCESS) 526ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ret; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 528ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return len; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* check whether the os has configured the device */ 532ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) { 533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usb_device_t **darwin_device = dev->device; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOUSBConfigurationDescriptorPtr configDesc; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOUSBFindInterfaceRequest request; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kern_return_t kresult; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_iterator_t interface_iterator; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_service_t firstInterface; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 541ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (dev->dev_descriptor.bNumConfigurations < 1) { 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (ctx, "device has no configurations"); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */ 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* find the first configuration */ 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc); 548ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* check if the device is already configured. there is probably a better way than iterating over the 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to accomplish this (the trick is we need to avoid a call to GetConfigurations since buggy devices 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) might lock up on the device request) */ 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Setup the Interface Request */ 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.bInterfaceClass = kIOUSBFindInterfaceDontCare; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.bAlternateSetting = kIOUSBFindInterfaceDontCare; 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* iterate once */ 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) firstInterface = IOIteratorNext(interface_iterator); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* done with the interface iterator */ 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObjectRelease(interface_iterator); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (firstInterface) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObjectRelease (firstInterface); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* device is configured */ 574ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (dev->dev_descriptor.bNumConfigurations == 1) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* to avoid problems with some devices get the configurations value from the configuration descriptor */ 576ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->active_config = dev->first_config; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* devices with more than one configuration should work with GetConfiguration */ 579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*darwin_device)->GetConfiguration (darwin_device, &dev->active_config); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* not configured */ 582ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->active_config = 0; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 584ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 589ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) { 590ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOUSBDevRequestTO req; 591ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 592ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch memset (buffer, 0, buffer_size); 593ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* Set up request for descriptor/ */ 595ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); 596ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch req.bRequest = kUSBRqGetDescriptor; 597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch req.wValue = desc << 8; 598ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch req.wIndex = desc_index; 599ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch req.wLength = buffer_size; 600ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch req.pData = buffer; 601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch req.noDataTimeout = 20; 602ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch req.completionTimeout = 100; 603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 604ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return (*device)->DeviceRequestTO (device, &req); 605ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 606ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 607ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) { 608ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usb_device_t **device = dev->device; 609ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int retries = 1, delay = 30000; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int is_open = 0; 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret = 0, ret2; 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt8 bDeviceClass; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt16 idProduct, idVendor; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 616ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->can_enumerate = 0; 617ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*device)->GetDeviceClass (device, &bDeviceClass); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*device)->GetDeviceProduct (device, &idProduct); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*device)->GetDeviceVendor (device, &idVendor); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 622ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* According to Apple's documentation the device must be open for DeviceRequest but we may not be able to open some 623ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * devices and Apple's USB Prober doesn't bother to open the device before issuing a descriptor request. Still, 624ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * to follow the spec as closely as possible, try opening the device */ 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_open = ((*device)->USBDeviceOpenSeize(device) == kIOReturnSuccess); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /**** retrieve device descriptor ****/ 629ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = darwin_request_descriptor (device, kUSBDeviceDesc, 0, &dev->dev_descriptor, sizeof(dev->dev_descriptor)); 630ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 631ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kIOReturnOverrun == ret && kUSBDeviceDesc == dev->dev_descriptor.bDescriptorType) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* received an overrun error but we still received a device descriptor */ 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = kIOReturnSuccess; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kIOUSBVendorIDAppleComputer == idVendor) { 636ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* NTH: don't bother retrying or unsuspending Apple devices */ 637ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 639ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 640ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kIOReturnSuccess == ret && (0 == dev->dev_descriptor.bNumConfigurations || 641ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 0 == dev->dev_descriptor.bcdUSB)) { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* work around for incorrectly configured devices */ 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (try_reconfigure && is_open) { 644ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again..."); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* set the first configuration */ 647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*device)->SetConfiguration(device, 1); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 649ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* don't try to reconfigure again */ 650ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch try_reconfigure = 0; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = kIOUSBPipeStalled; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kIOReturnSuccess != ret && is_open && try_unsuspend) { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* device may be suspended. unsuspend it and try again */ 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DeviceVersion >= 320 659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UInt32 info = 0; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */ 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)(*device)->GetUSBDeviceInformation (device, &info); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 664ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* note that the device was suspended */ 665ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info) 666ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch try_unsuspend = 1; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (try_unsuspend) { 670ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* try to unsuspend the device */ 671ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret2 = (*device)->USBDeviceSuspend (device, 0); 672ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kIOReturnSuccess != ret2) { 673ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* prevent log spew from poorly behaving devices. this indicates the 674ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch os actually had trouble communicating with the device */ 675ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2)); 676ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else 677ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unsuspended = 1; 678ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 679ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch try_unsuspend = 0; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kIOReturnSuccess != ret) { 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* sleep for a little while before trying again */ 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usleep (delay); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (kIOReturnSuccess != ret && retries--); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unsuspended) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* resuspend the device */ 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)(*device)->USBDeviceSuspend (device, 1); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_open) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) (*device)->USBDeviceClose (device); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret != kIOReturnSuccess) { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* a debug message was already printed out for this error */ 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LIBUSB_CLASS_HUB == bDeviceClass) 700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device", 701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch idVendor, idProduct, darwin_error_str (ret), ret); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device", 704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch idVendor, idProduct, darwin_error_str (ret), ret); 70568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return darwin_to_libusb (ret); 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */ 709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (libusb_le16_to_cpu (dev->dev_descriptor.idProduct) != idProduct) { 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* not a valid device */ 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", 712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct)); 71368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return LIBUSB_ERROR_NO_DEVICE; 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 716ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("cached device descriptor:"); 717ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType); 718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" bcdUSB: 0x%04x", dev->dev_descriptor.bcdUSB); 719ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass); 720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass); 721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol); 722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0); 723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" idVendor: 0x%04x", dev->dev_descriptor.idVendor); 724ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" idProduct: 0x%04x", dev->dev_descriptor.idProduct); 725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" bcdDevice: 0x%04x", dev->dev_descriptor.bcdDevice); 726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer); 727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" iProduct: 0x%02x", dev->dev_descriptor.iProduct); 728ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber); 729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg (" bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations); 730ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->can_enumerate = 1; 732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 73368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return LIBUSB_SUCCESS; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, 737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device **cached_out) { 738ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *new_device; 73968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) UInt64 sessionID = 0, parent_sessionID = 0; 740ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int ret = LIBUSB_SUCCESS; 741ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usb_device_t **device; 742ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_service_t parent; 743ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kern_return_t result; 744ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UInt8 port = 0; 745ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 746ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* get some info from the io registry */ 747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID); 748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, &port); 749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("finding cached device for sessionID 0x\n" PRIx64, sessionID); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent); 753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kIOReturnSuccess == result) { 755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID); 756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOObjectRelease(parent); 757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_lock(&darwin_cached_devices_lock); 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 76168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *cached_out = NULL; 76268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) { 764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("matching sessionID 0x%x against cached device with sessionID 0x%x", sessionID, new_device->session); 765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (new_device->session == sessionID) { 766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("using cached device for device"); 767ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *cached_out = new_device; 768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 770ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 772ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (*cached_out) 773ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 774ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 775ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("caching new device with sessionID 0x%x\n", sessionID); 776ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 777ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch device = darwin_device_from_service (service); 778ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!device) { 779ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = LIBUSB_ERROR_NO_DEVICE; 78068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) break; 78168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 78268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 78368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) new_device = calloc (1, sizeof (*new_device)); 78468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!new_device) { 78568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ret = LIBUSB_ERROR_NO_MEM; 786ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 787ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 789ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* add this device to the cached device list */ 790ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch list_add(&new_device->list, &darwin_cached_devices); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 792ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address); 793ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 794ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* keep a reference to this device */ 795ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_ref_cached_device(new_device); 796ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 797ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new_device->device = device; 798ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new_device->session = sessionID; 799ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*device)->GetLocationID (device, &new_device->location); 800ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new_device->port = port; 801ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new_device->parent_session = parent_sessionID; 802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* cache the device descriptor */ 804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = darwin_cache_device_descriptor(ctx, new_device); 805ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (ret) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 808ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (new_device->can_enumerate) { 809ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch snprintf(new_device->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", new_device->address, 810ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new_device->dev_descriptor.idVendor, new_device->dev_descriptor.idProduct, 811ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new_device->dev_descriptor.bDeviceClass, new_device->dev_descriptor.bDeviceSubClass); 812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } while (0); 814ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_unlock(&darwin_cached_devices_lock); 816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* keep track of devices regardless of if we successfully enumerate them to 818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch prevent them from being enumerated multiple times */ 819ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 820ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *cached_out = new_device; 821ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 822ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ret; 823ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int process_new_device (struct libusb_context *ctx, io_service_t service) { 826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_device_priv *priv; 827ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device *dev = NULL; 828ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *cached_device; 829ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UInt8 devSpeed; 830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int ret = 0; 831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch do { 833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = darwin_get_cached_device (ctx, service, &cached_device); 834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 83568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ret < 0 || !cached_device->can_enumerate) { 836ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ret; 837ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 838ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 839ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* check current active configuration (and cache the first configuration value-- 840ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch which may be used by claim_interface) */ 841ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = darwin_check_configuration (ctx, cached_device); 842ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (ret) 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("allocating new device in context %p for with session 0x%08x", 846ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ctx, cached_device->session); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 84868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session); 849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!dev) { 850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NO_MEM; 851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 853ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch priv = (struct darwin_device_priv *)dev->os_priv; 854ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 855ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch priv->dev = cached_device; 856ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_ref_cached_device (priv->dev); 857ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 858ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (cached_device->parent_session > 0) { 85968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session); 860ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 861ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->parent_dev = NULL; 862ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->port_number = cached_device->port; 864ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->bus_number = cached_device->location >> 24; 865ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->device_address = cached_device->address; 866ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 867ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* need to add a reference to the parent device */ 868ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (dev->parent_dev) { 869ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch libusb_ref_device(dev->parent_dev); 870ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 871ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 872ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (devSpeed) { 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break; 878ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if DeviceVersion >= 500 879ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break; 880ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn (ctx, "Got unknown device speed %d", devSpeed); 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = usbi_sanitize_device (dev); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 889ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address, 890ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 893ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (0 == ret) { 894ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_connect_device (dev); 895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 896ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch libusb_unref_device (dev); 897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 902ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int darwin_scan_devices(struct libusb_context *ctx) { 903ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_iterator_t deviceIterator; 904ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_service_t service; 905ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kern_return_t kresult; 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = usb_setup_device_iterator (&deviceIterator, 0); 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 911ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while ((service = IOIteratorNext (deviceIterator))) { 912ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) process_new_device (ctx, service); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 914ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOObjectRelease(service); 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObjectRelease(deviceIterator); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_open (struct libusb_device_handle *dev_handle) { 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; 924ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == dpriv->open_count) { 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* try to open the device */ 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) { 931ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); 932ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 933ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kIOReturnExclusiveAccess != kresult) { 934ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return darwin_to_libusb (kresult); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 936ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 937ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* it is possible to perform some actions on a device that is not open so do not return an error */ 938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch priv->is_open = 0; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch priv->is_open = 1; 941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 943ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* create async event source */ 944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource); 945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kresult != kIOReturnSuccess) { 946ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult)); 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 948ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (priv->is_open) { 949ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*(dpriv->device))->USBDeviceClose (dpriv->device); 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 952ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch priv->is_open = 0; 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 954ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return darwin_to_libusb (kresult); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 956ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 957ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFRetain (libusb_darwin_acfl); 958ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 959ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* add the cfSource to the aync run loop */ 960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes); 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* device opened successfully */ 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpriv->open_count++; 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* create a file descriptor for notifications */ 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe (priv->fds); 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* set the pipe to be non-blocking */ 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fcntl (priv->fds[1], F_SETFD, O_NONBLOCK); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_add_pollfd(HANDLE_CTX(dev_handle), priv->fds[0], POLLIN); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 974ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("device open for access"); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_close (struct libusb_device_handle *dev_handle) { 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; 981ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dpriv->open_count == 0) { 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* something is probably very wrong if this is the case */ 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!\n"); 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpriv->open_count--; 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* make sure all interfaces are released */ 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0 ; i < USB_MAXINTERFACES ; i++) 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dev_handle->claimed_interfaces & (1 << i)) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) libusb_release_interface (dev_handle, i); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == dpriv->open_count) { 999ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* delete the device's async event source */ 1000ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (priv->cfSource) { 1001ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFRunLoopRemoveSource (libusb_darwin_acfl, priv->cfSource, kCFRunLoopDefaultMode); 1002ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFRelease (priv->cfSource); 1003ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch priv->cfSource = NULL; 1004ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFRelease (libusb_darwin_acfl); 1005ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1007ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (priv->is_open) { 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* close the device */ 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device); 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 1011ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* Log the fact that we had a problem closing the file, however failing a 1012ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * close isn't really an error, so return success anyway */ 1013ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult)); 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* file descriptors are maintained per-instance */ 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_remove_pollfd (HANDLE_CTX (dev_handle), priv->fds[0]); 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close (priv->fds[1]); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close (priv->fds[0]); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) priv->fds[0] = priv->fds[1] = -1; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) { 1027ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *config = (int) dpriv->active_config; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) { 1035ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Setting configuration will invalidate the interface, so we need 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to reclaim it. First, dispose of existing interfaces, if any. */ 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0 ; i < USB_MAXINTERFACES ; i++) 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dev_handle->claimed_interfaces & (1 << i)) 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) darwin_release_interface (dev_handle, i); 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, config); 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Reclaim any interfaces. */ 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0 ; i < USB_MAXINTERFACES ; i++) 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dev_handle->claimed_interfaces & (1 << i)) 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) darwin_claim_interface (dev_handle, i); 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpriv->active_config = config; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) { 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOUSBFindInterfaceRequest request; 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kern_return_t kresult; 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_iterator_t interface_iterator; 1063ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UInt8 bInterfaceNumber; 1064ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int ret; 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *usbInterfacep = IO_OBJECT_NULL; 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Setup the Interface Request */ 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.bInterfaceClass = kIOUSBFindInterfaceDontCare; 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.bAlternateSetting = kIOUSBFindInterfaceDontCare; 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kresult; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1078ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while ((*usbInterfacep = IOIteratorNext(interface_iterator))) { 1079ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* find the interface number */ 1080ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = get_ioregistry_value_number (*usbInterfacep, CFSTR("bInterfaceNumber"), kCFNumberSInt8Type, 1081ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch &bInterfaceNumber); 1082ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1083ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (ret && bInterfaceNumber == ifc) { 1084ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1085ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1086ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1087ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) IOObjectRelease (*usbInterfacep); 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* done with the interface iterator */ 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObjectRelease(interface_iterator); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* current interface */ 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface = &priv->interfaces[iface]; 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kern_return_t kresult; 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_int8_t numep, direction, number; 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_int8_t dont_care1, dont_care3; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_int16_t dont_care2; 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("building table of endpoints."); 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* retrieve the total number of endpoints on this interface */ 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* iterate through pipe references */ 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 1 ; i <= numep ; i++) { 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1, 1121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch &dont_care2, &dont_care3); 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) { 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult)); 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number); 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface->endpoint_addrs[i - 1] = ((direction << 7 & LIBUSB_ENDPOINT_DIR_MASK) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface->num_endpoints = numep; 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) { 1140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_service_t usbInterface = IO_OBJECT_NULL; 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOCFPlugInInterface **plugInInterface = NULL; 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SInt32 score; 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* current interface */ 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface = &priv->interfaces[iface]; 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* make sure we have an interface */ 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!usbInterface && dpriv->first_config != 0) { 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config); 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* set the configuration */ 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = darwin_set_configuration (dev_handle, dpriv->first_config); 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != LIBUSB_SUCCESS) { 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "could not set configuration"); 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kresult; 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!usbInterface) { 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "interface not found"); 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_FOUND; 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* get an interface to the device's interface */ 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID, 1179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch kIOCFPlugInInterfaceID, &plugInInterface, &score); 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ignore release error */ 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)IOObjectRelease (usbInterface); 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!plugInInterface) { 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found"); 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_FOUND; 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Do the actual claim */ 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*plugInInterface)->QueryInterface(plugInInterface, 1196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), 1197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (LPVOID)&cInterface->interface); 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We no longer need the intermediate plug-in */ 1199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ 1200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*plugInInterface)->Release (plugInInterface); 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult || !cInterface->interface) { 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult)); 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* claim the interface */ 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult)); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* update list of endpoints */ 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = get_endpoints (dev_handle, iface); 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this should not happen */ 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) darwin_release_interface (dev_handle, iface); 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kresult; 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface->cfSource = NULL; 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* create async event source */ 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource); 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) { 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "could not create async event source"); 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* can't continue without an async event source */ 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)darwin_release_interface (dev_handle, iface); 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* add the cfSource to the async thread's run loop */ 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("interface opened"); 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) { 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* current interface */ 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface = &priv->interfaces[iface]; 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check to see if an interface is open */ 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cInterface->interface) 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_SUCCESS; 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* clean up endpoint data */ 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface->num_endpoints = 0; 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* delete the interface's async event source */ 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cInterface->cfSource) { 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRunLoopRemoveSource (libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRelease (cInterface->cfSource); 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) 1265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->Release(cInterface->interface); 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) 1269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cInterface->interface = NULL; 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* current interface */ 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface = &priv->interfaces[iface]; 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cInterface->interface) 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NO_DEVICE; 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting); 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) darwin_reset_device (dev_handle); 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* update list of endpoints */ 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = get_endpoints (dev_handle, iface); 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this should not happen */ 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) darwin_release_interface (dev_handle, iface); 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kresult; 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* current interface */ 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface; 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t pipeRef, iface; 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* determine the interface/endpoint to use */ 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, &iface) != 0) { 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface"); 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_FOUND; 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface = &priv->interfaces[iface]; 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* newer versions of darwin support clearing additional bits on the device's endpoint */ 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) 1322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_reset_device(struct libusb_device_handle *dev_handle) { 1328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); 1329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOUSBDeviceDescriptor descriptor; 1330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOUSBConfigurationDescriptorPtr cached_configuration; 1331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOUSBConfigurationDescriptor configuration; 1332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool reenumerate = false; 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 1334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int i; 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(dpriv->device))->ResetDevice (dpriv->device); 1337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kresult) { 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult)); 1339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return darwin_to_libusb (kresult); 1340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch do { 1343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("darwin/reset_device: checking if device descriptor changed"); 1344ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* ignore return code. if we can't get a descriptor it might be worthwhile re-enumerating anway */ 1346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) darwin_request_descriptor (dpriv->device, kUSBDeviceDesc, 0, &descriptor, sizeof (descriptor)); 1347ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1348ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* check if the device descriptor has changed */ 1349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (0 != memcmp (&dpriv->dev_descriptor, &descriptor, sizeof (descriptor))) { 1350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch reenumerate = true; 1351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* check if any configuration descriptor has changed */ 1355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { 1356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("darwin/reset_device: checking if configuration descriptor %d changed", i); 1357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) darwin_request_descriptor (dpriv->device, kUSBConfDesc, i, &configuration, sizeof (configuration)); 1359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); 1360ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!cached_configuration || 0 != memcmp (cached_configuration, &configuration, sizeof (configuration))) { 1362ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch reenumerate = true; 1363ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1364ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } while (0); 1367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (reenumerate) { 1369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("darwin/reset_device: device requires reenumeration"); 1370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0); 1371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NOT_FOUND; 1372ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1373ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("darwin/reset_device: device reset complete"); 1375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1376ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) { 1380ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_service_t usbInterface; 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFTypeRef driver; 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = darwin_get_interface (dpriv->device, interface, &usbInterface); 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) driver = IORegistryEntryCreateCFProperty (usbInterface, kIOBundleIdentifierKey, kCFAllocatorDefault, 0); 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObjectRelease (usbInterface); 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (driver) { 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CFRelease (driver); 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* no driver */ 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */ 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) { 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)dev_handle; 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)interface; 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_SUPPORTED; 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) { 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)dev_handle; 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)interface; 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_SUPPORTED; 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_destroy_device(struct libusb_device *dev) { 1419ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_device_priv *dpriv = (struct darwin_device_priv *) dev->os_priv; 1420ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (dpriv->dev) { 1422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* need to hold the lock in case this is the last reference to the device */ 1423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_lock(&darwin_cached_devices_lock); 1424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_deref_cached_device (dpriv->dev); 1425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dpriv->dev = NULL; 1426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_unlock(&darwin_cached_devices_lock); 1427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int submit_bulk_transfer(struct usbi_transfer *itransfer) { 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn ret; 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t transferType; 1436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* None of the values below are used in libusbx for bulk transfers */ 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t direction, number, interval, pipeRef, iface; 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t maxPacketSize; 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface; 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_FOUND; 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface = &priv->interfaces[iface]; 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, 1451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) &transferType, &maxPacketSize, &interval); 1452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (ret) { 1454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", 1455424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) darwin_error_str(ret), ret); 1456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return darwin_to_libusb (ret); 1457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1458ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1459ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (0 != (transfer->length % maxPacketSize)) { 1460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* do not need a zero packet */ 1461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET; 1462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* submit the request */ 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* timeouts are unavailable on interrupt endpoints */ 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transferType == kUSBInterrupt) { 1467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IS_XFERIN(transfer)) 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer, 1469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->length, darwin_async_io_callback, itransfer); 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer, 1472ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->length, darwin_async_io_callback, itransfer); 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IS_XFERIN(transfer)) 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, 1478ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->length, transfer->timeout, transfer->timeout, 1479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_async_io_callback, (void *)itransfer); 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, 1482ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->length, transfer->timeout, transfer->timeout, 1483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_async_io_callback, (void *)itransfer); 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret) 1487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", 1488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_error_str(ret), ret); 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (ret); 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int submit_iso_transfer(struct usbi_transfer *itransfer) { 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1498ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch IOReturn kresult; 1499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint8_t direction, number, interval, pipeRef, iface, transferType; 1500ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint16_t maxPacketSize; 1501ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UInt64 frame; 1502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AbsoluteTime atTime; 1503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int i; 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface; 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* construct an array of IOUSBIsocFrames, reuse the old one if possible */ 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) { 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(tpriv->isoc_framelist); 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->isoc_framelist = NULL; 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tpriv->isoc_framelist) { 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->num_iso_packets = transfer->num_iso_packets; 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame)); 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tpriv->isoc_framelist) 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NO_MEM; 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* copy the frame list from the libusbx descriptor (the structures differ only is member order) */ 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0 ; i < transfer->num_iso_packets ; i++) 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->isoc_framelist[i].frReqCount = transfer->iso_packet_desc[i].length; 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* determine the interface/endpoint to use */ 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_FOUND; 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface = &priv->interfaces[iface]; 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* determine the properties of this endpoint and the speed of the device */ 1534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, 1535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch &transferType, &maxPacketSize, &interval); 1536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Last but not least we need the bus frame number */ 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult) { 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(tpriv->isoc_framelist); 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->isoc_framelist = NULL; 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1547ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, 1548ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch &transferType, &maxPacketSize, &interval); 1549ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* schedule for a frame a little in the future */ 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame += 4; 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cInterface->frames[transfer->endpoint] && frame < cInterface->frames[transfer->endpoint]) 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame = cInterface->frames[transfer->endpoint]; 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* submit the request */ 1557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IS_XFERIN(transfer)) 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, 1559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, 1560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch itransfer); 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, 1563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, 1564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch itransfer); 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed) 1567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* Full speed */ 1568ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)); 1569ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch else 1570ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* High/super speed */ 1571ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)) / 8; 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) { 1574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out", 1575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_error_str(kresult)); 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free (tpriv->isoc_framelist); 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->isoc_framelist = NULL; 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int submit_control_transfer(struct usbi_transfer *itransfer) { 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer; 1586ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bzero(&tpriv->req, sizeof(tpriv->req)); 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* IOUSBDeviceInterface expects the request in cpu endianess */ 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->req.bmRequestType = setup->bmRequestType; 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->req.bRequest = setup->bRequest; 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* these values should be in bus order from libusb_fill_control_setup */ 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->req.wValue = OSSwapLittleToHostInt16 (setup->wValue); 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->req.wIndex = OSSwapLittleToHostInt16 (setup->wIndex); 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->req.wLength = OSSwapLittleToHostInt16 (setup->wLength); 1601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* data is stored after the libusbx control block */ 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->req.pData = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->req.completionTimeout = transfer->timeout; 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->req.noDataTimeout = transfer->timeout; 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* all transfers in libusb-1.0 are async */ 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transfer->endpoint) { 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface; 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t pipeRef, iface; 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_FOUND; 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface = &priv->interfaces[iface]; 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer); 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* control request on endpoint 0 */ 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kresult != kIOReturnSuccess) 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_submit_transfer(struct usbi_transfer *itransfer) { 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (transfer->type) { 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TYPE_CONTROL: 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return submit_control_transfer(itransfer); 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TYPE_BULK: 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TYPE_INTERRUPT: 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return submit_bulk_transfer(itransfer); 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return submit_iso_transfer(itransfer); 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_INVALID_PARAM; 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int cancel_control_transfer(struct usbi_transfer *itransfer) { 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 1652ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe"); 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dpriv->device) 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NO_DEVICE; 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_abort_transfers (struct usbi_transfer *itransfer) { 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 1667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_interface *cInterface; 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t pipeRef, iface; 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOReturn kresult; 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NOT_FOUND; 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cInterface = &priv->interfaces[iface]; 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dpriv->device) 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_NO_DEVICE; 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1684ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions on interface %d pipe %d", iface, pipeRef); 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* abort transactions */ 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1689ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("calling clear pipe stall to clear the data toggle bit"); 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* newer versions of darwin support clearing additional bits on the device's endpoint */ 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_to_libusb (kresult); 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_cancel_transfer(struct usbi_transfer *itransfer) { 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (transfer->type) { 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TYPE_CONTROL: 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cancel_control_transfer(itransfer); 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TYPE_BULK: 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TYPE_INTERRUPT: 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return darwin_abort_transfers (itransfer); 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_INVALID_PARAM; 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) { 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && tpriv->isoc_framelist) { 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free (tpriv->isoc_framelist); 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tpriv->isoc_framelist = NULL; 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) { 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon; 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; 1727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_msg_async_io_complete message = {.itransfer = itransfer, .result = result, 1728ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .size = (UInt32) (uintptr_t) arg0}; 1729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1730ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("an async io operation has completed"); 1731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* if requested write a zero packet */ 1733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { 1734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_interface *cInterface; 1735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint8_t iface, pipeRef; 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface); 1738ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cInterface = &priv->interfaces[iface]; 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1740ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0); 1741ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* send a completion message to the device's file descriptor */ 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write (priv->fds[1], &message, sizeof (message)); 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) { 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = kIOUSBTransactionTimeout; 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (result) { 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnUnderrun: 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnSuccess: 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_TRANSFER_COMPLETED; 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnAborted: 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_TRANSFER_CANCELLED; 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOUSBPipeStalled: 1758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("transfer error: pipe is stalled"); 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_TRANSFER_STALL; 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOReturnOverrun: 1761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: data overrun"); 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_TRANSFER_OVERFLOW; 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kIOUSBTransactionTimeout: 1764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out"); 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itransfer->flags |= USBI_TRANSFER_TIMED_OUT; 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_TRANSFER_TIMED_OUT; 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result); 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_TRANSFER_ERROR; 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) { 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type; 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type; 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type; 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type; 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!isIsoc && !isBulk && !isControl && !isInterrupt) { 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1787ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("handling %s completion with kernel status %d", 1788ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", result); 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kIOReturnSuccess == result || kIOReturnUnderrun == result) { 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isIsoc && tpriv->isoc_framelist) { 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* copy isochronous results back */ 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < transfer->num_iso_packets ; i++) { 1795ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; 1796ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus); 1797ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount; 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!isIsoc) 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itransfer->transferred += io_size; 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */ 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, result)); 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { 1808ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct darwin_msg_async_io_complete message; 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) POLL_NFDS_TYPE i = 0; 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t ret; 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_mutex_lock(&ctx->open_devs_lock); 1813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < nfds && num_ready > 0; i++) { 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct pollfd *pollfd = &fds[i]; 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("checking fd %i with revents = %x", pollfd->fd, pollfd->revents); 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pollfd->revents) 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_ready--; 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (pollfd->revents & POLLERR) { 1825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* this probably will never happen so ignore the error an move on. */ 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1827ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1829ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* there is only one type of message */ 1830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = read (pollfd->fd, &message, sizeof (message)); 1831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (ret < (ssize_t) sizeof (message)) { 1832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg ("WARNING: short read on async io completion pipe\n"); 1833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch continue; 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1836ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch darwin_handle_callback (message.itransfer, message.result, message.size); 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_mutex_unlock(&ctx->open_devs_lock); 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int darwin_clock_gettime(int clk_id, struct timespec *tp) { 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mach_timespec_t sys_time; 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clock_serv_t clock_ref; 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (clk_id) { 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case USBI_CLOCK_REALTIME: 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* CLOCK_REALTIME represents time since the epoch */ 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clock_ref = clock_realtime; 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case USBI_CLOCK_MONOTONIC: 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* use system boot time as reference for the monotonic clock */ 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clock_ref = clock_monotonic; 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ERROR_INVALID_PARAM; 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clock_get_time (clock_ref, &sys_time); 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp->tv_sec = sys_time.tv_sec; 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp->tv_nsec = sys_time.tv_nsec; 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const struct usbi_os_backend darwin_backend = { 1870ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .name = "Darwin", 1871ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .caps = 0, 1872ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .init = darwin_init, 1873ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .exit = darwin_exit, 1874ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .get_device_list = NULL, /* not needed */ 1875ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .get_device_descriptor = darwin_get_device_descriptor, 1876ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .get_active_config_descriptor = darwin_get_active_config_descriptor, 1877ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .get_config_descriptor = darwin_get_config_descriptor, 1878ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1879ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .open = darwin_open, 1880ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .close = darwin_close, 1881ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .get_configuration = darwin_get_configuration, 1882ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .set_configuration = darwin_set_configuration, 1883ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .claim_interface = darwin_claim_interface, 1884ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .release_interface = darwin_release_interface, 1885ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1886ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .set_interface_altsetting = darwin_set_interface_altsetting, 1887ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .clear_halt = darwin_clear_halt, 1888ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .reset_device = darwin_reset_device, 1889ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1890ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .kernel_driver_active = darwin_kernel_driver_active, 1891ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .detach_kernel_driver = darwin_detach_kernel_driver, 1892ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .attach_kernel_driver = darwin_attach_kernel_driver, 1893ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1894ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .destroy_device = darwin_destroy_device, 1895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1896ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .submit_transfer = darwin_submit_transfer, 1897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .cancel_transfer = darwin_cancel_transfer, 1898ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .clear_transfer_priv = darwin_clear_transfer_priv, 1899ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1900ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .handle_events = op_handle_events, 1901ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1902ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .clock_gettime = darwin_clock_gettime, 1903ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1904ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .device_priv_size = sizeof(struct darwin_device_priv), 1905ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .device_handle_priv_size = sizeof(struct darwin_device_handle_priv), 1906ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .transfer_priv_size = sizeof(struct darwin_transfer_priv), 1907ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .add_iso_packet_size = 0, 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1909