Changeset 9504

Show
Ignore:
Timestamp:
08/14/09 21:00:17 (4 years ago)
Author:
ttsou
Message:

works fully through libusb1.0 needs testing

Location:
ossiedev/branches/ttsou/gnuradio/usrp/host/lib
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • ossiedev/branches/ttsou/gnuradio/usrp/host/lib/fusb_libusb1.cc

    r9503 r9504  
    2828#include <libusb-1.0/libusb.h> 
    2929#include <cstdio> 
    30  
    31 static const int USB_TIMEOUT = 1000;    // in milliseconds 
    32  
    33 fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh) 
    34   : fusb_devhandle (udh) 
    35 { 
    36   // that's it 
    37 } 
    38  
    39 fusb_devhandle_libusb1::~fusb_devhandle_libusb1 () 
    40 { 
    41   // nop 
     30#include <linux/usbdevice_fs.h> // interface to kernel portion of user mode usb driver 
     31#include <sys/ioctl.h> 
     32#include <assert.h> 
     33#include <string.h> 
     34#include <algorithm> 
     35#include <errno.h> 
     36#include <string.h> 
     37#include <cstdio> 
     38#include <pthread.h> 
     39 
     40#define MINIMIZE_TX_BUFFERING true  
     41 
     42static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size();             // hard limit 
     43static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE; 
     44static const int DEFAULT_BUFFER_SIZE = 4 * (1L << 20);                          // 4 MB / endpoint 
     45 
     46inline static void 
     47lut_set_ephandle (libusb_transfer *lut, fusb_ephandle_libusb1 *handle) 
     48{ 
     49  lut->user_data = handle; 
     50} 
     51 
     52inline static fusb_ephandle_libusb1 * 
     53lut_get_ephandle (libusb_transfer *lut) 
     54{ 
     55  return (fusb_ephandle_libusb1 *) lut->user_data; 
    4256} 
    4357 
     
    7387write_callback(struct libusb_transfer *lut) 
    7488{ 
    75   print_transfer_status (lut); 
    76   libusb_free_transfer (lut); 
     89  //print_transfer_status (lut); 
     90  lut_get_ephandle(lut)->completed_list_add(lut); 
    7791}  
    7892 
     
    8094read_callback(struct libusb_transfer *lut) 
    8195{ 
    82   libusb_free_transfer (lut); 
    83 } 
     96  //print_transfer_status(lut); 
     97  lut_get_ephandle(lut)->completed_list_add(lut); 
     98} 
     99// ------------------------------------------------------------------------ 
     100//                      libusb_transfer allocation 
     101// ------------------------------------------------------------------------ 
     102 
     103static libusb_transfer* 
     104alloc_lut (fusb_ephandle_libusb1 *self, int buffer_length, int endpoint, 
     105           bool input_p, unsigned char *write_buffer, 
     106           libusb_device_handle *dev_handle) 
     107{ 
     108  struct libusb_transfer* lut = libusb_alloc_transfer(0); 
     109 
     110  endpoint = (endpoint & 0x7f) | (input_p ? 0x80 : 0); 
     111 
     112  if (input_p) 
     113    write_buffer = new unsigned char [buffer_length]; 
     114 
     115  libusb_fill_bulk_transfer (lut,               // transfer 
     116                             dev_handle,        // allocate later  
     117                             endpoint,          // endpoint 
     118                             write_buffer,      // buffer 
     119                             buffer_length,     // length 
     120                             write_callback,    // callback 
     121                             self,              // user_data 
     122                             0);                // timeout 
     123 
     124//  urb_set_ephandle(lut, self);  
     125 
     126  return lut; 
     127} 
     128 
     129static void 
     130free_lut (libusb_transfer *lut) 
     131{ 
     132  // if this was an input lut, free the buffer 
     133  if (lut->endpoint & 0x80) 
     134      delete [] ((unsigned char *) lut->buffer); 
     135 
     136  libusb_free_transfer(lut);  
     137} 
     138         
     139// ------------------------------------------------------------------------ 
     140//                              device handle 
     141// ------------------------------------------------------------------------ 
     142 
     143fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh) 
     144  : fusb_devhandle (udh) 
     145{ 
     146  // that's it 
     147} 
     148 
     149fusb_devhandle_libusb1::~fusb_devhandle_libusb1 () 
     150{ 
     151} 
     152 
     153 
    84154 
    85155fusb_ephandle * 
     
    92162 
    93163// ------------------------------------------------------------------------ 
    94 //                      libusb_transfer allocation 
    95 // ------------------------------------------------------------------------ 
    96  
    97 #if 0 
    98 static libusb_transfer* 
    99 alloc_libusb_transfer (fusb_ephandle_libusb1 *self, int endpoint, 
    100                                 bool input_p) 
    101 { 
    102   struct libusb_transfer* lut; 
    103   lut = libusb_alloc_transfer(0); 
    104  
    105   if (input_p) 
    106     callback = read_callback; 
    107   else 
    108     callback = write_callback; 
    109  
    110   libusb_fill_bulk_transfer (lut,               // transfer 
    111                              self->devhandle,   // dev_handle    
    112                              endpoint,          // endpoint 
    113                              write_buffer,      // buffer 
    114                              block_size,        // length 
    115                              callback           // callback 
    116                              NULL,              // user_data 
    117                              0);                // timeout 
    118  
    119   return lut; 
    120 } 
    121 #endif 
    122  
    123 // ------------------------------------------------------------------------ 
    124164//                            end point handle 
    125165// ------------------------------------------------------------------------ 
    126  
    127166 
    128167fusb_ephandle_libusb1::fusb_ephandle_libusb1 (fusb_devhandle_libusb1 *dh, 
     
    130169                                              int block_size, int nblocks) 
    131170  : fusb_ephandle (endpoint, input_p, block_size, nblocks), 
    132     d_devhandle (dh) 
    133 { 
    134   // nop  
     171    d_devhandle (dh), 
     172    d_write_work_in_progress (0), d_write_buffer (0), 
     173    d_read_work_in_progress (0), d_read_buffer (0), d_read_buffer_end (0) 
     174{ 
     175//  if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE) 
     176//    throw std::out_of_range ("fusb_ephandle_linux: block_size"); 
     177 
     178//  if (d_nblocks < 0) 
     179//    throw std::out_of_range ("fusb_ephandle_linux: nblocks"); 
     180 
     181  if (d_block_size == 0) 
     182    d_block_size = DEFAULT_BLOCK_SIZE; 
     183 
     184  if (d_nblocks == 0) 
     185    d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size); 
     186 
     187   if (!d_input_p) 
     188     if (!MINIMIZE_TX_BUFFERING) 
     189       d_write_buffer = new unsigned char [d_block_size]; 
     190 
     191  if (1) 
     192    fprintf(stderr, "fusb_ephandle_linux::ctor: d_block_size = %d  d_nblocks = %d\n", 
     193            d_block_size, d_nblocks); 
     194 
     195  // allocate libusb_transfers  
     196   
     197  for (int i = 0; i < d_nblocks; i++) 
     198    d_free_list.push_back (alloc_lut (this, d_block_size, d_endpoint, 
     199                                      d_input_p, d_write_buffer, 
     200                                      d_devhandle->get_usb_dev_handle())); 
    135201} 
    136202 
    137203fusb_ephandle_libusb1::~fusb_ephandle_libusb1 () 
    138204{ 
    139   // nop  
     205  // free libusb_transfers  
    140206} 
    141207 
     
    154220} 
    155221 
     222// ---------------------------------------------------------------- 
     223//                      routines for writing  
     224// ---------------------------------------------------------------- 
     225 
     226#if (MINIMIZE_TX_BUFFERING) 
     227 
    156228int 
    157229fusb_ephandle_libusb1::write (const void *buffer, int nbytes) 
     
    163235    return -1; 
    164236 
    165   libusb_transfer *lut = libusb_alloc_transfer(0); 
    166   libusb_fill_bulk_transfer (lut,                       // transfer 
    167                              d_devhandle->get_usb_dev_handle(), 
    168                              d_endpoint,                // endpoint 
    169                              (unsigned char*) buffer,   // buffer 
    170                              nbytes,                    // length 
    171                              write_callback,            // callback 
    172                              NULL,                      // user_data 
    173                              USB_TIMEOUT);              // timeout 
    174   
    175   libusb_submit_transfer(lut);   
    176   //libusb_handle_events; 
     237  assert(nbytes % 512 == 0); 
     238 
     239  unsigned char *src = (unsigned char *) buffer; 
     240 
     241  int n = 0; 
     242  while (n < nbytes){ 
     243 
     244    struct libusb_transfer *lut = get_write_work_in_progress(); 
     245    if (!lut) 
     246      return -1; 
     247    assert(lut->actual_length == 0); 
     248    int m = std::min(nbytes - n, MAX_BLOCK_SIZE); 
     249    lut->buffer = src; 
     250    lut->length = m; 
     251 
     252    n += m; 
     253    src += m; 
     254    
     255    if (libusb_submit_transfer(lut) < 0) 
     256      return -1; 
     257 
     258    d_write_work_in_progress = 0; 
     259  } 
     260 
    177261  return nbytes; 
    178262} 
     263 
     264#else 
     265int 
     266fusb_ephandle_libusb1::write (const void *buffer, int nbytes) 
     267{ 
     268  if (!d_started) 
     269    return -1; 
     270 
     271  if (d_input_p) 
     272    return -1; 
     273 
     274  unsigned char *src = (unsigned char *) buffer; 
     275 
     276  int n = 0; 
     277  while (n < nbytes){ 
     278 
     279    libusb_transfer *lut = get_write_work_in_progress (); 
     280    if (!lut) 
     281      return -1; 
     282    unsigned char *dst = (unsigned char *) lut->buffer; 
     283    int m = std::min (nbytes - n, lut->length - lut->actual_length); 
     284 
     285    memcpy (&dst[lut->actual_length], &src[n], m); 
     286    lut->actual_length += m; 
     287    n += m; 
     288 
     289    if (lut->actual_length == lut->length){ 
     290      if (libusb_submit_transfer (lut) < 0) 
     291        return -1; 
     292      d_write_work_in_progress = 0; 
     293    } 
     294  } 
     295 
     296  return n; 
     297} 
     298 
     299#endif 
     300 
     301 
     302struct libusb_transfer * 
     303fusb_ephandle_libusb1::get_write_work_in_progress () 
     304{ 
     305  if (d_write_work_in_progress) 
     306    return d_write_work_in_progress; 
     307 
     308  while (1){ 
     309 
     310    reap_complete_writes (); 
     311 
     312    struct libusb_transfer *lut = free_list_get (); 
     313 
     314    if (lut != 0){ 
     315      assert (lut->actual_length == 0); 
     316      d_write_work_in_progress = lut; 
     317      return lut; 
     318    } 
     319 
     320    libusb_handle_events(NULL); 
     321//   if (!d_devhandle->_reap (true)) 
     322//      return 0; 
     323//  } 
     324  } 
     325} 
     326 
     327void 
     328fusb_ephandle_libusb1::reap_complete_writes () 
     329{ 
     330  libusb_transfer *lut; 
     331 
     332  while ((lut = completed_list_get ()) != 0) { 
     333    if (lut->status != 0){ 
     334      fprintf (stderr, "fusb: (status %d) \n", 
     335               lut->status ); 
     336    } 
     337    else if (lut->actual_length != lut->length){ 
     338      fprintf (stderr, "fusb: short write xfer: %d != %d\n", 
     339               lut->actual_length, lut->length); 
     340    } 
     341 
     342    free_list_add (lut); 
     343  } 
     344} 
     345 
     346// ---------------------------------------------------------------- 
     347//                     routines for reading 
     348// ---------------------------------------------------------------- 
    179349 
    180350int 
     
    186356  if (!d_input_p) 
    187357    return -1; 
    188  
    189   libusb_transfer *lut = libusb_alloc_transfer(0); 
    190   libusb_fill_bulk_transfer (lut,                       // transfer 
    191                              d_devhandle->get_usb_dev_handle(), 
    192                              d_endpoint,                // endpoint 
    193                              (unsigned char*) buffer,   // buffer 
    194                              nbytes,                    // length 
    195                              read_callback,             // callback 
    196                              NULL,                      // user_data 
    197                              USB_TIMEOUT);              // timeout 
    198   
    199   libusb_submit_transfer(lut);   
    200 } 
    201  
     358} 
     359 
     360// ---------------------------------------------------------------- 
     361 
     362void 
     363fusb_ephandle_libusb1::free_list_add (libusb_transfer *lut) 
     364{ 
     365  assert (lut_get_ephandle (lut) == this); 
     366  lut->actual_length = 0; 
     367  d_free_list.push_back (lut); 
     368} 
     369 
     370libusb_transfer * 
     371fusb_ephandle_libusb1::free_list_get () 
     372{ 
     373  if (d_free_list.empty ()) 
     374    return 0; 
     375 
     376  libusb_transfer *lut = d_free_list.front (); 
     377  d_free_list.pop_front (); 
     378  return lut; 
     379} 
     380 
     381void 
     382fusb_ephandle_libusb1::completed_list_add (libusb_transfer *lut) 
     383{ 
     384  assert (lut_get_ephandle (lut) == this); 
     385  d_completed_list.push_back (lut); 
     386} 
     387 
     388libusb_transfer * 
     389fusb_ephandle_libusb1::completed_list_get () 
     390{ 
     391  if (d_completed_list.empty ()) 
     392    return 0; 
     393 
     394  libusb_transfer *lut = d_completed_list.front (); 
     395  d_completed_list.pop_front (); 
     396  return lut; 
     397} 
     398 
  • ossiedev/branches/ttsou/gnuradio/usrp/host/lib/fusb_libusb1.h

    r9503 r9504  
    2525 
    2626#include <fusb.h> 
     27#include <list> 
     28 
     29struct libusb_transfer; 
     30class fusb_ephandle_libusb1; 
    2731 
    2832/*! 
     
    3236{ 
    3337private: 
    34    
     38  std::list<libusb_transfer*>   d_pending_rqsts; 
     39 
     40  void pending_add (struct libusb_transfer *lut); 
     41  bool pending_remove (struct libusb_transfer *lut); 
     42  struct libusb_transfer * pending_get (); 
     43 
    3544 
    3645public: 
     
    4251  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, 
    4352                                        int block_size = 0, int nblocks = 0); 
     53 
     54 
    4455}; 
    4556 
     
    5162{ 
    5263private: 
    53   fusb_devhandle_libusb1        *d_devhandle; 
     64  fusb_devhandle_libusb1         *d_devhandle; 
     65  std::list<libusb_transfer*>     d_free_list; 
     66  std::list<libusb_transfer*>     d_completed_list; 
     67  libusb_transfer                *d_write_work_in_progress; 
     68  unsigned char                  *d_write_buffer; 
     69  libusb_transfer                *d_read_work_in_progress; 
     70  unsigned char                  *d_read_buffer; 
     71  unsigned char                  *d_read_buffer_end; 
     72 
     73  libusb_transfer *get_write_work_in_progress (); 
     74  void reap_complete_writes (); 
     75 
    5476   
    5577public: 
     
    81103   */ 
    82104  virtual void wait_for_completion () { }; 
     105 
     106  void free_list_add (struct libusb_transfer *lut); 
     107  void completed_list_add (struct libusb_transfer *lut); 
     108  struct libusb_transfer *free_list_get (); 
     109  struct libusb_transfer *completed_list_get (); 
    83110}; 
    84111 
  • ossiedev/branches/ttsou/gnuradio/usrp/host/lib/fusb_sysconfig_libusb1.cc

    r9503 r9504  
    2525 
    2626static const int MAX_BLOCK_SIZE = 16 * 1024;            // hard limit 
     27static const int DEFAULT_BLOCK_SIZE =   4 * 1024; 
    2728static const int FUSB_BUFFER_SIZE = 2 * (1L << 20);     // 2 MB 
    2829 
     
    4041int fusb_sysconfig::default_block_size () 
    4142{ 
    42   return fusb_sysconfig::max_block_size (); 
     43  return DEFAULT_BLOCK_SIZE; 
    4344} 
    4445