diff options
Diffstat (limited to 'utils/rtl_tcp.c')
-rw-r--r-- | utils/rtl_tcp.c | 660 |
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; -} |