Changeset 9507

Show
Ignore:
Timestamp:
08/15/09 16:22:01 (4 years ago)
Author:
ttsou
Message:

teardowns cleanly

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

Legend:

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

    r9506 r9507  
    2727#include <fusb_libusb1.h> 
    2828#include <libusb-1.0/libusb.h> 
     29#include <stdexcept> 
    2930#include <cstdio> 
    3031#include <assert.h> 
     
    4445 */ 
    4546 
    46  
    4747inline static fusb_ephandle_libusb1 * 
    4848lut_get_ephandle (libusb_transfer *lut) 
     
    7979} 
    8080 
     81static void 
     82free_lut (libusb_transfer *lut) 
     83{ 
     84 
     85  // if this was an input lut, free the buffer 
     86  if (lut->endpoint & 0x80) 
     87    delete [] ((unsigned char *) lut->buffer); 
     88 
     89  libusb_free_transfer(lut);  
     90} 
    8191/* 
    8292 * Since libusb1.0 takes care of reaping during the libusb-handle_events 
    83  * call, just add the completed luts directly to the compeleted_list  
     93 * call, libusb_transfers are completed at this point. Check status and 
     94 * move to complted_list  
    8495 */ 
    8596 
    8697static void 
    87 write_callback(struct libusb_transfer *lut) 
    88 { 
    89   //print_transfer_status (lut); 
     98generic_callback(struct libusb_transfer *lut) 
     99{ 
     100  // Remove from the pending list 
     101  // Need a better way to do this 
     102  fusb_devhandle_libusb1* dev_handle =  
     103    lut_get_ephandle(lut)->get_fusb_devhandle_libusb1(); 
     104   
     105  dev_handle->pending_remove(lut); 
     106 
     107  switch (lut->status) { 
     108  case LIBUSB_TRANSFER_COMPLETED: 
     109    // Move to the completed list  
     110    break; 
     111  case LIBUSB_TRANSFER_ERROR: 
     112    break; 
     113  case LIBUSB_TRANSFER_TIMED_OUT: 
     114    break; 
     115  case LIBUSB_TRANSFER_CANCELLED: 
     116    // On teardown we need to free the libusb_transfer 
     117    // otherwise let it go to the completed list 
     118    if (dev_handle->teardown()) { 
     119      free_lut (lut); 
     120      return; 
     121    } 
     122    break; 
     123  case LIBUSB_TRANSFER_STALL: 
     124    break; 
     125  case LIBUSB_TRANSFER_NO_DEVICE: 
     126    break; 
     127  case LIBUSB_TRANSFER_OVERFLOW: 
     128    break; 
     129  } 
     130 
     131  // If all is well then move to competed list 
    90132  lut_get_ephandle(lut)->completed_list_add(lut); 
     133 
    91134}  
    92  
    93 static void 
    94 read_callback(struct libusb_transfer *lut) 
    95 { 
    96   //print_transfer_status(lut); 
    97   lut_get_ephandle(lut)->completed_list_add(lut); 
    98 } 
    99135 
    100136/* 
     
    104140static libusb_transfer* 
    105141alloc_lut (fusb_ephandle_libusb1 *self, int buffer_length, int endpoint, 
    106            bool input_p, unsigned char *write_buffer, 
    107            libusb_device_handle *dev_handle) 
     142           bool input_p, unsigned char *write_buffer) 
    108143{ 
    109144  struct libusb_transfer* lut = libusb_alloc_transfer(0); 
    110   void (*callback)(libusb_transfer *) = write_callback; 
    111145 
    112146  endpoint = (endpoint & 0x7f) | (input_p ? 0x80 : 0); 
     
    114148  if (input_p) { 
    115149    write_buffer = new unsigned char [buffer_length]; 
    116     callback = read_callback; 
    117150  } 
    118151 
     
    121154   
    122155  libusb_fill_bulk_transfer (lut,               // transfer 
    123                              dev_handle,        // dev_handle  
     156                             NULL,              // fill device before submit 
    124157                             endpoint,          // endpoint 
    125158                             write_buffer,      // buffer 
    126159                             buffer_length,     // length 
    127                              callback,          // callback 
     160                             NULL,              // fill callback before sub. 
    128161                             self,              // user_data 
    129162                             0);                // timeout 
     
    132165} 
    133166 
    134 static void 
    135 free_lut (libusb_transfer *lut) 
    136 { 
    137   // if this was an input lut, free the buffer 
    138   if (lut->endpoint & 0x80) 
    139       delete [] ((unsigned char *) lut->buffer); 
    140  
    141   libusb_free_transfer(lut);  
    142 } 
     167 
    143168         
    144169/*  
     
    147172 
    148173fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh) 
    149   : fusb_devhandle (udh) 
     174  : fusb_devhandle (udh), d_teardown (0) 
    150175{ 
    151176  // nop  
     
    154179fusb_devhandle_libusb1::~fusb_devhandle_libusb1 () 
    155180{ 
    156   // nop 
    157 } 
    158  
    159  
     181  std::list<libusb_transfer*>::reverse_iterator it; 
     182  d_teardown = true; 
     183 
     184  for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++) { 
     185    _cancel_lut (*it); 
     186    // libusb_transfer still active and callback will fire 
     187    // so delete in callback  
     188  } 
     189} 
    160190 
    161191fusb_ephandle * 
     
    165195  return new fusb_ephandle_libusb1 (this, endpoint, input_p, 
    166196                                    block_size, nblocks); 
     197} 
     198 
     199void 
     200fusb_devhandle_libusb1::_cancel_pending_rqsts (fusb_ephandle_libusb1 *eph) 
     201{ 
     202  std::list<libusb_transfer*>::reverse_iterator it; 
     203 
     204  for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){ 
     205    if (lut_get_ephandle (*it) == eph) 
     206      _cancel_lut (*it); 
     207  } 
     208} 
     209 
     210void  
     211fusb_devhandle_libusb1::pending_add (libusb_transfer *lut) 
     212{ 
     213  d_pending_rqsts.push_back (lut); 
     214} 
     215 
     216libusb_transfer * 
     217fusb_devhandle_libusb1::pending_get () 
     218{ 
     219  if (d_pending_rqsts.empty ()) 
     220    return 0; 
     221 
     222  libusb_transfer *lut = d_pending_rqsts.front (); 
     223  d_pending_rqsts.pop_front (); 
     224  return lut; 
     225} 
     226 
     227bool 
     228fusb_devhandle_libusb1::pending_remove (libusb_transfer *lut) 
     229{ 
     230  std::list<libusb_transfer*>::iterator result; 
     231  result = find (d_pending_rqsts.begin (), d_pending_rqsts.end (), lut); 
     232 
     233  if (result == d_pending_rqsts.end ()) { 
     234    fprintf (stderr, "fusb::pending_remove: failed to find lut in pending_rqsts: %p\n", lut); 
     235    return false; 
     236  } 
     237  d_pending_rqsts.erase (result); 
     238  return true; 
     239} 
     240 
     241bool 
     242fusb_devhandle_libusb1::_submit_lut (libusb_transfer *lut) 
     243{ 
     244  int ret; 
     245 
     246  // Fill out device and callback 
     247  lut->dev_handle = get_usb_dev_handle(); 
     248  lut->callback = generic_callback;  
     249 
     250  ret = libusb_submit_transfer (lut); 
     251  if (ret < 0) { 
     252    fprintf(stderr, "fusb::_submit_lut %d", ret); 
     253    return false; 
     254  } 
     255 
     256  pending_add(lut); 
     257  return true; 
     258} 
     259 
     260bool 
     261fusb_devhandle_libusb1::_cancel_lut (libusb_transfer *lut) 
     262{ 
     263  // call on a transfer that has already completed is undefined 
     264 
     265  int ret = libusb_cancel_transfer (lut); 
     266  if (ret < 0) { 
     267    fprintf (stderr, "fusb::_cancel_lut"); 
     268    return false; 
     269  } 
     270  return true; 
     271 
    167272} 
    168273 
     
    179284    d_read_work_in_progress (0), d_read_buffer (0), d_read_buffer_end (0) 
    180285{ 
    181 //  if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE) 
    182 //    throw std::out_of_range ("fusb_ephandle_linux: block_size"); 
    183  
    184 //  if (d_nblocks < 0) 
    185 //    throw std::out_of_range ("fusb_ephandle_linux: nblocks"); 
     286  if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE) 
     287    throw std::out_of_range ("fusb_ephandle_libusb1: block_size"); 
     288 
     289  if (d_nblocks < 0) 
     290    throw std::out_of_range ("fusb_ephandle_libusb1: nblocks"); 
    186291 
    187292  if (d_block_size == 0) 
     
    196301 
    197302  if (0) 
    198     fprintf(stderr, "fusb_ephandle_linux::ctor: d_block_size = %d  d_nblocks = %d\n", 
     303    fprintf(stderr, "fusb_ephandle_libusb1::ctor: d_block_size = %d  d_nblocks = %d\n", 
    199304            d_block_size, d_nblocks); 
    200305 
     
    202307  for (int i = 0; i < d_nblocks; i++) 
    203308    d_free_list.push_back (alloc_lut (this, d_block_size, d_endpoint, 
    204                                       d_input_p, d_write_buffer, 
    205                                       d_devhandle->get_usb_dev_handle())); 
     309                                      d_input_p, d_write_buffer)); 
    206310} 
    207311 
    208312fusb_ephandle_libusb1::~fusb_ephandle_libusb1 () 
    209313{ 
    210   // free libusb_transfers  
     314  stop (); 
     315 
     316  libusb_transfer *lut; 
     317 
     318  while ((lut = free_list_get ()) != 0) 
     319    free_lut (lut); 
     320 
     321  while ((lut = completed_list_get ()) != 0) 
     322    free_lut (lut); 
     323 
     324  if (d_write_work_in_progress) 
     325    free_lut (d_write_work_in_progress); 
     326 
     327  delete [] d_write_buffer; 
     328 
     329  if (d_read_work_in_progress) 
     330    free_lut (d_read_work_in_progress); 
    211331} 
    212332 
     
    224344     int nerrors = 0; 
    225345     while ((lut = free_list_get ()) !=0 && nerrors < d_nblocks) { 
    226        if (libusb_submit_transfer (lut)) 
     346       if (!submit_lut (lut)) 
    227347         nerrors++; 
    228348     } 
     
    235355fusb_ephandle_libusb1::stop () 
    236356{ 
     357  int ret; 
     358  if (!d_started) 
     359    return true; 
     360 
     361  if (d_write_work_in_progress){ 
     362    free_list_add (d_write_work_in_progress); 
     363    d_write_work_in_progress = 0; 
     364  } 
     365 
     366  if (d_read_work_in_progress){ 
     367    free_list_add (d_read_work_in_progress); 
     368    d_read_work_in_progress = 0; 
     369    d_read_buffer = 0; 
     370    d_read_buffer_end = 0; 
     371  } 
     372 
     373  d_devhandle->_cancel_pending_rqsts (this); 
     374  // Blocking call with libusb1 hardcoded timeout of 2 seconds 
     375  ret = libusb_handle_events(0); 
     376  if (ret < 0) { 
     377    perror ("fusb::libusb_handle_events"); 
     378    return false; 
     379  } 
     380 
     381  while (1){ 
     382    libusb_transfer *lut; 
     383    while ((lut = completed_list_get ()) != 0) 
     384      free_list_add (lut); 
     385 
     386    if (d_free_list.size () == (unsigned) d_nblocks) 
     387      break; 
     388 
     389    if ((ret = libusb_handle_events(0)) < 0) { 
     390      perror ("fusb::libusb_handle_events"); 
     391      return false; 
     392    } 
     393  } 
     394 
    237395  d_started = false; 
    238396  return true; 
     
    272430    src += m; 
    273431    
    274     if (libusb_submit_transfer(lut) < 0) 
     432    if (!submit_lut(lut)) 
    275433      return -1; 
    276434 
     
    307465 
    308466    if (lut->actual_length == lut->length){ 
    309       if (libusb_submit_transfer (lut) < 0) 
     467      if (!submit_lut (lut)) 
    310468        return -1; 
    311469      d_write_work_in_progress = 0; 
     
    337495    } 
    338496 
     497    // Blocking call with libusb1 hardcoded timeout of 2 seconds 
    339498    libusb_handle_events(NULL); 
    340499  } 
     
    406565    d_read_buffer_end = 0; 
    407566    lut->actual_length = 0; 
    408     if (libusb_submit_transfer (lut) < 0) 
     567    if (!submit_lut (lut)) 
    409568      return false; 
    410569  } 
     
    413572 
    414573    while ((lut = completed_list_get ()) == 0 ) { 
     574      // Blocking call with libusb1 hardcoded timeout of 2 seconds 
    415575      libusb_handle_events(NULL); 
    416576    } 
     
    475635} 
    476636 
     637bool 
     638fusb_ephandle_libusb1::submit_lut (libusb_transfer *lut) 
     639{ 
     640  if (!d_devhandle->_submit_lut (lut)) { 
     641    fprintf (stderr, "_submit_lut failed\n"); 
     642    free_list_add (lut); 
     643    return false; 
     644  } 
     645  return true; 
     646} 
  • ossiedev/branches/ttsou/gnuradio/usrp/host/lib/fusb_libusb1.h

    r9506 r9507  
    3939 
    4040  void pending_add (struct libusb_transfer *lut); 
    41   bool pending_remove (struct libusb_transfer *lut); 
     41  //bool pending_remove (struct libusb_transfer *lut); 
    4242  struct libusb_transfer * pending_get (); 
    4343 
     44  bool d_teardown; 
    4445 
    4546public: 
     
    5152  virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, 
    5253                                        int block_size = 0, int nblocks = 0); 
     54  // internal use only 
     55  bool _submit_lut (libusb_transfer *); 
     56  bool _cancel_lut (libusb_transfer *); 
     57  void _cancel_pending_rqsts (fusb_ephandle_libusb1 *eph); 
     58  void _wait_for_completion (); 
    5359 
     60  // This needs to be public for the libusb_tranfer callback to work 
     61  // Find a better way 
     62  bool pending_remove (struct libusb_transfer *lut); 
     63  inline bool teardown() { return d_teardown; } 
    5464 
     65//  static void generic_callback (libusb_transfer *lut); 
    5566}; 
    5667 
     
    7485  void reap_complete_writes (); 
    7586  bool reload_read_buffer (); 
    76    
     87  bool submit_lut (libusb_transfer *lut);  
     88  
    7789public: 
    7890  // CREATORS 
     
    108120  struct libusb_transfer *free_list_get (); 
    109121  struct libusb_transfer *completed_list_get (); 
     122 
     123  // ACCESSORS 
     124  fusb_devhandle_libusb1* get_fusb_devhandle_libusb1 () const { 
     125    return d_devhandle; 
     126  } 
    110127}; 
    111128