switch source package format to 3.0 quilt
[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,                \
130               format, ## args);                                         \
131     if (usb_debug) {                                                    \
132       std::cerr << "USB error: " << usb_error_str << std::cerr;         \
133     }                                                                   \
134     return (r);                                                         \
135   } while (0)
136
137 #define USB_ERROR_STR_ORIG(x, format, args...)                          \
138   do {                                                                  \
139     usb_error_type = USB_ERROR_TYPE_STRING;                             \
140     snprintf (usb_error_str, sizeof (usb_error_str) - 1,                \
141               format, ## args);                                         \
142     if (usb_debug) {                                                    \
143       std::cerr << "USB error: " << usb_error_str << std::endl;         \
144     }                                                                   \
145     return (x);                                                         \
146   } while (0)
147
148 #define USB_ERROR_STR_NO_RET(x, format, args...)                        \
149   do {                                                                  \
150     usb_error_type = USB_ERROR_TYPE_STRING;                             \
151     snprintf (usb_error_str, sizeof (usb_error_str) - 1,                \
152               format, ## args);                                         \
153     if (usb_debug) {                                                    \
154       std::cerr << "USB error: " << usb_error_str << std::endl;         \
155     }                                                                   \
156   } while (0)
157
158 /*
159  * simple function that figures out what pipeRef
160  * is associated with an endpoint
161  */
162 static int ep_to_pipeRef (darwin_dev_handle *device, int ep)
163 {
164   io_return_t ret;
165   UInt8 numep, direction, number;
166   UInt8 dont_care1, dont_care3;
167   UInt16 dont_care2;
168   int i;
169
170   if (usb_debug > 3) {
171     std::cerr << "Converting ep address to pipeRef." << std::endl;
172   }
173
174   /* retrieve the total number of endpoints on this interface */
175   ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
176   if ( ret ) {
177     if ( usb_debug > 3 ) {
178       std::cerr << "ep_to_pipeRef: interface is "
179                 << device->interface << std::endl;
180     }
181     USB_ERROR_STR_ORIG ( -ret, "ep_to_pipeRef: can't get number of "
182                          "endpoints for interface" );
183   }
184
185   /* iterate through the pipeRefs until we find the correct one */
186   for (i = 1 ; i <= numep ; i++) {
187     ret = (*(device->interface))->GetPipeProperties
188       (device->interface, i, &direction, &number,
189        &dont_care1, &dont_care2, &dont_care3);
190
191     if (ret != kIOReturnSuccess) {
192       std::cerr << "ep_to_pipeRef: an error occurred getting "
193                 << "pipe information on pipe " << i << std::endl;
194
195       USB_ERROR_STR_ORIG (-darwin_to_errno(ret),
196                           "ep_to_pipeRef(GetPipeProperties): %s",
197                           darwin_error_str(ret));
198     }
199
200     if (usb_debug > 3) {
201       std::cerr << "ep_to_pipeRef: Pipe " << i << ": DIR: "
202                 << direction << " number: " << number << std::endl;
203     }
204
205     /* calculate the endpoint of the pipe and check it versus
206        the requested endpoint */
207     if ( ((direction << 7 & USB_ENDPOINT_DIR_MASK) |
208           (number & USB_ENDPOINT_ADDRESS_MASK)) == ep ) {
209       if (usb_debug > 3) {
210         std::cerr << "ep_to_pipeRef: pipeRef for ep address "
211                   << ep << " found: " << i << std::endl;
212       }
213       return (i);
214     }
215   }
216
217   if (usb_debug > 3) {
218     std::cerr << "ep_to_pipeRef: No pipeRef found with endpoint address "
219               << ep << std::endl;
220   }
221
222   /* none of the found pipes match the requested endpoint */
223   return (-1);
224 }
225
226 }
227 #endif /* __DARWIN_LIBUSB_H__ */