OSX 10.6 x86_64 fixes for configure and libusb; Audio is next
[debian/gnuradio] / usrp / host / lib / darwin_libusb.h
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006,2009 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio.
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /*
24  * The following code was taken from LIBUSB verion 0.1.10a,
25  * and makes the fusb_darwin codes do-able in the current GR
26  * programming framework.  Parts and pieces were taken from
27  * usbi.h, darwin.c, and error.h .
28  *
29  * LIBUSB version 0.1.10a is covered by the LGPL, version 2;
30  * These codes are used with permission from:
31  *   (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
32  *   (c) 2002-2005 Nathan Hjelm <hjelmn@users.sourceforge.net>
33  * All rights reserved.
34  */
35
36 #ifndef __DARWIN_LIBUSB_H__
37 #define __DARWIN_LIBUSB_H__
38
39 #include <IOKit/IOCFBundle.h>
40 #include <IOKit/IOCFPlugIn.h>
41 #include <IOKit/usb/IOUSBLib.h>
42 #include <IOKit/IOKitLib.h>
43
44 extern "C" {
45
46 static const char* darwin_error_strings[] = {
47   "no error",
48   "device not opened for exclusive access",
49   "no connection to an IOService",
50   "no asyc port has been opened for interface",
51   "another process has device opened for exclusive access",
52   "pipe is stalled",
53   "could not establish a connection to Darin kernel",
54   "invalid argument",
55   "unknown error"
56 };
57
58 static const char *
59 darwin_error_str (int result)
60 {
61   switch (result) {
62   case kIOReturnSuccess:
63     return (darwin_error_strings[0]);
64   case kIOReturnNotOpen:
65     return (darwin_error_strings[1]);
66   case kIOReturnNoDevice:
67     return (darwin_error_strings[2]);
68   case kIOUSBNoAsyncPortErr:
69     return (darwin_error_strings[3]);
70   case kIOReturnExclusiveAccess:
71     return (darwin_error_strings[4]);
72   case kIOUSBPipeStalled:
73     return (darwin_error_strings[5]);
74   case kIOReturnError:
75     return (darwin_error_strings[6]);
76   case kIOReturnBadArgument:
77     return (darwin_error_strings[7]);
78   default:
79     return (darwin_error_strings[8]);
80   }
81 }
82
83 /* not a valid errorno outside darwin.c */
84 #define LUSBDARWINSTALL (ELAST+1)
85
86 static int
87 darwin_to_errno (int result)
88 {
89   switch (result) {
90   case kIOReturnSuccess:
91     return 0;
92   case kIOReturnNotOpen:
93     return EBADF;
94   case kIOReturnNoDevice:
95   case kIOUSBNoAsyncPortErr:
96     return ENXIO;
97   case kIOReturnExclusiveAccess:
98     return EBUSY;
99   case kIOUSBPipeStalled:
100     return LUSBDARWINSTALL;
101   case kIOReturnBadArgument:
102     return EINVAL;
103   case kIOReturnError:
104   default:
105     return 1;
106   }
107 }
108
109 typedef enum {
110   USB_ERROR_TYPE_NONE = 0,
111   USB_ERROR_TYPE_STRING,
112   USB_ERROR_TYPE_ERRNO,
113 } usb_error_type_t;
114
115 extern char usb_error_str[1024];
116 extern int usb_error_errno;
117 extern usb_error_type_t usb_error_type;
118
119 #define USB_ERROR(r, x)                         \
120         do { \
121           usb_error_type = USB_ERROR_TYPE_ERRNO; \
122           usb_error_errno = x; \
123           return r; \
124         } while (0)
125
126 #define USB_ERROR_STR(r, x, format, args...)    \
127         do { \
128           usb_error_type = USB_ERROR_TYPE_STRING; \
129           snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
130           if (usb_debug) \
131             fprintf(stderr, "USB error: %s\n", usb_error_str);  \
132           return r; \
133         } while (0)
134
135 #define USB_ERROR_STR_ORIG(x, format, args...)  \
136         do { \
137           usb_error_type = USB_ERROR_TYPE_STRING; \
138           snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
139           if (usb_debug) \
140             fprintf(stderr, "USB error: %s\n", usb_error_str);  \
141           return x; \
142         } while (0)
143
144 #define USB_ERROR_STR_NO_RET(x, format, args...)        \
145         do { \
146           usb_error_type = USB_ERROR_TYPE_STRING; \
147           snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
148           if (usb_debug) \
149             fprintf(stderr, "USB error: %s\n", usb_error_str);  \
150         } while (0)
151
152 /* simple function that figures out what pipeRef is associated with an endpoint */
153 static int ep_to_pipeRef (darwin_dev_handle *device, int ep)
154 {
155   io_return_t ret;
156   UInt8 numep, direction, number;
157   UInt8 dont_care1, dont_care3;
158   UInt16 dont_care2;
159   int i;
160
161   if (usb_debug > 3)
162     fprintf(stderr, "Converting ep address to pipeRef.\n");
163
164   /* retrieve the total number of endpoints on this interface */
165   ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
166   if ( ret ) {
167     if ( usb_debug > 3 )
168       fprintf ( stderr, "ep_to_pipeRef: interface is %p\n", device->interface );
169     USB_ERROR_STR_ORIG ( -ret, "ep_to_pipeRef: can't get number of endpoints for interface" );
170   }
171
172   /* iterate through the pipeRefs until we find the correct one */
173   for (i = 1 ; i <= numep ; i++) {
174     ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number,
175                                                     &dont_care1, &dont_care2, &dont_care3);
176
177     if (ret != kIOReturnSuccess) {
178       fprintf (stderr, "ep_to_pipeRef: an error occurred getting pipe information on pipe %d\n",
179                i );
180       USB_ERROR_STR_ORIG (-darwin_to_errno(ret), "ep_to_pipeRef(GetPipeProperties): %s", darwin_error_str(ret));
181     }
182
183     if (usb_debug > 3)
184       fprintf (stderr, "ep_to_pipeRef: Pipe %i: DIR: %i number: %i\n", i, direction, number);
185
186     /* calculate the endpoint of the pipe and check it versus the requested endpoint */
187     if ( ((direction << 7 & USB_ENDPOINT_DIR_MASK) | (number & USB_ENDPOINT_ADDRESS_MASK)) == ep ) {
188       if (usb_debug > 3)
189         fprintf(stderr, "ep_to_pipeRef: pipeRef for ep address 0x%02x found: 0x%02x\n", ep, i);
190
191       return i;
192     }
193   }
194
195   if (usb_debug > 3)
196     fprintf(stderr, "ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep);
197   
198   /* none of the found pipes match the requested endpoint */
199   return -1;
200 }
201
202 }
203 #endif /* __DARWIN_LIBUSB_H__ */