Revision 543a6364 host/lib/transport/libusb1_zero_copy.cpp

b/host/lib/transport/libusb1_zero_copy.cpp
30 30

  
31 31
const int libusb_timeout = 0;
32 32

  
33
static const size_t DEFAULT_NUM_XFERS = 16;     //num xfers
34
static const size_t DEFAULT_XFER_SIZE = 32*512; //bytes
35

  
33 36
/***********************************************************************
34 37
 * Helper functions
35 38
 ***********************************************************************/
......
56 59
 *   create a bidirectional interface. It is a zero copy implementation
57 60
 *   with respect to libusb, however, each send and recv requires a copy
58 61
 *   operation from kernel to userspace; this is due to the usbfs
59
 *   interface provided by the kernel. 
62
 *   interface provided by the kernel.
60 63
 **********************************************************************/
61 64
class usb_endpoint {
62 65
public:
......
107 110
    //! a list of shared arrays for the transfer buffers
108 111
    std::vector<boost::shared_array<boost::uint8_t> > _buffers;
109 112

  
110
    // Calls for processing asynchronous I/O 
113
    // Calls for processing asynchronous I/O
111 114
    libusb_transfer *allocate_transfer(int buff_len);
112 115
    void print_transfer_status(libusb_transfer *lut);
113 116
};
......
142 145
 * Constructor
143 146
 * Allocate libusb transfers and mark as free.  For IN endpoints,
144 147
 * submit the transfers so that they're ready to return when
145
 * data is available. 
148
 * data is available.
146 149
 */
