From d696ea3a6d640cd96a1ba2ac39bdc51d7f884e1d Mon Sep 17 00:00:00 2001 From: ZoRo Date: Fri, 18 Feb 2022 20:33:58 +0000 Subject: Update to latest --- include/rtl-sdr.h | 20 +++++++ src/librtlsdr.c | 121 ++++++++++++++++++++++++++++++++++------ src/tuner_fc0013.c | 4 +- src/tuner_r82xx.c | 96 +++++++------------------------ utils/convenience/convenience.c | 4 ++ utils/rtl_adsb.c | 21 +++++-- utils/rtl_biast.c | 101 +++++++++++++++++++++++++++++++++ utils/rtl_eeprom.c | 7 ++- utils/rtl_fm.c | 41 +++++++++++--- utils/rtl_power.c | 21 ++++++- utils/rtl_tcp.c | 119 +++++++++++++++++++++++++++++---------- utils/rtl_test.c | 62 +++++++++++++++----- 12 files changed, 459 insertions(+), 158 deletions(-) create mode 100644 utils/rtl_biast.c diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index fe64bea..d64701e 100644 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -380,6 +380,26 @@ RTLSDR_API int rtlsdr_read_async(rtlsdr_dev_t *dev, */ RTLSDR_API int rtlsdr_cancel_async(rtlsdr_dev_t *dev); +/*! + * Enable or disable the bias tee on GPIO PIN 0. + * + * \param dev the device handle given by rtlsdr_open() + * \param on 1 for Bias T on. 0 for Bias T off. + * \return -1 if device is not initialized. 0 otherwise. + */ +RTLSDR_API int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on); + +/*! + * Enable or disable the bias tee on the given GPIO pin. + * + * \param dev the device handle given by rtlsdr_open() + * \param gpio the gpio pin to configure as a Bias T control. + * \param on 1 for Bias T on. 0 for Bias T off. + * \return -1 if device is not initialized. 0 otherwise. + */ +RTLSDR_API int rtlsdr_set_bias_tee_gpio(rtlsdr_dev_t *dev, int gpio, int on); + + #ifdef __cplusplus } #endif diff --git a/src/librtlsdr.c b/src/librtlsdr.c index cdf1ca9..096abae 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -39,12 +39,6 @@ #define LIBUSB_CALL #endif -/* libusb < 1.0.9 doesn't have libusb_handle_events_timeout_completed */ -#ifndef HAVE_LIBUSB_HANDLE_EVENTS_TIMEOUT_COMPLETED -#define libusb_handle_events_timeout_completed(ctx, tv, c) \ - libusb_handle_events_timeout(ctx, tv) -#endif - /* two raised to the power of n */ #define TWO_POW(n) ((double)(1ULL<<(n))) @@ -103,6 +97,7 @@ struct rtlsdr_dev { void *cb_ctx; enum rtlsdr_async_status async_status; int async_cancel; + int use_zerocopy; /* rtl demod context */ uint32_t rate; /* Hz */ uint32_t rtl_xtal; /* Hz */ @@ -329,6 +324,7 @@ static rtlsdr_dongle_t known_devices[] = { { 0x0ccd, 0x00e0, "Terratec NOXON DAB/DAB+ USB dongle (rev 2)" }, { 0x1554, 0x5020, "PixelView PV-DT235U(RN)" }, { 0x15f4, 0x0131, "Astrometa DVB-T/DVB-T2" }, + { 0x15f4, 0x0133, "HanfTek DAB+FM+DVB-T" }, { 0x185b, 0x0620, "Compro Videomate U620F"}, { 0x185b, 0x0650, "Compro Videomate U650F"}, { 0x185b, 0x0680, "Compro Videomate U680F"}, @@ -569,7 +565,7 @@ void rtlsdr_set_gpio_output(rtlsdr_dev_t *dev, uint8_t gpio) gpio = 1 << gpio; r = rtlsdr_read_reg(dev, SYSB, GPD, 1); - rtlsdr_write_reg(dev, SYSB, GPO, r & ~gpio, 1); + rtlsdr_write_reg(dev, SYSB, GPD, r & ~gpio, 1); r = rtlsdr_read_reg(dev, SYSB, GPOE, 1); rtlsdr_write_reg(dev, SYSB, GPOE, r | gpio, 1); } @@ -1564,11 +1560,11 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) } /* initialise GPIOs */ - rtlsdr_set_gpio_output(dev, 5); + rtlsdr_set_gpio_output(dev, 4); /* reset tuner before probing */ - rtlsdr_set_gpio_bit(dev, 5, 1); - rtlsdr_set_gpio_bit(dev, 5, 0); + rtlsdr_set_gpio_bit(dev, 4, 1); + rtlsdr_set_gpio_bit(dev, 4, 0); reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, FC2580_CHECK_ADDR); if ((reg & 0x7f) == FC2580_CHECK_VAL) { @@ -1593,6 +1589,7 @@ found: switch (dev->tuner_type) { case RTLSDR_TUNER_R828D: dev->tun_xtal = R828D_XTAL_FREQ; + /* fall-through */ case RTLSDR_TUNER_R820T: /* disable Zero-IF mode */ rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1a, 1); @@ -1625,6 +1622,9 @@ found: return 0; err: if (dev) { + if (dev->devh) + libusb_close(dev->devh); + if (dev->ctx) libusb_exit(dev->ctx); @@ -1739,12 +1739,64 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev) dev->xfer[i] = libusb_alloc_transfer(0); } - if (!dev->xfer_buf) { - dev->xfer_buf = malloc(dev->xfer_buf_num * - sizeof(unsigned char *)); + if (dev->xfer_buf) + return -2; - for(i = 0; i < dev->xfer_buf_num; ++i) + dev->xfer_buf = malloc(dev->xfer_buf_num * sizeof(unsigned char *)); + memset(dev->xfer_buf, 0, dev->xfer_buf_num * sizeof(unsigned char *)); + +#if defined(ENABLE_ZEROCOPY) && defined (__linux__) && LIBUSB_API_VERSION >= 0x01000105 + fprintf(stderr, "Allocating %d zero-copy buffers\n", dev->xfer_buf_num); + + dev->use_zerocopy = 1; + for (i = 0; i < dev->xfer_buf_num; ++i) { + dev->xfer_buf[i] = libusb_dev_mem_alloc(dev->devh, dev->xfer_buf_len); + + if (dev->xfer_buf[i]) { + /* Check if Kernel usbfs mmap() bug is present: if the + * mapping is correct, the buffers point to memory that + * was memset to 0 by the Kernel, otherwise, they point + * to random memory. We check if the buffers are zeroed + * and otherwise fall back to buffers in userspace. + */ + if (dev->xfer_buf[i][0] || memcmp(dev->xfer_buf[i], + dev->xfer_buf[i] + 1, + dev->xfer_buf_len - 1)) { + fprintf(stderr, "Detected Kernel usbfs mmap() " + "bug, falling back to buffers " + "in userspace\n"); + dev->use_zerocopy = 0; + break; + } + } else { + fprintf(stderr, "Failed to allocate zero-copy " + "buffer for transfer %d\nFalling " + "back to buffers in userspace\n", i); + dev->use_zerocopy = 0; + break; + } + } + + /* zero-copy buffer allocation failed (partially or completely) + * we need to free the buffers again if already allocated */ + if (!dev->use_zerocopy) { + for (i = 0; i < dev->xfer_buf_num; ++i) { + if (dev->xfer_buf[i]) + libusb_dev_mem_free(dev->devh, + dev->xfer_buf[i], + dev->xfer_buf_len); + } + } +#endif + + /* no zero-copy available, allocate buffers in userspace */ + if (!dev->use_zerocopy) { + for (i = 0; i < dev->xfer_buf_num; ++i) { dev->xfer_buf[i] = malloc(dev->xfer_buf_len); + + if (!dev->xfer_buf[i]) + return -ENOMEM; + } } return 0; @@ -1769,9 +1821,18 @@ static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev) } if (dev->xfer_buf) { - for(i = 0; i < dev->xfer_buf_num; ++i) { - if (dev->xfer_buf[i]) - free(dev->xfer_buf[i]); + for (i = 0; i < dev->xfer_buf_num; ++i) { + if (dev->xfer_buf[i]) { + if (dev->use_zerocopy) { +#if defined (__linux__) && LIBUSB_API_VERSION >= 0x01000105 + libusb_dev_mem_free(dev->devh, + dev->xfer_buf[i], + dev->xfer_buf_len); +#endif + } else { + free(dev->xfer_buf[i]); + } + } } free(dev->xfer_buf); @@ -1826,7 +1887,12 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, r = libusb_submit_transfer(dev->xfer[i]); if (r < 0) { - fprintf(stderr, "Failed to submit transfer %i!\n", i); + fprintf(stderr, "Failed to submit transfer %i\n" + "Please increase your allowed " + "usbfs buffer size with the " + "following command:\n" + "echo 0 > /sys/module/usbcore" + "/parameters/usbfs_memory_mb\n", i); dev->async_status = RTLSDR_CANCELING; break; } @@ -1858,6 +1924,9 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, /* handle events after canceling * to allow transfer status to * propagate */ +#ifdef _WIN32 + Sleep(1); +#endif libusb_handle_events_timeout_completed(dev->ctx, &zerotv, NULL); if (r < 0) @@ -1936,3 +2005,19 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len) return -1; } + +int rtlsdr_set_bias_tee_gpio(rtlsdr_dev_t *dev, int gpio, int on) +{ + if (!dev) + return -1; + + rtlsdr_set_gpio_output(dev, gpio); + rtlsdr_set_gpio_bit(dev, gpio, on); + + return 0; +} + +int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on) +{ + return rtlsdr_set_bias_tee_gpio(dev, 0, on); +} diff --git a/src/tuner_fc0013.c b/src/tuner_fc0013.c index 78b696e..5984dfb 100644 --- a/src/tuner_fc0013.c +++ b/src/tuner_fc0013.c @@ -248,11 +248,11 @@ int fc0013_set_params(void *dev, uint32_t freq, uint32_t bandwidth) if (ret) goto exit; - /* disable UHF & enable GPS */ + /* enable UHF & disable GPS */ ret = fc0013_readreg(dev, 0x14, &tmp); if (ret) goto exit; - ret = fc0013_writereg(dev, 0x14, (tmp & 0x1f) | 0x20); + ret = fc0013_writereg(dev, 0x14, (tmp & 0x1f) | 0x40); if (ret) goto exit; } diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c index f620238..997abd7 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -330,8 +330,14 @@ static int r82xx_read(struct r82xx_priv *priv, uint8_t reg, uint8_t *val, int le priv->buf[0] = reg; rc = rtlsdr_i2c_write_fn(priv->rtl_dev, priv->cfg->i2c_addr, priv->buf, 1); - if (rc < 1) - return rc; + + if (rc != 1) { + fprintf(stderr, "%s: i2c wr failed=%d reg=%02x len=%d\n", + __FUNCTION__, rc, reg, 1); + if (rc < 0) + return rc; + return -1; + } rc = rtlsdr_i2c_read_fn(priv->rtl_dev, priv->cfg->i2c_addr, p, len); @@ -770,78 +776,18 @@ static int r82xx_set_tv_standard(struct r82xx_priv *priv, uint8_t lt_att, flt_ext_widest, polyfil_cur; int need_calibration; - if (delsys == SYS_ISDBT) { - if_khz = 4063; - filt_cal_lo = 59000; - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x6a; /* 1.7m disable, +2cap, 1.25mhz */ - ext_enable = 0x40; /* r30[6], ext enable; r30[5]:0 ext at lna max */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ - } else { - if (bw <= 6) { - if_khz = 3570; - filt_cal_lo = 56000; /* 52000->56000 */ - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x6b; /* 1.7m disable, +2cap, 1.0mhz */ - ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ - } else if (bw == 7) { -#if 0 - /* - * There are two 7 MHz tables defined on the original - * driver, but just the second one seems to be visible - * by rtl2832. Keep this one here commented, as it - * might be needed in the future - */ - - if_khz = 4070; - filt_cal_lo = 60000; - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x2b; /* 1.7m disable, +1cap, 1.0mhz */ - ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ -#endif - /* 7 MHz, second table */ - if_khz = 4570; - filt_cal_lo = 63000; - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x2a; /* 1.7m disable, +1cap, 1.25mhz */ - ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ - } else { - if_khz = 4570; - filt_cal_lo = 68500; - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x0b; /* 1.7m disable, +0cap, 1.0mhz */ - ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ - } - } + /* BW < 6 MHz */ + if_khz = 3570; + filt_cal_lo = 56000; /* 52000->56000 */ + filt_gain = 0x10; /* +3db, 6mhz on */ + img_r = 0x00; /* image negative */ + filt_q = 0x10; /* r10[4]:low q(1'b1) */ + hp_cor = 0x6b; /* 1.7m disable, +2cap, 1.0mhz */ + ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ + loop_through = 0x01; /* r5[7], lt off */ + lt_att = 0x00; /* r31[7], lt att enable */ + flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ + polyfil_cur = 0x60; /* r25[6:5]:min */ /* Initialize the shadow registers */ memcpy(priv->regs, r82xx_init_array, sizeof(r82xx_init_array)); @@ -1196,7 +1142,7 @@ int r82xx_standby(struct r82xx_priv *priv) rc = r82xx_write_reg(priv, 0x06, 0xb1); if (rc < 0) return rc; - rc = r82xx_write_reg(priv, 0x05, 0x03); + rc = r82xx_write_reg(priv, 0x05, 0xa0); if (rc < 0) return rc; rc = r82xx_write_reg(priv, 0x07, 0x3a); diff --git a/utils/convenience/convenience.c b/utils/convenience/convenience.c index 517dc4e..00cc2cc 100644 --- a/utils/convenience/convenience.c +++ b/utils/convenience/convenience.c @@ -49,9 +49,11 @@ double atofs(char *s) case 'g': case 'G': suff *= 1e3; + /* fall-through */ case 'm': case 'M': suff *= 1e3; + /* fall-through */ case 'k': case 'K': suff *= 1e3; @@ -76,9 +78,11 @@ double atoft(char *s) case 'h': case 'H': suff *= 60; + /* fall-through */ case 'm': case 'M': suff *= 60; + /* fall-through */ case 's': case 'S': suff *= atof(s); diff --git a/utils/rtl_adsb.c b/utils/rtl_adsb.c index 7de9204..7aea8dd 100644 --- a/utils/rtl_adsb.c +++ b/utils/rtl_adsb.c @@ -96,6 +96,7 @@ void usage(void) "\t[-e allowed_errors (default: 5)]\n" "\t[-g tuner_gain (default: automatic)]\n" "\t[-p ppm_error (default: 0)]\n" + "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" "\tfilename (a '-' dumps samples to stdout)\n" "\t (omitting the filename also uses stdout)\n\n" "Streaming with netcat:\n" @@ -182,7 +183,7 @@ int magnitute(uint8_t *buf, int len) return len/2; } -uint16_t single_manchester(uint16_t a, uint16_t b, uint16_t c, uint16_t d) +static inline uint16_t single_manchester(uint16_t a, uint16_t b, uint16_t c, uint16_t d) /* takes 4 consecutive real samples, return 0 or 1, BADSAMPLE on error */ { int bit, bit_p; @@ -223,17 +224,17 @@ uint16_t single_manchester(uint16_t a, uint16_t b, uint16_t c, uint16_t d) return BADSAMPLE; } -inline uint16_t min16(uint16_t a, uint16_t b) +static inline uint16_t min16(uint16_t a, uint16_t b) { return ab ? a : b; } -int preamble(uint16_t *buf, int i) +static inline int preamble(uint16_t *buf, int i) /* returns 0/1 for preamble at index i */ { int i2; @@ -371,11 +372,12 @@ int main(int argc, char **argv) int dev_index = 0; int dev_given = 0; int ppm_error = 0; + int enable_biastee = 0; pthread_cond_init(&ready, NULL); pthread_mutex_init(&ready_m, NULL); squares_precompute(); - while ((opt = getopt(argc, argv, "d:g:p:e:Q:VS")) != -1) + while ((opt = getopt(argc, argv, "d:g:p:e:Q:VST")) != -1) { switch (opt) { case 'd': @@ -400,6 +402,9 @@ int main(int argc, char **argv) case 'Q': quality = (int)(atof(optarg) * 10); break; + case 'T': + enable_biastee = 1; + break; default: usage(); return 0; @@ -470,6 +475,10 @@ int main(int argc, char **argv) /* Set the sample rate */ verbose_set_sample_rate(dev, ADSB_RATE); + rtlsdr_set_bias_tee(dev, enable_biastee); + if (enable_biastee) + fprintf(stderr, "activated bias-T on GPIO PIN 0\n"); + /* Reset endpoint before we start reading from it (mandatory) */ verbose_reset_buffer(dev); @@ -483,6 +492,8 @@ int main(int argc, char **argv) else { fprintf(stderr, "\nLibrary error %d, exiting...\n", r);} rtlsdr_cancel_async(dev); + pthread_cancel(demod_thread); + pthread_join(demod_thread, NULL); pthread_cond_destroy(&ready); pthread_mutex_destroy(&ready_m); diff --git a/utils/rtl_biast.c b/utils/rtl_biast.c new file mode 100644 index 0000000..185e838 --- /dev/null +++ b/utils/rtl_biast.c @@ -0,0 +1,101 @@ +/* + * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver + * rtl_biast, tool to set bias tee gpio output + * Copyright (C) 2012 by Steve Markgraf + * + * 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 2 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 . + */ + +#include +#include +#include + +#ifndef _WIN32 +#include +#else +#include +#include "getopt/getopt.h" +#endif + +#include "rtl-sdr.h" +#include "convenience/convenience.h" + +static rtlsdr_dev_t *dev = NULL; + +void usage(void) +{ + fprintf(stderr, + "rtl_biast, a tool for turning the RTL-SDR.com \n" + "bias tee or any GPIO ON and OFF. Example to turn on the \n" + "bias tee: rtl_biast -d 0 -b 1\n" + "Any GPIO: rtl_biast -d 0 -g 1 -b 1\n\n" + "Usage:\n" + "\t[-d device_index (default: 0)]\n" + "\t[-b bias_on (default: 0)]\n" + "\t[-g GPIO select (default: 0)]\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int i, r, opt; + int dev_index = 0; + int dev_given = 0; + uint32_t bias_on = 0; + uint32_t gpio_pin = 0; + int device_count; + + while ((opt = getopt(argc, argv, "d:b:g:h?")) != -1) { + switch (opt) { + case 'd': + dev_index = verbose_device_search(optarg); + dev_given = 1; + break; + case 'b': + bias_on = atoi(optarg); + break; + case 'g': + gpio_pin = atoi(optarg); + break; + default: + usage(); + break; + } + } + + if (!dev_given) { + dev_index = verbose_device_search("0"); + } + + if (dev_index < 0) { + exit(1); + } + + r = rtlsdr_open(&dev, dev_index); + rtlsdr_set_bias_tee_gpio(dev, gpio_pin, bias_on); + +exit: + /* + * Note - rtlsdr_close() in this tree does not clear the bias tee + * GPIO line, so it leaves the bias tee enabled if a client program + * doesn't explictly disable it. + * + * If that behaviour changes then another rtlsdr_close() will be + * needed that takes some extension flags, and one of them should + * be to either explicitly close the biast or leave it alone. + */ + rtlsdr_close(dev); + + return r >= 0 ? r : -r; +} diff --git a/utils/rtl_eeprom.c b/utils/rtl_eeprom.c index 5259820..24be900 100644 --- a/utils/rtl_eeprom.c +++ b/utils/rtl_eeprom.c @@ -303,6 +303,7 @@ int main(int argc, char **argv) case 'w': flash_file = 1; change = 1; + /* fall-through */ case 'r': filename = optarg; break; @@ -369,14 +370,14 @@ int main(int argc, char **argv) } if (manuf_str) - strncpy((char*)&conf.manufacturer, manuf_str, MAX_STR_SIZE); + strncpy((char*)&conf.manufacturer, manuf_str, MAX_STR_SIZE - 1); if (product_str) - strncpy((char*)&conf.product, product_str, MAX_STR_SIZE); + strncpy((char*)&conf.product, product_str, MAX_STR_SIZE - 1); if (serial_str) { conf.have_serial = 1; - strncpy((char*)&conf.serial, serial_str, MAX_STR_SIZE); + strncpy((char*)&conf.serial, serial_str, MAX_STR_SIZE - 1); } if (ir_endpoint != 0) diff --git a/utils/rtl_fm.c b/utils/rtl_fm.c index e89e42d..7c84332 100644 --- a/utils/rtl_fm.c +++ b/utils/rtl_fm.c @@ -193,6 +193,7 @@ void usage(void) "\t raw mode outputs 2x16 bit IQ pairs\n" "\t[-s sample_rate (default: 24k)]\n" "\t[-d device_index (default: 0)]\n" + "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" "\t[-g tuner_gain (default: automatic)]\n" "\t[-l squelch_level (default: 0/off)]\n" //"\t for fm squelch is inverted\n" @@ -200,11 +201,12 @@ void usage(void) "\t[-p ppm_error (default: 0)]\n" "\t[-E enable_option (default: none)]\n" "\t use multiple -E to enable multiple options\n" - "\t edge: enable lower edge tuning\n" - "\t dc: enable dc blocking filter\n" - "\t deemp: enable de-emphasis filter\n" - "\t direct: enable direct sampling\n" - "\t offset: enable offset tuning\n" + "\t edge: enable lower edge tuning\n" + "\t dc: enable dc blocking filter\n" + "\t deemp: enable de-emphasis filter\n" + "\t direct: enable direct sampling 1 (usually I)\n" + "\t direct2: enable direct sampling 2 (usually Q)\n" + "\t offset: enable offset tuning\n" "\tfilename ('-' means stdout)\n" "\t omitting the filename also uses stdout\n\n" "Experimental options:\n" @@ -502,7 +504,7 @@ int polar_disc_lut(int ar, int aj, int br, int bj) if (x_abs >= atan_lut_size) { /* we can use linear range, but it is not necessary */ - return (cj > 0) ? 1<<13 : -1<<13; + return (cj > 0) ? 1<<13 : -(1<<13); } if (x > 0) { @@ -891,7 +893,7 @@ static void *controller_thread_fn(void *arg) /* set up primary channel */ optimal_settings(s->freqs[0], demod.rate_in); if (dongle.direct_sampling) { - verbose_direct_sampling(dongle.dev, 1);} + verbose_direct_sampling(dongle.dev, dongle.direct_sampling);} if (dongle.offset_tuning) { verbose_offset_tuning(dongle.dev);} @@ -925,8 +927,21 @@ void frequency_range(struct controller_state *s, char *arg) int i; start = arg; stop = strchr(start, ':') + 1; + if (stop == (char *)1) { // no stop or step given + s->freqs[s->freq_len] = (uint32_t) atofs(start); + s->freq_len++; + return; + } stop[-1] = '\0'; step = strchr(stop, ':') + 1; + if (step == (char *)1) { // no step given + s->freqs[s->freq_len] = (uint32_t) atofs(start); + s->freq_len++; + s->freqs[s->freq_len] = (uint32_t) atofs(stop); + s->freq_len++; + stop[-1] = ':'; + return; + } step[-1] = '\0'; for(i=(int)atofs(start); i<=(int)atofs(stop); i+=(int)atofs(step)) { @@ -1042,12 +1057,13 @@ int main(int argc, char **argv) int r, opt; int dev_given = 0; int custom_ppm = 0; + int enable_biastee = 0; dongle_init(&dongle); demod_init(&demod); output_init(&output); controller_init(&controller); - while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:E:F:A:M:h")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:E:F:A:M:hT")) != -1) { switch (opt) { case 'd': dongle.dev_index = verbose_device_search(optarg); @@ -1104,6 +1120,8 @@ int main(int argc, char **argv) demod.deemph = 1;} if (strcmp("direct", optarg) == 0) { dongle.direct_sampling = 1;} + if (strcmp("direct2", optarg) == 0) { + dongle.direct_sampling = 2;} if (strcmp("offset", optarg) == 0) { dongle.offset_tuning = 1;} break; @@ -1142,6 +1160,9 @@ int main(int argc, char **argv) demod.deemph = 1; demod.squelch_level = 0;} break; + case 'T': + enable_biastee = 1; + break; case 'h': default: usage(); @@ -1205,6 +1226,10 @@ int main(int argc, char **argv) verbose_gain_set(dongle.dev, dongle.gain); } + rtlsdr_set_bias_tee(dongle.dev, enable_biastee); + if (enable_biastee) + fprintf(stderr, "activated bias-T on GPIO PIN 0\n"); + verbose_ppm_set(dongle.dev, dongle.ppm_error); if (strcmp(output.filename, "-") == 0) { /* Write samples to stdout */ diff --git a/utils/rtl_power.c b/utils/rtl_power.c index 23b516c..6204de2 100644 --- a/utils/rtl_power.c +++ b/utils/rtl_power.c @@ -133,6 +133,7 @@ void usage(void) "\t[-d device_index (default: 0)]\n" "\t[-g tuner_gain (default: automatic)]\n" "\t[-p ppm_error (default: 0)]\n" + "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" "\tfilename (a '-' dumps samples to stdout)\n" "\t (omitting the filename also uses stdout)\n" "\n" @@ -249,7 +250,7 @@ void sine_table(int size) } } -int16_t FIX_MPY(int16_t a, int16_t b) +static inline int16_t FIX_MPY(int16_t a, int16_t b) /* fixed point multiply and scale */ { int c = ((int)a * (int)b) >> 14; @@ -436,8 +437,16 @@ void frequency_range(char *arg, double crop) /* hacky string parsing */ start = arg; stop = strchr(start, ':') + 1; + if (stop == (char *)1) { + fprintf(stderr, "Bad frequency range specification: %s\n", arg); + exit(1); + } stop[-1] = '\0'; step = strchr(stop, ':') + 1; + if (step == (char *)1) { + fprintf(stderr, "Bad frequency range specification: %s\n", arg); + exit(1); + } step[-1] = '\0'; lower = (int)atofs(start); upper = (int)atofs(stop); @@ -771,6 +780,7 @@ int main(int argc, char **argv) int single = 0; int direct_sampling = 0; int offset_tuning = 0; + int enable_biastee = 0; double crop = 0.0; char *freq_optarg; time_t next_tick; @@ -781,7 +791,7 @@ int main(int argc, char **argv) double (*window_fn)(int, int) = rectangle; freq_optarg = ""; - while ((opt = getopt(argc, argv, "f:i:s:t:d:g:p:e:w:c:F:1PDOh")) != -1) { + while ((opt = getopt(argc, argv, "f:i:s:t:d:g:p:e:w:c:F:1PDOhT")) != -1) { switch (opt) { case 'f': // lower:upper:bin_size freq_optarg = strdup(optarg); @@ -849,6 +859,9 @@ int main(int argc, char **argv) boxcar = 0; comp_fir_size = atoi(optarg); break; + case 'T': + enable_biastee = 1; + break; case 'h': default: usage(); @@ -925,6 +938,10 @@ int main(int argc, char **argv) verbose_ppm_set(dev, ppm_error); + rtlsdr_set_bias_tee(dev, enable_biastee); + if (enable_biastee) + fprintf(stderr, "activated bias-T on GPIO PIN 0\n"); + if (strcmp(filename, "-") == 0) { /* Write log to stdout */ file = stdout; #ifdef _WIN32 diff --git a/utils/rtl_tcp.c b/utils/rtl_tcp.c index 317e0f3..84f5591 100644 --- a/utils/rtl_tcp.c +++ b/utils/rtl_tcp.c @@ -30,10 +30,12 @@ #include #include #include +#include #include #include #else #include +#include #include "getopt/getopt.h" #endif @@ -54,6 +56,10 @@ typedef int socklen_t; #define SOCKET_ERROR -1 #endif +#define DEFAULT_PORT_STR "1234" +#define DEFAULT_SAMPLE_RATE_HZ 2048000 +#define DEFAULT_MAX_NUM_BUFFERS 500 + static SOCKET s; static pthread_t tcp_worker_thread; @@ -78,24 +84,27 @@ typedef struct { /* structure size must be multiple of 2 bytes */ static rtlsdr_dev_t *dev = NULL; +static int enable_biastee = 0; static int global_numq = 0; static struct llist *ll_buffers = 0; -static int llbuf_num = 500; +static int llbuf_num = DEFAULT_MAX_NUM_BUFFERS; static volatile int do_exit = 0; + void usage(void) { - printf("rtl_tcp, an I/Q spectrum server for RTL2832 based DVB-T receivers\n\n" - "Usage:\t[-a listen address]\n" - "\t[-p listen port (default: 1234)]\n" - "\t[-f frequency to tune to [Hz]]\n" - "\t[-g gain (default: 0 for auto)]\n" - "\t[-s samplerate in Hz (default: 2048000 Hz)]\n" - "\t[-b number of buffers (default: 15, set by library)]\n" - "\t[-n max number of linked list buffers to keep (default: 500)]\n" - "\t[-d device index (default: 0)]\n" - "\t[-P ppm_error (default: 0)]\n"); + printf("rtl_tcp, an I/Q spectrum server for RTL2832 based DVB-T receivers\n\n"); + printf("Usage:\t[-a listen address]\n"); + printf("\t[-p listen port (default: %s)]\n", DEFAULT_PORT_STR); + printf("\t[-f frequency to tune to [Hz]]\n"); + printf("\t[-g gain (default: 0 for auto)]\n"); + printf("\t[-s samplerate in Hz (default: %d Hz)]\n", DEFAULT_SAMPLE_RATE_HZ); + printf("\t[-b number of buffers (default: 15, set by library)]\n"); + printf("\t[-n max number of linked list buffers to keep (default: %d)]\n", DEFAULT_MAX_NUM_BUFFERS); + printf("\t[-d device index (default: 0)]\n"); + printf("\t[-P ppm_error (default: 0)]\n"); + printf("\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n"); exit(1); } @@ -355,6 +364,10 @@ static void *command_worker(void *arg) printf("set tuner gain by index %d\n", ntohl(cmd.param)); set_gain_by_index(dev, ntohl(cmd.param)); break; + case 0x0e: + printf("set bias tee %d\n", ntohl(cmd.param)); + rtlsdr_set_bias_tee(dev, (int)ntohl(cmd.param)); + break; default: break; } @@ -365,10 +378,18 @@ static void *command_worker(void *arg) int main(int argc, char **argv) { int r, opt, i; - char* addr = "127.0.0.1"; - int port = 1234; - uint32_t frequency = 100000000, samp_rate = 2048000; - struct sockaddr_in local, remote; + char *addr = "127.0.0.1"; + const char *port = DEFAULT_PORT_STR; + uint32_t frequency = 100000000, samp_rate = DEFAULT_SAMPLE_RATE_HZ; + struct sockaddr_storage local, remote; + struct addrinfo *ai; + struct addrinfo *aiHead; + struct addrinfo hints; + char hostinfo[NI_MAXHOST]; + char portinfo[NI_MAXSERV]; + char remhostinfo[NI_MAXHOST]; + char remportinfo[NI_MAXSERV]; + int aiErr; uint32_t buf_num = 0; int dev_index = 0; int dev_given = 0; @@ -379,7 +400,7 @@ int main(int argc, char **argv) void *status; struct timeval tv = {1,0}; struct linger ling = {1,0}; - SOCKET listensocket; + SOCKET listensocket = 0; socklen_t rlen; fd_set readfds; u_long blockmode = 1; @@ -391,7 +412,7 @@ int main(int argc, char **argv) struct sigaction sigact, sigign; #endif - while ((opt = getopt(argc, argv, "a:p:f:g:s:b:n:d:P:")) != -1) { + while ((opt = getopt(argc, argv, "a:p:f:g:s:b:n:d:P:T")) != -1) { switch (opt) { case 'd': dev_index = verbose_device_search(optarg); @@ -407,10 +428,10 @@ int main(int argc, char **argv) samp_rate = (uint32_t)atofs(optarg); break; case 'a': - addr = optarg; + addr = strdup(optarg); break; case 'p': - port = atoi(optarg); + port = strdup(optarg); break; case 'b': buf_num = atoi(optarg); @@ -421,6 +442,9 @@ int main(int argc, char **argv) case 'P': ppm_error = atoi(optarg); break; + case 'T': + enable_biastee = 1; + break; default: usage(); break; @@ -491,6 +515,10 @@ int main(int argc, char **argv) fprintf(stderr, "Tuner gain set to %f dB.\n", gain/10.0); } + rtlsdr_set_bias_tee(dev, enable_biastee); + if (enable_biastee) + fprintf(stderr, "activated bias-T on GPIO PIN 0\n"); + /* Reset endpoint before we start reading from it (mandatory) */ r = rtlsdr_reset_buffer(dev); if (r < 0) @@ -502,16 +530,42 @@ int main(int argc, char **argv) pthread_cond_init(&cond, NULL); pthread_cond_init(&exit_cond, NULL); - memset(&local,0,sizeof(local)); - local.sin_family = AF_INET; - local.sin_port = htons(port); - local.sin_addr.s_addr = inet_addr(addr); + hints.ai_flags = AI_PASSIVE; /* Server mode. */ + hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6. */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if ((aiErr = getaddrinfo(addr, + port, + &hints, + &aiHead )) != 0) + { + fprintf(stderr, "local address %s ERROR - %s.\n", + addr, gai_strerror(aiErr)); + return(-1); + } + memcpy(&local, aiHead->ai_addr, aiHead->ai_addrlen); + + for (ai = aiHead; ai != NULL; ai = ai->ai_next) { + aiErr = getnameinfo((struct sockaddr *)ai->ai_addr, ai->ai_addrlen, + hostinfo, NI_MAXHOST, + portinfo, NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + if (aiErr) + fprintf( stderr, "getnameinfo ERROR - %s.\n",hostinfo); + + listensocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (listensocket < 0) + continue; + + r = 1; + setsockopt(listensocket, SOL_SOCKET, SO_REUSEADDR, (char *)&r, sizeof(int)); + setsockopt(listensocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - listensocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - r = 1; - setsockopt(listensocket, SOL_SOCKET, SO_REUSEADDR, (char *)&r, sizeof(int)); - setsockopt(listensocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - bind(listensocket,(struct sockaddr *)&local,sizeof(local)); + if (bind(listensocket, (struct sockaddr *)&local, sizeof(local))) + fprintf(stderr, "rtl_tcp bind error: %s", strerror(errno)); + else + break; + } #ifdef _WIN32 ioctlsocket(listensocket, FIONBIO, &blockmode); @@ -522,11 +576,11 @@ int main(int argc, char **argv) while(1) { printf("listening...\n"); - printf("Use the device argument 'rtl_tcp=%s:%d' in OsmoSDR " + printf("Use the device argument 'rtl_tcp=%s:%s' in OsmoSDR " "(gr-osmosdr) source\n" "to receive samples in GRC and control " "rtl_tcp parameters (frequency, gain, ...).\n", - addr, port); + hostinfo, portinfo); listen(listensocket,1); while(1) { @@ -546,7 +600,10 @@ int main(int argc, char **argv) setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - printf("client accepted!\n"); + getnameinfo((struct sockaddr *)&remote, rlen, + remhostinfo, NI_MAXHOST, + remportinfo, NI_MAXSERV, NI_NUMERICSERV); + printf("client accepted! %s %s\n", remhostinfo, remportinfo); memset(&dongle_info, 0, sizeof(dongle_info)); memcpy(&dongle_info.magic, "RTL0", 4); diff --git a/utils/rtl_test.c b/utils/rtl_test.c index 9a6cfda..9b44097 100644 --- a/utils/rtl_test.c +++ b/utils/rtl_test.c @@ -53,6 +53,21 @@ #define PPM_DURATION 10 #define PPM_DUMP_TIME 5 +struct time_generic +/* holds all the platform specific values */ +{ +#ifndef _WIN32 + time_t tv_sec; + long tv_nsec; +#else + long tv_sec; + long tv_nsec; + int init; + LARGE_INTEGER frequency; + LARGE_INTEGER ticks; +#endif +}; + static enum { NO_BENCHMARK, TUNER_BENCHMARK, @@ -134,21 +149,42 @@ static void underrun_test(unsigned char *buf, uint32_t len, int mute) } #ifndef _WIN32 -static int ppm_gettime(struct timespec *ts) +static int ppm_gettime(struct time_generic *tg) { int rv = ENOSYS; + struct timespec ts; #ifdef __unix__ - rv = clock_gettime(CLOCK_MONOTONIC, ts); + rv = clock_gettime(CLOCK_MONOTONIC, &ts); + tg->tv_sec = ts.tv_sec; + tg->tv_nsec = ts.tv_nsec; #elif __APPLE__ struct timeval tv; rv = gettimeofday(&tv, NULL); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; + tg->tv_sec = tv.tv_sec; + tg->tv_nsec = tv.tv_usec * 1000; #endif return rv; } +#endif + +#ifdef _WIN32 +static int ppm_gettime(struct time_generic *tg) +{ + int rv; + int64_t frac; + if (!tg->init) { + QueryPerformanceFrequency(&tg->frequency); + tg->init = 1; + } + rv = QueryPerformanceCounter(&tg->ticks); + tg->tv_sec = tg->ticks.QuadPart / tg->frequency.QuadPart; + frac = (int64_t)(tg->ticks.QuadPart - (tg->tv_sec * tg->frequency.QuadPart)); + tg->tv_nsec = (long)(frac * 1000000000L / (int64_t)tg->frequency.QuadPart); + return !rv; +} +#endif static int ppm_report(uint64_t nsamples, uint64_t interval) { @@ -165,8 +201,8 @@ static void ppm_test(uint32_t len) static uint64_t interval = 0; static uint64_t nsamples_total = 0; static uint64_t interval_total = 0; - struct timespec ppm_now; - static struct timespec ppm_recent; + struct time_generic ppm_now; + static struct time_generic ppm_recent; static enum { PPM_INIT_NO, PPM_INIT_DUMP, @@ -174,6 +210,7 @@ static void ppm_test(uint32_t len) } ppm_init = PPM_INIT_NO; ppm_gettime(&ppm_now); + if (ppm_init != PPM_INIT_RUN) { /* * Kyle Keen wrote: @@ -189,11 +226,11 @@ static void ppm_test(uint32_t len) } if (ppm_init == PPM_INIT_DUMP && ppm_recent.tv_sec < ppm_now.tv_sec) return; - ppm_recent.tv_sec = ppm_now.tv_sec; - ppm_recent.tv_nsec = ppm_now.tv_nsec; + ppm_recent = ppm_now; ppm_init = PPM_INIT_RUN; return; } + nsamples += (uint64_t)(len / 2UL); interval = (uint64_t)(ppm_now.tv_sec - ppm_recent.tv_sec); if (interval < ppm_duration) @@ -206,19 +243,16 @@ static void ppm_test(uint32_t len) (int)((1000000000UL * nsamples) / interval), ppm_report(nsamples, interval), ppm_report(nsamples_total, interval_total)); - ppm_recent.tv_sec = ppm_now.tv_sec; - ppm_recent.tv_nsec = ppm_now.tv_nsec; + ppm_recent = ppm_now; nsamples = 0; } -#endif static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) { underrun_test(buf, len, 0); -#ifndef _WIN32 + if (test_mode == PPM_BENCHMARK) ppm_test(len); -#endif } void e4k_benchmark(void) @@ -375,7 +409,7 @@ int main(int argc, char **argv) verbose_reset_buffer(dev); if ((test_mode == PPM_BENCHMARK) && !sync_mode) { - fprintf(stderr, "Reporting PPM error measurement every %i seconds...\n", ppm_duration); + fprintf(stderr, "Reporting PPM error measurement every %u seconds...\n", ppm_duration); fprintf(stderr, "Press ^C after a few minutes.\n"); } -- cgit v1.2.3