aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp_clock/usrp_clock_c.cpp
blob: c0408bc5ea3889c8b77d8b0e65e430c25f28f852 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright 2015 Ettus Research LLC
 * Copyright 2018 Ettus Research, a National Instruments Company
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

/* C-Interface for multi_usrp_clock */

#include <uhd/usrp_clock/multi_usrp_clock.hpp>
#include <uhd/usrp_clock/usrp_clock.h>
#include <uhd/utils/static.hpp>
#include <string.h>
#include <map>
#include <mutex>

/****************************************************************************
 * 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 std::mutex _usrp_clock_find_mutex;
uhd_error uhd_usrp_clock_find(const char* args, uhd_string_vector_t* devices_out)
{
    UHD_SAFE_C(
        std::lock_guard<std::mutex> lock(_usrp_clock_find_mutex);

        uhd::device_addrs_t devs =
            uhd::device::find(std::string(args), uhd::device::CLOCK);
        devices_out->string_vector_cpp.clear();
        for (const uhd::device_addr_t& dev
             : devs) { devices_out->string_vector_cpp.push_back(dev.to_string()); })
}

static std::mutex _usrp_clock_make_mutex;
uhd_error uhd_usrp_clock_make(uhd_usrp_clock_handle* h, const char* args)
{
    UHD_SAFE_C(std::lock_guard<std::mutex> 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 std::mutex _usrp_clock_free_mutex;
uhd_error uhd_usrp_clock_free(uhd_usrp_clock_handle* h)
{
    UHD_SAFE_C(std::lock_guard<std::mutex> 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, uhd_string_vector_handle* sensor_names_out)
{
    UHD_SAFE_C_SAVE_ERROR(
        h,
        (*sensor_names_out)->string_vector_cpp = USRP_CLOCK(h)->get_sensor_names(board);)
}