Changeset 9507
- Timestamp:
- 08/15/09 16:22:01 (4 years ago)
- Location:
- ossiedev/branches/ttsou/gnuradio/usrp/host/lib
- Files:
-
- 2 modified
-
fusb_libusb1.cc (modified) (21 diffs)
-
fusb_libusb1.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
ossiedev/branches/ttsou/gnuradio/usrp/host/lib/fusb_libusb1.cc
r9506 r9507 27 27 #include <fusb_libusb1.h> 28 28 #include <libusb-1.0/libusb.h> 29 #include <stdexcept> 29 30 #include <cstdio> 30 31 #include <assert.h> … … 44 45 */ 45 46 46 47 47 inline static fusb_ephandle_libusb1 * 48 48 lut_get_ephandle (libusb_transfer *lut) … … 79 79 } 80 80 81 static void 82 free_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 } 81 91 /* 82 92 * 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 84 95 */ 85 96 86 97 static void 87 write_callback(struct libusb_transfer *lut) 88 { 89 //print_transfer_status (lut); 98 generic_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 90 132 lut_get_ephandle(lut)->completed_list_add(lut); 133 91 134 } 92 93 static void94 read_callback(struct libusb_transfer *lut)95 {96 //print_transfer_status(lut);97 lut_get_ephandle(lut)->completed_list_add(lut);98 }99 135 100 136 /* … … 104 140 static libusb_transfer* 105 141 alloc_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) 108 143 { 109 144 struct libusb_transfer* lut = libusb_alloc_transfer(0); 110 void (*callback)(libusb_transfer *) = write_callback;111 145 112 146 endpoint = (endpoint & 0x7f) | (input_p ? 0x80 : 0); … … 114 148 if (input_p) { 115 149 write_buffer = new unsigned char [buffer_length]; 116 callback = read_callback;117 150 } 118 151 … … 121 154 122 155 libusb_fill_bulk_transfer (lut, // transfer 123 dev_handle, // dev_handle156 NULL, // fill device before submit 124 157 endpoint, // endpoint 125 158 write_buffer, // buffer 126 159 buffer_length, // length 127 callback, // callback160 NULL, // fill callback before sub. 128 161 self, // user_data 129 162 0); // timeout … … 132 165 } 133 166 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 143 168 144 169 /* … … 147 172 148 173 fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh) 149 : fusb_devhandle (udh) 174 : fusb_devhandle (udh), d_teardown (0) 150 175 { 151 176 // nop … … 154 179 fusb_devhandle_libusb1::~fusb_devhandle_libusb1 () 155 180 { 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 } 160 190 161 191 fusb_ephandle * … … 165 195 return new fusb_ephandle_libusb1 (this, endpoint, input_p, 166 196 block_size, nblocks); 197 } 198 199 void 200 fusb_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 210 void 211 fusb_devhandle_libusb1::pending_add (libusb_transfer *lut) 212 { 213 d_pending_rqsts.push_back (lut); 214 } 215 216 libusb_transfer * 217 fusb_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 227 bool 228 fusb_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 241 bool 242 fusb_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 260 bool 261 fusb_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 167 272 } 168 273 … … 179 284 d_read_work_in_progress (0), d_read_buffer (0), d_read_buffer_end (0) 180 285 { 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"); 186 291 187 292 if (d_block_size == 0) … … 196 301 197 302 if (0) 198 fprintf(stderr, "fusb_ephandle_li nux::ctor: d_block_size = %d d_nblocks = %d\n",303 fprintf(stderr, "fusb_ephandle_libusb1::ctor: d_block_size = %d d_nblocks = %d\n", 199 304 d_block_size, d_nblocks); 200 305 … … 202 307 for (int i = 0; i < d_nblocks; i++) 203 308 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)); 206 310 } 207 311 208 312 fusb_ephandle_libusb1::~fusb_ephandle_libusb1 () 209 313 { 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); 211 331 } 212 332 … … 224 344 int nerrors = 0; 225 345 while ((lut = free_list_get ()) !=0 && nerrors < d_nblocks) { 226 if ( libusb_submit_transfer(lut))346 if (!submit_lut (lut)) 227 347 nerrors++; 228 348 } … … 235 355 fusb_ephandle_libusb1::stop () 236 356 { 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 237 395 d_started = false; 238 396 return true; … … 272 430 src += m; 273 431 274 if ( libusb_submit_transfer(lut) < 0)432 if (!submit_lut(lut)) 275 433 return -1; 276 434 … … 307 465 308 466 if (lut->actual_length == lut->length){ 309 if ( libusb_submit_transfer (lut) < 0)467 if (!submit_lut (lut)) 310 468 return -1; 311 469 d_write_work_in_progress = 0; … … 337 495 } 338 496 497 // Blocking call with libusb1 hardcoded timeout of 2 seconds 339 498 libusb_handle_events(NULL); 340 499 } … … 406 565 d_read_buffer_end = 0; 407 566 lut->actual_length = 0; 408 if ( libusb_submit_transfer (lut) < 0)567 if (!submit_lut (lut)) 409 568 return false; 410 569 } … … 413 572 414 573 while ((lut = completed_list_get ()) == 0 ) { 574 // Blocking call with libusb1 hardcoded timeout of 2 seconds 415 575 libusb_handle_events(NULL); 416 576 } … … 475 635 } 476 636 637 bool 638 fusb_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 39 39 40 40 void pending_add (struct libusb_transfer *lut); 41 bool pending_remove (struct libusb_transfer *lut);41 //bool pending_remove (struct libusb_transfer *lut); 42 42 struct libusb_transfer * pending_get (); 43 43 44 bool d_teardown; 44 45 45 46 public: … … 51 52 virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, 52 53 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 (); 53 59 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; } 54 64 65 // static void generic_callback (libusb_transfer *lut); 55 66 }; 56 67 … … 74 85 void reap_complete_writes (); 75 86 bool reload_read_buffer (); 76 87 bool submit_lut (libusb_transfer *lut); 88 77 89 public: 78 90 // CREATORS … … 108 120 struct libusb_transfer *free_list_get (); 109 121 struct libusb_transfer *completed_list_get (); 122 123 // ACCESSORS 124 fusb_devhandle_libusb1* get_fusb_devhandle_libusb1 () const { 125 return d_devhandle; 126 } 110 127 }; 111 128