/* * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver * 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 #include #include #include #include #include "rtl-sdr.h" #define DEFAULT_SAMPLE_RATE 2048000 #define DEFAULT_ASYNC_BUF_NUMBER 32 #define DEFAULT_BUF_LENGTH (16 * 16384) #define MINIMAL_BUF_LENGTH 512 #define MAXIMAL_BUF_LENGTH (256 * 16384) static int do_exit = 0; static rtlsdr_dev_t *dev = NULL; void usage(void) { fprintf(stderr, "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[-g tuner_gain (default: 0 dB)]\n" "\t[-b output_block_size (default: 16 * 16384)]\n" "\t[-S force sync output (default: async)]\n" "\toutput_filename (a '-' dumps samples to stdout)\n\n"); exit(1); } static void sighandler(int signum) { do_exit = 1; rtlsdr_cancel_async(dev); } static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) { if (ctx) fwrite(buf, len, 1, (FILE*)ctx); } int main(int argc, char **argv) { struct sigaction sigact; char *filename = NULL; int n_read; int r, opt; int i, gain = 0; int sync_mode = 0; FILE *file; uint8_t *buffer; uint32_t dev_index = 0; uint32_t frequency = 0; uint32_t samp_rate = DEFAULT_SAMPLE_RATE; uint32_t out_block_size = DEFAULT_BUF_LENGTH; while ((opt = getopt(argc, argv, "d:f:g:s:b:S::")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); break; case 'f': frequency = (uint32_t)atof(optarg); break; case 'g': gain = atoi(optarg); break; case 's': samp_rate = (int)atof(optarg); break; case 'b': out_block_size = (uint32_t)atof(optarg); break; case 'S': sync_mode = 1; break; default: usage(); break; } } if (argc <= optind) { usage(); } else { filename = argv[optind]; } if(out_block_size < MINIMAL_BUF_LENGTH || out_block_size > MAXIMAL_BUF_LENGTH ){ fprintf(stderr, "Output block size wrong value, falling back to default\n"); fprintf(stderr, "Minimal length: %u\n", MINIMAL_BUF_LENGTH); fprintf(stderr, "Maximal length: %u\n", MAXIMAL_BUF_LENGTH); out_block_size = DEFAULT_BUF_LENGTH; } buffer = malloc(out_block_size * sizeof(uint8_t)); int device_count = rtlsdr_get_device_count(); if (!device_count) { fprintf(stderr, "No supported devices found.\n"); exit(1); } fprintf(stderr, "Found %d device(s):\n", device_count); for (i = 0; i < device_count; i++) fprintf(stderr, " %d: %s\n", i, rtlsdr_get_device_name(i)); fprintf(stderr, "\n"); fprintf(stderr, "Using device %d: %s\n", dev_index, rtlsdr_get_device_name(dev_index)); r = rtlsdr_open(&dev, dev_index); if (r < 0) { fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index); exit(1); } sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); /* Set the sample rate */ r = rtlsdr_set_sample_rate(dev, samp_rate); if (r < 0) fprintf(stderr, "WARNING: Failed to set sample rate.\n"); /* Set the frequency */ r = rtlsdr_set_center_freq(dev, frequency); if (r < 0) fprintf(stderr, "WARNING: Failed to set center freq.\n"); else fprintf(stderr, "Tuned to %u Hz.\n", frequency); /* Set the tuner gain */ r = rtlsdr_set_tuner_gain(dev, gain); if (r < 0) fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); else fprintf(stderr, "Tuner gain set to %i dB.\n", gain); if(strcmp(filename, "-") != 0) { file = fopen(filename, "wb"); if (!file) { fprintf(stderr, "Failed to open %s\n", filename); goto out; } } else { file = stdout; } /* Reset endpoint before we start reading from it (mandatory) */ r = rtlsdr_reset_buffer(dev); if (r < 0) fprintf(stderr, "WARNING: Failed to reset buffers.\n"); if (sync_mode) { fprintf(stderr, "Reading samples in sync mode...\n"); while (!do_exit) { r = rtlsdr_read_sync(dev, buffer, out_block_size, &n_read); if (r < 0) fprintf(stderr, "WARNING: sync read failed.\n"); fwrite(buffer, n_read, 1, file); if (n_read < out_block_size) { fprintf(stderr, "Short read, samples lost, exiting!\n"); break; } } } else { fprintf(stderr, "Reading samples...\n"); rtlsdr_read_async(dev, rtlsdr_callback, (void *)file, DEFAULT_ASYNC_BUF_NUMBER, out_block_size); } if (do_exit) fprintf(stderr, "\nUser cancel, exiting...\n"); else fprintf(stderr, "\nSystem cancel, exiting...\n"); if (file != stdout) fclose(file); rtlsdr_close(dev); free (buffer); out: return r >= 0 ? r : -r; }