Imported Upstream version 3.2.2
[debian/gnuradio] / usrp / host / lib / legacy / darwin_libusb.h
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 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 static char *
46 darwin_error_str (int result)
47 {
48   switch (result) {
49   case kIOReturnSuccess:
50     return "no error";
51   case kIOReturnNotOpen:
52     return "device not opened for exclusive access";
53   case kIOReturnNoDevice:
54     return "no connection to an IOService";
55   case kIOUSBNoAsyncPortErr:
56     return "no asyc port has been opened for interface";
57   case kIOReturnExclusiveAccess:
58     return "another process has device opened for exclusive access";
59   case kIOUSBPipeStalled:
60     return "pipe is stalled";
61   case kIOReturnError:
62     return "could not establish a connection to Darin kernel";
63   case kIOReturnBadArgument:
64     return "invalid argument";
65   default:
66     return "unknown error";
67   }
68 }
69
70 /* not a valid errorno outside darwin.c */
71 #define LUSBDARWINSTALL (ELAST+1)
72
73 static int
74 darwin_to_errno (int result)
75 {
76   switch (result) {
77   case kIOReturnSuccess:
78     return 0;
79   case kIOReturnNotOpen:
80     return EBADF;
81   case kIOReturnNoDevice:
82   case kIOUSBNoAsyncPortErr:
83     return ENXIO;
84   case kIOReturnExclusiveAccess:
85     return EBUSY;
86   case kIOUSBPipeStalled:
87     return LUSBDARWINSTALL;
88   case kIOReturnBadArgument:
89     return EINVAL;
90   case kIOReturnError:
91   default:
92     return 1;
93   }
94 }
95
96 typedef enum {
97   USB_ERROR_TYPE_NONE = 0,
98   USB_ERROR_TYPE_STRING,
99   USB_ERROR_TYPE_ERRNO,
100 } usb_error_type_t;
101
102 extern char usb_error_str[1024];
103 extern int usb_error_errno;
104 extern usb_error_type_t usb_error_type;
105
106 #define USB_ERROR(r, x)                         \
107         do { \
108           usb_error_type = USB_ERROR_TYPE_ERRNO; \
109           usb_error_errno = x; \
110           return r; \
111         } while (0)
112
113 #define USB_ERROR_STR(r, x, format, args...)    \
114         do { \
115           usb_error_type = USB_ERROR_TYPE_STRING; \
116           snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
117           if (usb_debug) \
118             fprintf(stderr, "USB error: %s\n", usb_error_str);  \
119           return r; \
120         } while (0)
121
122 #define USB_ERROR_STR_ORIG(x, format, args...)  \
123         do { \
124           usb_error_type = USB_ERROR_TYPE_STRING; \
125           snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
126           if (usb_debug) \
127             fprintf(stderr, "USB error: %s\n", usb_error_str);  \
128           return x; \
129         } while (0)
130
131 #define USB_ERROR_STR_NO_RET(x, format, args...)        \
132         do { \
133           usb_error_type = USB_ERROR_TYPE_STRING; \
134           snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
135           if (usb_debug) \
136             fprintf(stderr, "USB error: %s\n", usb_error_str);  \
137         } while (0)
138
139 /* simple function that figures out what pipeRef is associated with an endpoint */
140 static int ep_to_pipeRef (darwin_dev_handle *device, int ep)
141 {
142   io_return_t ret;
143   UInt8 numep, direction, number;
144   UInt8 dont_care1, dont_care3;
145   UInt16 dont_care2;
146   int i;
147
148   if (usb_debug > 3)
149     fprintf(stderr, "Converting ep address to pipeRef.\n");
150
151   /* retrieve the total number of endpoints on this interface */
152   ret = (*(device->interface))->GetNumEndpoints(device->interface, &numep);
153   if ( ret ) {
154     if ( usb_debug > 3 )
155       fprintf ( stderr, "ep_to_pipeRef: interface is %p\n", device->interface );
156     USB_ERROR_STR_ORIG ( -ret, "ep_to_pipeRef: can't get number of endpoints for interface" );
157   }
158
159   /* iterate through the pipeRefs until we find the correct one */
160   for (i = 1 ; i <= numep ; i++) {
161     ret = (*(device->interface))->GetPipeProperties(device->interface, i, &direction, &number,
162                                                     &dont_care1, &dont_care2, &dont_care3);
163
164     if (ret != kIOReturnSuccess) {
165       fprintf (stderr, "ep_to_pipeRef: an error occurred getting pipe information on pipe %d\n",
166                i );
167       USB_ERROR_STR_ORIG (-darwin_to_errno(ret), "ep_to_pipeRef(GetPipeProperties): %s", darwin_error_str(ret));
168     }
169
170     if (usb_debug > 3)
171       fprintf (stderr, "ep_to_pipeRef: Pipe %i: DIR: %i number: %i\n", i, direction, number);
172
173     /* calculate the endpoint of the pipe and check it versus the requested endpoint */
174     if ( ((direction << 7 & USB_ENDPOINT_DIR_MASK) | (number & USB_ENDPOINT_ADDRESS_MASK)) == ep ) {
175       if (usb_debug > 3)
176         fprintf(stderr, "ep_to_pipeRef: pipeRef for ep address 0x%02x found: 0x%02x\n", ep, i);
177
178       return i;
179     }
180   }
181
182   if (usb_debug > 3)
183     fprintf(stderr, "ep_to_pipeRef: No pipeRef found with endpoint address 0x%02x.\n", ep);
184   
185   /* none of the found pipes match the requested endpoint */
186   return -1;
187 }
188
189 }
190 #endif /* __DARWIN_LIBUSB_H__ */