147 150
usb_endpoint::usb_endpoint(
148 151
    libusb::device_handle::sptr handle,
......
194 197

  
195 198

  
196 199
/*
197
 * Allocate a libusb transfer 
200
 * Allocate a libusb transfer
198 201
 * The allocated transfer - and buffer it contains - is repeatedly
199 202
 * submitted, reaped, and reused and should not be freed until shutdown.
200 203
 * \param buff_len size of the individual buffer held by each transfer
......
225 228
 * Asynchonous transfer submission
226 229
 * Submit a libusb transfer to libusb add pending status
227 230
 * \param lut pointer to libusb_transfer
228
 * \return true on success or false on error 
231
 * \return true on success or false on error
229 232
 */
230 233
void usb_endpoint::submit(libusb_transfer *lut){
231 234
    UHD_ASSERT_THROW(libusb_submit_transfer(lut) == 0);
......
281 284
}
282 285

  
283 286
/***********************************************************************
284
 * Managed buffers 
287
 * Managed buffers
285 288
 **********************************************************************/
286 289
/*
287 290
 * Libusb managed receive buffer
288 291
 * Construct a recv buffer from a libusb transfer. The memory held by
289 292
 * the libusb transfer is exposed through the managed buffer interface.
290 293
 * Upon destruction, the transfer and buffer are resubmitted to the
291
 * endpoint for further use. 
294
 * endpoint for further use.
292 295
 */
293 296
class libusb_managed_recv_buffer_impl : public managed_recv_buffer {
294 297
public:
......
307 310
private:
308 311
    const boost::asio::const_buffer &get() const
309 312
    {
310
        return _buff; 
313
        return _buff;
311 314
    }
312 315

  
313 316
    libusb_transfer *_lut;
......
327 330
class libusb_managed_send_buffer_impl : public managed_send_buffer {
328 331
public:
329 332
    libusb_managed_send_buffer_impl(libusb_transfer *lut,
330
                                    usb_endpoint::sptr endpoint,
331
                                    size_t buff_size)
332
        : _buff(lut->buffer, buff_size), _committed(false)
333
                                    usb_endpoint::sptr endpoint)
334
        : _buff(lut->buffer, lut->length), _committed(false)
333 335
    {
334 336
        _lut = lut;
335 337
        _endpoint = endpoint;
......
349 351
            std::cerr << "UHD: send buffer already committed" << std::endl;
350 352
            return 0;
351 353
        }
352
        
354

  
353 355
        UHD_ASSERT_THROW(num_bytes <= boost::asio::buffer_size(_buff));
354 356

  
355 357
        _lut->length = num_bytes;
......
369 371
private:
370 372
    const boost::asio::mutable_buffer &get() const
371 373
    {
372
        return _buff; 
374
        return _buff;
373 375
    }
374 376

  
375 377
    libusb_transfer *_lut;
......
385 387
class libusb_zero_copy_impl : public usb_zero_copy
386 388
{
387 389
private:
388
    usb_endpoint::sptr _rx_ep, _tx_ep;
389

  
390 390
    libusb::device_handle::sptr _handle;
391

  
392
    size_t _recv_buff_size;
393
    size_t _send_buff_size;
394
    size_t _num_frames;
391
    size_t _recv_num_frames, _send_num_frames;
392
    usb_endpoint::sptr _recv_ep, _send_ep;
395 393

  
396 394
public:
397 395
    typedef boost::shared_ptr<libusb_zero_copy_impl> sptr;
398 396

  
399
    libusb_zero_copy_impl(libusb::device_handle::sptr handle,
400
                          unsigned int rx_endpoint,
401
                          unsigned int tx_endpoint,
402
                          size_t recv_buff_size,
403
                          size_t send_buff_size);
397
    libusb_zero_copy_impl(
398
		libusb::device_handle::sptr handle,
399
		unsigned int recv_endpoint, unsigned int send_endpoint,
400
		size_t recv_xfer_size, size_t recv_num_xfers,
401
		size_t send_xfer_size, size_t send_num_xfers
402
	);
404 403

  
405 404
    managed_recv_buffer::sptr get_recv_buff(void);
406 405
    managed_send_buffer::sptr get_send_buff(void);
407 406

  
408
    size_t get_num_recv_frames(void) const { return _num_frames; }
409
    size_t get_num_send_frames(void) const { return _num_frames; }
407
    size_t get_num_recv_frames(void) const { return _recv_num_frames; }
408
    size_t get_num_send_frames(void) const { return _send_num_frames; }
410 409
};
411 410

  
412 411
/*
413 412
 * Constructor
414 413
 * Initializes libusb, opens devices, and sets up interfaces for I/O.
415
 * Finally, creates endpoints for asynchronous I/O. 
414
 * Finally, creates endpoints for asynchronous I/O.
416 415
 */
417
libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle,
418
                                             unsigned int rx_endpoint,
419
                                             unsigned int tx_endpoint,
420
                                             size_t buff_size,
421
                                             size_t block_size)
422
 : _handle(handle),
423
   _recv_buff_size(block_size), _send_buff_size(block_size),
424
   _num_frames(buff_size / block_size)
425
{
426
    _handle->claim_interface(2 /*in interface*/);
416
libusb_zero_copy_impl::libusb_zero_copy_impl(
417
    libusb::device_handle::sptr handle,
418
    unsigned int recv_endpoint, unsigned int send_endpoint,
419
    size_t recv_xfer_size, size_t recv_num_xfers,
420
    size_t send_xfer_size, size_t send_num_xfers
421
){
422
	_handle = handle;
423

  
424
	//if the sizes are left at 0 (automatic) -> use the defaults
425
	if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE;
426
	if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS;
427
	if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE;
428
	if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS;
429

  
430
    //sanity check the transfer sizes
431
    UHD_ASSERT_THROW(recv_xfer_size % 512 == 0);
432
    UHD_ASSERT_THROW(send_xfer_size % 512 == 0);
433

  
434
	//store the num xfers for the num frames count
435
	_recv_num_frames = recv_num_xfers;
436
	_send_num_frames = send_num_xfers;
437

  
438
	_handle->claim_interface(2 /*in interface*/);
427 439
    _handle->claim_interface(1 /*out interface*/);
428 440

  
429
    _rx_ep = usb_endpoint::sptr(new usb_endpoint(
441
    _recv_ep = usb_endpoint::sptr(new usb_endpoint(
430 442
                              _handle,         // libusb device_handle
431
                              rx_endpoint,     // USB endpoint number
443
                              recv_endpoint,   // USB endpoint number
432 444
                              true,            // IN endpoint
433
                              _recv_buff_size, // buffer size per transfer 
434
                              _num_frames      // number of libusb transfers
445
                              recv_xfer_size,  // buffer size per transfer
446
                              recv_num_xfers   // number of libusb transfers
435 447
    ));
436 448

  
437
    _tx_ep = usb_endpoint::sptr(new usb_endpoint(
449
    _send_ep = usb_endpoint::sptr(new usb_endpoint(
438 450
                              _handle,         // libusb device_handle
439
                              tx_endpoint,     // USB endpoint number
451
                              send_endpoint,   // USB endpoint number
440 452
                              false,           // OUT endpoint
441
                              _send_buff_size, // buffer size per transfer
442
                              _num_frames      // number of libusb transfers
453
                              send_xfer_size,  // buffer size per transfer
454
                              send_num_xfers   // number of libusb transfers
443 455
    ));
444 456
}
445 457

  
......
447 459
 * Construct a managed receive buffer from a completed libusb transfer
448 460
 * (happy with buffer full of data) obtained from the receive endpoint.
449 461
 * Return empty pointer if no transfer is available (timeout or error).
450
 * \return pointer to a managed receive buffer 
462
 * \return pointer to a managed receive buffer
451 463
 */
452 464
managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){
453
    libusb_transfer *lut = _rx_ep->get_lut_with_wait(/* TODO timeout API */);
465
    libusb_transfer *lut = _recv_ep->get_lut_with_wait(/* TODO timeout API */);
454 466
    if (lut == NULL) {
455 467
        return managed_recv_buffer::sptr();
456 468
    }
457 469
    else {
458 470
        return managed_recv_buffer::sptr(
459 471
            new libusb_managed_recv_buffer_impl(lut,
460
                                                _rx_ep));
472
                                                _recv_ep));
461 473
    }
462 474
}
463 475

  
......
466 478
 * Construct a managed send buffer from a free libusb transfer (with
467 479
 * empty buffer). Return empty pointer of no transfer is available
468 480
 * (timeout or error).
469
 * \return pointer to a managed send buffer 
481
 * \return pointer to a managed send buffer
470 482
 */
471 483
managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){
472
    libusb_transfer *lut = _tx_ep->get_lut_with_wait(/* TODO timeout API */);
484
    libusb_transfer *lut = _send_ep->get_lut_with_wait(/* TODO timeout API */);
473 485
    if (lut == NULL) {
474 486
        return managed_send_buffer::sptr();
475 487
    }
476 488
    else {
477 489
        return managed_send_buffer::sptr(
478 490
            new libusb_managed_send_buffer_impl(lut,
479
                                                _tx_ep,
480
                                                _send_buff_size));
491
                                                _send_ep));
481 492
    }
482 493
}
483 494

  
484

  
485 495
/***********************************************************************
486 496
 * USB zero_copy make functions
487 497
 **********************************************************************/
488
usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle,
489
                                        unsigned int rx_endpoint,
490
                                        unsigned int tx_endpoint,
491
                                        size_t buff_size,
492
                                        size_t block_size)
493

  
494
{
498
usb_zero_copy::sptr usb_zero_copy::make(
499
	usb_device_handle::sptr handle,
500
    unsigned int recv_endpoint, unsigned int send_endpoint,
501
	size_t recv_xfer_size, size_t recv_num_xfers,
502
	size_t send_xfer_size, size_t send_num_xfers
503
){
495 504
    libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle(
496 505
        boost::static_pointer_cast<libusb::special_handle>(handle)->get_device()
497 506
    ));
498
    return sptr(new libusb_zero_copy_impl(dev_handle,
499
                                          rx_endpoint,
500
                                          tx_endpoint,
501
                                          buff_size, 
502
                                          block_size));
507
    return sptr(new libusb_zero_copy_impl(
508
		dev_handle,
509
		recv_endpoint,  send_endpoint,
510
		recv_xfer_size, recv_num_xfers,
511
		send_xfer_size, send_num_xfers
512
    ));
503 513
}

Also available in: Unified diff