struct _DISCOVERED {
int protocol;
int device;
- int can_tcp; // Radio can do UDP but is able to switch to TCP
- int only_tcp; // Radio can only be reached via TCP, UDP does not work
+ int use_tcp; // use TCP rather than UDP to connect to radio
char name[64];
int software_version;
int status;
*/
extern void discovery();
+extern char *ipaddr_tcp;
#include <errno.h>
#include "discovered.h"
+#include "discovery.h"
#include "old_discovery.h"
static char interface_name[64];
int rc;
struct sockaddr_in *sa;
struct sockaddr_in *mask;
+ struct sockaddr_in to_addr={0};
+ int flags;
+ struct timeval tv;
- strcpy(interface_name,iface->ifa_name);
- fprintf(stderr,"discover: looking for HPSDR devices on %s\n", interface_name);
-
- // send a broadcast to locate hpsdr boards on the network
- discovery_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
- if(discovery_socket<0) {
- perror("discover: create socket failed for discovery_socket\n");
- exit(-1);
- }
+ if (iface == NULL) {
+ //
+ // This indicates that we want to connect to an SDR which
+ // cannot be reached by (UDP) broadcast packets, but that
+ // we know its fixed IP address
+ // Therefore we try to send a METIS detection packet via TCP
+ // to a "fixed" ip address.
+ //
+ fprintf(stderr,"Trying to detect at TCP addr %s\n", ipaddr_tcp);
+ memset(&to_addr, 0, sizeof(to_addr));
+ to_addr.sin_family = AF_INET;
+ if (inet_aton(ipaddr_tcp, &to_addr.sin_addr) == 0) {
+ fprintf(stderr,"discover: TCP addr %s is invalid!\n",ipaddr_tcp);
+ return;
+ }
+ to_addr.sin_port=htons(DISCOVERY_PORT);
+
+ discovery_socket=socket(AF_INET, SOCK_STREAM, 0);
+ if(discovery_socket<0) {
+ perror("discover: create socket failed for TCP discovery_socket\n");
+ return;
+ }
+ //
+ // We make a time-out of 3 secs, otherwise we might "hang" in connect()
+ //
+ tv.tv_sec=3;
+ tv.tv_usec=0;
+ setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv));
+
+ if (connect(discovery_socket, (const struct sockaddr *)&to_addr, sizeof(to_addr)) < 0) {
+ perror("discover: connect() failed for TCP discovery_socket:");
+ close(discovery_socket);
+ return;
+ }
+ } else {
+
+ strcpy(interface_name,iface->ifa_name);
+ fprintf(stderr,"discover: looking for HPSDR devices on %s\n", interface_name);
+
+ // send a broadcast to locate hpsdr boards on the network
+ discovery_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+ if(discovery_socket<0) {
+ perror("discover: create socket failed for discovery_socket:");
+ exit(-1);
+ }
- int optval = 1;
- setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
- setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
+ sa = (struct sockaddr_in *) iface->ifa_addr;
+ mask = (struct sockaddr_in *) iface->ifa_netmask;
+ interface_netmask.sin_addr.s_addr = mask->sin_addr.s_addr;
+
+ // bind to this interface and the discovery port
+ interface_addr.sin_family = AF_INET;
+ interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr;
+ //interface_addr.sin_port = htons(DISCOVERY_PORT*2);
+ interface_addr.sin_port = htons(0); // system assigned port
+ if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) {
+ perror("discover: bind socket failed for discovery_socket:");
+ exit(-1);
+ }
- sa = (struct sockaddr_in *) iface->ifa_addr;
- mask = (struct sockaddr_in *) iface->ifa_netmask;
- interface_netmask.sin_addr.s_addr = mask->sin_addr.s_addr;
-
- // bind to this interface and the discovery port
- interface_addr.sin_family = AF_INET;
- interface_addr.sin_addr.s_addr = sa->sin_addr.s_addr;
- //interface_addr.sin_port = htons(DISCOVERY_PORT*2);
- interface_addr.sin_port = htons(0); // system assigned port
- if(bind(discovery_socket,(struct sockaddr*)&interface_addr,sizeof(interface_addr))<0) {
- perror("discover: bind socket failed for discovery_socket\n");
- exit(-1);
- }
+ fprintf(stderr,"discover: bound to %s\n",interface_name);
- fprintf(stderr,"discover: bound to %s\n",interface_name);
+ // allow broadcast on the socket
+ int on=1;
+ rc=setsockopt(discovery_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+ if(rc != 0) {
+ fprintf(stderr,"discover: cannot set SO_BROADCAST: rc=%d\n", rc);
+ exit(-1);
+ }
- // allow broadcast on the socket
- int on=1;
- rc=setsockopt(discovery_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
- if(rc != 0) {
- fprintf(stderr,"discover: cannot set SO_BROADCAST: rc=%d\n", rc);
- exit(-1);
+ // setup to address
+ to_addr.sin_family=AF_INET;
+ to_addr.sin_port=htons(DISCOVERY_PORT);
+ to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST);
}
+ int optval = 1;
+ setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+ setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
- // setup to address
- struct sockaddr_in to_addr={0};
- to_addr.sin_family=AF_INET;
- to_addr.sin_port=htons(DISCOVERY_PORT);
- to_addr.sin_addr.s_addr=htonl(INADDR_BROADCAST);
-
+ rc=devices;
// start a receive thread to collect discovery response packets
discover_thread_id = g_thread_new( "old discover receive", discover_receive_thread, NULL);
if( ! discover_thread_id )
// send discovery packet
- unsigned char buffer[63];
+ // If this is a TCP connection, send a "long" packet
+ unsigned char buffer[1032];
+ int len=63;
+ if (iface == NULL) len=1032;
buffer[0]=0xEF;
buffer[1]=0xFE;
buffer[2]=0x02;
int i;
- for(i=3;i<63;i++) {
+ for(i=3;i<len;i++) {
buffer[i]=0x00;
}
- if(sendto(discovery_socket,buffer,63,0,(struct sockaddr*)&to_addr,sizeof(to_addr))<0) {
- perror("discover: sendto socket failed for discovery_socket\n");
+ if(sendto(discovery_socket,buffer,len,0,(struct sockaddr*)&to_addr,sizeof(to_addr))<0) {
+ perror("discover: sendto socket failed for discovery_socket:");
exit(-1);
}
close(discovery_socket);
- fprintf(stderr,"discover: exiting discover for %s\n",iface->ifa_name);
+ if (iface == NULL) {
+ fprintf(stderr,"discover: exiting TCP discover for %s\n",ipaddr_tcp);
+ if (devices == rc+1) {
+ //
+ // We have exactly found one TCP device
+ // and have to patch the TCP addr into the device field
+ // and set the "use TCP" flag.
+ //
+ memcpy((void*)&discovered[rc].info.network.address,(void*)&to_addr,sizeof(to_addr));
+ discovered[rc].info.network.address_length=sizeof(to_addr);
+ memcpy((void*)&discovered[rc].info.network.interface_address,(void*)&to_addr,sizeof(to_addr));
+ memcpy((void*)&discovered[rc].info.network.interface_netmask,(void*)&to_addr,sizeof(to_addr));
+ discovered[rc].info.network.interface_length=sizeof(to_addr);
+ strcpy(discovered[rc].info.network.interface_name,"TCP");
+ discovered[rc].use_tcp=1;
+ }
+ } else {
+ fprintf(stderr,"discover: exiting discover for %s\n",iface->ifa_name);
+ }
}
discovery_addr.sin_port=htons(DISCOVERY_PORT);
ret=bind(discovery_socket, (struct sockaddr *)&discovery_addr, sizeof(discovery_addr));
if (ret < 0) {
- perror("BIND FAILED:");
+ perror("stemlab_get_info bind():");
return 1;
}
(struct sockaddr*)&(discovered[id].info.network.address),
sizeof(discovered[id].info.network.address));
if (ret < 63) {
- perror("SEND DISCOVERY PACKET:");
+ perror("stemlab_get_info UDP sendto():");
return -1;
}
discovery_socket = socket(AF_INET, SOCK_STREAM, 0);
if (discovery_socket < 0) {
- perror("TCP socket:");
+ perror("stemlab_get_info socket():");
return 1;
}
ret=connect(discovery_socket, (struct sockaddr*)&(discovered[id].info.network.address),
sizeof(discovered[id].info.network.address));
if (ret < 0) {
- perror("TCP connect:");
+ perror("stemlab_get_info connect():");
return 1;
}
(struct sockaddr*)&(discovered[id].info.network.address),
sizeof(discovered[id].info.network.address));
if (ret < 1032) {
- perror("SEND DISCOVERY PACKET:");
+ perror("stemlab_get_info TCP sendto():");
return -1;
}
// TCP
if (devices == id+1) {
fprintf(stderr,"UDP did not work, but TCP does!\n");
- discovered[id].only_tcp=1;
- discovered[id].can_tcp=0;
+ discovered[id].use_tcp=1;
return 0;
}
return 1;
//static void *discover_receive_thread(void* arg) {
static gpointer discover_receive_thread(gpointer data) {
struct sockaddr_in addr;
- // DL1YCF changed int to socklen_t
socklen_t len;
unsigned char buffer[2048];
int bytes_read;
tv.tv_sec = 2;
tv.tv_usec = 0;
-
setsockopt(discovery_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
len=sizeof(addr);
//
// some devices report TCP capability here
//
- discovered[devices].only_tcp=0;
- discovered[devices].can_tcp=0;
- if (buffer[11] == 'T' && buffer[12] == 'C' && buffer[13]=='P') {
- discovered[devices].can_tcp=1;
- }
- fprintf(stderr,"discovery: found device=%d CanTCP=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+ discovered[devices].use_tcp=0;
+ fprintf(stderr,"discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
discovered[devices].device,
- discovered[devices].can_tcp,
discovered[devices].software_version,
discovered[devices].status,
inet_ntoa(discovered[devices].info.network.address.sin_addr),
void old_discovery() {
struct ifaddrs *addrs,*ifa;
-fprintf(stderr,"old_discovery\n");
+ fprintf(stderr,"old_discovery\n");
getifaddrs(&addrs);
ifa = addrs;
while (ifa) {
ifa = ifa->ifa_next;
}
freeifaddrs(addrs);
-
- fprintf(stderr, "discovery found %d devices\n",devices);
+ // To one additional "discover" for a fixed TCP address
+ discover(NULL);
int i;
for(i=0;i<devices;i++) {
#endif
{
fprintf(stderr,"old_protocol starting receive thread: buffer_size=%d output_buffer_size=%d\n",buffer_size,output_buffer_size);
- if (radio->only_tcp) {
+ if (radio->use_tcp) {
open_tcp_socket();
} else {
open_udp_socket();
usleep(100000);
close(tmp);
}
- //memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length);
- //data_addr.sin_port=htons(DATA_PORT);
- memset(&data_addr, 0, sizeof(data_addr));
+ memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length);
+ data_addr.sin_port=htons(DATA_PORT);
data_addr.sin_family = AF_INET;
- inet_aton("192.168.1.100", &data_addr.sin_addr);
- data_addr.sin_port=htons(1024);
+ fprintf(stderr,"Trying to open TCP connection to %s\n", inet_ntoa(radio->info.network.address.sin_addr));
tmp=socket(AF_INET, SOCK_STREAM, 0);
if (tmp < 0) {
}
*/
-#ifdef PROTOCOL_DEBUG
-// DL1YCF Debug: save last values and print any changes to stderr
-static unsigned char last_c1[20], last_c2[20], last_c3[20], last_c4[20], last_mox;
-static long long last_tx, last_rx[8];
-#endif
-
void ozy_send_buffer() {
int mode;
output_buffer[C2]=txFrequency>>16;
output_buffer[C3]=txFrequency>>8;
output_buffer[C4]=txFrequency;
-#ifdef PROTOCOL_DEBUG
- if (last_tx != txFrequency) {
- fprintf(stderr,"TX1 FREQ CHANGE from %lld to %lld\n", last_tx, txFrequency);
- last_tx=txFrequency;
- }
-#endif
break;
case 2: // rx frequency
#ifdef PURESIGNAL
output_buffer[C0]=0x04+(current_rx*2);
#ifdef PURESIGNAL
int v=receiver[current_rx/2]->id;
- if(isTransmitting() && transmitter->puresignal) {
+ // DL1YCF: for the "last" receiver, v is out of range. In this case,
+ // use TX frequency also while receiving
+ if((isTransmitting() && transmitter->puresignal) || (v >= MAX_VFOS)) {
long long txFrequency;
if(active_receiver->id==VFO_A) {
if(split) {
output_buffer[C2]=rxFrequency>>16;
output_buffer[C3]=rxFrequency>>8;
output_buffer[C4]=rxFrequency;
-#ifdef PROTOCOL_DEBUG
- if (rxFrequency != last_rx[current_rx]) {
- fprintf(stderr,"RX%d FREQ CHANGE from %lld to %lld\n", current_rx+1, last_rx[current_rx], rxFrequency);
- last_rx[current_rx] = rxFrequency;
- }
-#endif
#ifdef PURESIGNAL
}
#endif
}
}
-#ifdef PROTOCOL_DEBUG
-//
-// DL1YCF debug:
-// look for changed parameters and log them
-// This is great for debugging protocol problems,
-// such as the HAMlab CW error fixed above, so I
-// leave it here deactivated
-//
- int ind = output_buffer[C0] >> 1;
- if (ind == 0 || ind > 8) {
- // Frequency changes are reported above.
- if (last_c1[ind] != output_buffer[C1]) {
- fprintf(stderr, "C0=%x Old C1=%x New C1=%x\n", 2*ind,last_c1[ind], output_buffer[C1]);
- last_c1[ind]=output_buffer[C1];
- }
- if (last_c2[ind] != output_buffer[C2]) {
- fprintf(stderr, "C0=%x Old C2=%x New C2=%x\n", 2*ind,last_c2[ind], output_buffer[C2]);
- last_c2[ind]=output_buffer[C2];
- }
- if (last_c3[ind] != output_buffer[C3]) {
- fprintf(stderr, "C0=%x Old C3=%x New C3=%x\n", 2*ind,last_c3[ind], output_buffer[C3]);
- last_c3[ind]=output_buffer[C3];
- }
- if (last_c4[ind] != output_buffer[C4]) {
- fprintf(stderr, "C0=%x Old C4=%x New C4=%x\n", 2*ind,last_c4[ind], output_buffer[C4]);
- last_c4[ind]=output_buffer[C4];
- }
- }
- if ((output_buffer[C0] & 1) != last_mox) {
- fprintf(stderr, "Last Mox=%d New Mox=%d\n", last_mox, output_buffer[C0] & 1);
- last_mox=output_buffer[C0] & 1;
- }
-#endif
-
#ifdef USBOZY
//
// if we have a USB interfaced Ozy device:
// has closed the socket. Note that the UDP socket, once
// opened is never closed.
//
- if (radio->only_tcp && tcp_socket < 1) open_tcp_socket();
+ if (radio->use_tcp && tcp_socket < 1) open_tcp_socket();
// reset metis frame
metis_offset=8;
buffer[2]=0x04; // start/stop command
buffer[3]=command; // send EP6 and EP4 data (0x00=stop)
- // switch to TCP if requested, but do this ONLY with a start command
- if (command == 1 && tcp_socket < 0 && use_tcp) {
- open_tcp_socket();
- }
-
if (tcp_socket < 0) {
// use UDP -- send a short packet
for(i=4;i<64;i++) {
double tone_level=0.2;
int filter_board=ALEX;
-int use_tcp=0;
//int pa=PA_ENABLED;
//int apollo_tuner=0;
if(value) tx_out_of_band=atoi(value);
value=getProperty("filter_board");
if(value) filter_board=atoi(value);
- value=getProperty("use_tcp");
- // use_tcp must remain zero if the device cannot or can-only use TCP
- if(value && radio->can_tcp && ! radio->only_tcp) use_tcp=atoi(value);
/*
value=getProperty("apollo_tuner");
if(value) apollo_tuner=atoi(value);
setProperty("atlas_penelope",value);
sprintf(value,"%d",filter_board);
setProperty("filter_board",value);
- sprintf(value,"%d",use_tcp);
- setProperty("use_tcp",value);
sprintf(value,"%d",tx_out_of_band);
setProperty("tx_out_of_band",value);
sprintf(value,"%d",updates_per_second);
extern double tone_level;
extern int filter_board;
-extern int use_tcp;
extern int pa;
extern int apollo_tuner;
}
}
-static void protocol_cb(GtkWidget *widget, gpointer data) {
- if (protocol == ORIGINAL_PROTOCOL) {
- use_tcp=gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
- old_protocol_stop();
- old_protocol_run();
- }
-}
-
static void charly25_cb(GtkWidget *widget, gpointer data) {
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
filter_board = CHARLY25;
gtk_grid_attach(GTK_GRID(grid),region_combo,2,0,1,1);
g_signal_connect(region_combo,"changed",G_CALLBACK(region_cb),NULL);
- if (protocol == ORIGINAL_PROTOCOL && radio->can_tcp && !radio->only_tcp) {
- GtkWidget *protocol_label=gtk_label_new("Protocol: ");
- gtk_grid_attach(GTK_GRID(grid),protocol_label,3,0,1,1);
- GtkWidget *protocol_combo=gtk_combo_box_text_new();
- gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(protocol_combo),NULL,"UDP");
- gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(protocol_combo),NULL,"TCP");
- gtk_combo_box_set_active(GTK_COMBO_BOX(protocol_combo),use_tcp);
- gtk_grid_attach(GTK_GRID(grid),protocol_combo,4,0,1,1);
- g_signal_connect(protocol_combo,"changed",G_CALLBACK(protocol_cb),NULL);
- }
-
int x=0;
GtkWidget *receivers_label=gtk_label_new("Receivers: ");
#include <string.h>
#include "discovered.h"
+#include "discovery.h"
#include "radio.h"
#ifndef NO_AVAHI
// but does not need avahi.
//
// Therefore we try to find the SDR apps on the RedPitaya
-// assuming is has the (fixed) ip address which can be
-// read from $HOME/.rp.inet, if this does not succeed it
-// defaults to 192.168.1.3.
+// assuming is has the (fixed) ip address which we can now set
+// in the discovery menu and which is saved to a local file.
//
// So, on MacOS, just configure your STEMLAB/HAMLAB to this
// fixed IP address and you need not open a browser to start
void stemlab_discovery() {
size_t len;
- char inet[20];
char txt[150];
CURL *curl_handle;
CURLcode curl_error;
struct sockaddr_in ip_address;
struct sockaddr_in netmask;
- fprintf(stderr,"Stripped-down STEMLAB/HAMLAB discovery...\n");
-//
-// Try to read inet addr from $HOME/.rp.inet, otherwise take 192.168.1.3
-//
- strcpy(inet,"192.168.1.3");
- p=getenv("HOME");
- if (p) {
- strncpy(txt,p, (size_t) 100); // way less than size of txt
- } else {
- strcpy(txt,".");
- }
- strcat(txt,"/.rp.inet");
- fprintf(stderr,"Trying to read inet addr from file=%s\n", txt);
- fpin=fopen(txt, "r");
- if (fpin) {
- len=100;
- p=txt;
- len=getline(&p, &len, fpin);
- // not txt now contains the trailing newline character
- while (*p != 0) {
- if (*p == '\n') *p = 0;
- p++;
- }
- if (len < 20) strcpy(inet,txt);
- fclose(fpin);
- }
- fprintf(stderr,"STEMLAB: using inet addr %s\n", inet);
+ fprintf(stderr,"Stripped-down STEMLAB/HAMLAB discovery...\n");
+ fprintf(stderr,"STEMLAB: using inet addr %s\n", ipaddr_tcp);
ip_address.sin_family = AF_INET;
- inet_aton(inet, &ip_address.sin_addr);
+ if (inet_aton(ipaddr_tcp, &ip_address.sin_addr) == 0) {
+ fprintf(stderr,"StemlabDiscovery: TCP %s is invalid!\n", ipaddr_tcp);
+ return;
+ }
netmask.sin_family = AF_INET;
inet_aton("0.0.0.0", &netmask.sin_addr);
//
// Do a HEAD request (poor curl's ping) to see whether the device is on-line
-// allow a 15 sec time-out
+// allow a 5 sec time-out
//
curl_handle = curl_easy_init();
if (curl_handle == NULL) {
fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
return;
}
- sprintf(txt,"http://%s",inet);
+ sprintf(txt,"http://%s",ipaddr_tcp);
curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
curl_error = curl_easy_setopt(curl_handle, CURLOPT_NOBODY, (long) 1);
- curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 15);
+ curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 5);
curl_error = curl_easy_perform(curl_handle);
curl_easy_cleanup(curl_handle);
if (curl_error == CURLE_OPERATION_TIMEDOUT) {
- sprintf(txt,"No response from web server at %s", inet);
+ sprintf(txt,"No response from web server at %s", ipaddr_tcp);
status_text(txt);
fprintf(stderr,"%s\n",txt);
}
return;
}
app_list=0;
- sprintf(txt,"http://%s/bazaar?apps=", inet);
+ sprintf(txt,"http://%s/bazaar?apps=", ipaddr_tcp);
curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 60);
curl_error = curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, app_list_cb);
sprintf(name,"transmitter.%d.single_on",tx->id);
sprintf(value,"%d",tx->single_on);
setProperty(name,value);
+ sprintf(name,"transmitter.%d.feedback",tx->id);
+ sprintf(value,"%d",tx->feedback);
+ setProperty(name,value);
#endif
sprintf(name,"transmitter.%d.ctcss",tx->id);
sprintf(value,"%d",tx->ctcss);
sprintf(name,"transmitter.%d.single_on",tx->id);
value=getProperty(name);
if(value) tx->single_on=atoi(value);
+ sprintf(name,"transmitter.%d.feedback",tx->id);
+ value=getProperty(name);
+ if(value) tx->feedback=atoi(value);
#endif
sprintf(name,"transmitter.%d.ctcss",tx->id);
value=getProperty(name);