aboutsummaryrefslogtreecommitdiffstats
path: root/utils/rtl_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rtl_tcp.c')
-rw-r--r--utils/rtl_tcp.c660
1 files changed, 0 insertions, 660 deletions
diff --git a/utils/rtl_tcp.c b/utils/rtl_tcp.c
deleted file mode 100644
index 84f5591..0000000
--- a/utils/rtl_tcp.c
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver
- * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de>
- * Copyright (C) 2012-2013 by Hoernchen <la@tfc-server.de>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef _WIN32
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include "getopt/getopt.h"
-#endif
-
-#include <pthread.h>
-
-#include "rtl-sdr.h"
-#include "convenience/convenience.h"
-
-#ifdef _WIN32
-#pragma comment(lib, "ws2_32.lib")
-
-typedef int socklen_t;
-
-#else
-#define closesocket close
-#define SOCKADDR struct sockaddr
-#define SOCKET int
-#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;
-static pthread_t command_thread;
-static pthread_cond_t exit_cond;
-static pthread_mutex_t exit_cond_lock;
-
-static pthread_mutex_t ll_mutex;
-static pthread_cond_t cond;
-
-struct llist {
- char *data;
- size_t len;
- struct llist *next;
-};
-
-typedef struct { /* structure size must be multiple of 2 bytes */
- char magic[4];
- uint32_t tuner_type;
- uint32_t tuner_gain_count;
-} dongle_info_t;
-
-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 = 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");
- 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);
-}
-
-#ifdef _WIN32
-int gettimeofday(struct timeval *tv, void* ignored)
-{
- FILETIME ft;
- unsigned __int64 tmp = 0;
- if (NULL != tv) {
- GetSystemTimeAsFileTime(&ft);
- tmp |= ft.dwHighDateTime;
- tmp <<= 32;
- tmp |= ft.dwLowDateTime;
- tmp /= 10;
-#ifdef _MSC_VER
- tmp -= 11644473600000000Ui64;
-#else
- tmp -= 11644473600000000ULL;
-#endif
- tv->tv_sec = (long)(tmp / 1000000UL);
- tv->tv_usec = (long)(tmp % 1000000UL);
- }
- return 0;
-}
-
-BOOL WINAPI
-sighandler(int signum)
-{
- if (CTRL_C_EVENT == signum) {
- fprintf(stderr, "Signal caught, exiting!\n");
- do_exit = 1;
- rtlsdr_cancel_async(dev);
- return TRUE;
- }
- return FALSE;
-}
-#else
-static void sighandler(int signum)
-{
- fprintf(stderr, "Signal caught, exiting!\n");
- rtlsdr_cancel_async(dev);
- do_exit = 1;
-}
-#endif
-
-void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
-{
- if(!do_exit) {
- struct llist *rpt = (struct llist*)malloc(sizeof(struct llist));
- rpt->data = (char*)malloc(len);
- memcpy(rpt->data, buf, len);
- rpt->len = len;
- rpt->next = NULL;
-
- pthread_mutex_lock(&ll_mutex);
-
- if (ll_buffers == NULL) {
- ll_buffers = rpt;
- } else {
- struct llist *cur = ll_buffers;
- int num_queued = 0;
-
- while (cur->next != NULL) {
- cur = cur->next;
- num_queued++;
- }
-
- if(llbuf_num && llbuf_num == num_queued-2){
- struct llist *curelem;
-
- free(ll_buffers->data);
- curelem = ll_buffers->next;
- free(ll_buffers);
- ll_buffers = curelem;
- }
-
- cur->next = rpt;
-
- if (num_queued > global_numq)
- printf("ll+, now %d\n", num_queued);
- else if (num_queued < global_numq)
- printf("ll-, now %d\n", num_queued);
-
- global_numq = num_queued;
- }
- pthread_cond_signal(&cond);
- pthread_mutex_unlock(&ll_mutex);
- }
-}
-
-static void *tcp_worker(void *arg)
-{
- struct llist *curelem,*prev;
- int bytesleft,bytessent, index;
- struct timeval tv= {1,0};
- struct timespec ts;
- struct timeval tp;
- fd_set writefds;
- int r = 0;
-
- while(1) {
- if(do_exit)
- pthread_exit(0);
-
- pthread_mutex_lock(&ll_mutex);
- gettimeofday(&tp, NULL);
- ts.tv_sec = tp.tv_sec+5;
- ts.tv_nsec = tp.tv_usec * 1000;
- r = pthread_cond_timedwait(&cond, &ll_mutex, &ts);
- if(r == ETIMEDOUT) {
- pthread_mutex_unlock(&ll_mutex);
- printf("worker cond timeout\n");
- sighandler(0);
- pthread_exit(NULL);
- }
-
- curelem = ll_buffers;
- ll_buffers = 0;
- pthread_mutex_unlock(&ll_mutex);
-
- while(curelem != 0) {
- bytesleft = curelem->len;
- index = 0;
- bytessent = 0;
- while(bytesleft > 0) {
- FD_ZERO(&writefds);
- FD_SET(s, &writefds);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- r = select(s+1, NULL, &writefds, NULL, &tv);
- if(r) {
- bytessent = send(s, &curelem->data[index], bytesleft, 0);
- bytesleft -= bytessent;
- index += bytessent;
- }
- if(bytessent == SOCKET_ERROR || do_exit) {
- printf("worker socket bye\n");
- sighandler(0);
- pthread_exit(NULL);
- }
- }
- prev = curelem;
- curelem = curelem->next;
- free(prev->data);
- free(prev);
- }
- }
-}
-
-static int set_gain_by_index(rtlsdr_dev_t *_dev, unsigned int index)
-{
- int res = 0;
- int* gains;
- int count = rtlsdr_get_tuner_gains(_dev, NULL);
-
- if (count > 0 && (unsigned int)count > index) {
- gains = malloc(sizeof(int) * count);
- count = rtlsdr_get_tuner_gains(_dev, gains);
-
- res = rtlsdr_set_tuner_gain(_dev, gains[index]);
-
- free(gains);
- }
-
- return res;
-}
-
-#ifdef _WIN32
-#define __attribute__(x)
-#pragma pack(push, 1)
-#endif
-struct command{
- unsigned char cmd;
- unsigned int param;
-}__attribute__((packed));
-#ifdef _WIN32
-#pragma pack(pop)
-#endif
-static void *command_worker(void *arg)
-{
- int left, received = 0;
- fd_set readfds;
- struct command cmd={0, 0};
- struct timeval tv= {1, 0};
- int r = 0;
- uint32_t tmp;
-
- while(1) {
- left=sizeof(cmd);
- while(left >0) {
- FD_ZERO(&readfds);
- FD_SET(s, &readfds);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- r = select(s+1, &readfds, NULL, NULL, &tv);
- if(r) {
- received = recv(s, (char*)&cmd+(sizeof(cmd)-left), left, 0);
- left -= received;
- }
- if(received == SOCKET_ERROR || do_exit) {
- printf("comm recv bye\n");
- sighandler(0);
- pthread_exit(NULL);
- }
- }
- switch(cmd.cmd) {
- case 0x01:
- printf("set freq %d\n", ntohl(cmd.param));
- rtlsdr_set_center_freq(dev,ntohl(cmd.param));
- break;
- case 0x02:
- printf("set sample rate %d\n", ntohl(cmd.param));
- rtlsdr_set_sample_rate(dev, ntohl(cmd.param));
- break;
- case 0x03:
- printf("set gain mode %d\n", ntohl(cmd.param));
- rtlsdr_set_tuner_gain_mode(dev, ntohl(cmd.param));
- break;
- case 0x04:
- printf("set gain %d\n", ntohl(cmd.param));
- rtlsdr_set_tuner_gain(dev, ntohl(cmd.param));
- break;
- case 0x05:
- printf("set freq correction %d\n", ntohl(cmd.param));
- rtlsdr_set_freq_correction(dev, ntohl(cmd.param));
- break;
- case 0x06:
- tmp = ntohl(cmd.param);
- printf("set if stage %d gain %d\n", tmp >> 16, (short)(tmp & 0xffff));
- rtlsdr_set_tuner_if_gain(dev, tmp >> 16, (short)(tmp & 0xffff));
- break;
- case 0x07:
- printf("set test mode %d\n", ntohl(cmd.param));
- rtlsdr_set_testmode(dev, ntohl(cmd.param));
- break;
- case 0x08:
- printf("set agc mode %d\n", ntohl(cmd.param));
- rtlsdr_set_agc_mode(dev, ntohl(cmd.param));
- break;
- case 0x09:
- printf("set direct sampling %d\n", ntohl(cmd.param));
- rtlsdr_set_direct_sampling(dev, ntohl(cmd.param));
- break;
- case 0x0a:
- printf("set offset tuning %d\n", ntohl(cmd.param));
- rtlsdr_set_offset_tuning(dev, ntohl(cmd.param));
- break;
- case 0x0b:
- printf("set rtl xtal %d\n", ntohl(cmd.param));
- rtlsdr_set_xtal_freq(dev, ntohl(cmd.param), 0);
- break;
- case 0x0c:
- printf("set tuner xtal %d\n", ntohl(cmd.param));
- rtlsdr_set_xtal_freq(dev, 0, ntohl(cmd.param));
- break;
- case 0x0d:
- 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;
- }
- cmd.cmd = 0xff;
- }
-}
-
-int main(int argc, char **argv)
-{
- int r, opt, i;
- 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;
- int gain = 0;
- int ppm_error = 0;
- struct llist *curelem,*prev;
- pthread_attr_t attr;
- void *status;
- struct timeval tv = {1,0};
- struct linger ling = {1,0};
- SOCKET listensocket = 0;
- socklen_t rlen;
- fd_set readfds;
- u_long blockmode = 1;
- dongle_info_t dongle_info;
-#ifdef _WIN32
- WSADATA wsd;
- i = WSAStartup(MAKEWORD(2,2), &wsd);
-#else
- struct sigaction sigact, sigign;
-#endif
-
- 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);
- dev_given = 1;
- break;
- case 'f':
- frequency = (uint32_t)atofs(optarg);
- break;
- case 'g':
- gain = (int)(atof(optarg) * 10); /* tenths of a dB */
- break;
- case 's':
- samp_rate = (uint32_t)atofs(optarg);
- break;
- case 'a':
- addr = strdup(optarg);
- break;
- case 'p':
- port = strdup(optarg);
- break;
- case 'b':
- buf_num = atoi(optarg);
- break;
- case 'n':
- llbuf_num = atoi(optarg);
- break;
- case 'P':
- ppm_error = atoi(optarg);
- break;
- case 'T':
- enable_biastee = 1;
- break;
- default:
- usage();
- break;
- }
- }
-
- if (argc < optind)
- usage();
-
- if (!dev_given) {
- dev_index = verbose_device_search("0");
- }
-
- if (dev_index < 0) {
- exit(1);
- }
-
- rtlsdr_open(&dev, (uint32_t)dev_index);
- if (NULL == dev) {
- fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index);
- exit(1);
- }
-
-#ifndef _WIN32
- sigact.sa_handler = sighandler;
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigign.sa_handler = SIG_IGN;
- sigaction(SIGINT, &sigact, NULL);
- sigaction(SIGTERM, &sigact, NULL);
- sigaction(SIGQUIT, &sigact, NULL);
- sigaction(SIGPIPE, &sigign, NULL);
-#else
- SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
-#endif
-
- /* Set the tuner error */
- verbose_ppm_set(dev, ppm_error);
-
- /* 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 %i Hz.\n", frequency);
-
- if (0 == gain) {
- /* Enable automatic gain */
- r = rtlsdr_set_tuner_gain_mode(dev, 0);
- if (r < 0)
- fprintf(stderr, "WARNING: Failed to enable automatic gain.\n");
- } else {
- /* Enable manual gain */
- r = rtlsdr_set_tuner_gain_mode(dev, 1);
- if (r < 0)
- fprintf(stderr, "WARNING: Failed to enable manual gain.\n");
-
- /* 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 %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)
- fprintf(stderr, "WARNING: Failed to reset buffers.\n");
-
- pthread_mutex_init(&exit_cond_lock, NULL);
- pthread_mutex_init(&ll_mutex, NULL);
- pthread_mutex_init(&exit_cond_lock, NULL);
- pthread_cond_init(&cond, NULL);
- pthread_cond_init(&exit_cond, NULL);
-
- 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));
-
- 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);
-#else
- r = fcntl(listensocket, F_GETFL, 0);
- r = fcntl(listensocket, F_SETFL, r | O_NONBLOCK);
-#endif
-
- while(1) {
- printf("listening...\n");
- 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",
- hostinfo, portinfo);
- listen(listensocket,1);
-
- while(1) {
- FD_ZERO(&readfds);
- FD_SET(listensocket, &readfds);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- r = select(listensocket+1, &readfds, NULL, NULL, &tv);
- if(do_exit) {
- goto out;
- } else if(r) {
- rlen = sizeof(remote);
- s = accept(listensocket,(struct sockaddr *)&remote, &rlen);
- break;
- }
- }
-
- setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling));
-
- 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);
-
- r = rtlsdr_get_tuner_type(dev);
- if (r >= 0)
- dongle_info.tuner_type = htonl(r);
-
- r = rtlsdr_get_tuner_gains(dev, NULL);
- if (r >= 0)
- dongle_info.tuner_gain_count = htonl(r);
-
- r = send(s, (const char *)&dongle_info, sizeof(dongle_info), 0);
- if (sizeof(dongle_info) != r)
- printf("failed to send dongle information\n");
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- r = pthread_create(&tcp_worker_thread, &attr, tcp_worker, NULL);
- r = pthread_create(&command_thread, &attr, command_worker, NULL);
- pthread_attr_destroy(&attr);
-
- r = rtlsdr_read_async(dev, rtlsdr_callback, NULL, buf_num, 0);
-
- pthread_join(tcp_worker_thread, &status);
- pthread_join(command_thread, &status);
-
- closesocket(s);
-
- printf("all threads dead..\n");
- curelem = ll_buffers;
- ll_buffers = 0;
-
- while(curelem != 0) {
- prev = curelem;
- curelem = curelem->next;
- free(prev->data);
- free(prev);
- }
-
- do_exit = 0;
- global_numq = 0;
- }
-
-out:
- rtlsdr_close(dev);
- closesocket(listensocket);
- closesocket(s);
-#ifdef _WIN32
- WSACleanup();
-#endif
- printf("bye!\n");
- return r >= 0 ? r : -r;
-}