Revision 55da3154 host/lib/transport/libusb1_zero_copy.cpp

b/host/lib/transport/libusb1_zero_copy.cpp
64 64
    size_t _transfer_size;
65 65
    size_t _num_transfers;
66 66

  
67
    /*
68
     * Transfer state lists (free, pending, or completed)
69
     */
67
    // Transfer state lists (transfers are free, pending, or completed)
70 68
    std::list<libusb_transfer *>  _free_list;
71 69
    std::list<libusb_transfer *>  _pending_list;
72 70
    std::list<libusb_transfer *>  _completed_list;
73 71

  
74
    /*
75
     * Calls for processing asynchronous I/O 
76
     */
72
    // Calls for processing asynchronous I/O 
77 73
    libusb_transfer *allocate_transfer(int buff_len);
78 74
    bool cancel(libusb_transfer *lut);
79 75
    bool cancel_all();
......
81 77
    bool reap_pending_list_timeout();
82 78
    bool reap_completed_list();
83 79

  
84
    /*
85
     * Transfer state manipulators 
86
     */
80
    // Transfer state manipulators 
87 81
    void free_list_add(libusb_transfer *lut);
88 82
    void pending_list_add(libusb_transfer *lut);
89 83
    void completed_list_add(libusb_transfer *lut);
......
91 85
    libusb_transfer *completed_list_get();
92 86
    bool pending_list_remove(libusb_transfer *lut);
93 87

  
94
    /*
95
     * Misc
96
     */
88
    // Debug use
97 89
    void print_transfer_status(libusb_transfer *lut);
98 90

  
99 91
public:
......
103 95

  
104 96
    ~usb_endpoint();
105 97

  
106
    /*
107
     * Accessors 
108
     */
98
    // Accessors 
109 99
    int get_endpoint() const { return _endpoint; }
110 100
    bool get_direction() const { return _input; }
111 101
    libusb_device_handle *get_dev_handle() const { return _dev_handle; }
112 102
    libusb_context *get_ctx() const { return _ctx; }
113 103

  
114
    /*
115
     * Exposed interface for submitting / retrieving transfer buffers
116
     * used in zero-copy interface
117
     */
104
    // Exposed interface for submitting / retrieving transfer buffers
118 105
    bool submit(libusb_transfer *lut);
119 106
    libusb_transfer *get_completed_transfer();
120 107
    libusb_transfer *get_free_transfer();
121 108

  
122
    /*
123
     * Callback use only
124
     */
109
    //Callback use only
125 110
    void callback_handle_transfer(libusb_transfer *lut);
126 111
};
127 112

  
......
130 115
 * Callback function called when submitted transfers complete.
131 116
 * The endpoint upon which the transfer is part of is recovered
132 117
 * and the transfer moved from pending to completed state.
118
 * Callbacks occur during the reaping calls where libusb_handle_events()
119
 * is used. The callback only modifies the transfer state by moving
120
 * it from the pending to completed status list.
121
 * \param lut pointer to libusb_transfer
133 122
 */
