1/*
2 * Darwin/MacOS X Support
3 *
4 * (c) 2002-2005 Nathan Hjelm <hjelmn@users.sourceforge.net>
5 *
6 * (04/17/2005):
7 *   - Lots of minor fixes.
8 *   - Endpoint table now made by claim_interface to fix a bug.
9 *   - Merged Read/Write to make modifications easier.
10 * (03/25/2005):
11 *   - Fixed a bug when using asynchronous callbacks within a multi-threaded application.
12 * (03/14/2005):
13 *   - Added an endpoint table to speed up bulk transfers.
14 * 0.1.11 (02/22/2005):
15 *   - Updated error checking in read/write routines to check completion codes.
16 *   - Updated set_configuration so that the open interface is reclaimed before completion.
17 *   - Fixed several typos.
18 * 0.1.8 (01/12/2004):
19 *   - Fixed several memory leaks.
20 *   - Readded 10.0 support
21 *   - Added support for USB fuctions defined in 10.3 and above
22 * (01/02/2003):
23 *   - Applied a patch by Philip Edelbrock <phil@edgedesign.us> that fixes a bug in usb_control_msg.
24 * (12/16/2003):
25 *   - Even better error printing.
26 *   - Devices that cannot be opened can have their interfaces opened.
27 * 0.1.6 (05/12/2002):
28 *   - Fixed problem where libusb holds resources after program completion.
29 *   - Mouse should no longer freeze up now.
30 * 0.1.2 (02/13/2002):
31 *   - Bulk functions should work properly now.
32 * 0.1.1 (02/11/2002):
33 *   - Fixed major bug (device and interface need to be released after use)
34 * 0.1.0 (01/06/2002):
35 *   - Tested driver with gphoto (works great as long as Image Capture isn't running)
36 * 0.1d  (01/04/2002):
37 *   - Implimented clear_halt and resetep
38 *   - Uploaded to CVS.
39 * 0.1b  (01/04/2002):
40 *   - Added usb_debug line to bulk read and write function.
41 * 0.1a  (01/03/2002):
42 *   - Driver mostly completed using the macosx driver I wrote for my rioutil software.
43 *
44 * Derived from Linux version by Richard Tobin.
45 * Also partly derived from BSD version.
46 *
47 * This library is covered by the LGPL, read LICENSE for details.
48 */
49
50#ifdef HAVE_CONFIG_H
51#include "config.h"
52#endif
53
54#include <stdlib.h>
55#include <stdio.h>
56#include <unistd.h>
57
58/* standard includes for darwin/os10 (IOKit) */
59#include <mach/mach_port.h>
60#include <IOKit/IOCFBundle.h>
61#include <IOKit/usb/IOUSBLib.h>
62#include <IOKit/IOCFPlugIn.h>
63
64#include "usbi.h"
65
66/* some defines */
67/* IOUSBInterfaceInferface */
68#if defined (kIOUSBInterfaceInterfaceID220)
69
70// #warning "libusb being compiled for 10.4 or later"
71#define usb_interface_t IOUSBInterfaceInterface220
72#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
73#define InterfaceVersion 220
74
75#elif defined (kIOUSBInterfaceInterfaceID197)
76
77// #warning "libusb being compiled for 10.3 or later"
78#define usb_interface_t IOUSBInterfaceInterface197
79#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID197
80#define InterfaceVersion 197
81
82#elif defined (kIOUSBInterfaceInterfaceID190)
83
84// #warning "libusb being compiled for 10.2 or later"
85#define usb_interface_t IOUSBInterfaceInterface190
86#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID190
87#define InterfaceVersion 190
88
89#elif defined (kIOUSBInterfaceInterfaceID182)
90
91// #warning "libusb being compiled for 10.1 or later"
92#define usb_interface_t IOUSBInterfaceInterface182
93#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID182
94#define InterfaceVersion 182
95
96#else
97
98/* No timeout functions available! Time to upgrade your os. */
99#warning "libusb being compiled without support for timeout bulk functions! 10.0 and up"
100#define usb_interface_t IOUSBInterfaceInterface
101#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID
102#define LIBUSB_NO_TIMEOUT_INTERFACE
103#define InterfaceVersion 180
104
105#endif
106
107/* IOUSBDeviceInterface */
108#if defined (kIOUSBDeviceInterfaceID197)
109
110#define usb_device_t    IOUSBDeviceInterface197
111#define DeviceInterfaceID kIOUSBDeviceInterfaceID197
112#define DeviceVersion 197
113
114#elif defined (kIOUSBDeviceInterfaceID187)
115
116#define usb_device_t    IOUSBDeviceInterface187
117#define DeviceInterfaceID kIOUSBDeviceInterfaceID187
118#define DeviceVersion 187
119
120#elif defined (kIOUSBDeviceInterfaceID182)
121
122#define usb_device_t    IOUSBDeviceInterface182
123#define DeviceInterfaceID kIOUSBDeviceInterfaceID182
124#define DeviceVersion 182
125
126#else
127
128#define usb_device_t    IOUSBDeviceInterface
129#define DeviceInterfaceID kIOUSBDeviceInterfaceID
130#define LIBUSB_NO_TIMEOUT_DEVICE
131#define LIBUSB_NO_SEIZE_DEVICE
132#define DeviceVersion 180
133
134#endif
135
136typedef IOReturn io_return_t;
137typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
138typedef SInt32 s_int32_t;
139typedef IOReturn (*rw_async_func_t)(void *self, UInt8 pipeRef, void *buf, UInt32 size,
140				    IOAsyncCallback1 callback, void *refcon);
141typedef IOReturn (*rw_async_to_func_t)(void *self, UInt8 pipeRef, void *buf, UInt32 size,
142				       UInt32 noDataTimeout, UInt32 completionTimeout,
143				       IOAsyncCallback1 callback, void *refcon);
144
145#if !defined(IO_OBJECT_NULL)
146#define IO_OBJECT_NULL ((io_object_t)0)
147#endif
148
149/* Darwin/OS X impl does not use fd field, instead it uses this */
150struct darwin_dev_handle {
151  usb_device_t **device;
152  usb_interface_t **interface;
153  int open;
154
155  /* stored translation table for pipes to endpoints */
156  int num_endpoints;
157  unsigned char *endpoint_addrs;
158};
159
160static CFMutableDictionaryRef matchingDict;
161static IONotificationPortRef gNotifyPort;
162static mach_port_t masterPort = MACH_PORT_NULL;
163
164static void darwin_cleanup (void)
165{
166  IONotificationPortDestroy(gNotifyPort);
167  mach_port_deallocate(mach_task_self(), masterPort);
168}
169
170static char *darwin_error_str (int result) {
171  switch (result) {
172  case kIOReturnSuccess:
173    return "no error";
174  case kIOReturnNotOpen:
175    return "device not opened for exclusive access";
176  case kIOReturnNoDevice:
177    return "no connection to an IOService";
178  case kIOUSBNoAsyncPortErr:
179    return "no async port has been opened for interface";
180  case kIOReturnExclusiveAccess:
181    return "another process has device opened for exclusive access";
182  case kIOUSBPipeStalled:
183    return "pipe is stalled";
184  case kIOReturnError:
185    return "could not establish a connection to the Darwin kernel";
186  case kIOUSBTransactionTimeout:
187    return "transaction timed out";
188  case kIOReturnBadArgument:
189    return "invalid argument";
190  case kIOReturnAborted:
191    return "transaction aborted";
192  default:
193    return "unknown error";
194  }
195}
196
197/* not a valid errorno outside darwin.c */
198#define LUSBDARWINSTALL (ELAST+1)
199
200static int darwin_to_errno (int result) {
201  switch (result) {
202  case kIOReturnSuccess:
203    return 0;
204  case kIOReturnNotOpen:
205    return EBADF;
206  case kIOReturnNoDevice:
207  case kIOUSBNoAsyncPortErr:
208    return ENXIO;
209  case kIOReturnExclusiveAccess:
210    return EBUSY;
211  case kIOUSBPipeStalled:
212    return LUSBDARWINSTALL;
213  case kIOReturnBadArgument:
214    return EINVAL;
215  case kIOUSBTransactionTimeout:
216    return ETIMEDOUT;
217  case kIOReturnError:
218  default:
219    return 1;
220  }
221}
222
223static int usb_setup_iterator (io_iterator_t *deviceIterator)
224{
225  int result;
226
227  /* set up the matching dictionary for class IOUSBDevice and its subclasses.
228     It will be consumed by the IOServiceGetMatchingServices call */
229  if ((matchingDict = IOServiceMatching(kIOUSBDeviceClassName)) == NULL) {
230    darwin_cleanup ();
231
232    USB_ERROR_STR(-1, "libusb/darwin.c usb_setup_iterator: Could not create a matching dictionary.\n");
233  }
234
235  result = IOServiceGetMatchingServices(masterPort, matchingDict, deviceIterator);
236  matchingDict = NULL;
237
238  if (result != kIOReturnSuccess)
239    USB_ERROR_STR (-darwin_to_errno (result), "libusb/darwin.c usb_setup_iterator: IOServiceGetMatchingServices: %s\n",
240		   darwin_error_str(result));
241
242  return 0;
243}
244
245static usb_device_t **usb_get_next_device (io_iterator_t deviceIterator, UInt32 *locationp)
246{
247  io_cf_plugin_ref_t *plugInInterface = NULL;
248  usb_device_t **device;
249  io_service_t usbDevice;
250  long result, score;
251
252  if (!IOIteratorIsValid (deviceIterator) || !(usbDevice = IOIteratorNext(deviceIterator)))
253    return NULL;
254
255  result = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID,
256					     kIOCFPlugInInterfaceID, &plugInInterface,
257					     &score);
258
259  result = IOObjectRelease(usbDevice);
260  if (result || !plugInInterface)
261    return NULL;
262
263  (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID),
264				     (LPVOID)&device);
265
266  (*plugInInterface)->Stop(plugInInterface);
267  IODestroyPlugInInterface (plugInInterface);
268  plugInInterface = NULL;
269
270  (*(device))->GetLocationID(device, locationp);
271
272  return device;
273}
274
275int usb_os_open(usb_dev_handle *dev)
276{
277  struct darwin_dev_handle *device;
278
279  io_return_t result;
280  io_iterator_t deviceIterator;
281
282  usb_device_t **darwin_device;
283
284  UInt32 location = *((UInt32 *)dev->device->dev);
285  UInt32 dlocation;
286
287  if (!dev)
288    USB_ERROR(-ENXIO);
289
290  if (masterPort == MACH_PORT_NULL)
291    USB_ERROR(-EINVAL);
292
293  device = calloc(1, sizeof(struct darwin_dev_handle));
294  if (!device)
295    USB_ERROR(-ENOMEM);
296
297  if (usb_debug > 3)
298    fprintf(stderr, "usb_os_open: %04x:%04x\n",
299	    dev->device->descriptor.idVendor,
300	    dev->device->descriptor.idProduct);
301
302  if ((result = usb_setup_iterator (&deviceIterator)) < 0)
303    return result;
304
305  /* This port of libusb uses locations to keep track of devices. */
306  while ((darwin_device = usb_get_next_device (deviceIterator, &dlocation)) != NULL) {
307    if (dlocation == location)
308      break;
309
310    (*darwin_device)->Release(darwin_device);
311  }
312
313  IOObjectRelease(deviceIterator);
314  device->device = darwin_device;
315
316  if (device->device == NULL)
317    USB_ERROR_STR (-ENOENT, "usb_os_open: %s\n", "Device not found!");
318
319#if !defined (LIBUSB_NO_SEIZE_DEVICE)
320  result = (*(device->device))->USBDeviceOpenSeize (device->device);
321#else
322  /* No Seize in OS X 10.0 (Darwin 1.4) */
323  result = (*(device->device))->USBDeviceOpen (device->device);
324#endif
325
326  if (result != kIOReturnSuccess) {
327    switch (result) {
328    case kIOReturnExclusiveAccess:
329      if (usb_debug > 0)
330	fprintf (stderr, "usb_os_open(USBDeviceOpenSeize): %s\n", darwin_error_str(result));
331      break;
332    default:
333      (*(device->device))->Release (device->device);
334      USB_ERROR_STR(-darwin_to_errno (result), "usb_os_open(USBDeviceOpenSeize): %s",
335		    darwin_error_str(result));
336    }
337
338    device->open = 0;
339  } else
340    device->open = 1;
341
342  dev->impl_info = device;
343  dev->interface = -1;
344  dev->altsetting = -1;
345
346  device->num_endpoints  = 0;
347  device->endpoint_addrs = NULL;
348
349  return 0;
350}
351
352int usb_os_close(usb_dev_handle *dev)
353{
354  struct darwin_dev_handle *device;
355  io_return_t result;
356
357  if (!dev)
358    USB_ERROR(-ENXIO);
359
360  if ((device = dev->impl_info) == NULL)
361    USB_ERROR(-ENOENT);
362
363  usb_release_interface(dev, dev->interface);
364
365  if (usb_debug > 3)
366    fprintf(stderr, "usb_os_close: %04x:%04x\n",
367	    dev->device->descriptor.idVendor,
368	    dev->device->descriptor.idProduct);
369
370  if (device->open == 1)
371    result = (*(device->device))->USBDeviceClose(device->device);
372  else
373    result = kIOReturnSuccess;
374
375  /* device may not need to be released, but if it has to... */
376  (*(device->device))->Release(device->device);
377
378  if (result != kIOReturnSuccess)
379    USB_ERROR_STR(-darwin_to_errno(result), "usb_os_close(USBDeviceClose): %s", darwin_error_str(result));
380
381  free (device);
382
383  return 0;
384}
385
386static int get_endpoints (struct darwin_dev_handle *device)
387{
388  io_return_t ret;
389
390  u_int8_t numep, direction, number;
391  u_int8_t dont_care1, dont_care3;
392  u_int16_t dont_care2;
393
394  int i;
395
396  if (device == NULL || device->interface == NULL)
397    return -EINVAL;
398
399  if (usb_debug > 1)
400    fprintf(stderr, "libusb/darwin.c get_endpoints: building table of endpoints.\n");
401
402  /* retrieve the total number of endpoints on this interface */
403  ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
404  if ( ret ) {
405    if ( usb_debug > 1 )
406      fprintf ( stderr, "get_endpoints: interface is %p\n", device->interface );
407
408    USB_ERROR_STR ( -ret, "get_endpoints: can't get number of endpoints for interface" );
409  }
410
411  free (device->endpoint_addrs);
412  device->endpoint_addrs = calloc (sizeof (unsigned char), numep);
413
414  /* iterate through pipe references */
415  for (i = 1 ; i <= numep ; i++) {
416    ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number,
417						    &dont_care1, &dont_care2, &dont_care3);
418
419    if (ret != kIOReturnSuccess) {
420      fprintf (stderr, "get_endpoints: an error occurred getting pipe information on pipe %d\n",
421	       i );
422      USB_ERROR_STR(-darwin_to_errno(ret), "get_endpoints(GetPipeProperties): %s", darwin_error_str(ret));
423    }
424
425    if (usb_debug > 1)
426      fprintf (stderr, "get_endpoints: Pipe %i: DIR: %i number: %i\n", i, direction, number);
427
428    device->endpoint_addrs[i - 1] = ((direction << 7 & USB_ENDPOINT_DIR_MASK) |
429				     (number & USB_ENDPOINT_ADDRESS_MASK));
430  }
431
432  device->num_endpoints = numep;
433
434  if (usb_debug > 1)
435    fprintf(stderr, "libusb/darwin.c get_endpoints: complete.\n");
436
437  return 0;
438}
439
440static int claim_interface (usb_dev_handle *dev, int interface)
441{
442  io_iterator_t interface_iterator;
443  io_service_t  usbInterface = IO_OBJECT_NULL;
444  io_return_t result;
445  io_cf_plugin_ref_t *plugInInterface = NULL;
446
447  IOUSBFindInterfaceRequest request;
448
449  struct darwin_dev_handle *device;
450  long score;
451  int current_interface;
452
453  device = dev->impl_info;
454
455  request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
456  request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
457  request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
458  request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
459
460  result = (*(device->device))->CreateInterfaceIterator(device->device, &request, &interface_iterator);
461  if (result != kIOReturnSuccess)
462    USB_ERROR_STR (-darwin_to_errno(result), "claim_interface(CreateInterfaceIterator): %s",
463		   darwin_error_str(result));
464
465  for ( current_interface=0 ; current_interface <= interface ; current_interface++ ) {
466    usbInterface = IOIteratorNext(interface_iterator);
467    if ( usb_debug > 3 )
468      fprintf ( stderr, "Interface %d of device is 0x%08x\n",
469		current_interface, usbInterface );
470  }
471
472  current_interface--;
473
474  /* the interface iterator is no longer needed, release it */
475  IOObjectRelease(interface_iterator);
476
477  if (!usbInterface) {
478    u_int8_t nConfig;			     /* Index of configuration to use */
479    IOUSBConfigurationDescriptorPtr configDesc; /* to describe which configuration to select */
480    /* Only a composite class device with no vendor-specific driver will
481       be configured. Otherwise, we need to do it ourselves, or there
482       will be no interfaces for the device. */
483
484    if ( usb_debug > 3 )
485      fprintf ( stderr,"claim_interface: No interface found; selecting configuration\n" );
486
487    result = (*(device->device))->GetNumberOfConfigurations ( device->device, &nConfig );
488    if (result != kIOReturnSuccess)
489      USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(GetNumberOfConfigurations): %s",
490		    darwin_error_str(result));
491
492    if (nConfig < 1)
493      USB_ERROR_STR(-ENXIO ,"claim_interface(GetNumberOfConfigurations): no configurations");
494    else if ( nConfig > 1 && usb_debug > 0 )
495      fprintf ( stderr, "claim_interface: device has more than one"
496		" configuration, using the first (warning)\n" );
497
498    if ( usb_debug > 3 )
499      fprintf ( stderr, "claim_interface: device has %d configuration%s\n",
500		(int)nConfig, (nConfig>1?"s":"") );
501
502    /* Always use the first configuration */
503    result = (*(device->device))->GetConfigurationDescriptorPtr ( (device->device), 0, &configDesc );
504    if (result != kIOReturnSuccess) {
505      if (device->open == 1) {
506        (*(device->device))->USBDeviceClose ( (device->device) );
507        (*(device->device))->Release ( (device->device) );
508      }
509
510      USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(GetConfigurationDescriptorPtr): %s",
511		    darwin_error_str(result));
512    } else if ( usb_debug > 3 )
513      fprintf ( stderr, "claim_interface: configuration value is %d\n",
514		configDesc->bConfigurationValue );
515
516    if (device->open == 1) {
517      result = (*(device->device))->SetConfiguration ( (device->device), configDesc->bConfigurationValue );
518
519      if (result != kIOReturnSuccess) {
520	(*(device->device))->USBDeviceClose ( (device->device) );
521	(*(device->device))->Release ( (device->device) );
522
523	USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(SetConfiguration): %s",
524		      darwin_error_str(result));
525      }
526
527      dev->config = configDesc->bConfigurationValue;
528    }
529
530    request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
531    request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
532    request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
533    request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
534
535    /* Now go back and get the chosen interface */
536    result = (*(device->device))->CreateInterfaceIterator(device->device, &request, &interface_iterator);
537    if (result != kIOReturnSuccess)
538      USB_ERROR_STR (-darwin_to_errno(result), "claim_interface(CreateInterfaceIterator): %s",
539		     darwin_error_str(result));
540
541    for (current_interface = 0 ; current_interface <= interface ; current_interface++) {
542      usbInterface = IOIteratorNext(interface_iterator);
543
544      if ( usb_debug > 3 )
545	fprintf ( stderr, "claim_interface: Interface %d of device is 0x%08x\n",
546		  current_interface, usbInterface );
547    }
548    current_interface--;
549
550    /* the interface iterator is no longer needed, release it */
551    IOObjectRelease(interface_iterator);
552
553    if (!usbInterface)
554      USB_ERROR_STR (-ENOENT, "claim_interface: interface iterator returned NULL");
555  }
556
557  result = IOCreatePlugInInterfaceForService(usbInterface,
558					     kIOUSBInterfaceUserClientTypeID,
559					     kIOCFPlugInInterfaceID,
560					     &plugInInterface, &score);
561  /* No longer need the usbInterface object after getting the plug-in */
562  result = IOObjectRelease(usbInterface);
563  if (result || !plugInInterface)
564    USB_ERROR(-ENOENT);
565
566  /* Now create the device interface for the interface */
567  result = (*plugInInterface)->QueryInterface(plugInInterface,
568					      CFUUIDGetUUIDBytes(InterfaceInterfaceID),
569					      (LPVOID) &device->interface);
570
571  /* No longer need the intermediate plug-in */
572  (*plugInInterface)->Stop(plugInInterface);
573  IODestroyPlugInInterface (plugInInterface);
574
575  if (result != kIOReturnSuccess)
576    USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(QueryInterface): %s",
577		  darwin_error_str(result));
578
579  if (!device->interface)
580    USB_ERROR(-EACCES);
581
582  if ( usb_debug > 3 )
583    fprintf ( stderr, "claim_interface: Interface %d of device from QueryInterface is %p\n",
584	      current_interface, device->interface);
585
586  /* claim the interface */
587  result = (*(device->interface))->USBInterfaceOpen(device->interface);
588  if (result)
589    USB_ERROR_STR(-darwin_to_errno(result), "claim_interface(USBInterfaceOpen): %s",
590		  darwin_error_str(result));
591
592  result = get_endpoints (device);
593
594  if (result) {
595    /* this should not happen */
596    usb_release_interface (dev, interface);
597    USB_ERROR_STR ( result, "claim_interface: could not build endpoint table");
598  }
599
600  return 0;
601}
602
603int usb_set_configuration (usb_dev_handle *dev, int configuration)
604{
605  struct darwin_dev_handle *device;
606  io_return_t result;
607  int interface;
608
609  if ( usb_debug > 3 )
610    fprintf ( stderr, "usb_set_configuration: called for config %x\n", configuration );
611
612  if (!dev)
613    USB_ERROR_STR ( -ENXIO, "usb_set_configuration: called with null device\n" );
614
615  if ((device = dev->impl_info) == NULL)
616    USB_ERROR_STR ( -ENOENT, "usb_set_configuration: device not properly initialized" );
617
618  /* Setting configuration will invalidate the interface, so we need
619     to reclaim it. First, dispose of existing interface, if any. */
620  interface = dev->interface;
621
622  if ( device->interface )
623    usb_release_interface(dev, dev->interface);
624
625  result = (*(device->device))->SetConfiguration(device->device, configuration);
626
627  if (result)
628    USB_ERROR_STR(-darwin_to_errno(result), "usb_set_configuration(SetConfiguration): %s",
629		  darwin_error_str(result));
630
631  /* Reclaim interface */
632  if (interface != -1)
633    result = usb_claim_interface (dev, interface);
634
635  dev->config = configuration;
636
637  return result;
638}
639
640int usb_claim_interface(usb_dev_handle *dev, int interface)
641{
642  struct darwin_dev_handle *device = dev->impl_info;
643
644  io_return_t result;
645
646  if ( usb_debug > 3 )
647    fprintf ( stderr, "usb_claim_interface: called for interface %d\n", interface );
648
649  if (!device)
650    USB_ERROR_STR ( -ENOENT, "usb_claim_interface: device is NULL" );
651
652  if (!(device->device))
653    USB_ERROR_STR ( -EINVAL, "usb_claim_interface: device->device is NULL" );
654
655  /* If we have already claimed an interface, release it */
656  if ( device->interface )
657    usb_release_interface(dev, dev->interface);
658
659  result = claim_interface ( dev, interface );
660  if ( result )
661    USB_ERROR_STR ( result, "usb_claim_interface: couldn't claim interface" );
662
663  dev->interface = interface;
664
665  /* interface is claimed and async IO is set up: return 0 */
666  return 0;
667}
668
669int usb_release_interface(usb_dev_handle *dev, int interface)
670{
671  struct darwin_dev_handle *device;
672  io_return_t result;
673
674  if (!dev)
675    USB_ERROR(-ENXIO);
676
677  if ((device = dev->impl_info) == NULL)
678    USB_ERROR(-ENOENT);
679
680  /* interface is not open */
681  if (!device->interface)
682    return 0;
683
684  result = (*(device->interface))->USBInterfaceClose(device->interface);
685
686  if (result != kIOReturnSuccess)
687    USB_ERROR_STR(-darwin_to_errno(result), "usb_release_interface(USBInterfaceClose): %s",
688		  darwin_error_str(result));
689
690  result = (*(device->interface))->Release(device->interface);
691
692  if (result != kIOReturnSuccess)
693    USB_ERROR_STR(-darwin_to_errno(result), "usb_release_interface(Release): %s",
694		  darwin_error_str(result));
695
696  device->interface = NULL;
697
698  free (device->endpoint_addrs);
699
700  device->num_endpoints  = 0;
701  device->endpoint_addrs = NULL;
702
703  dev->interface = -1;
704  dev->altsetting = -1;
705
706  return 0;
707}
708
709int usb_set_altinterface(usb_dev_handle *dev, int alternate)
710{
711  struct darwin_dev_handle *device;
712  io_return_t result;
713
714  if (!dev)
715    USB_ERROR(-ENXIO);
716
717  if ((device = dev->impl_info) == NULL)
718    USB_ERROR(-ENOENT);
719
720  /* interface is not open */
721  if (!device->interface)
722    USB_ERROR_STR(-EACCES, "usb_set_altinterface: interface used without being claimed");
723
724  result = (*(device->interface))->SetAlternateInterface(device->interface, alternate);
725
726  if (result)
727    USB_ERROR_STR(result, "usb_set_altinterface: could not set alternate interface");
728
729  dev->altsetting = alternate;
730
731  result = get_endpoints (device);
732  if (result) {
733    /* this should not happen */
734    USB_ERROR_STR ( result, "usb_set_altinterface: could not build endpoint table");
735  }
736
737  return 0;
738}
739
740/* simple function that figures out what pipeRef is associated with an endpoint */
741static int ep_to_pipeRef (struct darwin_dev_handle *device, int ep)
742{
743  int i;
744
745  if (usb_debug > 1)
746    fprintf(stderr, "libusb/darwin.c ep_to_pipeRef: Converting ep address to pipeRef.\n");
747
748  for (i = 0 ; i < device->num_endpoints ; i++)
749    if (device->endpoint_addrs[i] == ep)
750      return i + 1;
751
752  /* No pipe found with the correct endpoint address */
753  if (usb_debug > 1)
754    fprintf(stderr, "libusb/darwin.c ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep);
755
756  return -1;
757}
758
759/* argument to handle multiple parameters to rw_completed */
760struct rw_complete_arg {
761  UInt32        io_size;
762  IOReturn      result;
763  CFRunLoopRef  cf_loop;
764};
765
766static void rw_completed(void *refcon, io_return_t result, void *io_size)
767{
768  struct rw_complete_arg *rw_arg = (struct rw_complete_arg *)refcon;
769
770  if (usb_debug > 2)
771    fprintf(stderr, "io async operation completed: %s, size=%lu, result=0x%08x\n", darwin_error_str(result),
772	    (UInt32)io_size, result);
773
774  rw_arg->io_size = (UInt32)io_size;
775  rw_arg->result  = result;
776
777  CFRunLoopStop(rw_arg->cf_loop);
778}
779
780static int usb_bulk_transfer (usb_dev_handle *dev, int ep, char *bytes, int size, int timeout,
781			      rw_async_func_t rw_async, rw_async_to_func_t rw_async_to)
782{
783  struct darwin_dev_handle *device;
784
785  io_return_t result = -1;
786
787  CFRunLoopSourceRef cfSource;
788  int pipeRef;
789
790  struct rw_complete_arg rw_arg;
791
792  u_int8_t  transferType;
793
794  /* None of the values below are used in libusb for bulk transfers */
795  u_int8_t  direction, number, interval;
796  u_int16_t maxPacketSize;
797
798  if (!dev)
799    USB_ERROR_STR ( -ENXIO, "usb_bulk_transfer: Called with NULL device" );
800
801  if ((device = dev->impl_info) == NULL)
802    USB_ERROR_STR ( -ENOENT, "usb_bulk_transfer: Device not open" );
803
804  /* interface is not open */
805  if (!device->interface)
806    USB_ERROR_STR(-EACCES, "usb_bulk_transfer: Interface used before it was opened");
807
808
809  /* Set up transfer */
810  if ((pipeRef = ep_to_pipeRef(device, ep)) < 0)
811    USB_ERROR_STR ( -EINVAL, "usb_bulk_transfer: Invalid pipe reference" );
812
813  (*(device->interface))->GetPipeProperties (device->interface, pipeRef, &direction, &number,
814					     &transferType, &maxPacketSize, &interval);
815
816  (*(device->interface))->CreateInterfaceAsyncEventSource(device->interface, &cfSource);
817  CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
818
819  bzero((void *)&rw_arg, sizeof(struct rw_complete_arg));
820  rw_arg.cf_loop = CFRunLoopGetCurrent();
821  /* Transfer set up complete */
822
823  if (usb_debug > 0)
824    fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: Transfering %i bytes of data on endpoint 0x%02x\n",
825	     size, ep);
826
827  /* Bulk transfer */
828  if (transferType == kUSBInterrupt && usb_debug > 3)
829    fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: USB pipe is an interrupt pipe. Timeouts will not be used.\n");
830
831  if ( transferType != kUSBInterrupt && rw_async_to != NULL)
832
833    result = rw_async_to (device->interface, pipeRef, bytes, size, timeout, timeout,
834			  (IOAsyncCallback1)rw_completed, (void *)&rw_arg);
835  else
836    result = rw_async (device->interface, pipeRef, bytes, size, (IOAsyncCallback1)rw_completed,
837		       (void *)&rw_arg);
838
839  if (result == kIOReturnSuccess) {
840    /* wait for write to complete */
841    if (CFRunLoopRunInMode(kCFRunLoopDefaultMode, (timeout+999)/1000, true) == kCFRunLoopRunTimedOut) {
842      (*(device->interface))->AbortPipe(device->interface, pipeRef);
843      CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); /* Pick up aborted callback */
844      if (usb_debug)
845	fprintf(stderr, "usb_bulk_read: input timed out\n");
846    }
847  }
848
849  CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
850
851  /* Check the return code of both the write and completion functions. */
852  if (result != kIOReturnSuccess || (rw_arg.result != kIOReturnSuccess &&
853      rw_arg.result != kIOReturnAborted) ) {
854    int error_code;
855    char *error_str;
856
857    if (result == kIOReturnSuccess) {
858      error_code = darwin_to_errno (rw_arg.result);
859      error_str  = darwin_error_str (rw_arg.result);
860    } else {
861      error_code = darwin_to_errno(result);
862      error_str  = darwin_error_str (result);
863    }
864
865    if (transferType != kUSBInterrupt && rw_async_to != NULL)
866      USB_ERROR_STR(-error_code, "usb_bulk_transfer (w/ Timeout): %s", error_str);
867    else
868      USB_ERROR_STR(-error_code, "usb_bulk_transfer (No Timeout): %s", error_str);
869  }
870
871  return rw_arg.io_size;
872}
873
874int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
875{
876  int result;
877  rw_async_to_func_t to_func = NULL;
878  struct darwin_dev_handle *device;
879
880  if (dev == NULL || dev->impl_info == NULL)
881    return -EINVAL;
882
883  device = dev->impl_info;
884
885#if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
886  to_func = (*(device->interface))->WritePipeAsyncTO;
887#endif
888
889  if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout,
890				   (*(device->interface))->WritePipeAsync, to_func)) < 0)
891    USB_ERROR_STR (result, "usb_bulk_write: An error occured during write (see messages above)");
892
893  return result;
894}
895
896int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
897{
898  int result;
899  rw_async_to_func_t to_func = NULL;
900  struct darwin_dev_handle *device;
901
902  if (dev == NULL || dev->impl_info == NULL)
903    return -EINVAL;
904
905  ep |= 0x80;
906
907  device = dev->impl_info;
908
909#if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
910  to_func = (*(device->interface))->ReadPipeAsyncTO;
911#endif
912
913  if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout,
914				   (*(device->interface))->ReadPipeAsync, to_func)) < 0)
915    USB_ERROR_STR (result, "usb_bulk_read: An error occured during read (see messages above)");
916
917  return result;
918}
919
920/* interrupt endpoints seem to be treated just like any other endpoint under OSX/Darwin */
921int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
922	int timeout)
923{
924  return usb_bulk_write (dev, ep, bytes, size, timeout);
925}
926
927int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
928	int timeout)
929{
930  return usb_bulk_read (dev, ep, bytes, size, timeout);
931}
932
933int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
934		    int value, int index, char *bytes, int size, int timeout)
935{
936  struct darwin_dev_handle *device = dev->impl_info;
937
938  io_return_t result;
939
940#if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
941  IOUSBDevRequestTO urequest;
942#else
943  IOUSBDevRequest urequest;
944#endif
945
946  if (usb_debug >= 3)
947    fprintf(stderr, "usb_control_msg: %d %d %d %d %p %d %d\n",
948            requesttype, request, value, index, bytes, size, timeout);
949
950  bzero(&urequest, sizeof(urequest));
951
952  urequest.bmRequestType = requesttype;
953  urequest.bRequest = request;
954  urequest.wValue = value;
955  urequest.wIndex = index;
956  urequest.wLength = size;
957  urequest.pData = bytes;
958#if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
959  urequest.completionTimeout = timeout;
960  urequest.noDataTimeout = timeout;
961
962  result = (*(device->device))->DeviceRequestTO(device->device, &urequest);
963#else
964  result = (*(device->device))->DeviceRequest(device->device, &urequest);
965#endif
966  if (result != kIOReturnSuccess)
967    USB_ERROR_STR(-darwin_to_errno(result), "usb_control_msg(DeviceRequestTO): %s", darwin_error_str(result));
968
969  /* Bytes transfered is stored in the wLenDone field*/
970  return urequest.wLenDone;
971}
972
973int usb_os_find_busses(struct usb_bus **busses)
974{
975  struct usb_bus *fbus = NULL;
976
977  io_iterator_t deviceIterator;
978  io_return_t result;
979
980  usb_device_t **device;
981
982  UInt32 location;
983
984  char buf[20];
985  int i = 1;
986
987  /* Create a master port for communication with IOKit (this should
988     have been created if the user called usb_init() )*/
989  if (masterPort == MACH_PORT_NULL) {
990    usb_init ();
991
992    if (masterPort == MACH_PORT_NULL)
993      USB_ERROR(-ENOENT);
994  }
995
996  if ((result = usb_setup_iterator (&deviceIterator)) < 0)
997    return result;
998
999  while ((device = usb_get_next_device (deviceIterator, &location)) != NULL) {
1000    struct usb_bus *bus;
1001
1002    if (location & 0x00ffffff)
1003      continue;
1004
1005    bus = calloc(1, sizeof(struct usb_bus));
1006    if (bus == NULL)
1007      USB_ERROR(-ENOMEM);
1008
1009    sprintf(buf, "%03i", i++);
1010    bus->location = location;
1011
1012    strncpy(bus->dirname, buf, sizeof(bus->dirname) - 1);
1013    bus->dirname[sizeof(bus->dirname) - 1] = 0;
1014
1015    LIST_ADD(fbus, bus);
1016
1017    if (usb_debug >= 2)
1018      fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
1019
1020    (*(device))->Release(device);
1021  }
1022
1023  IOObjectRelease(deviceIterator);
1024
1025  *busses = fbus;
1026
1027  return 0;
1028}
1029
1030int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
1031{
1032  struct usb_device *fdev = NULL;
1033
1034  io_iterator_t deviceIterator;
1035  io_return_t result;
1036
1037  usb_device_t **device;
1038
1039  u_int16_t address;
1040  UInt32 location;
1041  UInt32 bus_loc = bus->location;
1042
1043  /* for use in retrieving device description */
1044  IOUSBDevRequest req;
1045
1046  /* a master port should have been created by usb_os_init */
1047  if (masterPort == MACH_PORT_NULL)
1048    USB_ERROR(-ENOENT);
1049
1050  if ((result = usb_setup_iterator (&deviceIterator)) < 0)
1051    return result;
1052
1053  /* Set up request for device descriptor */
1054  req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
1055  req.bRequest = kUSBRqGetDescriptor;
1056  req.wValue = kUSBDeviceDesc << 8;
1057  req.wIndex = 0;
1058  req.wLength = sizeof(IOUSBDeviceDescriptor);
1059
1060
1061  while ((device = usb_get_next_device (deviceIterator, &location)) != NULL) {
1062    unsigned char device_desc[DEVICE_DESC_LENGTH];
1063
1064    result = (*(device))->GetDeviceAddress(device, (USBDeviceAddress *)&address);
1065
1066    if (usb_debug >= 2)
1067      fprintf(stderr, "usb_os_find_devices: Found USB device at location 0x%08lx\n", location);
1068
1069    /* first byte of location appears to be associated with the device's bus */
1070    if (location >> 24 == bus_loc >> 24) {
1071      struct usb_device *dev;
1072
1073      dev = calloc(1, sizeof(struct usb_device));
1074      if (dev == NULL)
1075	USB_ERROR(-ENOMEM);
1076
1077      dev->bus = bus;
1078
1079      req.pData = device_desc;
1080      result = (*(device))->DeviceRequest(device, &req);
1081
1082      usb_parse_descriptor(device_desc, "bbwbbbbwwwbbbb", &dev->descriptor);
1083
1084      sprintf(dev->filename, "%03i-%04x-%04x-%02x-%02x", address,
1085	      dev->descriptor.idVendor, dev->descriptor.idProduct,
1086	      dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass);
1087
1088      dev->dev = (USBDeviceAddress *)malloc(4);
1089      memcpy(dev->dev, &location, 4);
1090
1091      LIST_ADD(fdev, dev);
1092
1093      if (usb_debug >= 2)
1094	fprintf(stderr, "usb_os_find_devices: Found %s on %s at location 0x%08lx\n",
1095		dev->filename, bus->dirname, location);
1096    }
1097
1098    /* release the device now */
1099    (*(device))->Release(device);
1100  }
1101
1102  IOObjectRelease(deviceIterator);
1103
1104  *devices = fdev;
1105
1106  return 0;
1107}
1108
1109int usb_os_determine_children(struct usb_bus *bus)
1110{
1111  /* Nothing yet */
1112  return 0;
1113}
1114
1115void usb_os_init(void)
1116{
1117  if (masterPort == MACH_PORT_NULL) {
1118    IOMasterPort(masterPort, &masterPort);
1119
1120    gNotifyPort = IONotificationPortCreate(masterPort);
1121  }
1122}
1123
1124void usb_os_cleanup (void)
1125{
1126  if (masterPort != MACH_PORT_NULL)
1127    darwin_cleanup ();
1128}
1129
1130int usb_resetep(usb_dev_handle *dev, unsigned int ep)
1131{
1132  struct darwin_dev_handle *device;
1133
1134  io_return_t result = -1;
1135
1136  int pipeRef;
1137
1138  if (!dev)
1139    USB_ERROR(-ENXIO);
1140
1141  if ((device = dev->impl_info) == NULL)
1142    USB_ERROR(-ENOENT);
1143
1144  /* interface is not open */
1145  if (!device->interface)
1146    USB_ERROR_STR(-EACCES, "usb_resetep: interface used without being claimed");
1147
1148  if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
1149    USB_ERROR(-EINVAL);
1150
1151  result = (*(device->interface))->ResetPipe(device->interface, pipeRef);
1152
1153  if (result != kIOReturnSuccess)
1154    USB_ERROR_STR(-darwin_to_errno(result), "usb_resetep(ResetPipe): %s", darwin_error_str(result));
1155
1156  return 0;
1157}
1158
1159int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
1160{
1161  struct darwin_dev_handle *device;
1162
1163  io_return_t result = -1;
1164
1165  int pipeRef;
1166
1167  if (!dev)
1168    USB_ERROR(-ENXIO);
1169
1170  if ((device = dev->impl_info) == NULL)
1171    USB_ERROR(-ENOENT);
1172
1173  /* interface is not open */
1174  if (!device->interface)
1175    USB_ERROR_STR(-EACCES, "usb_clear_halt: interface used without being claimed");
1176
1177  if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
1178    USB_ERROR(-EINVAL);
1179
1180  result = (*(device->interface))->ClearPipeStall(device->interface, pipeRef);
1181
1182  if (result != kIOReturnSuccess)
1183    USB_ERROR_STR(-darwin_to_errno(result), "usb_clear_halt(ClearPipeStall): %s", darwin_error_str(result));
1184
1185  return 0;
1186}
1187
1188int usb_reset(usb_dev_handle *dev)
1189{
1190  struct darwin_dev_handle *device;
1191
1192  io_return_t result;
1193
1194  if (!dev)
1195    USB_ERROR(-ENXIO);
1196
1197  if ((device = dev->impl_info) == NULL)
1198    USB_ERROR(-ENOENT);
1199
1200  if (!device->device)
1201    USB_ERROR_STR(-ENOENT, "usb_reset: no such device");
1202
1203  result = (*(device->device))->ResetDevice(device->device);
1204
1205  if (result != kIOReturnSuccess)
1206    USB_ERROR_STR(-darwin_to_errno(result), "usb_reset(ResetDevice): %s", darwin_error_str(result));
1207
1208  return 0;
1209}
1210