Imported Upstream version 3.0
[debian/gnuradio] / usrp / host / lib / fusb_darwin.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 2, 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 #ifndef _FUSB_DARWIN_H_
24 #define _FUSB_DARWIN_H_
25
26 #include <usb.h>
27 #include "fusb.h"
28 #include <IOKit/IOCFBundle.h>
29 #include <IOKit/IOCFPlugIn.h>
30 #include <IOKit/usb/IOUSBLib.h>
31 #include <IOKit/IOKitLib.h>
32 #include "circular_linked_list.h"
33 #include "circular_buffer.h"
34
35 // for MacOS X 10.4.[0-3]
36 #define usb_interface_t IOUSBInterfaceInterface220
37 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
38 #define InterfaceVersion 220
39
40 // for MacOS X 10.3.[0-9] and 10.4.[0-3]
41 #define usb_device_t    IOUSBDeviceInterface197
42 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197
43 #define DeviceVersion 197
44
45 extern "C" {
46 typedef struct usb_dev_handle {
47   int fd;
48
49   struct usb_bus *bus;
50   struct usb_device *device;
51
52   int config;
53   int interface;
54   int altsetting;
55
56   /* Added by RMT so implementations can store other per-open-device data */
57   void *impl_info;
58 } usb_dev_handle;
59
60 /* Darwin/OS X impl does not use fd field, instead it uses this */
61 typedef struct darwin_dev_handle {
62   usb_device_t** device;
63   usb_interface_t** interface;
64   int open;
65 } darwin_dev_handle;
66
67 typedef IOReturn io_return_t;
68 typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
69
70 static int ep_to_pipeRef (darwin_dev_handle* device, int ep);
71 extern int usb_debug;
72 }
73
74 class s_buffer
75 {
76 private:
77   char* d_buffer;
78   UInt32 d_n_used, d_n_alloc;
79
80 public:
81   inline s_buffer (UInt32 n_alloc = 0) {
82     d_n_used = 0;
83     d_n_alloc = n_alloc;
84     if (n_alloc) {
85       d_buffer = (char*) new char [n_alloc];
86     } else {
87       d_buffer = 0;
88     }
89   };
90   inline ~s_buffer () {
91     if (d_n_alloc) {
92       delete [] d_buffer;
93     }
94   };
95   inline UInt32 n_used () { return (d_n_used); };
96   inline void n_used (UInt32 bufLen) {
97     d_n_used = (bufLen > d_n_alloc) ? d_n_alloc : bufLen; };
98   inline UInt32 n_alloc () { return (d_n_alloc); };
99   void buffer (char* l_buffer, UInt32 bufLen) {
100     if (bufLen > d_n_alloc) {
101       fprintf (stderr, "s_buffer::set: Copying only allocated bytes.\n");
102       bufLen = d_n_alloc;
103     }
104     if (!l_buffer) {
105       fprintf (stderr, "s_buffer::set: NULL buffer.\n");
106       return;
107     }
108     bcopy (l_buffer, d_buffer, bufLen);
109     d_n_used = bufLen;
110   };
111   inline char* buffer () { return (d_buffer); };
112   inline void reset () {
113     bzero (d_buffer, d_n_alloc);
114     d_n_used = 0;
115   };
116 };
117
118 typedef s_buffer* s_buffer_ptr;
119 typedef s_node<s_buffer_ptr>* s_node_ptr;
120 typedef circular_linked_list<s_buffer_ptr>* s_queue_ptr;
121 typedef s_both<s_buffer_ptr>* s_both_ptr;
122
123 /*!
124  * \brief darwin implementation of fusb_devhandle
125  *
126  * This is currently identical to the generic implementation
127  * and is intended as a starting point for whatever magic is
128  * required to make usb fly.
129  */
130 class fusb_devhandle_darwin : public fusb_devhandle
131 {
132 public:
133   // CREATORS
134   fusb_devhandle_darwin (usb_dev_handle* udh);
135   virtual ~fusb_devhandle_darwin ();
136
137   // MANIPULATORS
138   virtual fusb_ephandle* make_ephandle (int endpoint, bool input_p,
139                                         int block_size = 0, int nblocks = 0);
140 };
141
142 /*!
143  * \brief darwin implementation of fusb_ephandle
144  *
145  * This is currently identical to the generic implementation
146  * and is intended as a starting point for whatever magic is
147  * required to make usb fly.
148  */
149 class fusb_ephandle_darwin : public fusb_ephandle
150 {
151 private:
152   fusb_devhandle_darwin* d_devhandle;
153   mld_thread_ptr d_runThread;
154   mld_mutex_ptr d_runThreadRunning;
155
156   CFRunLoopRef d_CFRunLoopRef;
157
158   static void write_completed (void* ret_io_size,
159                                io_return_t result,
160                                void* io_size);
161   static void read_completed (void* ret_io_size,
162                               io_return_t result,
163                               void* io_size);
164   static void run_thread (void* arg);
165   static void read_thread (void* arg);
166
167   void read_issue (s_both_ptr l_both);
168
169 public:
170   // variables, for now
171   UInt8 d_pipeRef, d_transferType;
172   usb_interface_t** d_interfaceRef;
173   usb_interface_t* d_interface;
174   s_queue_ptr d_queue;
175   circular_buffer<char>* d_buffer;
176   UInt32 d_bufLenBytes;
177   mld_mutex_ptr d_readRunning;
178   mld_condition_ptr d_runBlock, d_readBlock;
179
180 // CREATORS
181
182   fusb_ephandle_darwin (fusb_devhandle_darwin *dh, int endpoint, bool input_p,
183                          int block_size = 0, int nblocks = 0);
184   virtual ~fusb_ephandle_darwin ();
185
186 // MANIPULATORS
187
188   virtual bool start ();        //!< begin streaming i/o
189   virtual bool stop ();         //!< stop streaming i/o
190
191   /*!
192    * \returns \p nbytes if write was successfully enqueued, else -1.
193    * Will block if no free buffers available.
194    */
195   virtual int write (const void* buffer, int nbytes);
196
197   /*!
198    * \returns number of bytes read or -1 if error.
199    * number of bytes read will be <= nbytes.
200    * Will block if no input available.
201    */
202   virtual int read (void* buffer, int nbytes);
203
204   /*
205    * abort any pending IO transfers
206    */
207   void abort ();
208
209   /*
210    * block until all outstanding writes have completed
211    */
212   virtual void wait_for_completion ();
213 };
214
215 #endif /* _FUSB_DARWIN_H_ */