diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/librtlsdr.c | 121 | ||||
-rw-r--r-- | src/tuner_fc0013.c | 4 | ||||
-rw-r--r-- | src/tuner_r82xx.c | 96 |
3 files changed, 126 insertions, 95 deletions
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); |