GNU Radio 3.4.0 C++ API
fusb_darwin.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2006,2009,2010 Free Software Foundation, Inc.
00004  * 
00005  * This file is part of GNU Radio.
00006  *
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 3, or (at your option)
00010  * any later version.
00011  * 
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #ifndef _FUSB_DARWIN_H_
00024 #define _FUSB_DARWIN_H_
00025 
00026 #include <usb.h>
00027 #include "fusb.h"
00028 #include <IOKit/IOCFBundle.h>
00029 #include <IOKit/IOCFPlugIn.h>
00030 #include <IOKit/usb/IOUSBLib.h>
00031 #include <IOKit/IOKitLib.h>
00032 #include "circular_linked_list.h"
00033 #include "circular_buffer.h"
00034 
00035 // for MacOS X 10.4.[0-3]
00036 #define usb_interface_t IOUSBInterfaceInterface220
00037 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
00038 #define InterfaceVersion 220
00039 
00040 // for MacOS X 10.3.[0-9] and 10.4.[0-3]
00041 #define usb_device_t    IOUSBDeviceInterface197
00042 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197
00043 #define DeviceVersion 197
00044 
00045 extern "C" {
00046 typedef struct usb_dev_handle {
00047   int fd;
00048 
00049   struct usb_bus *bus;
00050   struct usb_device *device;
00051 
00052   int config;
00053   int interface;
00054   int altsetting;
00055 
00056   /* Added by RMT so implementations can store other per-open-device data */
00057   void *impl_info;
00058 } usb_dev_handle;
00059 
00060 /* Darwin/OS X impl does not use fd field, instead it uses this */
00061 typedef struct darwin_dev_handle {
00062   usb_device_t** device;
00063   usb_interface_t** interface;
00064   int open;
00065 } darwin_dev_handle;
00066 
00067 typedef IOReturn io_return_t;
00068 typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
00069 
00070 static int ep_to_pipeRef (darwin_dev_handle* device, int ep);
00071 extern int usb_debug;
00072 }
00073 
00074 class s_buffer
00075 {
00076 private:
00077   char* d_buffer;
00078   size_t d_n_used, d_n_alloc;
00079 
00080 public:
00081   inline s_buffer (size_t n_alloc = 0) {
00082     d_n_used = 0;
00083     d_n_alloc = n_alloc;
00084     if (n_alloc) {
00085       d_buffer = (char*) new char [n_alloc];
00086     } else {
00087       d_buffer = 0;
00088     }
00089   };
00090   inline ~s_buffer () {
00091     if (d_n_alloc) {
00092       delete [] d_buffer;
00093     }
00094   };
00095   inline size_t n_used () { return (d_n_used); };
00096   inline void n_used (size_t bufLen) {
00097     d_n_used = (bufLen > d_n_alloc) ? d_n_alloc : bufLen; };
00098   inline size_t n_alloc () { return (d_n_alloc); };
00099   void buffer (char* l_buffer, size_t bufLen) {
00100     if (bufLen > d_n_alloc) {
00101       std::cerr << "s_buffer::set: Copying only allocated bytes." << std::endl;
00102       bufLen = d_n_alloc;
00103     }
00104     if (!l_buffer) {
00105       std::cerr << "s_buffer::set: NULL buffer." << std::endl;
00106       return;
00107     }
00108     bcopy (l_buffer, d_buffer, bufLen);
00109     d_n_used = bufLen;
00110   };
00111   inline char* buffer () { return (d_buffer); };
00112   inline void reset () {
00113     bzero (d_buffer, d_n_alloc);
00114     d_n_used = 0;
00115   };
00116 };
00117 
00118 typedef s_buffer* s_buffer_ptr;
00119 typedef s_node<s_buffer_ptr>* s_node_ptr;
00120 typedef circular_linked_list<s_buffer_ptr>* s_queue_ptr;
00121 typedef s_both<s_buffer_ptr>* s_both_ptr;
00122 
00123 /*!
00124  * \brief darwin implementation of fusb_devhandle
00125  *
00126  * This is currently identical to the generic implementation
00127  * and is intended as a starting point for whatever magic is
00128  * required to make usb fly.
00129  */
00130 class fusb_devhandle_darwin : public fusb_devhandle
00131 {
00132 public:
00133   // CREATORS
00134   fusb_devhandle_darwin (usb_dev_handle* udh);
00135   virtual ~fusb_devhandle_darwin ();
00136 
00137   // MANIPULATORS
00138   virtual fusb_ephandle* make_ephandle (int endpoint, bool input_p,
00139                                         int block_size = 0, int nblocks = 0);
00140 };
00141 
00142 /*!
00143  * \brief darwin implementation of fusb_ephandle
00144  *
00145  * This is currently identical to the generic implementation
00146  * and is intended as a starting point for whatever magic is
00147  * required to make usb fly.
00148  */
00149 class fusb_ephandle_darwin : public fusb_ephandle
00150 {
00151 private:
00152   fusb_devhandle_darwin* d_devhandle;
00153   gruel::thread* d_runThread;
00154   gruel::mutex* d_runThreadRunning;
00155 
00156   CFRunLoopRef d_CFRunLoopRef;
00157 
00158   static void write_completed (void* ret_io_size,
00159                                io_return_t result,
00160                                void* io_size);
00161   static void read_completed (void* ret_io_size,
00162                               io_return_t result,
00163                               void* io_size);
00164   static void run_thread (void* arg);
00165   static void read_thread (void* arg);
00166 
00167   void read_issue (s_both_ptr l_both);
00168 
00169 public:
00170   // variables, for now
00171   UInt8 d_pipeRef, d_transferType;
00172   usb_interface_t** d_interfaceRef;
00173   usb_interface_t* d_interface;
00174   s_queue_ptr d_queue;
00175   circular_buffer<char>* d_buffer;
00176   size_t d_bufLenBytes;
00177   gruel::mutex* d_readRunning;
00178   gruel::mutex* d_runBlock_mutex;
00179   gruel::mutex* d_readBlock_mutex;
00180   gruel::condition_variable* d_runBlock;
00181   gruel::condition_variable* d_readBlock;
00182 
00183 // CREATORS
00184 
00185   fusb_ephandle_darwin (fusb_devhandle_darwin *dh, int endpoint, bool input_p,
00186                          int block_size = 0, int nblocks = 0);
00187   virtual ~fusb_ephandle_darwin ();
00188 
00189 // MANIPULATORS
00190 
00191   virtual bool start ();        //!< begin streaming i/o
00192   virtual bool stop ();         //!< stop streaming i/o
00193 
00194   /*!
00195    * \returns \p nbytes if write was successfully enqueued, else -1.
00196    * Will block if no free buffers available.
00197    */
00198   virtual int write (const void* buffer, int nbytes);
00199 
00200   /*!
00201    * \returns number of bytes read or -1 if error.
00202    * number of bytes read will be <= nbytes.
00203    * Will block if no input available.
00204    */
00205   virtual int read (void* buffer, int nbytes);
00206 
00207   /*
00208    * abort any pending IO transfers
00209    */
00210   void abort ();
00211 
00212   /*
00213    * block until all outstanding writes have completed
00214    */
00215   virtual void wait_for_completion ();
00216 };
00217 
00218 #endif /* _FUSB_DARWIN_H_ */