diff options
-rw-r--r-- | binding/radio-binding.c | 33 | ||||
-rw-r--r-- | binding/radio_impl.h | 3 | ||||
-rw-r--r-- | binding/radio_impl_kingfisher.c | 49 | ||||
-rw-r--r-- | binding/radio_impl_null.c | 20 | ||||
-rw-r--r-- | binding/radio_impl_rtlsdr.c | 161 | ||||
-rw-r--r-- | binding/radio_impl_tef665x.c | 46 |
6 files changed, 192 insertions, 120 deletions
diff --git a/binding/radio-binding.c b/binding/radio-binding.c index 3b8561d..8b5559c 100644 --- a/binding/radio-binding.c +++ b/binding/radio-binding.c @@ -678,36 +678,41 @@ static void onevent(afb_api_t api, const char *event, struct json_object *object static int init(afb_api_t api) { - // Look for RTL-SDR USB adapter + // Probe for radio backends radio_impl_ops = &rtlsdr_impl_ops; - int rc = radio_impl_ops->init(); + int rc = radio_impl_ops->probe(); if(rc != 0) { // Look for Kingfisher Si4689 radio_impl_ops = &kf_impl_ops; - rc = radio_impl_ops->init(); + rc = radio_impl_ops->probe(); } if(rc != 0) { radio_impl_ops = &tef665x_impl_ops; - rc = radio_impl_ops->init(); + rc = radio_impl_ops->probe(); } if (rc != 0) { radio_impl_ops = &null_impl_ops; - rc = radio_impl_ops->init(); + rc = radio_impl_ops->probe(); } if (rc != 0) { - // We don't expect the null implementation to fail init, but just in case... + // We don't expect the null implementation to fail probe, but just in case... AFB_API_ERROR(afbBindingV3root, "No radio device found, exiting"); + return rc; } - if(rc == 0) { - AFB_API_NOTICE(afbBindingV3root, "%s found\n", radio_impl_ops->name); - radio_impl_ops->set_frequency_callback(freq_callback, NULL); - if(radio_impl_ops->set_rds_callback) - { - radio_impl_ops->set_rds_callback(rds_callback); - } - } else { + // Try to initialize detected backend + rc = radio_impl_ops->init(); + if(rc < 0) { + AFB_API_ERROR(afbBindingV3root, + "%s initialization failed\n", + radio_impl_ops->name); return rc; } + AFB_API_NOTICE(afbBindingV3root, "%s found\n", radio_impl_ops->name); + radio_impl_ops->set_frequency_callback(freq_callback, NULL); + radio_impl_ops->set_frequency_callback(freq_callback, NULL); + if(radio_impl_ops->set_rds_callback) { + radio_impl_ops->set_rds_callback(rds_callback); + } rc = afb_daemon_require_api("signal-composer", 1); if (rc) { diff --git a/binding/radio_impl.h b/binding/radio_impl.h index 8f1ee94..3e549ac 100644 --- a/binding/radio_impl.h +++ b/binding/radio_impl.h @@ -71,6 +71,9 @@ typedef struct typedef struct { char *name; + int (*probe)(void); + + /* NOTE: init should return -1 if called before probe has been called and returned success */ int (*init)(void); void (*set_output)(const char *output); diff --git a/binding/radio_impl_kingfisher.c b/binding/radio_impl_kingfisher.c index dc59916..b7d243b 100644 --- a/binding/radio_impl_kingfisher.c +++ b/binding/radio_impl_kingfisher.c @@ -57,12 +57,13 @@ static fm_band_plan_t known_fm_band_plans[5] = { }; static unsigned int bandplan = 0; -static bool corking = false; -static bool present = false; +static bool corking; +static bool present; +static bool initialized; static uint32_t current_frequency; static int scan_valid_snr_threshold = 128; static int scan_valid_rssi_threshold = 128; -static bool scanning = false; +static bool scanning; // stream state static GstElement *pipeline; @@ -104,16 +105,9 @@ static void *gstreamer_loop_thread(void *ptr) return NULL; } -static int kf_init(void) +static int kf_probe(void) { - GKeyFile* conf_file; - int conf_file_present = 0; struct stat statbuf; - char *value_str; - char cmd[SI_CTL_CMDLINE_MAXLEN]; - int rc; - char gst_pipeline_str[GST_PIPELINE_LEN]; - pthread_t thread_id; if(present) return 0; @@ -126,6 +120,26 @@ static int kf_init(void) if(stat(SI_CTL, &statbuf) != 0) return -1; + present = true; + return 0; +} + +static int kf_init(void) +{ + GKeyFile* conf_file; + bool conf_file_present = false; + char *value_str; + char cmd[SI_CTL_CMDLINE_MAXLEN]; + int rc; + char gst_pipeline_str[GST_PIPELINE_LEN]; + pthread_t thread_id; + + if(!present) + return -1; + + if(initialized) + return 0; + // Load settings from configuration file if it exists conf_file = g_key_file_new(); if(conf_file && @@ -135,7 +149,7 @@ static int kf_init(void) NULL, G_KEY_FILE_KEEP_COMMENTS, NULL) == TRUE) { - conf_file_present = 1; + conf_file_present = true; // Set band plan if it is specified value_str = g_key_file_get_string(conf_file, @@ -229,7 +243,7 @@ static int kf_init(void) if(rc != 0) return rc; - present = true; + initialized = true; return 0; } @@ -247,7 +261,7 @@ static void kf_set_frequency(uint32_t frequency) char cmd[SI_CTL_CMDLINE_MAXLEN]; int rc; - if(!present) + if(!initialized) return; if(scanning) @@ -363,7 +377,7 @@ static bool kf_get_corking_state(void) static void kf_start(void) { - if(!present) + if(!initialized) return; if(!running || corking) { @@ -378,7 +392,7 @@ static void kf_stop(void) { GstEvent *event; - if(present && running) { + if(initialized && running) { // Stop pipeline running = false; @@ -416,7 +430,7 @@ static void kf_scan_start(radio_scan_direction_t direction, uint32_t new_frequency = 0; FILE *fp; - if(!present) + if(!initialized) return; if(scanning) @@ -487,6 +501,7 @@ static void kf_set_stereo_mode(radio_stereo_mode_t mode) radio_impl_ops_t kf_impl_ops = { .name = "Kingfisher Si4689", + .probe = kf_probe, .init = kf_init, .set_output = kf_set_output, .get_frequency = kf_get_frequency, diff --git a/binding/radio_impl_null.c b/binding/radio_impl_null.c index a90835b..b66c025 100644 --- a/binding/radio_impl_null.c +++ b/binding/radio_impl_null.c @@ -52,6 +52,7 @@ static fm_band_plan_t known_fm_band_plans[5] = { static unsigned int bandplan; static bool present; +static bool initialized; static bool active; static bool scanning; static uint32_t current_frequency; @@ -60,7 +61,12 @@ static void *freq_callback_data; static uint32_t null_get_min_frequency(radio_band_t band); static void null_set_frequency(uint32_t frequency); -//static void null_scan_stop(void); + +static int null_probe(void) +{ + present = true; + return 0; +} static int null_init(void) { @@ -69,7 +75,10 @@ static int null_init(void) char *rootdir; char *helper_path; - if(present) + if(!present) + return -1; + + if(initialized) return 0; // Load settings from configuration file if it exists @@ -103,7 +112,7 @@ static int null_init(void) // Start off with minimum bandplan frequency current_frequency = null_get_min_frequency(BAND_FM); - present = true; + initialized = true; null_set_frequency(current_frequency); return 0; @@ -184,7 +193,7 @@ static uint32_t null_get_frequency_step(radio_band_t band) static void null_start(void) { - if(!present) + if(!initialized) return; if(active) @@ -195,7 +204,7 @@ static void null_start(void) static void null_stop(void) { - if(!present) + if(!initialized) return; if (!active) @@ -251,6 +260,7 @@ static void null_set_stereo_mode(radio_stereo_mode_t mode) radio_impl_ops_t null_impl_ops = { .name = "null/mock radio", + .probe = null_probe, .init = null_init, .set_output = null_set_output, .get_frequency = null_get_frequency, diff --git a/binding/radio_impl_rtlsdr.c b/binding/radio_impl_rtlsdr.c index 62ec623..2087d10 100644 --- a/binding/radio_impl_rtlsdr.c +++ b/binding/radio_impl_rtlsdr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017,2018 Konsulko Group + * Copyright (C) 2017,2018,2020 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,6 +57,7 @@ static int helper_in; static int helper_out; static pthread_mutex_t helper_mutex = PTHREAD_MUTEX_INITIALIZER; static bool present; +static bool initialized; static bool active; static bool scanning; static uint32_t current_frequency; @@ -128,16 +129,89 @@ static pid_t popen2(char *command, int *in_fd, int *out_fd) return pid; } -static int rtlsdr_init(void) +static int rtlsdr_probe(void) { - GKeyFile *conf_file; - char *value_str; char *rootdir; char *helper_path; if(present) return 0; + rootdir = getenv("AFM_APP_INSTALL_DIR"); + if(!rootdir) + return -1; + + // Run helper to detect adapter + helper_path = malloc(HELPER_MAX); + if(!helper_path) + return -ENOMEM; + if(snprintf(helper_path, HELPER_MAX, "%s/bin/%s --detect", rootdir, HELPER_NAME) == HELPER_MAX) { + AFB_API_ERROR(afbBindingV3root, "Could not create command for \"%s --detect\"", HELPER_NAME); + return -EINVAL; + } + if(system(helper_path) != 0) { + free(helper_path); + return -1; + } + + present = true; + return 0; +} + +static int rtlsdr_start_helper(void) +{ + char *rootdir; + char *helper_path; + static bool helper_started = false; + + if(!present || initialized) + return -1; + + if(helper_started) + return 0; + + rootdir = getenv("AFM_APP_INSTALL_DIR"); + if(!rootdir) + return -1; + + if(helper_output) { + // Indicate desired output to helper + AFB_API_INFO(afbBindingV3root, "Setting RADIO_OUTPUT=%s", helper_output); + setenv("RADIO_OUTPUT", helper_output, 1); + } + + // Run helper + helper_path = malloc(HELPER_MAX); + if(!helper_path) + return -ENOMEM; + if(snprintf(helper_path, PATH_MAX, "%s/bin/%s", rootdir, HELPER_NAME) == PATH_MAX) { + AFB_API_ERROR(afbBindingV3root, "Could not create path to %s", HELPER_NAME); + return -EINVAL; + } + helper_pid = popen2(helper_path, &helper_out, &helper_in); + if(helper_pid < 0) { + AFB_API_ERROR(afbBindingV3root, "Could not run %s!", HELPER_NAME); + return -1; + } + AFB_API_DEBUG(afbBindingV3root, "%s started", HELPER_NAME); + helper_started = true; + free(helper_path); + + return 0; +} + +static int rtlsdr_init(void) +{ + GKeyFile *conf_file; + char *value_str; + int rc; + + if(!present) + return -1; + + if(initialized) + return 0; + // Load settings from configuration file if it exists conf_file = g_key_file_new(); if(conf_file && @@ -168,25 +242,12 @@ static int rtlsdr_init(void) // Start off with minimum bandplan frequency current_frequency = rtlsdr_get_min_frequency(BAND_FM); - - rootdir = getenv("AFM_APP_INSTALL_DIR"); - if(!rootdir) - return -1; - - // Run helper to detect adapter - helper_path = malloc(HELPER_MAX); - if(!helper_path) - return -ENOMEM; - if(snprintf(helper_path, HELPER_MAX, "%s/bin/%s --detect", rootdir, HELPER_NAME) == HELPER_MAX) { - AFB_API_ERROR(afbBindingV3root, "Could not create command for \"%s --detect\"", HELPER_NAME); - return -EINVAL; - } - if(system(helper_path) != 0) { - free(helper_path); - return -1; + rc = rtlsdr_start_helper(); + if(rc != 0) { + return rc; } - present = true; + initialized = true; rtlsdr_set_frequency(current_frequency); return 0; @@ -212,7 +273,7 @@ static void rtlsdr_set_frequency(uint32_t frequency) ssize_t rc; uint32_t n; - if(!present) + if(!initialized) return; if(frequency < known_fm_band_plans[bandplan].min || @@ -298,62 +359,17 @@ static uint32_t rtlsdr_get_frequency_step(radio_band_t band) return ret; } -static int rtlsdr_start_helper(void) -{ - char *rootdir; - char *helper_path; - static bool helper_started = false; - - if(!present) - return -1; - - if(helper_started) - return 0; - - rootdir = getenv("AFM_APP_INSTALL_DIR"); - if(!rootdir) - return -1; - - if(helper_output) { - // Indicate desired output to helper - AFB_API_INFO(afbBindingV3root, "Setting RADIO_OUTPUT=%s", helper_output); - setenv("RADIO_OUTPUT", helper_output, 1); - } - - // Run helper - helper_path = malloc(HELPER_MAX); - if(!helper_path) - return -ENOMEM; - if(snprintf(helper_path, PATH_MAX, "%s/bin/%s", rootdir, HELPER_NAME) == PATH_MAX) { - AFB_API_ERROR(afbBindingV3root, "Could not create path to %s", HELPER_NAME); - return -EINVAL; - } - helper_pid = popen2(helper_path, &helper_out, &helper_in); - if(helper_pid < 0) { - AFB_API_ERROR(afbBindingV3root, "Could not run %s!", HELPER_NAME); - return -1; - } - AFB_API_DEBUG(afbBindingV3root, "%s started", HELPER_NAME); - helper_started = true; - free(helper_path); - - return 0; -} - static void rtlsdr_start(void) { - if(!present) - return; + ssize_t rc; + char cmd[HELPER_CMD_MAXLEN]; - if(active) + if(!initialized) return; - if(rtlsdr_start_helper() < 0) + if(active) return; - ssize_t rc; - char cmd[HELPER_CMD_MAXLEN]; - snprintf(cmd, sizeof(cmd), "START\n"); pthread_mutex_lock(&helper_mutex); rc = write(helper_in, cmd, strlen(cmd)); @@ -368,7 +384,7 @@ static void rtlsdr_start(void) static void rtlsdr_stop(void) { ssize_t rc; - if(!present) + if(!initialized) return; if (!active) @@ -470,6 +486,7 @@ static void rtlsdr_set_stereo_mode(radio_stereo_mode_t mode) radio_impl_ops_t rtlsdr_impl_ops = { .name = "RTL-SDR USB adapter", + .probe = rtlsdr_probe, .init = rtlsdr_init, .set_output = rtlsdr_set_output, .get_frequency = rtlsdr_get_frequency, diff --git a/binding/radio_impl_tef665x.c b/binding/radio_impl_tef665x.c index 504f155..9bad684 100644 --- a/binding/radio_impl_tef665x.c +++ b/binding/radio_impl_tef665x.c @@ -137,9 +137,10 @@ static band_plan_t known_am_band_plans[1] = { static unsigned int fm_bandplan = 2; static unsigned int am_bandplan = 0; -static bool corking = false; -static bool present = false; -static bool scanning = false; +static bool corking; +static bool present; +static bool initialized; +static bool scanning; // stream state static GstElement *pipeline; @@ -1626,7 +1627,8 @@ static int i2c_init(const char *i2c, int state, uint32_t *i2c_file_desc) static void tef665x_start(void) { int ret; - if(!present) + + if(!initialized) return; _debug("file_desc ", file_desc); @@ -2078,7 +2080,7 @@ static void tef665x_stop(void) GstEvent *event; audio_set_mute(file_desc, 1); - if(present && running) { + if(initialized && running) { // Stop pipeline running = false; ret = gst_element_set_state(pipeline, GST_STATE_PAUSED); @@ -2093,13 +2095,12 @@ static void tef665x_stop(void) } } -static int tef665x_init() +static int tef665x_probe() { - char gst_pipeline_str[GST_PIPELINE_LEN]; int rc; - current_am_frequency = known_am_band_plans[am_bandplan].min; - current_fm_frequency = known_fm_band_plans[fm_bandplan].min; + if(present) + return 0; rc = i2c_init(I2C_DEV, _open, &file_desc); if(rc < 0) { @@ -2114,6 +2115,24 @@ static int tef665x_init() return -1; } + present = true; + return 0; +} + +static int tef665x_init() +{ + char gst_pipeline_str[GST_PIPELINE_LEN]; + int rc; + + if(!present) + return -1; + + if(initialized) + return 0; + + current_am_frequency = known_am_band_plans[am_bandplan].min; + current_fm_frequency = known_fm_band_plans[fm_bandplan].min; + current_band = BAND_AM; radio_powerSwitch(file_desc, 1); @@ -2150,12 +2169,12 @@ static int tef665x_init() rc = gst_bus_add_watch(gst_element_get_bus(pipeline), (GstBusFunc) handle_message, NULL); _debug("gst_bus_add_watch rc", rc); - present = true; - //Initialize Mutex Lock for Scan and RDS pthread_mutex_init(&scan_mutex, NULL); pthread_mutex_init (&RDS_Mutex, NULL); + initialized = true; + tef665x_start(); return 0; } @@ -2226,7 +2245,8 @@ static void tef665x_set_alternative_frequency(uint32_t frequency) static void tef665x_set_frequency(uint32_t frequency) { uint32_t fd = 0; - if(!present) + + if(!initialized) return; if(scanning) @@ -2357,8 +2377,10 @@ static uint32_t tef665x_get_frequency_step(radio_band_t band) } return ret; } + radio_impl_ops_t tef665x_impl_ops = { .name = "TEF665x", + .probe = tef665x_probe, .init = tef665x_init, .start = tef665x_start, .stop = tef665x_stop, |