aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/transport/libusb1_zero_copy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/transport/libusb1_zero_copy.cpp')
-rw-r--r--host/lib/transport/libusb1_zero_copy.cpp66
1 files changed, 39 insertions, 27 deletions
diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp
index 3e67264cd..28bff9709 100644
--- a/host/lib/transport/libusb1_zero_copy.cpp
+++ b/host/lib/transport/libusb1_zero_copy.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <uhd/utils/msg.hpp>
#include <uhd/exception.hpp>
#include <boost/foreach.hpp>
+#include <boost/make_shared.hpp>
#include <boost/thread/thread.hpp>
#include <list>
@@ -61,8 +62,18 @@ static void LIBUSB_CALL libusb_async_cb(libusb_transfer *lut){
* \return true for completion, false for timeout
*/
UHD_INLINE bool wait_for_completion(libusb_context *ctx, const double timeout, bool &completed){
- const boost::system_time timeout_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1000000));
+ //already completed by a previous call?
+ if (completed) return true;
+
+ //perform a non-blocking event handle
+ timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ libusb_handle_events_timeout(ctx, &tv);
+ if (completed) return true;
+ //finish the rest with a timeout loop
+ const boost::system_time timeout_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1000000));
while (not completed and (boost::get_system_time() < timeout_time)){
timeval tv;
tv.tv_sec = 0;
@@ -82,21 +93,18 @@ class libusb_zero_copy_mrb : public managed_recv_buffer{
public:
libusb_zero_copy_mrb(libusb_transfer *lut, const size_t frame_size):
_ctx(libusb::session::get_global_session()->get_context()),
- _lut(lut), _expired(false), _frame_size(frame_size) { /* NOP */ }
+ _lut(lut), _frame_size(frame_size) { /* NOP */ }
void release(void){
- if (_expired) return;
completed = false;
_lut->length = _frame_size; //always reset length
UHD_ASSERT_THROW(libusb_submit_transfer(_lut) == 0);
- _expired = true;
}
sptr get_new(const double timeout, size_t &index){
if (wait_for_completion(_ctx, timeout, completed)){
index++;
- _expired = false;
- return make_managed_buffer(this);
+ return make(this, _lut->buffer, _lut->actual_length);
}
return managed_recv_buffer::sptr();
}
@@ -104,12 +112,8 @@ public:
bool completed;
private:
- const void *get_buff(void) const{return _lut->buffer;}
- size_t get_size(void) const{return _lut->actual_length;}
-
libusb_context *_ctx;
libusb_transfer *_lut;
- bool _expired;
const size_t _frame_size;
};
@@ -122,22 +126,18 @@ class libusb_zero_copy_msb : public managed_send_buffer{
public:
libusb_zero_copy_msb(libusb_transfer *lut, const size_t frame_size):
_ctx(libusb::session::get_global_session()->get_context()),
- _lut(lut), _expired(false), _frame_size(frame_size) { /* NOP */ }
+ _lut(lut), _frame_size(frame_size) { completed = true; }
- void commit(size_t len){
- if (_expired) return;
+ void release(void){
completed = false;
- _lut->length = len;
- if (len == 0) libusb_async_cb(_lut);
- else UHD_ASSERT_THROW(libusb_submit_transfer(_lut) == 0);
- _expired = true;
+ _lut->length = size();
+ UHD_ASSERT_THROW(libusb_submit_transfer(_lut) == 0);
}
sptr get_new(const double timeout, size_t &index){
if (wait_for_completion(_ctx, timeout, completed)){
index++;
- _expired = false;
- return make_managed_buffer(this);
+ return make(this, _lut->buffer, _frame_size);
}
return managed_send_buffer::sptr();
}
@@ -145,12 +145,8 @@ public:
bool completed;
private:
- void *get_buff(void) const{return _lut->buffer;}
- size_t get_size(void) const{return _frame_size;}
-
libusb_context *_ctx;
libusb_transfer *_lut;
- bool _expired;
const size_t _frame_size;
};
@@ -181,13 +177,30 @@ public:
_handle->claim_interface(recv_interface);
_handle->claim_interface(send_interface);
+ //flush the buffers out of the recv endpoint
+ //limit the flushing to at most one second
+ for (size_t i = 0; i < 100; i++)
+ {
+ unsigned char buff[512];
+ int transfered = 0;
+ const int status = libusb_bulk_transfer(
+ _handle->get(), // dev_handle
+ (recv_endpoint & 0x7f) | 0x80, // endpoint
+ static_cast<unsigned char *>(buff),
+ sizeof(buff),
+ &transfered, //bytes xfered
+ 10 //timeout ms
+ );
+ if (status == LIBUSB_ERROR_TIMEOUT) break;
+ }
+
//allocate libusb transfer structs and managed receive buffers
for (size_t i = 0; i < get_num_recv_frames(); i++){
libusb_transfer *lut = libusb_alloc_transfer(0);
UHD_ASSERT_THROW(lut != NULL);
- _mrb_pool.push_back(boost::shared_ptr<libusb_zero_copy_mrb>(new libusb_zero_copy_mrb(lut, this->get_recv_frame_size())));
+ _mrb_pool.push_back(boost::make_shared<libusb_zero_copy_mrb>(lut, this->get_recv_frame_size()));
libusb_fill_bulk_transfer(
lut, // transfer
@@ -210,7 +223,7 @@ public:
libusb_transfer *lut = libusb_alloc_transfer(0);
UHD_ASSERT_THROW(lut != NULL);
- _msb_pool.push_back(boost::shared_ptr<libusb_zero_copy_msb>(new libusb_zero_copy_msb(lut, this->get_send_frame_size())));
+ _msb_pool.push_back(boost::make_shared<libusb_zero_copy_msb>(lut, this->get_send_frame_size()));
libusb_fill_bulk_transfer(
lut, // transfer
@@ -224,7 +237,6 @@ public:
);
_all_luts.push_back(lut);
- _msb_pool.back()->commit(0);
}
}