Skip to content

# File bluespy.h

File List > bluespy.h

Go to the documentation of this file

    #ifndef BLUESPY_INCLUDE_GUARD
    #define BLUESPY_INCLUDE_GUARD

    #ifndef BLUESPY_API
    #if defined _WIN32 || defined __CYGWIN__
    #define BLUESPY_API __declspec(dllimport)
    #else
    #define BLUESPY_API __attribute__((visibility("default")))
    #endif
    #endif

    #include "stdbool.h"
    #include "stdint.h"
    #include <stddef.h>

    #ifdef __cplusplus
    #include <utility>
    extern "C" {
    #endif

    #if defined(__has_cpp_attribute)
    #define BLUESPY_HASATTR(attr) __has_cpp_attribute(attr)
    #elif defined(__has_c_attribute)
    #define BLUESPY_HASATTR(attr) __has_c_attribute(attr)
    #else
    #define BLUESPY_HASATTR(attr) (0)
    #endif

    #if BLUESPY_HASATTR(deprecated)
    #define BLUESPY_DEPRECATED_API [[deprecated]] BLUESPY_API
    #else
    #define BLUESPY_DEPRECATED_API BLUESPY_API
    #endif

    typedef enum bluespy_error {
        BLUESPY_NO_ERROR = 0,
        BLUESPY_ERROR_NO_DEVICE,
        BLUESPY_ERROR_LICENCE,
        BLUESPY_ERROR_NO_FILE,
        BLUESPY_ERROR_CAPTURE_NOT_STARTED,
        BLUESPY_ERROR_INVALID_PACKET,
        BLUESPY_ERROR_INVALID_CAPTURE_OPTIONS,
        BLUESPY_ERROR_INVALID_CIS_CONFIG,
        BLUESPY_ERROR_AUDIOPOD_DISABLED,
        BLUESPY_ERROR_AUDIOPOD_OUTPUT_DISABLED,
        BLUESPY_ERROR_INVALID_PARAMETER,
        BLUESPY_ERROR_IUT_NOT_CONNECTED,
        BLUESPY_ERROR_INVALID_TCID,
        BLUESPY_ERROR_TESTCASE_FAILURE,
        BLUESPY_ERROR_ABORTED_TESTCASES,
        BLUESPY_ERROR_NOT_INITIALIZED,
    } bluespy_error;

    BLUESPY_API const char* bluespy_error_string(bluespy_error error);

    typedef enum bluespy_log_level {
        BLUESPY_LOG_PASS = 0x00,
        BLUESPY_LOG_WARN = 0x20,
        BLUESPY_LOG_INFO = 0x40,
        BLUESPY_LOG_DEBUG = 0x60,
        BLUESPY_LOG_ERROR = 0x80,

    } bluespy_log_level;
    BLUESPY_API void bluespy_init();

    BLUESPY_API void bluespy_deinit();

    BLUESPY_API void bluespy_start_gui();

    BLUESPY_API bluespy_error bluespy_connect(uint32_t serial);

    BLUESPY_API bluespy_error bluespy_connect_multiple(uint32_t* serial_data, uint64_t serial_size);

    BLUESPY_API uint64_t bluespy_morephs_connected(uint32_t** serials);

    BLUESPY_API bluespy_error bluespy_disconnect();

    BLUESPY_API bluespy_error bluespy_moreph_reboot(uint32_t serial);

    typedef int64_t bluespy_time_point;
    #define BLUESPY_TIME_INVALID (INT64_MAX)

    BLUESPY_API const char* bluespy_print_time(bluespy_time_point ts);

    BLUESPY_API bluespy_error bluespy_add_log_message(bluespy_log_level level, const char* message,
                                                      bluespy_time_point ts);

    typedef enum bluespy_logic_rate {
        bluespy_logic_rate_high,
        bluespy_logic_rate_mid,
        bluespy_logic_rate_low

    } bluespy_logic_rate;

    typedef struct bluespy_multi_moreph_options {
        bool enable_CL;
        bool enable_LE;
        bool enable_wifi;
    } bluespy_multi_moreph_options;
    typedef enum bluespy_audio_channel {
        BLUESPY_STEREO,
        BLUESPY_MONO_L,
        BLUESPY_MONO_R
    } bluespy_audio_channel;

    typedef enum bluespy_audio_connect {
        BLUESPY_NOAUDIO,
        BLUESPY_LINE,
        BLUESPY_JACK,
        BLUESPY_HEADSET,
        BLUESPY_COAX,
        BLUESPY_OPTICAL,
        BLUESPY_MIC,
        BLUESPY_I2S
    } bluespy_audio_connect;

    typedef enum bluespy_audio_bias {
        BLUESPY_BIAS_OFF,
        BLUESPY_BIAS_LOW,
        BLUESPY_BIAS_MID,
        BLUESPY_BIAS_HIG,
        BLUESPY_BIAS_VDD
    } bluespy_audio_bias;

    typedef struct bluespy_capture_audiopod_options {
        uint32_t sample_rate;
        bluespy_audio_channel channels;
        bluespy_audio_connect output;
        bluespy_audio_connect input;
        bluespy_audio_bias bias;
        bool current_probe;
        double LA_low_voltage;
        double LA_high_voltage;
        double power_supply_V;
        double VIO_dV;
        bool AGC;
        bool DRC;
        bool second_I2S_input; // Enable a second I2S input, output must be set to BLUESPY_NO_AUDIO
        double vol_in_left;
        double vol_in_right;
        double vol_out_left;
        double vol_out_right;
    } bluespy_capture_audiopod_options;

    typedef struct bluespy_capture_i2s_options {
        uint8_t SCLK_line;   // Valid values are [0,15]
        uint8_t WS_line;     // Valid values are [0,15]
        uint8_t SD_line;     // Valid values are [0,15]
        uint8_t n_channels;  // Valid values are [1,16]
        uint8_t bits_per_ch; // Valid values are [1,32]
        bool sample_on_rising_edge;
        bool first_chan_follows_WS_high;
        bool one_sample_delay;
        bool MSB_first;
        bool DSP_mode;
        bool master;
    } bluespy_capture_i2s_options;

    typedef struct bluespy_capture_options {
        bool enable_CL;
        bool enable_LE;
        bool enable_QHS;
        bool enable_15_4;
        bool enable_wifi;
        bool enable_MHDT_CL;
        bool enable_MHDT_LE;
        bool enable_Dukosi;
        bool enable_Varjo;
        bool enable_Channel_Sounding;
        bool enable_HDT;
        uint16_t spectrum_period;

        uint32_t logic_mask;
        bool logic_use_external_vref;
        bluespy_logic_rate logic_rate;
        bluespy_multi_moreph_options multi_moreph_opts[32];
        bluespy_capture_audiopod_options* audiopod_opts;
        bluespy_capture_i2s_options* i2s_opts[2];

        bool enable_Proprietary_1;
        bool enable_Proprietary_2;
        bool mask_payloads;
        bool disable_HDT_dewhitening;
        bool disable_AGC;
        int16_t maximum_input_signal_dbm; // Only valid when AGC is disabled
    } bluespy_capture_options;

    BLUESPY_API bluespy_capture_options* bluespy_capture_options_alloc();

    BLUESPY_DEPRECATED_API void bluespy_capture_options_delete(bluespy_capture_options* opts);

    BLUESPY_API void bluespy_delete(void* obj);

    BLUESPY_API bluespy_capture_audiopod_options* bluespy_capture_audiopod_options_alloc();

    BLUESPY_API bluespy_capture_i2s_options* bluespy_capture_i2s_options_alloc();

    BLUESPY_API bluespy_error bluespy_capture(const char* filename, bluespy_capture_options* opts);

    BLUESPY_API bluespy_error bluespy_stop_capture();

    BLUESPY_API bluespy_error bluespy_load_file(const char* filename);

    BLUESPY_API bluespy_error bluespy_close_file();

    BLUESPY_API uint32_t bluespy_packet_count(void);

    typedef uint64_t bluespy_id;

    #define BLUESPY_ID_INVALID ((bluespy_id)(-1))

    typedef bluespy_id bluespy_event_id;

    typedef bluespy_id bluespy_device_id;

    typedef bluespy_id bluespy_connection_id;

    typedef bluespy_id bluespy_audiostream_id;

    BLUESPY_API bluespy_event_id bluespy_get_baseband(uint32_t index);

    BLUESPY_API bluespy_event_id bluespy_get_parent(bluespy_event_id event);

    BLUESPY_API const bluespy_event_id* bluespy_get_children(bluespy_event_id event, uint32_t* count);

    BLUESPY_API const char* bluespy_query(bluespy_id event, const char* query);

    BLUESPY_API int64_t bluespy_query_int(bluespy_id event, const char* query);

    BLUESPY_API bool bluespy_query_bool(bluespy_id event, const char* query);

    BLUESPY_DEPRECATED_API int bluespy_query_auto(bluespy_id event, const char* query, const char** s,
                                                  int64_t* i, bool* b);

    typedef struct bluespy_bytes {
        const uint8_t* data;
        size_t len;
    } bluespy_bytes;

    BLUESPY_API bluespy_bytes bluespy_query_bytes(bluespy_id event, const char* query);

    typedef enum bluespy_query_type {
        bluespy_query_type_invalid = -1, /* This query can never be used on this kind of ID */
        bluespy_query_type_none = 0,     /* There is no value on this specific ID */
        bluespy_query_type_bool = 1,
        bluespy_query_type_int = 2,
        bluespy_query_type_string = 3,
        bluespy_query_type_bytes = 4,
        bluespy_query_type_double = 5,
        bluespy_query_type_id = 6,
    } bluespy_query_type;

    typedef struct bluespy_query_value {
        bluespy_query_type type;
        union {
            bool b;
            int64_t i;
            const char* s;
            bluespy_bytes bytes;
            double d;
            bluespy_id id;
        };
    } bluespy_query_value;

    BLUESPY_API bluespy_query_value bluespy_query_get(bluespy_id id, const char* query);

    typedef int32_t bluespy_filter_file_id;
    #define BLUESPY_FILTER_FILE_ID_INVALID ((bluespy_filter_file_id)(-1))

    typedef struct bluespy_filter_file_options {
        bluespy_time_point range_start;
        bool keep_spectrum;
        bool keep_logic;
        bool keep_uart;
        bool keep_i2s_and_audiopod;
    } bluespy_filter_file_options;

    BLUESPY_API bluespy_filter_file_options* bluespy_filter_file_options_alloc();

    BLUESPY_API void bluespy_filter_file_options_delete(bluespy_filter_file_options* opts);

    BLUESPY_API const char* bluespy_get_filter_file_name(bluespy_filter_file_id id);

    BLUESPY_API bluespy_filter_file_id bluespy_create_filter_file(const char* filename,
                                                                  bluespy_filter_file_options* opts);

    BLUESPY_API bluespy_error bluespy_add_to_filter_file(bluespy_filter_file_id file_id,
                                                         bluespy_event_id event_id);

    BLUESPY_API bluespy_error bluespy_close_filter_file(bluespy_filter_file_id file_id);

    BLUESPY_API uint32_t bluespy_get_logic_at_time(bluespy_time_point ts);

    typedef struct bluespy_logic_change {
        uint32_t state;          // New logic state - 32-bit mask of the new logic state
        uint32_t change_mask;    // Logic changed - 32-bit mask of lines which changed
        bluespy_time_point time; // The time of the logic change
    } bluespy_logic_change;

    BLUESPY_API bluespy_logic_change bluespy_get_next_logic_change(bluespy_time_point ts,
                                                                   uint32_t mask);

    BLUESPY_API bluespy_logic_change bluespy_wait_until_next_logic_change(uint32_t mask,
                                                                          int64_t timeout,
                                                                          bluespy_time_point start_ts);

    BLUESPY_API bluespy_error bluespy_add_link_key(const unsigned char* key, uint64_t addr0,
                                                   uint64_t addr1);

    BLUESPY_API void bluespy_add_IRK(const unsigned char* key, uint64_t* addr, uint64_t n_addresses);

    BLUESPY_API bluespy_device_id bluespy_get_device_id(const char* addr);

    typedef struct bluespy_connection_id_span {
        bluespy_connection_id* data;
        uint64_t size;
    } bluespy_connection_id_span;

    BLUESPY_API bluespy_connection_id_span bluespy_get_connections(bluespy_device_id dev_id);

    typedef struct bluespy_audiostream_id_span {
        bluespy_audiostream_id* data;
        uint64_t size;
    } bluespy_audiostream_id_span;

    BLUESPY_API bluespy_audiostream_id_span bluespy_get_audiostreams(bluespy_id id);

    BLUESPY_API bluespy_device_id bluespy_get_next_device_id(bluespy_device_id id);

    inline bluespy_device_id bluespy_get_first_device_id() {
        return bluespy_get_next_device_id(BLUESPY_ID_INVALID);
    }

    BLUESPY_API bluespy_connection_id bluespy_get_next_connection_id(bluespy_connection_id id);

    inline bluespy_connection_id bluespy_get_first_connection_id() {
        return bluespy_get_next_connection_id(BLUESPY_ID_INVALID);
    }

    BLUESPY_API bluespy_audiostream_id bluespy_get_next_audiostream_id(bluespy_audiostream_id id);

    inline bluespy_audiostream_id bluespy_get_first_audiostream_id() {
        return bluespy_get_next_audiostream_id(BLUESPY_ID_INVALID);
    }

    typedef enum bluespy_event_types {
        bluespy_event_bt_baseband,
        bluespy_event_custom,
        bluespy_event_proprietary_1,
        bluespy_event_proprietary_2,
    } bluespy_event_types;
    BLUESPY_API void bluespy_register_event_callback(bluespy_event_types types,
                                                     void (*callback)(bluespy_event_id));

    typedef struct bluespy_custom_query {
        const char* query;
        const char* pretty_name;
        const char* description;
    } bluespy_custom_query;

    typedef void (*bluespy_cleanup_t)(void*);
    BLUESPY_API void* bluespy_allocate(size_t bytes, bluespy_cleanup_t cleanup);

    typedef enum bluespy_custom_event_layer {
        bluespy_custom_event_layer_automatic, // One layer above its children
        bluespy_custom_event_layer_logical,
        bluespy_custom_event_layer_transaction,
        bluespy_custom_event_layer_application,
    } bluespy_custom_event_layer;

    typedef struct bluespy_custom_event {
        bluespy_event_id* children;
        unsigned int n_children;
        bluespy_query_value (*query)(const struct bluespy_custom_event* self, const char* query_str,
                                     bool prefer_string);
        bluespy_custom_event_layer layer;
    } bluespy_custom_event;

    BLUESPY_API bluespy_error bluespy_add_event(bluespy_custom_event* event);

    typedef enum bluespy_latency_status {
        BLUESPY_OK,
        BLUESPY_ZEROS,
        BLUESPY_NOT_ENOUGH_DATA,
        BLUESPY_ENERGY_THRESHOLD,
        BLUESPY_AMBIG_PEAK,
        BLUESPY_PERIODIC,
        BLUESPY_OTHER_ERROR
    } bluespy_latency_status;

    BLUESPY_API const char* bluespy_latency_status_string(bluespy_latency_status status);

    typedef struct bluespy_latency_result {
        int64_t time_difference_ns;
        int64_t time_difference_min_ns;
        int64_t time_difference_max_ns;
        bluespy_time_point measurement_time;
        bluespy_latency_status status;
        double total_energy;
        double peak_ratio;
        bool three_measurements_expected;
    } bluespy_latency_result;

    typedef struct bluespy_audio_channel_t {
        bluespy_audiostream_id ID;
        uint8_t channel_index;
    } bluespy_audio_channel_t;

    BLUESPY_API bluespy_latency_result bluespy_measure_latency(bluespy_audio_channel_t channel0,
                                                               bluespy_audio_channel_t channel1,
                                                               bool include_pres_delay,
                                                               bluespy_time_point ts);

    typedef struct bluespy_cis_lc3_config {
        uint64_t codec_frames_per_SDU;
        uint64_t presentation_delay_us;
        uint32_t octets_per_codec_frame;
        uint32_t frame_duration_us;
        uint32_t sampling_frequency_Hz;
        uint32_t audio_channel_allocation;
    } bluespy_cis_lc3_config;

    BLUESPY_API bluespy_error bluespy_set_cis_lc3_config(bluespy_audiostream_id id,
                                                         bluespy_cis_lc3_config* conf);
    BLUESPY_API bluespy_error bluespy_play_to_audiopod_output(const char* filename, bool loop);

    BLUESPY_API bluespy_error bluespy_stop_audio();

    BLUESPY_API bluespy_error bluespy_mark_key_used(const char* key, size_t len);

    typedef struct bluespy_key {
        size_t length;
        uint8_t* key;
    } bluespy_key;

    BLUESPY_API bluespy_error bluespy_list_keys(bluespy_key** keys, size_t* count);

    BLUESPY_API bluespy_error bluespy_free_keys(bluespy_key* keys, size_t count);

    /*------------------------------------------------------------------------------
     * Bluespy Codec Interface Definitions
     *----------------------------------------------------------------------------*/

    #define BLUESPY_AUDIO_API_VERSION 1

    typedef struct bluespy_audio_codec_lib_info {
        int api_version;        // <- Must be set to BLUESPY_AUDIO_API_VERSION
        const char* codec_name; // <- Human-readable codec name (e.g., "AAC", "aptX", "LDAC")
    } bluespy_audio_codec_lib_info;

    typedef bluespy_audio_codec_lib_info (*bluespy_audio_codec_lib_init_t)(void);

    typedef enum bluespy_codec_container {
        BLUESPY_CODEC_AVDTP,
        BLUESPY_CODEC_CIS,
        BLUESPY_CODEC_BIS
    } bluespy_codec_container;

    typedef struct bluespy_audio_codec_info {
        bluespy_codec_container container;
        const void* config;  // <- pointer to container-specific data block
        uint32_t config_len; // <- length of container-specific block
    } bluespy_audio_codec_info;

    typedef enum bluespy_audio_sample_format {
        BLUESPY_AUDIO_FORMAT_S16_LE = 0,
    } bluespy_audio_sample_format;

    typedef struct bluespy_audio_codec_decoded_format {
        uint32_t sample_rate; // <- Sample rate in Hz
        uint8_t n_channels;   // Number of audio channels (1=mono, 2=stereo)

        /* Format of the PCM samples. Currently only S16_LE (signed 16-bit, little endian) is supported.
         */
        bluespy_audio_sample_format sample_format;
    } bluespy_audio_codec_decoded_format;

    BLUESPY_API void bluespy_add_audio(const uint8_t* pcm_data, uint32_t pcm_data_len,
                                       bluespy_event_id source_id, uint32_t missing_samples);

    typedef void (*bluespy_audio_decode_t)(uintptr_t context, const uint8_t* payload,
                                           const uint32_t payload_len, bluespy_event_id event_id,
                                           uint64_t sequence_number);

    typedef void (*bluespy_audio_codec_deinit_t)(uintptr_t context);

    typedef struct bluespy_audio_codec_funcs {
        bluespy_audio_decode_t decode;
        bluespy_audio_codec_deinit_t deinit;
    } bluespy_audio_codec_funcs;

    typedef struct bluespy_audio_codec_init_ret {
        int error; // <- 0 = success; < 0 = failure.
        bluespy_audio_codec_decoded_format format;
        bluespy_audio_codec_funcs fns;
        uintptr_t context_handle;
    } bluespy_audio_codec_init_ret;

    typedef bluespy_audio_codec_init_ret (*bluespy_audio_codec_init_t)(
        bluespy_audiostream_id stream_id, const bluespy_audio_codec_info* info);

    BLUESPY_API bluespy_error bluespy_enable_custom_decoders();

    BLUESPY_API bluespy_error bluespy_disable_custom_decoders();

    typedef struct bluespy_custom_decoder_status_t {
        bool enabled;
        size_t count;
        const char** names;
    } bluespy_custom_decoder_status_t;

    BLUESPY_API bluespy_custom_decoder_status_t bluespy_custom_decoders_status();

    typedef struct bluespy_spectrum_data {
        int8_t (*data)[79];
        size_t count;
        uint32_t interval; // Nanoseconds
    } bluespy_spectrum_data;
    BLUESPY_API bluespy_spectrum_data bluespy_get_spectrum(bluespy_time_point start,
                                                           bluespy_time_point end);

    BLUESPY_API bluespy_error bluespy_export_logic(const char* filename);

    typedef enum bluespy_audiopod_pin_current {
        bluespy_1mA = 1,
        bluespy_10mA = 10,
        bluespy_100mA = 100,
        bluespy_1A = 1000,
    } bluespy_audiopod_pin_current;

    BLUESPY_API bluespy_error bluespy_set_pin_current(bluespy_audiopod_pin_current current);

    typedef struct bluespy_audiopod_current_data {
        double* data; // In mA
        size_t count;
    } bluespy_audiopod_current_data;
    BLUESPY_API bluespy_audiopod_current_data bluespy_audiopod_current(bluespy_time_point start,
                                                                       bluespy_time_point end);

    BLUESPY_API uint32_t bluespy_version();

    BLUESPY_API void bluespy_enable_key_storage(bool enable);

    #ifdef __cplusplus
    }

    namespace bluespy {
    template <class T, class... Args>
    T* allocate(Args&&... args) {
        T* p = static_cast<T*>(bluespy_allocate(sizeof(T), [](void* p) { ((T*)p)->~T(); }));
        new (p) T(std::forward<Args>(args)...);
        return p;
    }

    inline bluespy_error connect(uint32_t serial = -1) { return bluespy_connect(serial); }
    } // namespace bluespy

    #endif

    #endif