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