Hello,
I am working on getting rtl-sdr working on Android inside a Termux environment. Termux-usb
(
https://wiki.termux.com/wiki/Termux-usb) negotiates with Android to get an fd, and the fd
gets passed as command line argument to the program needing the USB device. This patch
adds support for it.
With it, I can run
termux-usb -e "./rtl-sdr/build/src/rtl_fm -f 440M -M fm -N" /dev/bus/usb/001/002
| ./direwolf/build/src/direwolf -t 0 stdin
in Termux, and connecto to it from APRSDroid.
---
include/rtl-sdr.h | 2 ++
src/librtlsdr.c | 92 +++++++++++++++++++++++++++++++++++++++++++++--
src/rtl_adsb.c | 21 ++++++++---
src/rtl_biast.c | 19 +++++++---
src/rtl_fm.c | 19 +++++++---
src/rtl_power.c | 19 +++++++---
src/rtl_sdr.c | 17 +++++++--
src/rtl_tcp.c | 19 +++++++---
src/rtl_test.c | 19 +++++++---
9 files changed, 196 insertions(+), 31 deletions(-)
diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h
index d64701e..bd88f74 100644
--- a/include/rtl-sdr.h
+++ b/include/rtl-sdr.h
@@ -62,6 +62,8 @@ RTLSDR_API int rtlsdr_get_index_by_serial(const char *serial);
RTLSDR_API int rtlsdr_open(rtlsdr_dev_t **dev, uint32_t index);
+RTLSDR_API int rtlsdr_open_fd(rtlsdr_dev_t **dev, intptr_t fd);
+
RTLSDR_API int rtlsdr_close(rtlsdr_dev_t *dev);
/* configuration functions */
diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index ee13556..1c4985b 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -125,6 +125,7 @@ struct rtlsdr_dev {
void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val);
static int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq);
+static int rtlsdr_init(rtlsdr_dev_t *dev);
/* generic tuner interface functions, shall be moved to the tuner implementations */
int e4000_init(void *dev) {
@@ -1451,7 +1452,6 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
libusb_device *device = NULL;
uint32_t device_count = 0;
struct libusb_device_descriptor dd;
- uint8_t reg;
ssize_t cnt;
dev = malloc(sizeof(rtlsdr_dev_t));
@@ -1503,6 +1503,94 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
libusb_free_device_list(list, 1);
+ r = rtlsdr_init(dev);
+ if (r < 0) {
+ goto err;
+ }
+
+ *out_dev = dev;
+
+ return r;
+err:
+ if (dev) {
+ if (dev->devh)
+ libusb_close(dev->devh);
+
+ if (dev->ctx)
+ libusb_exit(dev->ctx);
+
+ free(dev);
+ }
+
+ return r;
+}
+
+int rtlsdr_open_fd(rtlsdr_dev_t **out_dev, intptr_t fd)
+{
+ int r;
+ rtlsdr_dev_t *dev = NULL;
+ libusb_device *device = NULL;
+ struct libusb_device_descriptor dd;
+
+ dev = malloc(sizeof(rtlsdr_dev_t));
+ if (NULL == dev)
+ return -ENOMEM;
+
+ memset(dev, 0, sizeof(rtlsdr_dev_t));
+ memcpy(dev->fir, fir_default, sizeof(fir_default));
+
+ libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY);
+ r = libusb_init(&dev->ctx);
+ if(r < 0){
+ free(dev);
+ return -1;
+ }
+
+ dev->dev_lost = 1;
+
+ r = libusb_wrap_sys_device(dev->ctx, fd, &dev->devh);
+ if (r < 0) {
+ fprintf(stderr, "usb_open error %d\n", r);
+ if(r == LIBUSB_ERROR_ACCESS)
+ fprintf(stderr, "Please fix the device permissions, e.g. "
+ "by installing the udev rules file rtl-sdr.rules\n");
+ goto err;
+ }
+
+ device = libusb_get_device(dev->devh);
+ libusb_get_device_descriptor(device, &dd);
+ if (!find_known_device(dd.idVendor, dd.idProduct)) {
+ fprintf(stderr, "Unrecognized device\n");
+ r = -1;
+ goto err;
+ }
+
+ r = rtlsdr_init(dev);
+ if (r < 0) {
+ goto err;
+ }
+
+ *out_dev = dev;
+
+ return r;
+err:
+ if (dev) {
+ if (dev->devh)
+ libusb_close(dev->devh);
+
+ if (dev->ctx)
+ libusb_exit(dev->ctx);
+
+ free(dev);
+ }
+
+ return r;
+}
+
+static int rtlsdr_init(rtlsdr_dev_t *dev) {
+ int r;
+ uint8_t reg;
+
if (libusb_kernel_driver_active(dev->devh, 0) == 1) {
dev->driver_active = 1;
@@ -1639,8 +1727,6 @@ found:
rtlsdr_set_i2c_repeater(dev, 0);
- *out_dev = dev;
-
return 0;
err:
if (dev) {
diff --git a/src/rtl_adsb.c b/src/rtl_adsb.c
index 8119ac8..ae5eccd 100644
--- a/src/rtl_adsb.c
+++ b/src/rtl_adsb.c
@@ -89,7 +89,8 @@ void usage(void)
fprintf(stderr,
"rtl_adsb, a simple ADS-B decoder\n\n"
"Use:\trtl_adsb [-R] [-g gain] [-p ppm] [output file]\n"
- "\t[-d device_index (default: 0)]\n"
+ "\t[-d device_index (default: 1)]\n"
+ "\t[-N file_desc use file descriptor instead of libusb index\n"
"\t[-V verbove output (default: off)]\n"
"\t[-S show short frames (default: off)]\n"
"\t[-Q quality (0: no sanity checks, 0.5: half bit, 1: one bit (default), 2: two
bits)]\n"
@@ -372,19 +373,24 @@ int main(int argc, char **argv)
int gain = AUTO_GAIN; /* tenths of a dB */
int dev_index = 0;
int dev_given = 0;
+ int fd_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:VST")) != -1)
+ while ((opt = getopt(argc, argv, "d:N:g:p:e:Q:VST")) != -1)
{
switch (opt) {
case 'd':
dev_index = verbose_device_search(optarg);
dev_given = 1;
break;
+ case 'N':
+ dev_index = atoi(optarg);
+ fd_given = 1;
+ break;
case 'g':
gain = (int)(atof(optarg) * 10);
break;
@@ -420,7 +426,7 @@ int main(int argc, char **argv)
buffer = malloc(DEFAULT_BUF_LENGTH * sizeof(uint8_t));
- if (!dev_given) {
+ if (!dev_given && !fd_given) {
dev_index = verbose_device_search("0");
}
@@ -428,7 +434,12 @@ int main(int argc, char **argv)
exit(1);
}
- r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ if (fd_given) {
+ r = rtlsdr_open_fd(&dev, dev_index);
+ } else {
+ r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ }
+
if (r < 0) {
fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index);
exit(1);
@@ -493,7 +504,7 @@ int main(int argc, char **argv)
else {
fprintf(stderr, "\nLibrary error %d, exiting...\n", r);}
rtlsdr_cancel_async(dev);
- pthread_cancel(demod_thread);
+ pthread_kill(demod_thread, 0);
pthread_join(demod_thread, NULL);
pthread_cond_destroy(&ready);
pthread_mutex_destroy(&ready_m);
diff --git a/src/rtl_biast.c b/src/rtl_biast.c
index 185e838..e9c914e 100644
--- a/src/rtl_biast.c
+++ b/src/rtl_biast.c
@@ -41,7 +41,8 @@ void usage(void)
"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[-d device_index (default: 1)]\n"
+ "\t[-N file_desc use file descriptor instead of libusb index\n"
"\t[-b bias_on (default: 0)]\n"
"\t[-g GPIO select (default: 0)]\n");
exit(1);
@@ -52,16 +53,21 @@ int main(int argc, char **argv)
int i, r, opt;
int dev_index = 0;
int dev_given = 0;
+ int fd_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) {
+ while ((opt = getopt(argc, argv, "d:N:b:g:h?")) != -1) {
switch (opt) {
case 'd':
dev_index = verbose_device_search(optarg);
dev_given = 1;
break;
+ case 'N':
+ dev_index = atoi(optarg);
+ fd_given = 1;
+ break;
case 'b':
bias_on = atoi(optarg);
break;
@@ -74,7 +80,7 @@ int main(int argc, char **argv)
}
}
- if (!dev_given) {
+ if (!dev_given && !fd_given) {
dev_index = verbose_device_search("0");
}
@@ -82,7 +88,12 @@ int main(int argc, char **argv)
exit(1);
}
- r = rtlsdr_open(&dev, dev_index);
+ if (fd_given) {
+ r = rtlsdr_open_fd(&dev, dev_index);
+ } else {
+ r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ }
+
rtlsdr_set_bias_tee_gpio(dev, gpio_pin, bias_on);
exit:
diff --git a/src/rtl_fm.c b/src/rtl_fm.c
index 037793c..c1b562c 100644
--- a/src/rtl_fm.c
+++ b/src/rtl_fm.c
@@ -192,7 +192,8 @@ void usage(void)
"\t wbfm == -M fm -s 170k -o 4 -A fast -r 32k -l 0 -E deemp\n"
"\t raw mode outputs 2x16 bit IQ pairs\n"
"\t[-s sample_rate (default: 24k)]\n"
- "\t[-d device_index (default: 0)]\n"
+ "\t[-d device_index (default: 1)]\n"
+ "\t[-N file_desc use file descriptor instead of libusb index\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"
@@ -1057,6 +1058,7 @@ int main(int argc, char **argv)
#endif
int r, opt;
int dev_given = 0;
+ int fd_given = 0;
int custom_ppm = 0;
int enable_biastee = 0;
dongle_init(&dongle);
@@ -1064,12 +1066,16 @@ int main(int argc, char **argv)
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:hT")) != -1) {
+ while ((opt = getopt(argc, argv, "d:N: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);
dev_given = 1;
break;
+ case 'N':
+ dongle.dev_index = atoi(optarg);
+ fd_given = 1;
+ break;
case 'f':
if (controller.freq_len >= FREQUENCIES_LIMIT) {
break;}
@@ -1190,7 +1196,7 @@ int main(int argc, char **argv)
ACTUAL_BUF_LENGTH = lcm_post[demod.post_downsample] * DEFAULT_BUF_LENGTH;
- if (!dev_given) {
+ if (!dev_given && !fd_given) {
dongle.dev_index = verbose_device_search("0");
}
@@ -1198,7 +1204,12 @@ int main(int argc, char **argv)
exit(1);
}
- r = rtlsdr_open(&dongle.dev, (uint32_t)dongle.dev_index);
+ if (fd_given) {
+ r = rtlsdr_open_fd(&dongle.dev, dongle.dev_index);
+ } else {
+ r = rtlsdr_open(&dongle.dev, (uint32_t)dongle.dev_index);
+ }
+
if (r < 0) {
fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dongle.dev_index);
exit(1);
diff --git a/src/rtl_power.c b/src/rtl_power.c
index df3ceb7..3c750ce 100644
--- a/src/rtl_power.c
+++ b/src/rtl_power.c
@@ -130,7 +130,8 @@ void usage(void)
"\t[-e exit_timer (default: off/0)]\n"
//"\t[-s avg/iir smoothing (default: avg)]\n"
//"\t[-t threads (default: 1)]\n"
- "\t[-d device_index (default: 0)]\n"
+ "\t[-d device_index (default: 1)]\n"
+ "\t[-N file_desc use file descriptor instead of libusb index\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"
@@ -774,6 +775,7 @@ int main(int argc, char **argv)
int gain = AUTO_GAIN; // tenths of a dB
int dev_index = 0;
int dev_given = 0;
+ int fd_given = 0;
int ppm_error = 0;
int interval = 10;
int fft_threads = 1;
@@ -792,7 +794,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:1PDOhT")) != -1) {
+ while ((opt = getopt(argc, argv, "f:i:s:t:d:N:g:p:e:w:c:F:1PDOhT")) != -1) {
switch (opt) {
case 'f': // lower:upper:bin_size
freq_optarg = strdup(optarg);
@@ -802,6 +804,10 @@ int main(int argc, char **argv)
dev_index = verbose_device_search(optarg);
dev_given = 1;
break;
+ case 'N':
+ dev_index = atoi(optarg);
+ fd_given = 1;
+ break;
case 'g':
gain = (int)(atof(optarg) * 10);
break;
@@ -896,7 +902,7 @@ int main(int argc, char **argv)
fprintf(stderr, "Reporting every %i seconds\n", interval);
- if (!dev_given) {
+ if (!dev_given && !fd_given) {
dev_index = verbose_device_search("0");
}
@@ -904,7 +910,12 @@ int main(int argc, char **argv)
exit(1);
}
- r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ if (fd_given) {
+ r = rtlsdr_open_fd(&dev, dev_index);
+ } else {
+ r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ }
+
if (r < 0) {
fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index);
exit(1);
diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c
index ccd6d76..60acd78 100644
--- a/src/rtl_sdr.c
+++ b/src/rtl_sdr.c
@@ -49,7 +49,8 @@ void usage(void)
"rtl_sdr, an I/Q recorder for RTL2832 based DVB-T receivers\n\n"
"Usage:\t -f frequency_to_tune_to [Hz]\n"
"\t[-s samplerate (default: 2048000 Hz)]\n"
- "\t[-d device_index (default: 0)]\n"
+ "\t[-d device_index (default: 1)]\n"
+ "\t[-N file_desc use file descriptor instead of libusb index\n"
"\t[-g gain (default: 0 for auto)]\n"
"\t[-p ppm_error (default: 0)]\n"
"\t[-b output_block_size (default: 16 * 16384)]\n"
@@ -120,6 +121,7 @@ int main(int argc, char **argv)
uint8_t *buffer;
int dev_index = 0;
int dev_given = 0;
+ int fd_given = 0;
uint32_t frequency = 100000000;
uint32_t samp_rate = DEFAULT_SAMPLE_RATE;
uint32_t out_block_size = DEFAULT_BUF_LENGTH;
@@ -130,6 +132,10 @@ int main(int argc, char **argv)
dev_index = verbose_device_search(optarg);
dev_given = 1;
break;
+ case 'N':
+ dev_index = atoi(optarg);
+ fd_given = 1;
+ break;
case 'f':
frequency = (uint32_t)atofs(optarg);
break;
@@ -179,7 +185,7 @@ int main(int argc, char **argv)
buffer = malloc(out_block_size * sizeof(uint8_t));
- if (!dev_given) {
+ if (!dev_given && !fd_given) {
dev_index = verbose_device_search("0");
}
@@ -187,7 +193,12 @@ int main(int argc, char **argv)
exit(1);
}
- r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ if (fd_given) {
+ r = rtlsdr_open_fd(&dev, dev_index);
+ } else {
+ r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ }
+
if (r < 0) {
fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index);
exit(1);
diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c
index 78d625a..c3d5e11 100644
--- a/src/rtl_tcp.c
+++ b/src/rtl_tcp.c
@@ -102,7 +102,8 @@ void usage(void)
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[-d device_index (default: 1)]\n");
+ printf("\t[-N file_desc use file descriptor instead of libusb index\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");
printf("\t[-D enable direct sampling (default: off)]\n");
@@ -395,6 +396,7 @@ int main(int argc, char **argv)
uint32_t buf_num = 0;
int dev_index = 0;
int dev_given = 0;
+ int fd_given = 0;
int gain = 0;
int ppm_error = 0;
int direct_sampling = 0;
@@ -415,12 +417,16 @@ 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:TD")) != -1) {
+ while ((opt = getopt(argc, argv, "a:p:f:g:s:b:n:d:N:P:TD")) != -1) {
switch (opt) {
case 'd':
dev_index = verbose_device_search(optarg);
dev_given = 1;
break;
+ case 'N':
+ dev_index = atoi(optarg);
+ fd_given = 1;
+ break;
case 'f':
frequency = (uint32_t)atofs(optarg);
break;
@@ -460,7 +466,7 @@ int main(int argc, char **argv)
if (argc < optind)
usage();
- if (!dev_given) {
+ if (!dev_given && !fd_given) {
dev_index = verbose_device_search("0");
}
@@ -468,7 +474,12 @@ int main(int argc, char **argv)
exit(1);
}
- rtlsdr_open(&dev, (uint32_t)dev_index);
+ if (fd_given) {
+ r = rtlsdr_open_fd(&dev, dev_index);
+ } else {
+ r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ }
+
if (NULL == dev) {
fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index);
exit(1);
diff --git a/src/rtl_test.c b/src/rtl_test.c
index b7f46ea..033aeb1 100644
--- a/src/rtl_test.c
+++ b/src/rtl_test.c
@@ -90,7 +90,8 @@ void usage(void)
"rtl_test, a benchmark tool for RTL2832 based DVB-T receivers\n\n"
"Usage:\n"
"\t[-s samplerate (default: 2048000 Hz)]\n"
- "\t[-d device_index (default: 0)]\n"
+ "\t[-d device_index (default: 1)]\n"
+ "\t[-N file_desc use file descriptor instead of libusb index\n"
"\t[-t enable Elonics E4000 tuner benchmark]\n"
#ifndef _WIN32
"\t[-p[seconds] enable PPM error measurement (default: 10 seconds)]\n"
@@ -312,16 +313,21 @@ int main(int argc, char **argv)
uint8_t *buffer;
int dev_index = 0;
int dev_given = 0;
+ int fd_given = 0;
uint32_t out_block_size = DEFAULT_BUF_LENGTH;
int count;
int gains[100];
- while ((opt = getopt(argc, argv, "d:s:b:tp::Sh")) != -1) {
+ while ((opt = getopt(argc, argv, "d:N:D:s:b:tp::Sh")) != -1) {
switch (opt) {
case 'd':
dev_index = verbose_device_search(optarg);
dev_given = 1;
break;
+ case 'N':
+ dev_index = atoi(optarg);
+ fd_given = 1;
+ break;
case 's':
samp_rate = (uint32_t)atof(optarg);
break;
@@ -359,7 +365,7 @@ int main(int argc, char **argv)
buffer = malloc(out_block_size * sizeof(uint8_t));
- if (!dev_given) {
+ if (!dev_given && !fd_given) {
dev_index = verbose_device_search("0");
}
@@ -367,7 +373,12 @@ int main(int argc, char **argv)
exit(1);
}
- r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ if (fd_given) {
+ r = rtlsdr_open_fd(&dev, dev_index);
+ } else {
+ r = rtlsdr_open(&dev, (uint32_t)dev_index);
+ }
+
if (r < 0) {
fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index);
exit(1);
--
2.44.0