aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorNicholas Corgan <nick.corgan@ettus.com>2015-08-06 10:42:23 -0700
committerNicholas Corgan <nick.corgan@ettus.com>2015-08-06 10:42:23 -0700
commit30f87afcba71a07fbd28d51318e791448c28314e (patch)
tree11393add7fde99950a252577882211845fe75d1d /host/lib
parentb08352f267730ea417ec345cd90833a6746a1114 (diff)
downloaduhd-30f87afcba71a07fbd28d51318e791448c28314e.tar.gz
uhd-30f87afcba71a07fbd28d51318e791448c28314e.tar.bz2
uhd-30f87afcba71a07fbd28d51318e791448c28314e.zip
uhd: C API wrapper
* multi_usrp, multi_usrp_clock, and associated classes accessible through C * Added Doxygen documentation explaining structure and API * Simple RX and TX streaming examples * Unit tests for different parts of C interface and C++ error conversion
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/CMakeLists.txt6
-rw-r--r--host/lib/error_c.cpp40
-rw-r--r--host/lib/types/CMakeLists.txt10
-rw-r--r--host/lib/types/metadata_c.cpp315
-rw-r--r--host/lib/types/ranges_c.cpp162
-rw-r--r--host/lib/types/sensors_c.cpp228
-rw-r--r--host/lib/types/tune_c.cpp76
-rw-r--r--host/lib/types/usrp_info_c.cpp44
-rw-r--r--host/lib/usrp/CMakeLists.txt11
-rw-r--r--host/lib/usrp/dboard_eeprom_c.cpp109
-rw-r--r--host/lib/usrp/mboard_eeprom_c.cpp72
-rw-r--r--host/lib/usrp/subdev_spec_c.cpp149
-rw-r--r--host/lib/usrp/usrp_c.cpp1509
-rw-r--r--host/lib/usrp_clock/CMakeLists.txt8
-rw-r--r--host/lib/usrp_clock/usrp_clock_c.cpp175
-rw-r--r--host/lib/utils/CMakeLists.txt6
-rw-r--r--host/lib/utils/thread_priority.cpp2
-rw-r--r--host/lib/utils/thread_priority_c.cpp33
18 files changed, 2952 insertions, 3 deletions
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 3d4ba8a68..f74af1f29 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -96,6 +96,12 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_BINARY_DIR}/version.cpp
)
+IF(ENABLE_C_API)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/error_c.cpp
+ )
+ENDIF(ENABLE_C_API)
+
########################################################################
# Add DLL resource file to Windows build
########################################################################
diff --git a/host/lib/error_c.cpp b/host/lib/error_c.cpp
new file mode 100644
index 000000000..c3a83eec9
--- /dev/null
+++ b/host/lib/error_c.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/error.h>
+#include <uhd/exception.hpp>
+
+#define MAP_TO_ERROR(exception_type, error_type) \
+ if (dynamic_cast<const uhd::exception_type*>(e)) return error_type;
+
+uhd_error error_from_uhd_exception(const uhd::exception* e){
+ MAP_TO_ERROR(index_error, UHD_ERROR_INDEX)
+ MAP_TO_ERROR(key_error, UHD_ERROR_KEY)
+ MAP_TO_ERROR(not_implemented_error, UHD_ERROR_NOT_IMPLEMENTED)
+ MAP_TO_ERROR(usb_error, UHD_ERROR_USB)
+ MAP_TO_ERROR(io_error, UHD_ERROR_IO)
+ MAP_TO_ERROR(os_error, UHD_ERROR_OS)
+ MAP_TO_ERROR(assertion_error, UHD_ERROR_ASSERTION)
+ MAP_TO_ERROR(lookup_error, UHD_ERROR_LOOKUP)
+ MAP_TO_ERROR(type_error, UHD_ERROR_TYPE)
+ MAP_TO_ERROR(value_error, UHD_ERROR_VALUE)
+ MAP_TO_ERROR(runtime_error, UHD_ERROR_RUNTIME)
+ MAP_TO_ERROR(environment_error, UHD_ERROR_ENVIRONMENT)
+ MAP_TO_ERROR(system_error, UHD_ERROR_SYSTEM)
+
+ return UHD_ERROR_EXCEPT;
+}
diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt
index 5e97628f0..d8938c8a8 100644
--- a/host/lib/types/CMakeLists.txt
+++ b/host/lib/types/CMakeLists.txt
@@ -94,3 +94,13 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/filters.cpp
${CMAKE_CURRENT_SOURCE_DIR}/byte_vector.cpp
)
+
+IF(ENABLE_C_API)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/metadata_c.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/ranges_c.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/sensors_c.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tune_c.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/usrp_info_c.cpp
+ )
+ENDIF()
diff --git a/host/lib/types/metadata_c.cpp b/host/lib/types/metadata_c.cpp
new file mode 100644
index 000000000..96f43d140
--- /dev/null
+++ b/host/lib/types/metadata_c.cpp
@@ -0,0 +1,315 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/metadata.h>
+
+#include <uhd/types/time_spec.hpp>
+
+#include <string.h>
+
+/*
+ * RX metadata
+ */
+
+uhd_error uhd_rx_metadata_make(
+ uhd_rx_metadata_handle* handle
+){
+ UHD_SAFE_C(
+ *handle = new uhd_rx_metadata_t;
+ )
+}
+
+uhd_error uhd_rx_metadata_free(
+ uhd_rx_metadata_handle* handle
+){
+ UHD_SAFE_C(
+ delete *handle;
+ *handle = NULL;
+ )
+}
+
+uhd_error uhd_rx_metadata_has_time_spec(
+ uhd_rx_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->rx_metadata_cpp.has_time_spec;
+ )
+}
+
+uhd_error uhd_rx_metadata_time_spec(
+ uhd_rx_metadata_handle h,
+ time_t *full_secs_out,
+ double *frac_secs_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp = h->rx_metadata_cpp.time_spec;
+ *full_secs_out = time_spec_cpp.get_full_secs();
+ *frac_secs_out = time_spec_cpp.get_frac_secs();
+ )
+}
+
+uhd_error uhd_rx_metadata_more_fragments(
+ uhd_rx_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->rx_metadata_cpp.more_fragments;
+ )
+}
+
+uhd_error uhd_rx_metadata_fragment_offset(
+ uhd_rx_metadata_handle h,
+ size_t *fragment_offset_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *fragment_offset_out = h->rx_metadata_cpp.fragment_offset;
+ )
+}
+
+uhd_error uhd_rx_metadata_start_of_burst(
+ uhd_rx_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->rx_metadata_cpp.start_of_burst;
+ )
+}
+
+uhd_error uhd_rx_metadata_end_of_burst(
+ uhd_rx_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->rx_metadata_cpp.end_of_burst;
+ )
+}
+
+uhd_error uhd_rx_metadata_out_of_sequence(
+ uhd_rx_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->rx_metadata_cpp.out_of_sequence;
+ )
+}
+
+uhd_error uhd_rx_metadata_to_pp_string(
+ uhd_rx_metadata_handle h,
+ char* pp_string_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string pp_string_cpp = h->rx_metadata_cpp.to_pp_string();
+ memset(pp_string_out, '\0', strbuffer_len);
+ strncpy(pp_string_out, pp_string_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_rx_metadata_error_code(
+ uhd_rx_metadata_handle h,
+ uhd_rx_metadata_error_code_t *error_code_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *error_code_out = uhd_rx_metadata_error_code_t(h->rx_metadata_cpp.error_code);
+ )
+}
+
+uhd_error uhd_rx_metadata_strerror(
+ uhd_rx_metadata_handle h,
+ char* strerror_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string strerror_cpp = h->rx_metadata_cpp.strerror();
+ memset(strerror_out, '\0', strbuffer_len);
+ strncpy(strerror_out, strerror_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_rx_metadata_last_error(
+ uhd_rx_metadata_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
+
+/*
+ * TX metadata
+ */
+
+uhd_error uhd_tx_metadata_make(
+ uhd_tx_metadata_handle* handle,
+ bool has_time_spec,
+ time_t full_secs,
+ double frac_secs,
+ bool start_of_burst,
+ bool end_of_burst
+){
+ UHD_SAFE_C(
+ *handle = new uhd_tx_metadata_t;
+ (*handle)->tx_metadata_cpp.has_time_spec = has_time_spec;
+ if(has_time_spec){
+ (*handle)->tx_metadata_cpp.time_spec = uhd::time_spec_t(full_secs, frac_secs);
+ }
+ (*handle)->tx_metadata_cpp.start_of_burst = start_of_burst;
+ (*handle)->tx_metadata_cpp.end_of_burst = end_of_burst;
+ )
+}
+
+uhd_error uhd_tx_metadata_free(
+ uhd_tx_metadata_handle* handle
+){
+ UHD_SAFE_C(
+ delete *handle;
+ *handle = NULL;
+ )
+}
+
+uhd_error uhd_tx_metadata_has_time_spec(
+ uhd_tx_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->tx_metadata_cpp.has_time_spec;
+ )
+}
+
+uhd_error uhd_tx_metadata_time_spec(
+ uhd_tx_metadata_handle h,
+ time_t *full_secs_out,
+ double *frac_secs_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp = h->tx_metadata_cpp.time_spec;
+ *full_secs_out = time_spec_cpp.get_full_secs();
+ *frac_secs_out = time_spec_cpp.get_frac_secs();
+ )
+}
+
+uhd_error uhd_tx_metadata_start_of_burst(
+ uhd_tx_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->tx_metadata_cpp.start_of_burst;
+ )
+}
+
+uhd_error uhd_tx_metadata_end_of_burst(
+ uhd_tx_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->tx_metadata_cpp.end_of_burst;
+ )
+}
+
+uhd_error uhd_tx_metadata_last_error(
+ uhd_tx_metadata_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
+
+/*
+ * Async metadata
+ */
+
+uhd_error uhd_async_metadata_make(
+ uhd_async_metadata_handle* handle
+){
+ UHD_SAFE_C(
+ *handle = new uhd_async_metadata_t;
+ )
+}
+
+uhd_error uhd_async_metadata_free(
+ uhd_async_metadata_handle* handle
+){
+ UHD_SAFE_C(
+ delete *handle;
+ *handle = NULL;
+ )
+}
+
+uhd_error uhd_async_metadata_channel(
+ uhd_async_metadata_handle h,
+ size_t *channel_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *channel_out = h->async_metadata_cpp.channel;
+ )
+}
+
+uhd_error uhd_async_metadata_has_time_spec(
+ uhd_async_metadata_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->async_metadata_cpp.has_time_spec;
+ )
+}
+
+uhd_error uhd_async_metadata_time_spec(
+ uhd_async_metadata_handle h,
+ time_t *full_secs_out,
+ double *frac_secs_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp = h->async_metadata_cpp.time_spec;
+ *full_secs_out = time_spec_cpp.get_full_secs();
+ *frac_secs_out = time_spec_cpp.get_frac_secs();
+ )
+}
+
+uhd_error uhd_async_metadata_event_code(
+ uhd_async_metadata_handle h,
+ uhd_async_metadata_event_code_t *event_code_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *event_code_out = uhd_async_metadata_event_code_t(h->async_metadata_cpp.event_code);
+ )
+}
+
+uhd_error uhd_async_metadata_user_payload(
+ uhd_async_metadata_handle h,
+ uint32_t user_payload_out[4]
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ memcpy(user_payload_out, h->async_metadata_cpp.user_payload, 4*sizeof(uint32_t));
+ )
+}
+
+uhd_error uhd_async_metadata_last_error(
+ uhd_async_metadata_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
diff --git a/host/lib/types/ranges_c.cpp b/host/lib/types/ranges_c.cpp
new file mode 100644
index 000000000..0c0df24ce
--- /dev/null
+++ b/host/lib/types/ranges_c.cpp
@@ -0,0 +1,162 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/ranges.h>
+
+#include <string.h>
+
+/*
+ * uhd::range_t
+ */
+uhd_error uhd_range_to_pp_string(
+ const uhd_range_t *range,
+ char* pp_string_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ uhd::range_t range_cpp = uhd_range_c_to_cpp(range);
+ std::string pp_string_cpp = range_cpp.to_pp_string();
+
+ memset(pp_string_out, '\0', strbuffer_len);
+ strncpy(pp_string_out, pp_string_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd::range_t uhd_range_c_to_cpp(
+ const uhd_range_t *range_c
+){
+ return uhd::range_t(range_c->start, range_c->stop, range_c->step);
+}
+
+void uhd_range_cpp_to_c(
+ const uhd::range_t &range_cpp,
+ uhd_range_t *range_c
+){
+ range_c->start = range_cpp.start();
+ range_c->stop = range_cpp.stop();
+ range_c->step = range_cpp.step();
+}
+
+/*
+ * uhd::meta_range_t
+ */
+uhd_error uhd_meta_range_make(
+ uhd_meta_range_handle* h
+){
+ UHD_SAFE_C(
+ (*h) = new uhd_meta_range_t;
+ )
+}
+
+uhd_error uhd_meta_range_free(
+ uhd_meta_range_handle* h
+){
+ UHD_SAFE_C(
+ delete (*h);
+ (*h) = NULL;
+ )
+}
+
+uhd_error uhd_meta_range_start(
+ uhd_meta_range_handle h,
+ double *start_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *start_out = h->meta_range_cpp.start();
+ )
+}
+
+uhd_error uhd_meta_range_stop(
+ uhd_meta_range_handle h,
+ double *stop_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *stop_out = h->meta_range_cpp.stop();
+ )
+}
+
+uhd_error uhd_meta_range_step(
+ uhd_meta_range_handle h,
+ double *step_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *step_out = h->meta_range_cpp.step();
+ )
+}
+
+uhd_error uhd_meta_range_clip(
+ uhd_meta_range_handle h,
+ double value,
+ bool clip_step,
+ double *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = h->meta_range_cpp.clip(value, clip_step);
+ )
+}
+
+uhd_error uhd_meta_range_size(
+ uhd_meta_range_handle h,
+ size_t *size_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *size_out = h->meta_range_cpp.size();
+ )
+}
+
+uhd_error uhd_meta_range_push_back(
+ uhd_meta_range_handle h,
+ const uhd_range_t *range
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ h->meta_range_cpp.push_back(uhd_range_c_to_cpp(range));
+ )
+}
+
+uhd_error uhd_meta_range_at(
+ uhd_meta_range_handle h,
+ size_t num,
+ uhd_range_t *range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd_range_cpp_to_c(h->meta_range_cpp.at(num),
+ range_out);
+ )
+}
+
+uhd_error uhd_meta_range_to_pp_string(
+ uhd_meta_range_handle h,
+ char* pp_string_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string pp_string_cpp = h->meta_range_cpp.to_pp_string();
+ memset(pp_string_out, '\0', strbuffer_len);
+ strncpy(pp_string_out, pp_string_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_meta_range_last_error(
+ uhd_meta_range_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
diff --git a/host/lib/types/sensors_c.cpp b/host/lib/types/sensors_c.cpp
new file mode 100644
index 000000000..f1976c102
--- /dev/null
+++ b/host/lib/types/sensors_c.cpp
@@ -0,0 +1,228 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/sensors.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <stdexcept>
+#include <string.h>
+#include <string>
+
+uhd_error uhd_sensor_value_make_from_bool(
+ uhd_sensor_value_handle* h,
+ const char* name,
+ bool value,
+ const char* utrue,
+ const char* ufalse
+){
+ try{
+ *h = new uhd_sensor_value_t;
+ }
+ catch(...){
+ return UHD_ERROR_UNKNOWN;
+ }
+
+ UHD_SAFE_C_SAVE_ERROR((*h),
+ (*h)->sensor_value_cpp = new uhd::sensor_value_t(name,
+ value,
+ utrue,
+ ufalse);
+ )
+}
+
+uhd_error uhd_sensor_value_make_from_int(
+ uhd_sensor_value_handle* h,
+ const char* name,
+ int value,
+ const char* unit,
+ const char* formatter
+){
+ try{
+ *h = new uhd_sensor_value_t;
+ }
+ catch(...){
+ return UHD_ERROR_UNKNOWN;
+ }
+
+ UHD_SAFE_C_SAVE_ERROR((*h),
+ std::string fmt(formatter);
+ if(fmt.empty()){
+ (*h)->sensor_value_cpp = new uhd::sensor_value_t(name,
+ value,
+ unit);
+ }
+ else{
+ (*h)->sensor_value_cpp = new uhd::sensor_value_t(name,
+ value,
+ unit,
+ fmt);
+ }
+ )
+}
+
+uhd_error uhd_sensor_value_make_from_realnum(
+ uhd_sensor_value_handle* h,
+ const char* name,
+ double value,
+ const char* unit,
+ const char* formatter
+){
+ try{
+ *h = new uhd_sensor_value_t;
+ }
+ catch(...){
+ return UHD_ERROR_UNKNOWN;
+ }
+
+ UHD_SAFE_C_SAVE_ERROR((*h),
+ std::string fmt(formatter);
+ if(fmt.empty()){
+ (*h)->sensor_value_cpp = new uhd::sensor_value_t(name,
+ value,
+ unit);
+ }
+ else{
+ (*h)->sensor_value_cpp = new uhd::sensor_value_t(name,
+ value,
+ unit,
+ fmt);
+ }
+ )
+}
+
+uhd_error uhd_sensor_value_make_from_string(
+ uhd_sensor_value_handle* h,
+ const char* name,
+ const char* value,
+ const char* unit
+){
+ try{
+ *h = new uhd_sensor_value_t;
+ }
+ catch(...){
+ return UHD_ERROR_UNKNOWN;
+ }
+
+ UHD_SAFE_C_SAVE_ERROR((*h),
+ (*h)->sensor_value_cpp = new uhd::sensor_value_t(name,
+ value,
+ unit);
+ )
+}
+
+uhd_error uhd_sensor_value_free(
+ uhd_sensor_value_handle *h
+){
+ UHD_SAFE_C(
+ delete (*h)->sensor_value_cpp;
+ delete *h;
+ *h = NULL;
+ )
+}
+
+uhd_error uhd_sensor_value_to_bool(
+ uhd_sensor_value_handle h,
+ bool *value_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *value_out = h->sensor_value_cpp->to_bool();
+ )
+}
+
+uhd_error uhd_sensor_value_to_int(
+ uhd_sensor_value_handle h,
+ int *value_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *value_out = h->sensor_value_cpp->to_int();
+ )
+}
+
+uhd_error uhd_sensor_value_to_realnum(
+ uhd_sensor_value_handle h,
+ double *value_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *value_out = h->sensor_value_cpp->to_real();
+ )
+}
+
+uhd_error uhd_sensor_value_name(
+ uhd_sensor_value_handle h,
+ char* name_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ memset(name_out, '\0', strbuffer_len);
+ strncpy(name_out, h->sensor_value_cpp->name.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_sensor_value_value(
+ uhd_sensor_value_handle h,
+ char* value_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ memset(value_out, '\0', strbuffer_len);
+ strncpy(value_out, h->sensor_value_cpp->value.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_sensor_value_unit(
+ uhd_sensor_value_handle h,
+ char* unit_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ memset(unit_out, '\0', strbuffer_len);
+ strncpy(unit_out, h->sensor_value_cpp->unit.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_sensor_value_data_type(
+ uhd_sensor_value_handle h,
+ uhd_sensor_value_data_type_t *data_type_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *data_type_out = uhd_sensor_value_data_type_t(h->sensor_value_cpp->type);
+ )
+}
+
+uhd_error uhd_sensor_value_to_pp_string(
+ uhd_sensor_value_handle h,
+ char* pp_string_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string pp_string_cpp = h->sensor_value_cpp->to_pp_string();
+ memset(pp_string_out, '\0', strbuffer_len);
+ strncpy(pp_string_out, pp_string_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_sensor_value_last_error(
+ uhd_sensor_value_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
diff --git a/host/lib/types/tune_c.cpp b/host/lib/types/tune_c.cpp
new file mode 100644
index 000000000..c62935cb8
--- /dev/null
+++ b/host/lib/types/tune_c.cpp
@@ -0,0 +1,76 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/tune_request.h>
+#include <uhd/types/tune_result.h>
+
+#include <boost/format.hpp>
+
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+/*
+ * Tune request
+ */
+
+uhd::tune_request_t uhd_tune_request_c_to_cpp(uhd_tune_request_t *tune_request_c){
+ uhd::tune_request_t tune_request_cpp;
+
+ tune_request_cpp.target_freq = tune_request_c->target_freq;
+ tune_request_cpp.rf_freq_policy = uhd::tune_request_t::policy_t(tune_request_c->rf_freq_policy);
+ tune_request_cpp.rf_freq = tune_request_c->rf_freq;
+ tune_request_cpp.dsp_freq_policy = uhd::tune_request_t::policy_t(tune_request_c->dsp_freq_policy);
+ tune_request_cpp.dsp_freq = tune_request_c->dsp_freq;
+
+ std::string args_cpp = (tune_request_c->args) ? tune_request_c->args : std::string("");
+ tune_request_cpp.args = uhd::device_addr_t(args_cpp);
+
+ return tune_request_cpp;
+}
+
+/*
+ * Tune result
+ */
+
+void uhd_tune_result_to_pp_string(uhd_tune_result_t *tune_result_c,
+ char* pp_string_out, size_t strbuffer_len){
+ std::string pp_string_cpp = uhd_tune_result_c_to_cpp(tune_result_c).to_pp_string();
+ memset(pp_string_out, '\0', strbuffer_len);
+ strncpy(pp_string_out, pp_string_cpp.c_str(), strbuffer_len);
+}
+
+uhd::tune_result_t uhd_tune_result_c_to_cpp(uhd_tune_result_t *tune_result_c){
+ uhd::tune_result_t tune_result_cpp;
+
+ tune_result_cpp.clipped_rf_freq = tune_result_c->clipped_rf_freq;
+ tune_result_cpp.target_rf_freq = tune_result_c->target_rf_freq;
+ tune_result_cpp.actual_rf_freq = tune_result_c->actual_rf_freq;
+ tune_result_cpp.target_dsp_freq = tune_result_c->target_dsp_freq;
+ tune_result_cpp.actual_dsp_freq = tune_result_c->actual_dsp_freq;
+
+ return tune_result_cpp;
+}
+
+void uhd_tune_result_cpp_to_c(const uhd::tune_result_t &tune_result_cpp,
+ uhd_tune_result_t *tune_result_c){
+ tune_result_c->clipped_rf_freq = tune_result_cpp.clipped_rf_freq;
+ tune_result_c->target_rf_freq = tune_result_cpp.target_rf_freq;
+ tune_result_c->actual_rf_freq = tune_result_cpp.actual_rf_freq;
+ tune_result_c->target_dsp_freq = tune_result_cpp.target_dsp_freq;
+ tune_result_c->actual_dsp_freq = tune_result_cpp.actual_dsp_freq;
+}
diff --git a/host/lib/types/usrp_info_c.cpp b/host/lib/types/usrp_info_c.cpp
new file mode 100644
index 000000000..77354d901
--- /dev/null
+++ b/host/lib/types/usrp_info_c.cpp
@@ -0,0 +1,44 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/usrp_info.h>
+
+uhd_error uhd_usrp_rx_info_free(uhd_usrp_rx_info_t *rx_info){
+ free(rx_info->mboard_id);
+ free(rx_info->mboard_name);
+ free(rx_info->mboard_serial);
+ free(rx_info->rx_id);
+ free(rx_info->rx_subdev_name);
+ free(rx_info->rx_subdev_spec);
+ free(rx_info->rx_serial);
+ free(rx_info->rx_antenna);
+
+ return UHD_ERROR_NONE;
+}
+
+uhd_error uhd_usrp_tx_info_free(uhd_usrp_tx_info_t *tx_info){
+ free(tx_info->mboard_id);
+ free(tx_info->mboard_name);
+ free(tx_info->mboard_serial);
+ free(tx_info->tx_id);
+ free(tx_info->tx_subdev_name);
+ free(tx_info->tx_subdev_spec);
+ free(tx_info->tx_serial);
+ free(tx_info->tx_antenna);
+
+ return UHD_ERROR_NONE;
+}
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index ce913aaf6..e01e5e09d 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010-2013 Ettus Research LLC
+# Copyright 2010-2015 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
@@ -34,6 +34,15 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/subdev_spec.cpp
)
+IF(ENABLE_C_API)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/dboard_eeprom_c.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/mboard_eeprom_c.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/subdev_spec_c.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/usrp_c.cpp
+ )
+ENDIF(ENABLE_C_API)
+
LIBUHD_REGISTER_COMPONENT("GPSD" ENABLE_GPSD OFF "ENABLE_LIBUHD;ENABLE_GPSD;LIBGPS_FOUND" OFF)
IF(ENABLE_GPSD)
diff --git a/host/lib/usrp/dboard_eeprom_c.cpp b/host/lib/usrp/dboard_eeprom_c.cpp
new file mode 100644
index 000000000..e3ef4933f
--- /dev/null
+++ b/host/lib/usrp/dboard_eeprom_c.cpp
@@ -0,0 +1,109 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/usrp/dboard_eeprom.h>
+#include <uhd/error.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <string.h>
+
+uhd_error uhd_dboard_eeprom_make(
+ uhd_dboard_eeprom_handle* h
+){
+ UHD_SAFE_C(
+ *h = new uhd_dboard_eeprom_t;
+ )
+}
+
+uhd_error uhd_dboard_eeprom_free(
+ uhd_dboard_eeprom_handle* h
+){
+ UHD_SAFE_C(
+ delete *h;
+ *h = NULL;
+ )
+}
+
+uhd_error uhd_dboard_eeprom_get_id(
+ uhd_dboard_eeprom_handle h,
+ char* id_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string dboard_id_cpp = h->dboard_eeprom_cpp.id.to_string();
+ strncpy(id_out, dboard_id_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_dboard_eeprom_set_id(
+ uhd_dboard_eeprom_handle h,
+ const char* id
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ h->dboard_eeprom_cpp.id = uhd::usrp::dboard_id_t::from_string(id);
+ )
+}
+
+uhd_error uhd_dboard_eeprom_get_serial(
+ uhd_dboard_eeprom_handle h,
+ char* id_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string dboard_serial_cpp = h->dboard_eeprom_cpp.serial;
+ strncpy(id_out, dboard_serial_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_dboard_eeprom_set_serial(
+ uhd_dboard_eeprom_handle h,
+ const char* serial
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ h->dboard_eeprom_cpp.serial = serial;
+ )
+}
+
+uhd_error uhd_dboard_eeprom_get_revision(
+ uhd_dboard_eeprom_handle h,
+ int* revision_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *revision_out = boost::lexical_cast<int>(h->dboard_eeprom_cpp.revision);
+ )
+}
+
+uhd_error uhd_dboard_eeprom_set_revision(
+ uhd_dboard_eeprom_handle h,
+ int revision
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ h->dboard_eeprom_cpp.revision = boost::lexical_cast<std::string>(revision);
+ )
+}
+
+uhd_error uhd_dboard_eeprom_last_error(
+ uhd_dboard_eeprom_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
diff --git a/host/lib/usrp/mboard_eeprom_c.cpp b/host/lib/usrp/mboard_eeprom_c.cpp
new file mode 100644
index 000000000..8d5c069b9
--- /dev/null
+++ b/host/lib/usrp/mboard_eeprom_c.cpp
@@ -0,0 +1,72 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/usrp/mboard_eeprom.h>
+
+#include <uhd/exception.hpp>
+
+#include <string.h>
+
+uhd_error uhd_mboard_eeprom_make(
+ uhd_mboard_eeprom_handle* h
+){
+ UHD_SAFE_C(
+ *h = new uhd_mboard_eeprom_t;
+ )
+}
+
+uhd_error uhd_mboard_eeprom_free(
+ uhd_mboard_eeprom_handle* h
+){
+ UHD_SAFE_C(
+ delete *h;
+ *h = NULL;
+ )
+}
+
+uhd_error uhd_mboard_eeprom_get_value(
+ uhd_mboard_eeprom_handle h,
+ const char* key,
+ char* value_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string value_cpp = h->mboard_eeprom_cpp.get(key);
+ strncpy(value_out, value_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_mboard_eeprom_set_value(
+ uhd_mboard_eeprom_handle h,
+ const char* key,
+ const char* value
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ h->mboard_eeprom_cpp[key] = value;
+ )
+}
+
+uhd_error uhd_mboard_eeprom_last_error(
+ uhd_mboard_eeprom_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
diff --git a/host/lib/usrp/subdev_spec_c.cpp b/host/lib/usrp/subdev_spec_c.cpp
new file mode 100644
index 000000000..2c9c20506
--- /dev/null
+++ b/host/lib/usrp/subdev_spec_c.cpp
@@ -0,0 +1,149 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/usrp/subdev_spec.h>
+
+#include <string.h>
+
+uhd_error uhd_subdev_spec_pair_free(
+ uhd_subdev_spec_pair_t *subdev_spec_pair
+){
+ UHD_SAFE_C(
+ if(subdev_spec_pair->db_name){
+ free(subdev_spec_pair->db_name);
+ subdev_spec_pair->db_name = NULL;
+ }
+ if(subdev_spec_pair->sd_name){
+ free(subdev_spec_pair->sd_name);
+ subdev_spec_pair->sd_name = NULL;
+ }
+ )
+}
+
+uhd_error uhd_subdev_spec_pairs_equal(
+ const uhd_subdev_spec_pair_t* first,
+ const uhd_subdev_spec_pair_t* second,
+ bool *result_out
+){
+ UHD_SAFE_C(
+ *result_out = (uhd_subdev_spec_pair_c_to_cpp(first) ==
+ uhd_subdev_spec_pair_c_to_cpp(second));
+ )
+}
+
+uhd_error uhd_subdev_spec_make(
+ uhd_subdev_spec_handle* h,
+ const char* markup
+){
+ UHD_SAFE_C(
+ (*h) = new uhd_subdev_spec_t;
+ std::string markup_cpp(markup);
+ if(!markup_cpp.empty()){
+ (*h)->subdev_spec_cpp = uhd::usrp::subdev_spec_t(markup_cpp);
+ }
+ )
+}
+
+uhd_error uhd_subdev_spec_free(
+ uhd_subdev_spec_handle* h
+){
+ UHD_SAFE_C(
+ delete (*h);
+ (*h) = NULL;
+ )
+}
+
+uhd_error uhd_subdev_spec_size(
+ uhd_subdev_spec_handle h,
+ size_t *size_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *size_out = h->subdev_spec_cpp.size();
+ )
+}
+
+uhd_error uhd_subdev_spec_push_back(
+ uhd_subdev_spec_handle h,
+ const char* markup
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ h->subdev_spec_cpp.push_back(uhd::usrp::subdev_spec_pair_t(markup));
+ )
+}
+
+uhd_error uhd_subdev_spec_at(
+ uhd_subdev_spec_handle h,
+ size_t num,
+ uhd_subdev_spec_pair_t *subdev_spec_pair_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd_subdev_spec_pair_cpp_to_c(
+ h->subdev_spec_cpp.at(num),
+ subdev_spec_pair_out
+ );
+ )
+}
+
+uhd_error uhd_subdev_spec_to_pp_string(
+ uhd_subdev_spec_handle h,
+ char* pp_string_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string pp_string_cpp = h->subdev_spec_cpp.to_pp_string();
+ memset(pp_string_out, '\0', strbuffer_len);
+ strncpy(pp_string_out, pp_string_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_subdev_spec_to_string(
+ uhd_subdev_spec_handle h,
+ char* string_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string string_cpp = h->subdev_spec_cpp.to_string();
+ memset(string_out, '\0', strbuffer_len);
+ strncpy(string_out, string_cpp.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_subdev_spec_last_error(
+ uhd_subdev_spec_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
+
+uhd::usrp::subdev_spec_pair_t uhd_subdev_spec_pair_c_to_cpp(
+ const uhd_subdev_spec_pair_t *subdev_spec_pair_c
+){
+ return uhd::usrp::subdev_spec_pair_t(subdev_spec_pair_c->db_name,
+ subdev_spec_pair_c->sd_name);
+}
+
+void uhd_subdev_spec_pair_cpp_to_c(
+ const uhd::usrp::subdev_spec_pair_t &subdev_spec_pair_cpp,
+ uhd_subdev_spec_pair_t *subdev_spec_pair_c
+){
+ subdev_spec_pair_c->db_name = strdup(subdev_spec_pair_cpp.db_name.c_str());
+ subdev_spec_pair_c->sd_name = strdup(subdev_spec_pair_cpp.sd_name.c_str());
+}
diff --git a/host/lib/usrp/usrp_c.cpp b/host/lib/usrp/usrp_c.cpp
new file mode 100644
index 000000000..3eaf70405
--- /dev/null
+++ b/host/lib/usrp/usrp_c.cpp
@@ -0,0 +1,1509 @@
+/*
+ * Copyright 2015 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* C-Interface for multi_usrp */
+
+#include <uhd/utils/static.hpp>
+#include <uhd/usrp/multi_usrp.hpp>
+
+#include <uhd/error.h>
+#include <uhd/usrp/usrp.h>
+
+#include <boost/foreach.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <string.h>
+#include <map>
+
+/****************************************************************************
+ * Helpers
+ ***************************************************************************/
+uhd::stream_args_t stream_args_c_to_cpp(const uhd_stream_args_t *stream_args_c)
+{
+ std::string otw_format(stream_args_c->otw_format);
+ std::string cpu_format(stream_args_c->cpu_format);
+ std::string args(stream_args_c->args);
+ std::vector<size_t> channels(stream_args_c->channel_list, stream_args_c->channel_list + stream_args_c->n_channels);
+
+ uhd::stream_args_t stream_args_cpp(cpu_format, otw_format);
+ stream_args_cpp.args = args;
+ stream_args_cpp.channels = channels;
+
+ return stream_args_cpp;
+}
+
+uhd::stream_cmd_t stream_cmd_c_to_cpp(const uhd_stream_cmd_t *stream_cmd_c)
+{
+ uhd::stream_cmd_t stream_cmd_cpp(uhd::stream_cmd_t::stream_mode_t(stream_cmd_c->stream_mode));
+ stream_cmd_cpp.num_samps = stream_cmd_c->num_samps;
+ stream_cmd_cpp.stream_now = stream_cmd_c->stream_now;
+ stream_cmd_cpp.time_spec = uhd::time_spec_t(stream_cmd_c->time_spec_full_secs, stream_cmd_c->time_spec_frac_secs);
+ return stream_cmd_cpp;
+}
+
+/****************************************************************************
+ * Registry / Pointer Management
+ ***************************************************************************/
+/* Public structs */
+struct uhd_usrp {
+ size_t usrp_index;
+ std::string last_error;
+};
+
+struct uhd_tx_streamer {
+ size_t usrp_index;
+ size_t streamer_index;
+ std::string last_error;
+};
+
+struct uhd_rx_streamer {
+ size_t usrp_index;
+ size_t streamer_index;
+ std::string last_error;
+};
+
+/* Not public: We use this for our internal registry */
+struct usrp_ptr {
+ uhd::usrp::multi_usrp::sptr ptr;
+ std::vector< uhd::rx_streamer::sptr > rx_streamers;
+ std::vector< uhd::tx_streamer::sptr > tx_streamers;
+ static size_t usrp_counter;
+};
+size_t usrp_ptr::usrp_counter = 0;
+typedef struct usrp_ptr usrp_ptr;
+/* Prefer map, because the list can be discontiguous */
+typedef std::map<size_t, usrp_ptr> usrp_ptrs;
+
+UHD_SINGLETON_FCN(usrp_ptrs, get_usrp_ptrs);
+/* Shortcut for accessing the underlying USRP sptr from a uhd_usrp_handle* */
+#define USRP(h_ptr) (get_usrp_ptrs()[h_ptr->usrp_index].ptr)
+#define RX_STREAMER(h_ptr) (get_usrp_ptrs()[h_ptr->usrp_index].rx_streamers[h_ptr->streamer_index])
+#define TX_STREAMER(h_ptr) (get_usrp_ptrs()[h_ptr->usrp_index].tx_streamers[h_ptr->streamer_index])
+
+/****************************************************************************
+ * RX Streamer
+ ***************************************************************************/
+static boost::mutex _rx_streamer_make_mutex;
+uhd_error uhd_rx_streamer_make(uhd_rx_streamer_handle* h){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock(_rx_streamer_make_mutex);
+ (*h) = new uhd_rx_streamer;
+ )
+}
+
+static boost::mutex _rx_streamer_free_mutex;
+uhd_error uhd_rx_streamer_free(uhd_rx_streamer_handle* h){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_rx_streamer_free_mutex);
+ delete (*h);
+ (*h) = NULL;
+ )
+}
+
+uhd_error uhd_rx_streamer_num_channels(uhd_rx_streamer_handle h,
+ size_t *num_channels_out){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *num_channels_out = RX_STREAMER(h)->get_num_channels();
+ )
+}
+
+uhd_error uhd_rx_streamer_max_num_samps(uhd_rx_streamer_handle h,
+ size_t *max_num_samps_out){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *max_num_samps_out = RX_STREAMER(h)->get_max_num_samps();
+ )
+}
+
+uhd_error uhd_rx_streamer_recv(
+ uhd_rx_streamer_handle h,
+ void **buffs,
+ size_t samps_per_buff,
+ uhd_rx_metadata_handle md,
+ double timeout,
+ bool one_packet,
+ size_t *items_recvd
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::rx_streamer::buffs_type buffs_cpp(buffs, RX_STREAMER(h)->get_num_channels());
+ *items_recvd = RX_STREAMER(h)->recv(buffs_cpp, samps_per_buff, md->rx_metadata_cpp, timeout, one_packet);
+ )
+}
+
+uhd_error uhd_rx_streamer_issue_stream_cmd(
+ uhd_rx_streamer_handle h,
+ const uhd_stream_cmd_t *stream_cmd
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ RX_STREAMER(h)->issue_stream_cmd(stream_cmd_c_to_cpp(stream_cmd));
+ )
+}
+
+uhd_error uhd_rx_streamer_last_error(
+ uhd_rx_streamer_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
+
+/****************************************************************************
+ * TX Streamer
+ ***************************************************************************/
+static boost::mutex _tx_streamer_make_mutex;
+uhd_error uhd_tx_streamer_make(
+ uhd_tx_streamer_handle* h
+){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_tx_streamer_make_mutex);
+ (*h) = new uhd_tx_streamer;
+ )
+}
+
+static boost::mutex _tx_streamer_free_mutex;
+uhd_error uhd_tx_streamer_free(
+ uhd_tx_streamer_handle* h
+){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_tx_streamer_free_mutex);
+ delete *h;
+ *h = NULL;
+ )
+}
+
+uhd_error uhd_tx_streamer_num_channels(
+ uhd_tx_streamer_handle h,
+ size_t *num_channels_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *num_channels_out = TX_STREAMER(h)->get_num_channels();
+ )
+}
+
+uhd_error uhd_tx_streamer_max_num_samps(
+ uhd_tx_streamer_handle h,
+ size_t *max_num_samps_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *max_num_samps_out = TX_STREAMER(h)->get_max_num_samps();
+ )
+}
+
+uhd_error uhd_tx_streamer_send(
+ uhd_tx_streamer_handle h,
+ const void **buffs,
+ const size_t samps_per_buff,
+ const uhd_tx_metadata_handle md,
+ const double timeout,
+ size_t *items_sent
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::tx_streamer::buffs_type buffs_cpp(buffs, TX_STREAMER(h)->get_num_channels());
+ *items_sent = TX_STREAMER(h)->send(
+ buffs_cpp,
+ samps_per_buff,
+ md->tx_metadata_cpp,
+ timeout
+ );
+ )
+}
+
+uhd_error uhd_tx_streamer_recv_async_msg(
+ uhd_tx_streamer_handle h,
+ uhd_async_metadata_handle md,
+ const double timeout,
+ bool *valid
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *valid = TX_STREAMER(h)->recv_async_msg(md->async_metadata_cpp, timeout);
+ )
+}
+
+uhd_error uhd_tx_streamer_last_error(
+ uhd_tx_streamer_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
+
+/****************************************************************************
+ * Generate / Destroy API calls
+ ***************************************************************************/
+static boost::mutex _usrp_make_mutex;
+uhd_error uhd_usrp_make(
+ uhd_usrp_handle *h,
+ const char *args
+){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_usrp_make_mutex);
+
+ size_t usrp_count = usrp_ptr::usrp_counter;
+ usrp_ptr::usrp_counter++;
+
+ // Initialize USRP
+ uhd::device_addr_t device_addr(args);
+ usrp_ptr P;
+ P.ptr = uhd::usrp::multi_usrp::make(device_addr);
+
+ // Dump into registry
+ get_usrp_ptrs()[usrp_count] = P;
+
+ // Update handle
+ (*h) = new uhd_usrp;
+ (*h)->usrp_index = usrp_count;
+ )
+}
+
+static boost::mutex _usrp_free_mutex;
+uhd_error uhd_usrp_free(
+ uhd_usrp_handle *h
+){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_usrp_free_mutex);
+
+ if(!get_usrp_ptrs().count((*h)->usrp_index)){
+ return UHD_ERROR_INVALID_DEVICE;
+ }
+
+ get_usrp_ptrs().erase((*h)->usrp_index);
+ delete *h;
+ *h = NULL;
+ )
+}
+
+uhd_error uhd_usrp_last_error(
+ uhd_usrp_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
+
+static boost::mutex _usrp_get_rx_stream_mutex;
+uhd_error uhd_usrp_get_rx_stream(
+ uhd_usrp_handle h_u,
+ uhd_stream_args_t *stream_args,
+ uhd_rx_streamer_handle h_s
+){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_usrp_get_rx_stream_mutex);
+
+ if(!get_usrp_ptrs().count(h_u->usrp_index)){
+ return UHD_ERROR_INVALID_DEVICE;
+ }
+
+ usrp_ptr &usrp = get_usrp_ptrs()[h_u->usrp_index];
+ usrp.rx_streamers.push_back(
+ usrp.ptr->get_rx_stream(stream_args_c_to_cpp(stream_args))
+ );
+ h_s->usrp_index = h_u->usrp_index;
+ h_s->streamer_index = usrp.rx_streamers.size() - 1;
+ )
+}
+
+static boost::mutex _usrp_get_tx_stream_mutex;
+uhd_error uhd_usrp_get_tx_stream(
+ uhd_usrp_handle h_u,
+ uhd_stream_args_t *stream_args,
+ uhd_tx_streamer_handle h_s
+){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_usrp_get_tx_stream_mutex);
+
+ if(!get_usrp_ptrs().count(h_u->usrp_index)){
+ return UHD_ERROR_INVALID_DEVICE;
+ }
+
+ usrp_ptr &usrp = get_usrp_ptrs()[h_u->usrp_index];
+ usrp.tx_streamers.push_back(
+ usrp.ptr->get_tx_stream(stream_args_c_to_cpp(stream_args))
+ );
+ h_s->usrp_index = h_u->usrp_index;
+ h_s->streamer_index = usrp.tx_streamers.size() - 1;
+ )
+}
+
+/****************************************************************************
+ * multi_usrp API calls
+ ***************************************************************************/
+
+#define COPY_INFO_FIELD(out, dict, field) \
+ out->field = strdup(dict.get(BOOST_STRINGIZE(field)).c_str())
+
+uhd_error uhd_usrp_get_rx_info(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_usrp_rx_info_t *info_out
+) {
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::dict<std::string, std::string> rx_info = USRP(h)->get_usrp_rx_info(chan);
+
+ COPY_INFO_FIELD(info_out, rx_info, mboard_id);
+ COPY_INFO_FIELD(info_out, rx_info, mboard_serial);
+ COPY_INFO_FIELD(info_out, rx_info, rx_id);
+ COPY_INFO_FIELD(info_out, rx_info, rx_subdev_name);
+ COPY_INFO_FIELD(info_out, rx_info, rx_subdev_spec);
+ COPY_INFO_FIELD(info_out, rx_info, rx_serial);
+ COPY_INFO_FIELD(info_out, rx_info, rx_antenna);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_info(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_usrp_tx_info_t *info_out
+) {
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::dict<std::string, std::string> tx_info = USRP(h)->get_usrp_tx_info(chan);
+
+ COPY_INFO_FIELD(info_out, tx_info, mboard_id);
+ COPY_INFO_FIELD(info_out, tx_info, mboard_serial);
+ COPY_INFO_FIELD(info_out, tx_info, tx_id);
+ COPY_INFO_FIELD(info_out, tx_info, tx_subdev_name);
+ COPY_INFO_FIELD(info_out, tx_info, tx_subdev_spec);
+ COPY_INFO_FIELD(info_out, tx_info, tx_serial);
+ COPY_INFO_FIELD(info_out, tx_info, tx_antenna);
+ )
+}
+
+/****************************************************************************
+ * Motherboard methods
+ ***************************************************************************/
+uhd_error uhd_usrp_set_master_clock_rate(
+ uhd_usrp_handle h,
+ double rate,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_master_clock_rate(rate, mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_master_clock_rate(
+ uhd_usrp_handle h,
+ size_t mboard,
+ double *clock_rate_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *clock_rate_out = USRP(h)->get_master_clock_rate(mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_pp_string(
+ uhd_usrp_handle h,
+ char* pp_string_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ strncpy(pp_string_out, USRP(h)->get_pp_string().c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_get_mboard_name(
+ uhd_usrp_handle h,
+ size_t mboard,
+ char* mboard_name_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ strncpy(mboard_name_out, USRP(h)->get_mboard_name(mboard).c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_get_time_now(
+ uhd_usrp_handle h,
+ size_t mboard,
+ time_t *full_secs_out,
+ double *frac_secs_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp = USRP(h)->get_time_now(mboard);
+ *full_secs_out = time_spec_cpp.get_full_secs();
+ *frac_secs_out = time_spec_cpp.get_frac_secs();
+ )
+}
+
+uhd_error uhd_usrp_get_time_last_pps(
+ uhd_usrp_handle h,
+ size_t mboard,
+ time_t *full_secs_out,
+ double *frac_secs_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp = USRP(h)->get_time_last_pps(mboard);
+ *full_secs_out = time_spec_cpp.get_full_secs();
+ *frac_secs_out = time_spec_cpp.get_frac_secs();
+ )
+}
+
+uhd_error uhd_usrp_set_time_now(
+ uhd_usrp_handle h,
+ time_t full_secs,
+ double frac_secs,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp(full_secs, frac_secs);
+ USRP(h)->set_time_now(time_spec_cpp, mboard);
+ )
+}
+
+uhd_error uhd_usrp_set_time_next_pps(
+ uhd_usrp_handle h,
+ time_t full_secs,
+ double frac_secs,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp(full_secs, frac_secs);
+ USRP(h)->set_time_next_pps(time_spec_cpp, mboard);
+ )
+}
+
+uhd_error uhd_usrp_set_time_unknown_pps(
+ uhd_usrp_handle h,
+ time_t full_secs,
+ double frac_secs
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp(full_secs, frac_secs);
+ USRP(h)->set_time_unknown_pps(time_spec_cpp);
+ )
+}
+
+uhd_error uhd_usrp_get_time_synchronized(
+ uhd_usrp_handle h,
+ bool *result_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *result_out = USRP(h)->get_time_synchronized();
+ return UHD_ERROR_NONE;
+ )
+}
+
+uhd_error uhd_usrp_set_command_time(
+ uhd_usrp_handle h,
+ time_t full_secs,
+ double frac_secs,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::time_spec_t time_spec_cpp(full_secs, frac_secs);
+ USRP(h)->set_command_time(time_spec_cpp, mboard);
+ )
+}
+
+uhd_error uhd_usrp_clear_command_time(
+ uhd_usrp_handle h,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->clear_command_time(mboard);
+ )
+}
+
+uhd_error uhd_usrp_issue_stream_cmd(
+ uhd_usrp_handle h,
+ uhd_stream_cmd_t *stream_cmd,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->issue_stream_cmd(stream_cmd_c_to_cpp(stream_cmd), chan);
+ )
+}
+
+uhd_error uhd_usrp_set_time_source(
+ uhd_usrp_handle h,
+ const char* time_source,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_time_source(std::string(time_source), mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_time_source(
+ uhd_usrp_handle h,
+ size_t mboard,
+ char* time_source_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ strncpy(time_source_out, USRP(h)->get_time_source(mboard).c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_get_time_sources(
+ uhd_usrp_handle h,
+ size_t mboard,
+ char* time_sources_out,
+ size_t strbuffer_len,
+ size_t *num_time_sources_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> time_sources = USRP(h)->get_time_sources(mboard);
+ *num_time_sources_out = time_sources.size();
+
+ std::string time_sources_str = "";
+ BOOST_FOREACH(const std::string &time_source, time_sources){
+ time_sources_str += time_source;
+ time_sources_str += ',';
+ }
+ if(time_sources.size() > 0){
+ time_sources_str.resize(time_sources_str.size()-1);
+ }
+
+ memset(time_sources_out, '\0', strbuffer_len);
+ strncpy(time_sources_out, time_sources_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_clock_source(
+ uhd_usrp_handle h,
+ const char* clock_source,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_clock_source(std::string(clock_source), mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_clock_source(
+ uhd_usrp_handle h,
+ size_t mboard,
+ char* clock_source_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ strncpy(clock_source_out, USRP(h)->get_clock_source(mboard).c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_get_clock_sources(
+ uhd_usrp_handle h,
+ size_t mboard,
+ char* clock_sources_out,
+ size_t strbuffer_len,
+ size_t *num_clock_sources_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> clock_sources = USRP(h)->get_clock_sources(mboard);
+ *num_clock_sources_out = clock_sources.size();
+
+ std::string clock_sources_str = "";
+ BOOST_FOREACH(const std::string &clock_source, clock_sources){
+ clock_sources_str += clock_source;
+ clock_sources_str += ',';
+ }
+ if(clock_sources.size() > 0){
+ clock_sources_str.resize(clock_sources_str.size()-1);
+ }
+
+ memset(clock_sources_out, '\0', strbuffer_len);
+ strncpy(clock_sources_out, clock_sources_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_clock_source_out(
+ uhd_usrp_handle h,
+ bool enb,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_clock_source_out(enb, mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_num_mboards(
+ uhd_usrp_handle h,
+ size_t *num_mboards_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *num_mboards_out = USRP(h)->get_num_mboards();
+ )
+}
+
+uhd_error uhd_usrp_get_mboard_sensor(
+ uhd_usrp_handle h,
+ const char* name,
+ size_t mboard,
+ uhd_sensor_value_handle sensor_value_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ delete sensor_value_out->sensor_value_cpp;
+ sensor_value_out->sensor_value_cpp = new uhd::sensor_value_t(USRP(h)->get_mboard_sensor(name, mboard));
+ )
+}
+
+uhd_error uhd_usrp_get_mboard_sensor_names(
+ uhd_usrp_handle h,
+ size_t mboard,
+ char* mboard_sensor_names_out,
+ size_t strbuffer_len,
+ size_t *num_mboard_sensors_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> mboard_sensor_names = USRP(h)->get_mboard_sensor_names(mboard);
+ *num_mboard_sensors_out = mboard_sensor_names.size();
+
+ std::string mboard_sensor_names_str = "";
+ BOOST_FOREACH(const std::string &mboard_sensor_name, mboard_sensor_names){
+ mboard_sensor_names_str += mboard_sensor_name;
+ mboard_sensor_names_str += ',';
+ }
+ if(mboard_sensor_names.size() > 0){
+ mboard_sensor_names_str.resize(mboard_sensor_names_str.size()-1);
+ }
+
+ memset(mboard_sensor_names_out, '\0', strbuffer_len);
+ strncpy(mboard_sensor_names_out, mboard_sensor_names_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_user_register(
+ uhd_usrp_handle h,
+ uint8_t addr,
+ uint32_t data,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_user_register(addr, data, mboard);
+ )
+}
+
+/****************************************************************************
+ * EEPROM access methods
+ ***************************************************************************/
+
+uhd_error uhd_usrp_get_mboard_eeprom(
+ uhd_usrp_handle h,
+ uhd_mboard_eeprom_handle mb_eeprom,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::fs_path eeprom_path = str(boost::format("/mboards/%d/eeprom")
+ % mboard);
+
+ uhd::property_tree::sptr ptree = USRP(h)->get_device()->get_tree();
+ mb_eeprom->mboard_eeprom_cpp = ptree->access<uhd::usrp::mboard_eeprom_t>(eeprom_path).get();
+ )
+}
+
+uhd_error uhd_usrp_set_mboard_eeprom(
+ uhd_usrp_handle h,
+ uhd_mboard_eeprom_handle mb_eeprom,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::fs_path eeprom_path = str(boost::format("/mboards/%d/eeprom")
+ % mboard);
+
+ uhd::property_tree::sptr ptree = USRP(h)->get_device()->get_tree();
+ ptree->access<uhd::usrp::mboard_eeprom_t>(eeprom_path).set(mb_eeprom->mboard_eeprom_cpp);
+ )
+}
+
+uhd_error uhd_usrp_get_dboard_eeprom(
+ uhd_usrp_handle h,
+ uhd_dboard_eeprom_handle db_eeprom,
+ const char* unit,
+ const char* slot,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::fs_path eeprom_path = str(boost::format("/mboards/%d/dboards/%s/%s_eeprom")
+ % mboard % slot % unit);
+
+ uhd::property_tree::sptr ptree = USRP(h)->get_device()->get_tree();
+ db_eeprom->dboard_eeprom_cpp = ptree->access<uhd::usrp::dboard_eeprom_t>(eeprom_path).get();
+ )
+}
+
+uhd_error uhd_usrp_set_dboard_eeprom(
+ uhd_usrp_handle h,
+ uhd_dboard_eeprom_handle db_eeprom,
+ const char* unit,
+ const char* slot,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::fs_path eeprom_path = str(boost::format("/mboards/%d/dboards/%s/%s_eeprom")
+ % mboard % slot % unit);
+
+ uhd::property_tree::sptr ptree = USRP(h)->get_device()->get_tree();
+ ptree->access<uhd::usrp::dboard_eeprom_t>(eeprom_path).set(db_eeprom->dboard_eeprom_cpp);
+ )
+}
+
+/****************************************************************************
+ * RX methods
+ ***************************************************************************/
+
+uhd_error uhd_usrp_set_rx_subdev_spec(
+ uhd_usrp_handle h,
+ uhd_subdev_spec_handle subdev_spec,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_rx_subdev_spec(subdev_spec->subdev_spec_cpp, mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_subdev_spec(
+ uhd_usrp_handle h,
+ size_t mboard,
+ uhd_subdev_spec_handle subdev_spec_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ subdev_spec_out->subdev_spec_cpp = USRP(h)->get_rx_subdev_spec(mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_num_channels(
+ uhd_usrp_handle h,
+ size_t *num_channels_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *num_channels_out = USRP(h)->get_rx_num_channels();
+ )
+}
+
+uhd_error uhd_usrp_get_rx_subdev_name(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* rx_subdev_name_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string rx_subdev_name = USRP(h)->get_rx_subdev_name(chan);
+ strncpy(rx_subdev_name_out, rx_subdev_name.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_rx_rate(
+ uhd_usrp_handle h,
+ double rate,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_rx_rate(rate, chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_rate(
+ uhd_usrp_handle h,
+ size_t chan,
+ double *rate_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *rate_out = USRP(h)->get_rx_rate(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_rates(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_meta_range_handle rates_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ rates_out->meta_range_cpp = USRP(h)->get_rx_rates(chan);
+ )
+}
+
+uhd_error uhd_usrp_set_rx_freq(
+ uhd_usrp_handle h,
+ uhd_tune_request_t *tune_request,
+ size_t chan,
+ uhd_tune_result_t *tune_result
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::tune_request_t tune_request_cpp = uhd_tune_request_c_to_cpp(tune_request);
+ uhd::tune_result_t tune_result_cpp = USRP(h)->set_rx_freq(tune_request_cpp, chan);
+ uhd_tune_result_cpp_to_c(tune_result_cpp, tune_result);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_freq(
+ uhd_usrp_handle h,
+ size_t chan,
+ double *freq_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *freq_out = USRP(h)->get_rx_freq(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_freq_range(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_meta_range_handle freq_range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ freq_range_out->meta_range_cpp = USRP(h)->get_rx_freq_range(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_fe_rx_freq_range(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_meta_range_handle freq_range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ freq_range_out->meta_range_cpp = USRP(h)->get_fe_rx_freq_range(chan);
+ )
+}
+
+uhd_error uhd_usrp_set_rx_gain(
+ uhd_usrp_handle h,
+ double gain,
+ size_t chan,
+ const char *gain_name
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string name(gain_name);
+ if(name.empty()){
+ USRP(h)->set_rx_gain(gain, chan);
+ }
+ else{
+ USRP(h)->set_rx_gain(gain, name, chan);
+ }
+ )
+}
+
+uhd_error uhd_usrp_set_normalized_rx_gain(
+ uhd_usrp_handle h,
+ double gain,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_normalized_rx_gain(gain, chan);
+ )
+}
+
+uhd_error uhd_usrp_set_rx_agc(
+ uhd_usrp_handle h,
+ bool enable,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_rx_agc(enable, chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_gain(
+ uhd_usrp_handle h,
+ size_t chan,
+ const char *gain_name,
+ double *gain_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string name(gain_name);
+ if(name.empty()){
+ *gain_out = USRP(h)->get_rx_gain(chan);
+ }
+ else{
+ *gain_out = USRP(h)->get_rx_gain(name, chan);
+ }
+ )
+}
+
+uhd_error uhd_usrp_get_normalized_rx_gain(
+ uhd_usrp_handle h,
+ size_t chan,
+ double *gain_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *gain_out = USRP(h)->get_normalized_rx_gain(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_gain_range(
+ uhd_usrp_handle h,
+ const char* name,
+ size_t chan,
+ uhd_meta_range_handle gain_range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ gain_range_out->meta_range_cpp = USRP(h)->get_rx_gain_range(name, chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_gain_names(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* gain_names_out,
+ size_t strbuffer_len,
+ size_t *num_rx_gain_names_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> rx_gain_names = USRP(h)->get_rx_gain_names(chan);
+ *num_rx_gain_names_out = rx_gain_names.size();
+
+ std::string rx_gain_names_str = "";
+ BOOST_FOREACH(const std::string &gain_name, rx_gain_names){
+ rx_gain_names_str += gain_name;
+ rx_gain_names_str += ',';
+ }
+ if(rx_gain_names.size() > 0){
+ rx_gain_names_str.resize(rx_gain_names_str.size()-1);
+ }
+
+ memset(gain_names_out, '\0', strbuffer_len);
+ strncpy(gain_names_out, rx_gain_names_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_rx_antenna(
+ uhd_usrp_handle h,
+ const char* ant,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_rx_antenna(std::string(ant), chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_antenna(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* ant_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string rx_antenna = USRP(h)->get_rx_antenna(chan);
+ strncpy(ant_out, rx_antenna.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_antennas(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* antennas_out,
+ size_t strbuffer_len,
+ size_t *num_rx_antennas_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> rx_antennas = USRP(h)->get_rx_antennas(chan);
+ *num_rx_antennas_out = rx_antennas.size();
+
+ std::string rx_antennas_str = "";
+ BOOST_FOREACH(const std::string &rx_antenna, rx_antennas){
+ rx_antennas_str += rx_antenna;
+ rx_antennas_str += ',';
+ }
+ if(rx_antennas.size() > 0){
+ rx_antennas_str.resize(rx_antennas_str.size()-1);
+ }
+
+ memset(antennas_out, '\0', strbuffer_len);
+ strncpy(antennas_out, rx_antennas_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_rx_bandwidth(
+ uhd_usrp_handle h,
+ double bandwidth,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_rx_bandwidth(bandwidth, chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_bandwidth(
+ uhd_usrp_handle h,
+ size_t chan,
+ double *bandwidth_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *bandwidth_out = USRP(h)->get_rx_bandwidth(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_bandwidth_range(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_meta_range_handle bandwidth_range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ bandwidth_range_out->meta_range_cpp = USRP(h)->get_rx_bandwidth_range(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_rx_sensor(
+ uhd_usrp_handle h,
+ const char* name,
+ size_t chan,
+ uhd_sensor_value_handle sensor_value_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ delete sensor_value_out->sensor_value_cpp;
+ sensor_value_out->sensor_value_cpp = new uhd::sensor_value_t(USRP(h)->get_rx_sensor(name, chan));
+ )
+}
+
+uhd_error uhd_usrp_get_rx_sensor_names(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* sensor_names_out,
+ size_t strbuffer_len,
+ size_t *num_rx_sensors_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> rx_sensor_names = USRP(h)->get_rx_sensor_names(chan);
+ *num_rx_sensors_out = rx_sensor_names.size();
+
+ std::string rx_sensor_names_str = "";
+ BOOST_FOREACH(const std::string &rx_sensor_name, rx_sensor_names){
+ rx_sensor_names_str += rx_sensor_name;
+ rx_sensor_names_str += ',';
+ }
+ if(rx_sensor_names.size() > 0){
+ rx_sensor_names_str.resize(rx_sensor_names_str.size()-1);
+ }
+
+ memset(sensor_names_out, '\0', strbuffer_len);
+ strncpy(sensor_names_out, rx_sensor_names_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_rx_dc_offset_enabled(
+ uhd_usrp_handle h,
+ bool enb,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_rx_dc_offset(enb, chan);
+ )
+}
+
+uhd_error uhd_usrp_set_rx_iq_balance_enabled(
+ uhd_usrp_handle h,
+ bool enb,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_rx_iq_balance(enb, chan);
+ )
+}
+
+/****************************************************************************
+ * TX methods
+ ***************************************************************************/
+
+uhd_error uhd_usrp_set_tx_subdev_spec(
+ uhd_usrp_handle h,
+ uhd_subdev_spec_handle subdev_spec,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_tx_subdev_spec(subdev_spec->subdev_spec_cpp, mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_subdev_spec(
+ uhd_usrp_handle h,
+ size_t mboard,
+ uhd_subdev_spec_handle subdev_spec_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ subdev_spec_out->subdev_spec_cpp = USRP(h)->get_tx_subdev_spec(mboard);
+ )
+}
+
+
+uhd_error uhd_usrp_get_tx_num_channels(
+ uhd_usrp_handle h,
+ size_t *num_channels_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *num_channels_out = USRP(h)->get_tx_num_channels();
+ )
+}
+
+uhd_error uhd_usrp_get_tx_subdev_name(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* tx_subdev_name_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string tx_subdev_name = USRP(h)->get_tx_subdev_name(chan);
+ strncpy(tx_subdev_name_out, tx_subdev_name.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_tx_rate(
+ uhd_usrp_handle h,
+ double rate,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_tx_rate(rate, chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_rate(
+ uhd_usrp_handle h,
+ size_t chan,
+ double *rate_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *rate_out = USRP(h)->get_tx_rate(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_rates(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_meta_range_handle rates_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ rates_out->meta_range_cpp = USRP(h)->get_tx_rates(chan);
+ )
+}
+
+uhd_error uhd_usrp_set_tx_freq(
+ uhd_usrp_handle h,
+ uhd_tune_request_t *tune_request,
+ size_t chan,
+ uhd_tune_result_t *tune_result
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ uhd::tune_request_t tune_request_cpp = uhd_tune_request_c_to_cpp(tune_request);
+ uhd::tune_result_t tune_result_cpp = USRP(h)->set_tx_freq(tune_request_cpp, chan);
+ uhd_tune_result_cpp_to_c(tune_result_cpp, tune_result);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_freq(
+ uhd_usrp_handle h,
+ size_t chan,
+ double *freq_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *freq_out = USRP(h)->get_tx_freq(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_freq_range(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_meta_range_handle freq_range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ freq_range_out->meta_range_cpp = USRP(h)->get_tx_freq_range(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_fe_tx_freq_range(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_meta_range_handle freq_range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ freq_range_out->meta_range_cpp = USRP(h)->get_fe_tx_freq_range(chan);
+ )
+}
+
+uhd_error uhd_usrp_set_tx_gain(
+ uhd_usrp_handle h,
+ double gain,
+ size_t chan,
+ const char *gain_name
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string name(gain_name);
+ if(name.empty()){
+ USRP(h)->set_tx_gain(gain, chan);
+ }
+ else{
+ USRP(h)->set_tx_gain(gain, name, chan);
+ }
+ )
+}
+
+uhd_error uhd_usrp_set_normalized_tx_gain(
+ uhd_usrp_handle h,
+ double gain,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_normalized_tx_gain(gain, chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_gain(
+ uhd_usrp_handle h,
+ size_t chan,
+ const char *gain_name,
+ double *gain_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string name(gain_name);
+ if(name.empty()){
+ *gain_out = USRP(h)->get_tx_gain(chan);
+ }
+ else{
+ *gain_out = USRP(h)->get_tx_gain(name, chan);
+ }
+ )
+}
+
+uhd_error uhd_usrp_get_normalized_tx_gain(
+ uhd_usrp_handle h,
+ size_t chan,
+ double *gain_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *gain_out = USRP(h)->get_normalized_tx_gain(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_gain_range(
+ uhd_usrp_handle h,
+ const char* name,
+ size_t chan,
+ uhd_meta_range_handle gain_range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ gain_range_out->meta_range_cpp = USRP(h)->get_tx_gain_range(name, chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_gain_names(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* gain_names_out,
+ size_t strbuffer_len,
+ size_t *num_tx_gain_names_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> tx_gain_names = USRP(h)->get_tx_gain_names(chan);
+ *num_tx_gain_names_out = tx_gain_names.size();
+
+ std::string tx_gain_names_str = "";
+ BOOST_FOREACH(const std::string &tx_gain_name, tx_gain_names){
+ tx_gain_names_str += tx_gain_name;
+ tx_gain_names_str += ',';
+ }
+ if(tx_gain_names.size() > 0){
+ tx_gain_names_str.resize(tx_gain_names_str.size()-1);
+ }
+
+ memset(gain_names_out, '\0', strbuffer_len);
+ strncpy(gain_names_out, tx_gain_names_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_tx_antenna(
+ uhd_usrp_handle h,
+ const char* ant,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_tx_antenna(std::string(ant), chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_antenna(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* ant_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::string tx_antenna = USRP(h)->get_tx_antenna(chan);
+ strncpy(ant_out, tx_antenna.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_antennas(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* antennas_out,
+ size_t strbuffer_len,
+ size_t *num_tx_antennas_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> tx_antennas = USRP(h)->get_tx_antennas(chan);
+ *num_tx_antennas_out = tx_antennas.size();
+
+ std::string tx_antennas_str = "";
+ BOOST_FOREACH(const std::string &tx_antenna, tx_antennas){
+ tx_antennas_str += tx_antenna;
+ tx_antennas_str += ',';
+ }
+ if(tx_antennas.size() > 0){
+ tx_antennas_str.resize(tx_antennas_str.size()-1);
+ }
+
+ memset(antennas_out, '\0', strbuffer_len);
+ strncpy(antennas_out, tx_antennas_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_tx_bandwidth(
+ uhd_usrp_handle h,
+ double bandwidth,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_tx_bandwidth(bandwidth, chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_bandwidth(
+ uhd_usrp_handle h,
+ size_t chan,
+ double *bandwidth_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *bandwidth_out = USRP(h)->get_tx_bandwidth(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_bandwidth_range(
+ uhd_usrp_handle h,
+ size_t chan,
+ uhd_meta_range_handle bandwidth_range_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ bandwidth_range_out->meta_range_cpp = USRP(h)->get_tx_bandwidth_range(chan);
+ )
+}
+
+uhd_error uhd_usrp_get_tx_sensor(
+ uhd_usrp_handle h,
+ const char* name,
+ size_t chan,
+ uhd_sensor_value_handle sensor_value_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ delete sensor_value_out->sensor_value_cpp;
+ sensor_value_out->sensor_value_cpp = new uhd::sensor_value_t(USRP(h)->get_tx_sensor(name, chan));
+ )
+}
+
+uhd_error uhd_usrp_get_tx_sensor_names(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* sensor_names_out,
+ size_t strbuffer_len,
+ size_t *num_tx_sensors_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> tx_sensor_names = USRP(h)->get_tx_sensor_names(chan);
+ *num_tx_sensors_out = tx_sensor_names.size();
+
+ std::string tx_sensor_names_str = "";
+ BOOST_FOREACH(const std::string &tx_sensor_name, tx_sensor_names){
+ tx_sensor_names_str += tx_sensor_name;
+ tx_sensor_names_str += ',';
+ }
+ if(tx_sensor_names.size() > 0){
+ tx_sensor_names_str.resize(tx_sensor_names_str.size()-1);
+ }
+
+ memset(sensor_names_out, '\0', strbuffer_len);
+ strncpy(sensor_names_out, tx_sensor_names_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_tx_dc_offset_enabled(
+ uhd_usrp_handle h,
+ bool enb,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_tx_dc_offset(enb, chan);
+ )
+}
+
+uhd_error uhd_usrp_set_tx_iq_balance_enabled(
+ uhd_usrp_handle h,
+ bool enb,
+ size_t chan
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_tx_iq_balance(enb, chan);
+ )
+}
+
+/****************************************************************************
+ * GPIO methods
+ ***************************************************************************/
+
+uhd_error uhd_usrp_get_gpio_banks(
+ uhd_usrp_handle h,
+ size_t chan,
+ char* gpio_banks_out,
+ size_t strbuffer_len,
+ size_t *num_gpio_banks_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> gpio_banks = USRP(h)->get_gpio_banks(chan);
+ *num_gpio_banks_out = gpio_banks.size();
+
+ std::string gpio_banks_str = "";
+ BOOST_FOREACH(const std::string &gpio_bank, gpio_banks){
+ gpio_banks_str += gpio_bank;
+ gpio_banks_str += ',';
+ }
+ if(gpio_banks.size() > 0){
+ gpio_banks_str.resize(gpio_banks_str.size()-1);
+ }
+
+ memset(gpio_banks_out, '\0', strbuffer_len);
+ strncpy(gpio_banks_out, gpio_banks_str.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_set_gpio_attr(
+ uhd_usrp_handle h,
+ const char* bank,
+ const char* attr,
+ uint32_t value,
+ uint32_t mask,
+ size_t mboard
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ USRP(h)->set_gpio_attr(std::string(bank), std::string(attr),
+ value, mask, mboard);
+ )
+}
+
+uhd_error uhd_usrp_get_gpio_attr(
+ uhd_usrp_handle h,
+ const char* bank,
+ const char* attr,
+ size_t mboard,
+ uint32_t *attr_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *attr_out = USRP(h)->get_gpio_attr(std::string(bank), std::string(attr), mboard);
+ )
+}
diff --git a/host/lib/usrp_clock/CMakeLists.txt b/host/lib/usrp_clock/CMakeLists.txt
index 8a58aa9ac..ba0f5fe0a 100644
--- a/host/lib/usrp_clock/CMakeLists.txt
+++ b/host/lib/usrp_clock/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2011-2014 Ettus Research LLC
+# Copyright 2011-2015 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
@@ -23,4 +23,10 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/multi_usrp_clock.cpp
)
+IF(ENABLE_C_API)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/usrp_clock_c.cpp
+ )
+ENDIF(ENABLE_C_API)
+
INCLUDE_SUBDIRECTORY(octoclock)
diff --git a/host/lib/usrp_clock/usrp_clock_c.cpp b/host/lib/usrp_clock/usrp_clock_c.cpp
new file mode 100644
index 000000000..b55abc852
--- /dev/null
+++ b/host/lib/usrp_clock/usrp_clock_c.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2015 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* C-Interface for multi_usrp_clock */
+
+#include <uhd/utils/static.hpp>
+#include <uhd/usrp_clock/multi_usrp_clock.hpp>
+
+#include <uhd/usrp_clock/usrp_clock.h>
+
+#include <boost/foreach.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <string.h>
+#include <map>
+
+/****************************************************************************
+ * Registry / Pointer Management
+ ***************************************************************************/
+/* Public structs */
+struct uhd_usrp_clock {
+ size_t usrp_clock_index;
+ std::string last_error;
+};
+
+/* Not public: We use this for our internal registry */
+struct usrp_clock_ptr {
+ uhd::usrp_clock::multi_usrp_clock::sptr ptr;
+ static size_t usrp_clock_counter;
+};
+size_t usrp_clock_ptr::usrp_clock_counter = 0;
+typedef struct usrp_clock_ptr usrp_clock_ptr;
+/* Prefer map, because the list can be discontiguous */
+typedef std::map<size_t, usrp_clock_ptr> usrp_clock_ptrs;
+
+UHD_SINGLETON_FCN(usrp_clock_ptrs, get_usrp_clock_ptrs);
+/* Shortcut for accessing the underlying USRP clock sptr from a uhd_usrp_clock_handle* */
+#define USRP_CLOCK(h_ptr) (get_usrp_clock_ptrs()[h_ptr->usrp_clock_index].ptr)
+
+/****************************************************************************
+ * Generate / Destroy API calls
+ ***************************************************************************/
+static boost::mutex _usrp_clock_make_mutex;
+uhd_error uhd_usrp_clock_make(
+ uhd_usrp_clock_handle *h,
+ const char *args
+){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_usrp_clock_make_mutex);
+
+ size_t usrp_clock_count = usrp_clock_ptr::usrp_clock_counter;
+ usrp_clock_ptr::usrp_clock_counter++;
+
+ // Initialize USRP Clock
+ uhd::device_addr_t device_addr(args);
+ usrp_clock_ptr P;
+ P.ptr = uhd::usrp_clock::multi_usrp_clock::make(device_addr);
+
+ // Dump into registry
+ get_usrp_clock_ptrs()[usrp_clock_count] = P;
+
+ // Update handle
+ (*h) = new uhd_usrp_clock;
+ (*h)->usrp_clock_index = usrp_clock_count;
+ )
+}
+
+static boost::mutex _usrp_clock_free_mutex;
+uhd_error uhd_usrp_clock_free(
+ uhd_usrp_clock_handle *h
+){
+ UHD_SAFE_C(
+ boost::mutex::scoped_lock lock(_usrp_clock_free_mutex);
+
+ if(!get_usrp_clock_ptrs().count((*h)->usrp_clock_index)){
+ return UHD_ERROR_INVALID_DEVICE;
+ }
+
+ get_usrp_clock_ptrs().erase((*h)->usrp_clock_index);
+ delete *h;
+ *h = NULL;
+ )
+}
+
+uhd_error uhd_usrp_clock_last_error(
+ uhd_usrp_clock_handle h,
+ char* error_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C(
+ memset(error_out, '\0', strbuffer_len);
+ strncpy(error_out, h->last_error.c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_clock_get_pp_string(
+ uhd_usrp_clock_handle h,
+ char* pp_string_out,
+ size_t strbuffer_len
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ memset(pp_string_out, '\0', strbuffer_len);
+ strncpy(pp_string_out, USRP_CLOCK(h)->get_pp_string().c_str(), strbuffer_len);
+ )
+}
+
+uhd_error uhd_usrp_clock_get_num_boards(
+ uhd_usrp_clock_handle h,
+ size_t *num_boards_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *num_boards_out = USRP_CLOCK(h)->get_num_boards();
+ )
+}
+
+uhd_error uhd_usrp_clock_get_time(
+ uhd_usrp_clock_handle h,
+ size_t board,
+ uint32_t *clock_time_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ *clock_time_out = USRP_CLOCK(h)->get_time(board);
+ )
+}
+
+uhd_error uhd_usrp_clock_get_sensor(
+ uhd_usrp_clock_handle h,
+ const char* name,
+ size_t board,
+ uhd_sensor_value_handle sensor_value_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ delete sensor_value_out->sensor_value_cpp;
+ sensor_value_out->sensor_value_cpp = new uhd::sensor_value_t(USRP_CLOCK(h)->get_sensor(name, board));
+ )
+}
+
+uhd_error uhd_usrp_clock_get_sensor_names(
+ uhd_usrp_clock_handle h,
+ size_t board,
+ char* sensor_names_out,
+ size_t strbuffer_len,
+ size_t *num_sensors_out
+){
+ UHD_SAFE_C_SAVE_ERROR(h,
+ std::vector<std::string> sensor_names = USRP_CLOCK(h)->get_sensor_names(board);
+ *num_sensors_out = sensor_names.size();
+
+ std::string sensor_names_str = "";
+ BOOST_FOREACH(const std::string &sensor_name, sensor_names){
+ sensor_names_str += sensor_name;
+ sensor_names_str += ',';
+ }
+ if(sensor_names.size() > 0){
+ sensor_names_str.resize(sensor_names_str.size()-1);
+ }
+
+ memset(sensor_names_out, '\0', strbuffer_len);
+ strncpy(sensor_names_out, sensor_names_str.c_str(), strbuffer_len);
+ )
+}
diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt
index 369920ac1..c5c975dfa 100644
--- a/host/lib/utils/CMakeLists.txt
+++ b/host/lib/utils/CMakeLists.txt
@@ -141,3 +141,9 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/tasks.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp
)
+
+IF(ENABLE_C_API)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/thread_priority_c.cpp
+ )
+ENDIF(ENABLE_C_API)
diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp
index af25d088a..98023c5aa 100644
--- a/host/lib/utils/thread_priority.cpp
+++ b/host/lib/utils/thread_priority.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2011,2015 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
diff --git a/host/lib/utils/thread_priority_c.cpp b/host/lib/utils/thread_priority_c.cpp
new file mode 100644
index 000000000..fe019e51d
--- /dev/null
+++ b/host/lib/utils/thread_priority_c.cpp
@@ -0,0 +1,33 @@
+//
+// Copyright 2015 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
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/error.h>
+#include <uhd/utils/thread_priority.h>
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/utils/msg.hpp>
+#include <uhd/exception.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+
+uhd_error uhd_set_thread_priority(
+ float priority,
+ bool realtime
+){
+ UHD_SAFE_C(
+ uhd::set_thread_priority(priority, realtime);
+ )
+}