134 123
static void callback(libusb_transfer *lut)
135 124
{
......
140 129

  
141 130
/*
142 131
 * Accessor call to allow list access from callback space
132
 * \param pointer to libusb_transfer
143 133
 */
144 134
void usb_endpoint::callback_handle_transfer(libusb_transfer *lut)
145 135
{
......
154 144

  
155 145
/*
156 146
 * Constructor
157
 *
158
 * Allocate libusb transfers. For IN endpoints, submit the transfers
159
 * so that they're ready to return when data is available. 
147
 * Allocate libusb transfers and mark as free.  For IN endpoints,
148
 * submit the transfers so that they're ready to return when
149
 * data is available. 
160 150
 */
161 151
usb_endpoint::usb_endpoint(libusb_device_handle *dev_handle,
162 152
                          libusb_context *ctx, int endpoint, bool input,
......
177 167

  
178 168
/*
179 169
 * Destructor
170
 * Make sure all the memory is freed. Cancel any pending transfers.
171
 * When all completed transfers are moved to the free list, release
172
 * the transfers. Libusb will deallocate the data buffer held by
173
 * each transfer.
180 174
 */
181 175
usb_endpoint::~usb_endpoint()
182 176
{
......
200 194

  
201 195
/*
202 196
 * Allocate a libusb transfer 
203
 *
204
 * The allocated transfer is continuously reused and should be freed at
205
 * shutdown.
197
 * The allocated transfer - and buffer it contains - is repeatedly
198
 * submitted, reaped, and reused and should not be freed until shutdown.
199
 * \param buff_len size of the individual buffer held by each transfer
200
 * \return pointer to an allocated libusb_transfer
206 201
 */
207 202
libusb_transfer *usb_endpoint::allocate_transfer(int buff_len)
208 203
{
......
226 221

  
227 222
/*
228 223
 * Asynchonous transfer submission
229
 *
230
 * Submit and mark transfer as pending.
224
 * Submit a libusb transfer to libusb add pending status
225
 * \param lut pointer to libusb_transfer
226
 * \return true on success or false on error 
231 227
 */
232 228
bool usb_endpoint::submit(libusb_transfer *lut)
233 229
{
......
244 240

  
245 241
/*
246 242
 * Cancel a pending transfer 
247
 *
248 243
 * Search the pending list for the transfer and cancel if found.
249
 * Returns true on success. False otherwise or on error. 
244
 * \param lut pointer to libusb_transfer to cancel
245
 * \return true on success or false if transfer is not found
250 246
 *
251 247
 * Note: success only indicates submission of cancelation request.
252 248
 * Sucessful cancelation is not known until the callback occurs.
......
266 262

  
267 263
/*
268 264
 * Cancel all pending transfers 
265
 * \return bool true if cancelation request is submitted
269 266
 *
270 267
 * Note: success only indicates submission of cancelation request.
271 268
 * Sucessful cancelation is not known until the callback occurs.
......
287 284

  
288 285
/*
289 286
 * Reap completed transfers
290
 * 
291 287
 * return true if at least one transfer was reaped, false otherwise. 
292
 *
293 288
 * Check completed transfers for errors and mark as free. This is a
294 289
 * blocking call. 
290
 * \return bool true if a libusb transfer is reaped, false otherwise
295 291
 */
296 292
bool usb_endpoint::reap_completed_list()
297 293
{
......
313 309

  
314 310

  
315 311
/*
316
 * Print completed transfer status error(s) 
317
 * 
318
 * return true if at least one transfer was reaped, false otherwise. 
319
 *
320
 * Check completed transfers for errors and mark as free. This is a
321
 * blocking call. 
312
 * Print status errors of a completed transfer
313
 * \param lut pointer to an libusb_transfer
322 314
 */
323 315
void usb_endpoint::print_transfer_status(libusb_transfer *lut)
324 316
{
......
359 351

  
360 352

  
361 353
/*
362
 * Reap pending transfers 
363
 *
364
 * Return true if at least one transfer was reaped, false otherwise. This is
365
 * a blocking call.
366
 *
367
 * Reaping submitted transfers is handled by libusb and the assigned callback
368
 * function. Block until at least one transfer is reaped.
354
 * Reap pending transfers without timeout 
355
 * This is a blocking call. Reaping submitted transfers is
356
 * handled by libusb and the assigned callback function.
357
 * Block until at least one transfer is reaped.
358
 * \return true true if a transfer was reaped or false otherwise
369 359
 */
370 360
bool usb_endpoint::reap_pending_list()
371 361
{
......
382 372

  
383 373
/*
384 374
 * Reap pending transfers with timeout 
385
 *
386
 * Return true if at least one transfer was reaped, false otherwise. This call
387
 * blocks until a transfer is reaped or timeout.
388
 *
389
 * Reaping submitted transfers is handled by libusb and the assigned callback
390
 * function. Block until at least one transfer is reaped or timeout occurs.
375
 * This call blocks until a transfer is reaped or timeout.
376
 * Reaping submitted transfers is handled by libusb and the
377
 * assigned callback function. Block until at least one
378
 * transfer is reaped or timeout occurs.
379
 * \return true if a transfer was reaped or false otherwise
391 380
 */
392 381
bool usb_endpoint::reap_pending_list_timeout()
393 382
{
......
414 403

  
415 404

  
416 405
/*
417
 * Returns a free transfer with empty data bufer for OUT requests 
406
 * Get a free transfer
407
 * The transfer has an empty data bufer for OUT requests 
408
 * \return pointer to a libusb_transfer
418 409
 */
419 410
libusb_transfer *usb_endpoint::get_free_transfer()
420 411
{
......
428 419

  
429 420

  
430 421
/*
431
 * Returns a transfer containing data for IN requests
422
 * Get a completed transfer 
423
 * The transfer has a full data buffer for IN requests
424
 * \return pointer to libusb_transfer
432 425
 */
433 426
libusb_transfer *usb_endpoint::get_completed_transfer()
434 427
{
......
461 454

  
462 455
/*
463 456
 * Free and completed lists don't have ordered content 
464
 *
465 457
 * Pop transfers from the front as needed
466 458
 */
467 459
libusb_transfer *usb_endpoint::free_list_get()
......
481 473

  
482 474
/*
483 475
 * Free and completed lists don't have ordered content 
484
 *
485 476
 * Pop transfers from the front as needed
486 477
 */
487 478
libusb_transfer *usb_endpoint::completed_list_get()
......
501 492

  
502 493
/*
503 494
 * Search and remove transfer from pending list
504
 *
505 495
 * Assuming that the callbacks occur in order, the front element
506 496
 * should yield the correct transfer. If not, then something else
507 497
 * is going on. If no transfers match, then something went wrong.
......
522 512
/***********************************************************************
523 513
 * Managed buffers 
524 514
 **********************************************************************/
515
/*
516
 * Libusb managed receive buffer
517
 * Construct a recv buffer from a libusb transfer. The memory held by
518
 * the libusb transfer is exposed through the managed buffer interface.
519
 * Upon destruction, the transfer and buffer are resubmitted to the
520
 * endpoint for further use. 
521
 */
525 522
class libusb_managed_recv_buffer_impl : public managed_recv_buffer {
526 523
public:
527 524
    libusb_managed_recv_buffer_impl(libusb_transfer *lut,
......
549 546
    const boost::asio::const_buffer _buff;
550 547
};
551 548

  
552

  
549
/*
550
 * Libusb managed send buffer
551
 * Construct a send buffer from a libusb transfer. The memory held by
552
 * the libusb transfer is exposed through the managed buffer interface.
553
 * Committing the buffer will set the data length and submit the buffer
554
 * to the endpoint. Submitting a buffer multiple times or destroying
555
 * the buffer before committing is an error. For the latter, the transfer
556
 * is returned to the endpoint with no data for reuse.
557
 */
553 558
class libusb_managed_send_buffer_impl : public managed_send_buffer {
554 559
public:
555 560
    libusb_managed_send_buffer_impl(libusb_transfer *lut,
......
613 618
    usb_endpoint          *_rx_ep;
614 619
    usb_endpoint          *_tx_ep;
615 620

  
616
    /*
617
     * Libusb handles
618
     */
621
    // Maintain libusb values
619 622
    libusb_context       *_rx_ctx;
620 623
    libusb_context       *_tx_ctx;
621 624
    libusb_device_handle *_rx_dev_handle;
......
628 631
public:
629 632
    typedef boost::shared_ptr<libusb_zero_copy_impl> sptr;
630 633

  
631
    /*
632
     * Structors
633
     */
634 634
    libusb_zero_copy_impl(usb_device_handle::sptr handle,
635 635
                          unsigned int rx_endpoint,
636 636
                          unsigned int tx_endpoint,
......
646 646
    size_t get_num_send_frames(void) const { return _num_frames; }
647 647
};
648 648

  
649

  
649
/*
650
 * Constructor
651
 * Initializes libusb, opens devices, and sets up interfaces for I/O.
652
 * Finally, creates endpoints for asynchronous I/O. 
653
 */
650 654
libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle,
651 655
                                             unsigned int rx_endpoint,
652 656
                                             unsigned int tx_endpoint,
......
656 660
   _recv_buff_size(block_size), _send_buff_size(block_size),
657 661
   _num_frames(buff_size / block_size)
658 662
{
663
    // Initialize libusb with separate contexts to allow
664
    // thread safe operation of transmit and receive 
659 665
    libusb::init(&_rx_ctx, libusb_debug_level);
660 666
    libusb::init(&_tx_ctx, libusb_debug_level);
661 667

  
662 668
    UHD_ASSERT_THROW((_rx_ctx != NULL) && (_tx_ctx != NULL));
663 669

  
670
    // Find and open the libusb_device corresponding to the
671
    // given handle and return the libusb_device_handle
672
    // that can be used for I/O purposes.
664 673
    _rx_dev_handle = libusb::open_device(_rx_ctx, handle);
665 674
    _tx_dev_handle = libusb::open_device(_tx_ctx, handle);
666 675

  
676
    // Open USB interfaces for tx/rx using magic values.
677
    // IN interface:      2
678
    // OUT interface:     1
679
    // Control interface: 0
667 680
    libusb::open_interface(_rx_dev_handle, 2);
668 681
    libusb::open_interface(_tx_dev_handle, 1);
669 682

  
670
    _rx_ep = new usb_endpoint(_rx_dev_handle,
671
                              _rx_ctx,
672
                              rx_endpoint,
673
                              true,
674
                              _recv_buff_size,
675
                              _num_frames); 
676

  
677
    _tx_ep = new usb_endpoint(_tx_dev_handle,
678
                              _tx_ctx,
679
                              tx_endpoint,
680
                              false,
681
                              _send_buff_size,
682
                              _num_frames);
683
    _rx_ep = new usb_endpoint(_rx_dev_handle,  // libusb device_handle
684
                              _rx_ctx,         // libusb context
685
                              rx_endpoint,     // USB endpoint number
686
                              true,            // IN endpoint
687
                              _recv_buff_size, // buffer size per transfer 
688
                              _num_frames);    // number of libusb transfers
689

  
690
    _tx_ep = new usb_endpoint(_tx_dev_handle,  // libusb device_handle
691
                              _tx_ctx,         // libusb context
692
                              tx_endpoint,     // USB endpoint number
693
                              false,           // OUT endpoint
694
                              _send_buff_size, // buffer size per transfer
695
                              _num_frames);    // number of libusb transfers
683 696
}
684 697

  
685 698

  
......
696 709
}
697 710

  
698 711

  
712
/*
713
 * Construct a managed receive buffer from a completed libusb transfer
714
 * (happy with buffer full of data) obtained from the receive endpoint.
715
 * Return empty pointer if no transfer is available (timeout or error).
716
 * \return pointer to a managed receive buffer 
717
 */
699 718
managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff()
700 719
{
701 720
    libusb_transfer *lut = _rx_ep->get_completed_transfer();
......
710 729
}
711 730

  
712 731

  
732
/*
733
 * Construct a managed send buffer from a free libusb transfer (with
734
 * empty buffer). Return empty pointer of no transfer is available
735
 * (timeout or error).
736
 * \return pointer to a managed send buffer 
737
 */
713 738
managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff()
714 739
{
715 740
    libusb_transfer *lut = _tx_ep->get_free_transfer();

Also available in: Unified diff