]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Re-worked TCP support.
authorc vw <chwu@macintosh.speedport.ip>
Sat, 9 Feb 2019 20:25:42 +0000 (21:25 +0100)
committerc vw <chwu@macintosh.speedport.ip>
Sat, 9 Feb 2019 20:25:42 +0000 (21:25 +0100)
discovered.h
discovery.c
old_discovery.c
old_discovery.h
old_protocol.c
radio.c
radio_menu.c
receiver.c
rx_menu.c

index e7d18fc281fd1b88595712e80248568a4be41623..88ea3c572027db69ff38d4507c2fe9718b07e06c 100644 (file)
@@ -86,6 +86,8 @@
 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
     char name[64];
     int software_version;
     int status;
index 876a119139a5b67cbb6e3246d3309da09232c533..b6355fdeeef7dbbadcecc4c15c13cdf1b8ac6c9c 100644 (file)
@@ -63,14 +63,18 @@ fprintf(stderr,"start_cb: %p\n",data);
     const int device_id = radio - discovered;
     int ret;
     ret=stemlab_start_app(gtk_combo_box_get_active_id(GTK_COMBO_BOX(apps_combobox[device_id])));
-#ifdef NO_AVAHI
-    // We only have started the app, but not queried e.g. the MAC address.
-    // Therefore, we have to clean up and re-start the discovery process.
-    stemlab_cleanup();
-    gtk_widget_destroy(discovery_dialog);
-    g_idle_add(ext_discovery,NULL);
-    return TRUE;
-#endif
+    //
+    // We have started the SDR app on the RedPitaya, but may need to fill
+    // in information necessary for starting the radio, including the
+    // MAC address and the interface listening to. Even when using AVAHI,
+    // we miss some information (can_tcp, METIS vs. HERMES, etc).
+    // To get all required info, we do a "fake" discovery on the RedPitaya IP address.
+    // Here we also try TCP if UDP does not work, such that we can work with STEMlabs
+    // in remote subnets.
+    //
+    if (ret == 0) {
+      ret=stemlab_get_info(device_id);
+    }
     // At this point, if stemlab_start_app failed, we cannot recover
     if (ret != 0) exit(-1);
   }
@@ -252,7 +256,7 @@ fprintf(stderr,"%p Protocol=%d name=%s\n",d,d->protocol,d->name);
 #ifdef STEMLAB_DISCOVERY
         case STEMLAB_PROTOCOL:
 #ifdef NO_AVAHI
-         sprintf(text,"Choose App from %s and re-Discover:",inet_ntoa(d->info.network.address.sin_addr));
+         sprintf(text,"Choose RedPitaya App from %s and start radio:",inet_ntoa(d->info.network.address.sin_addr));
 #else
           sprintf(text, "STEMlab (%02X:%02X:%02X:%02X:%02X:%02X) on %s",
                          d->info.network.mac_address[0],
index 620a28b0f99449921cab28a867287e883297fb5d..a9e9efec28a5a7442a938ba4fefe9cdce1ee2a4d 100644 (file)
@@ -130,6 +130,138 @@ static void discover(struct ifaddrs* iface) {
 
 }
 
+#ifdef STEMLAB_DISCOVERY
+//
+// We have just started the SDR app on the RedPitaya without using AVAHI.
+// Therefore we must send a discovery packet and analyze its response
+// to have all information to start the radio.
+// Since this essentially what happens in the original discovery process,
+// we put this function HERE and not into stemlab_discovery.c
+//
+int stemlab_get_info(int id) {
+  int ret;
+  unsigned char buffer[1032];
+  int optval,i;
+
+  // Allow RP app to come up
+  sleep(2);
+
+  devices=id;
+
+  discovery_socket = socket(AF_INET, SOCK_DGRAM, 0);
+  if (discovery_socket < 0) return(1);
+
+  optval = 1;
+  setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+  setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
+
+  memset(&discovery_addr, 0, sizeof(discovery_addr));
+  discovery_addr.sin_family=AF_INET;
+  discovery_addr.sin_addr.s_addr=htonl(INADDR_ANY);
+  discovery_addr.sin_port=htons(DISCOVERY_PORT);
+  ret=bind(discovery_socket, (struct sockaddr *)&discovery_addr, sizeof(discovery_addr));
+  if (ret < 0) {
+    perror("BIND FAILED:");
+    return 1;
+  }
+
+  // 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 )
+  {
+      fprintf(stderr,"g_thread_new failed on discover_receive_thread\n");
+      return 1;
+  }
+
+  // send discovery packet
+  buffer[0]=0xEF;
+  buffer[1]=0xFE;
+  buffer[2]=0x02;
+  for(i=3;i<63;i++) {
+      buffer[i]=0x00;
+  }
+
+  ret=sendto(discovery_socket,buffer,63,0,
+             (struct sockaddr*)&(discovered[id].info.network.address),
+             sizeof(discovered[id].info.network.address));
+  if (ret < 63) {
+    perror("SEND DISCOVERY PACKET:");
+    return -1;
+  }
+
+  // wait for receive thread to complete
+  g_thread_join(discover_thread_id);
+
+  close(discovery_socket);
+
+  // if all went well, we have now filled in data for exactly
+  // one device.
+  if (devices == id+1) return 0;
+
+  if (devices > id+1) return 1;
+
+  // If we have not received an answer, then possibly the STEMlab is located
+  // on a different subnet and UDP packets are not correctly routed through.
+  // In this case, we try to open a connection using TCP.
+
+  discovery_socket = socket(AF_INET, SOCK_STREAM, 0);
+  if (discovery_socket < 0) {
+    perror("TCP socket:");
+    return 1;
+  }
+
+  optval = 1;
+  setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+  setsockopt(discovery_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
+  ret=connect(discovery_socket, (struct sockaddr*)&(discovered[id].info.network.address),
+                                  sizeof(discovered[id].info.network.address));
+  if (ret < 0) {
+    perror("TCP connect:");
+    return 1;
+  }
+
+  // send discovery packet
+  buffer[0]=0xEF;
+  buffer[1]=0xFE;
+  buffer[2]=0x02;
+  for(i=3;i<1032;i++) {
+      buffer[i]=0x00;
+  }
+
+  // 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 )
+  {
+      fprintf(stderr,"g_thread_new failed on discover_receive_thread\n");
+      return 1;
+  }
+
+  ret=sendto(discovery_socket,buffer,1032,0,
+             (struct sockaddr*)&(discovered[id].info.network.address),
+             sizeof(discovered[id].info.network.address));
+  if (ret < 1032) {
+    perror("SEND DISCOVERY PACKET:");
+    return -1;
+  }
+
+  // wait for receive thread to complete
+  g_thread_join(discover_thread_id);
+
+  close(discovery_socket);
+
+  // if all went well, we have now filled in data for exactly
+  // one device. We must set a flag that this one can ONLY do
+  // 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;
+     return 0;
+  }
+  return 1;
+}
+#endif
+
 //static void *discover_receive_thread(void* arg) {
 static gpointer discover_receive_thread(gpointer data) {
     struct sockaddr_in addr;
@@ -149,12 +281,13 @@ fprintf(stderr,"discover_receive_thread\n");
 
     len=sizeof(addr);
     while(1) {
-        bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&len);
+        bytes_read=recvfrom(discovery_socket,buffer,sizeof(buffer),1032,(struct sockaddr*)&addr,&len);
         if(bytes_read<0) {
             fprintf(stderr,"discovery: bytes read %d\n", bytes_read);
             perror("discovery: recvfrom socket failed for discover_receive_thread");
             break;
         }
+        if (bytes_read == 0) break;
         fprintf(stderr,"Old Protocol discovered: received %d bytes\n",bytes_read);
         if ((buffer[0] & 0xFF) == 0xEF && (buffer[1] & 0xFF) == 0xFE) {
             int status = buffer[2] & 0xFF;
@@ -190,7 +323,8 @@ fprintf(stderr,"discover_receive_thread\n");
                             strcpy(discovered[devices].name,"Orion 2");
                             break;
                        case DEVICE_STEMLAB:
-                           // In most respects similar to HERMES, but this indicates TCP capability
+                           // This is in principle the same as HERMES so pretend a HERMES
+                           discovered[devices].device = DEVICE_HERMES;
                             strcpy(discovered[devices].name,"STEMlab");
                             break;
                         default:
@@ -208,8 +342,17 @@ fprintf(stderr,"discover_receive_thread\n");
                     memcpy((void*)&discovered[devices].info.network.interface_netmask,(void*)&interface_netmask,sizeof(interface_netmask));
                     discovered[devices].info.network.interface_length=sizeof(interface_addr);
                     strcpy(discovered[devices].info.network.interface_name,interface_name);
-                    fprintf(stderr,"discovery: found device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n",
+                   //
+                   // 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].device,
+                            discovered[devices].can_tcp,
                             discovered[devices].software_version,
                             discovered[devices].status,
                             inet_ntoa(discovered[devices].info.network.address.sin_addr),
index fb3a2f54208e77f4223fe47b4143b421c95a724c..94872060c130fb0824b5eb803a85812f245078f8 100644 (file)
@@ -21,5 +21,8 @@
 #define _OLD_DISCOVERY_H
 
 void old_discovery(void);
+#ifdef STEMLAB_DISCOVERY
+int  stemlab_get_info(int id);
+#endif
 
 #endif
index b25fb612bd769f3e324ec34550f616fe05686aa7..7910b7dc337d8a7fffd8a2e30e928e18e5c5d308 100644 (file)
@@ -117,10 +117,9 @@ static int speed;
 static int dsp_rate=48000;
 static int output_rate=48000;
 
-static int data_socket;
+static int data_socket=-1;
 static int tcp_socket=-1;
 static struct sockaddr_in data_addr;
-static int data_addr_length;
 
 static int output_buffer_size;
 
@@ -163,7 +162,6 @@ static int output_buffer_index=8;
 static int command=1;
 
 static GThread *receive_thread_id;
-static void start_receive_thread();
 static gpointer receive_thread(gpointer arg);
 static void process_ozy_input_buffer(unsigned char  *buffer);
 static void process_bandscope_buffer(char  *buffer);
@@ -178,6 +176,9 @@ static void metis_start_stop(int command);
 static void metis_send_buffer(unsigned char* buffer,int length);
 static void metis_restart();
 
+static void open_tcp_socket(void);
+static void open_udp_socket(void);
+
 #define COMMON_MERCURY_FREQUENCY 0x80
 #define PENELOPE_MIC 0x80
 
@@ -240,7 +241,22 @@ void old_protocol_init(int rx,int pixels,int rate) {
   }
   else
 #endif
-  start_receive_thread();
+  {
+    fprintf(stderr,"old_protocol starting receive thread: buffer_size=%d output_buffer_size=%d\n",buffer_size,output_buffer_size);
+    if (radio->only_tcp) {
+      open_tcp_socket();
+    } else  {
+      open_udp_socket();
+    }
+    receive_thread_id = g_thread_new( "old protocol", receive_thread, NULL);
+    if( ! receive_thread_id )
+    {
+      fprintf(stderr,"g_thread_new failed on receive_thread\n");
+      exit( -1 );
+    }
+    fprintf(stderr, "receive_thread: id=%p\n",receive_thread_id);
+  }
+
 
   fprintf(stderr,"old_protocol_init: prime radio\n");
   for(i=8;i<OZY_BUFFER_SIZE;i++) {
@@ -318,72 +334,99 @@ static gpointer ozy_ep6_rx_thread(gpointer arg) {
 }
 #endif
 
-static void start_receive_thread() {
-  int i;
-  int rc;
-  struct hostent *h;
+static void open_udp_socket() {
+    int tmp;
 
-  fprintf(stderr,"old_protocol starting receive thread: buffer_size=%d output_buffer_size=%d\n",buffer_size,output_buffer_size);
+    if (data_socket >= 0) {
+      tmp=data_socket;
+      data_socket=-1;
+      usleep(100000);
+      close(tmp);
+    }
+    tmp=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+    if(tmp<0) {
+      perror("old_protocol: create socket failed for data_socket\n");
+      exit(-1);
+    }
 
-  switch(device) {
-#ifdef USBOZY
-    case DEVICE_OZY:
-      break;
-#endif
-    default:
-      data_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
-      if(data_socket<0) {
-        perror("old_protocol: create socket failed for data_socket\n");
-        exit(-1);
-      }
+    int optval = 1;
+    if(setsockopt(tmp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0) {
+      perror("data_socket: SO_REUSEADDR");
+    }
+    if(setsockopt(tmp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval))<0) {
+      perror("data_socket: SO_REUSEPORT");
+    }
+    optval=0xffff;
+    if (setsockopt(tmp, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval))<0) {
+      perror("data_socket: SO_SNDBUF");
+    }
+    if (setsockopt(tmp, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))<0) {
+      perror("data_socket: SO_RCVBUF");
+    }
+    //
+    // set a timeout for receive
+    // This is necessary because we might already "sit" in an UDP recvfrom() call while
+    // instructing the radio to switch to TCP. Then this call has to finish eventually
+    // and the next recvfrom() then uses the TCP socket.
+    //
+    struct timeval tv;
+    tv.tv_sec=0;
+    tv.tv_usec=100000;
+    if(setsockopt(tmp, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))<0) {
+      perror("data_socket: SO_RCVTIMEO");
+    }
 
-      int optval = 1;
-      if(setsockopt(data_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0) {
-        perror("data_socket: SO_REUSEADDR");
-      }
-      if(setsockopt(data_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval))<0) {
-        perror("data_socket: SO_REUSEPORT");
-      }
-      optval=0xffff;
-      if (setsockopt(data_socket, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval))<0) {
-        perror("tcp_socket: SO_SNDBUF");
-      }
-      if (setsockopt(data_socket, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))<0) {
-        perror("tcp_socket: SO_RCVBUF");
-      }
-      //
-      // set a timeout for receive
-      // This is necessary because we might already "sit" in an UDP recvfrom() call while
-      // instructing the radio to switch to TCP. Then this call has to finish eventually
-      // and the next recvfrom() then uses the TCP socket.
-      //
-      struct timeval tv;
-      tv.tv_sec=0;
-      tv.tv_usec=100000;
-      if(setsockopt(data_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))<0) {
-        perror("data_socket: SO_RCVTIMEO");
-      }
+    // bind to the interface
+    if(bind(tmp,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) {
+      perror("old_protocol: bind socket failed for data_socket\n");
+      exit(-1);
+    }
 
-      // bind to the interface
-      if(bind(data_socket,(struct sockaddr*)&radio->info.network.interface_address,radio->info.network.interface_length)<0) {
-        perror("old_protocol: bind socket failed for data_socket\n");
-        exit(-1);
-      }
+    memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length);
+    data_addr.sin_port=htons(DATA_PORT);
+    data_socket=tmp;
+    fprintf(stderr,"UDP socket established: %d\n", data_socket);
+}
 
-      memcpy(&data_addr,&radio->info.network.address,radio->info.network.address_length);
-      data_addr_length=radio->info.network.address_length;
-      data_addr.sin_port=htons(DATA_PORT);
-      break;
-  }
+static void open_tcp_socket() {
+    int tmp;
 
-  receive_thread_id = g_thread_new( "old protocol", receive_thread, NULL);
-  if( ! receive_thread_id )
-  {
-    fprintf(stderr,"g_thread_new failed on receive_thread\n");
-    exit( -1 );
-  }
-  fprintf(stderr, "receive_thread: id=%p\n",receive_thread_id);
+    if (tcp_socket >= 0) {
+      tmp=tcp_socket;
+      tcp_socket=-1;
+      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));
+    data_addr.sin_family = AF_INET;
+    inet_aton("192.168.1.100", &data_addr.sin_addr);
+    data_addr.sin_port=htons(1024);
 
+    tmp=socket(AF_INET, SOCK_STREAM, 0);
+    if (tmp < 0) {
+      perror("tcp_socket: create socket failed for TCP socket");
+    }
+    int optval = 1;
+    if(setsockopt(tmp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0) {
+      perror("tcp_socket: SO_REUSEADDR");
+    }
+    if(setsockopt(tmp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval))<0) {
+      perror("tcp_socket: SO_REUSEPORT");
+    }
+    if (connect(tmp,(const struct sockaddr *)&data_addr,sizeof(data_addr)) < 0) {
+      perror("tcp_socket: connect");
+    }
+    optval=0xffff;
+    if (setsockopt(tmp, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval))<0) {
+      perror("tcp_socket: SO_SNDBUF");
+    }
+    if (setsockopt(tmp, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))<0) {
+      perror("tcp_socket: SO_RCVBUF");
+    }
+    tcp_socket=tmp;
+    fprintf(stderr,"TCP socket established: %d\n", tcp_socket);
 }
 
 static gpointer receive_thread(gpointer arg) {
@@ -426,14 +469,17 @@ static gpointer receive_thread(gpointer arg) {
              bytes_read=ret;                          // error case: discard whole packet
               //perror("old_protocol recvfrom TCP:");
            }
-         } else {
+         } else if (data_socket >= 0) {
             bytes_read=recvfrom(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&addr,&length);
-            //if(bytes_read < 0) perror("old_protocol recvfrom UDP:");
             if(bytes_read < 0 && errno != EAGAIN) perror("old_protocol recvfrom UDP:");
-          } 
+          } else {
+           // no Socket available, wait a While
+           usleep(100000);
+           bytes_read=0;
+         }
           if(bytes_read >= 0 || errno != EAGAIN) break;
        }
-        if(bytes_read < 0) {
+        if(bytes_read <= 0) {
           continue;
         }
 
@@ -637,13 +683,13 @@ static void process_ozy_input_buffer(unsigned char  *buffer) {
               }
               break;
             case 2:
-              if(device==DEVICE_HERMES || device==DEVICE_STEMLAB)  {
+              if(device==DEVICE_HERMES)  {
                 left_sample_double_rx=left_sample_double;
                 right_sample_double_rx=right_sample_double;
               }
               break;
             case 3:
-              if(device==DEVICE_HERMES || device==DEVICE_STEMLAB)  {
+              if(device==DEVICE_HERMES)  {
                 left_sample_double_tx=left_sample_double;
                 right_sample_double_tx=right_sample_double;
                 add_ps_iq_samples(transmitter, left_sample_double_tx,right_sample_double_tx,left_sample_double_rx,right_sample_double_rx);
@@ -1402,6 +1448,14 @@ static int metis_write(unsigned char ep,unsigned char* buffer,int length) {
 }
 
 static void metis_restart() {
+  //
+  // In TCP-ONLY mode, we possibly need to re-connect
+  // since if we come from a METIS-stop, the server
+  // has closed the socket. Note that the UDP socket, once
+  // opened is never closed.
+  //
+  if (radio->only_tcp && tcp_socket < 1) open_tcp_socket();
+
   // reset metis frame
   metis_offset=8;
 
@@ -1440,15 +1494,7 @@ static void metis_restart() {
   sleep(1);
 
   // start the data flowing
-#ifdef RADIOBERRY
-  if (use_tcp && (device == DEVICE_STEMLAB || device == DEVICE_HERMESLITE)) {
-#else
-  if (use_tcp && device == DEVICE_STEMLAB) {
-#endif
-    metis_start_stop(0x11);
-  } else {
-    metis_start_stop(0x01);
-  }
+  metis_start_stop(0x01);
 }
 
 static void metis_start_stop(int command) {
@@ -1466,6 +1512,11 @@ static void metis_start_stop(int command) {
   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++) {
@@ -1492,49 +1543,15 @@ static void metis_start_stop(int command) {
     usleep(100000);
     suppress_ozy_packet=0;
   }
-  //
-  // If the "start" command reads 0x11 instead of 1, and no TCP socket has
-  // been connected so far, then connect to a TCP socket with the same port
-  // number and address. This is currently available for STEMlab and RADIOBERRY
-  // SDRs.
-  //
-  // Note that the variable tcp_socket must not be set until the socket is fully
-  // fully functional.
-  //
   if (command == 0 && tcp_socket >= 0) {
-    // We just have sent a METIS stop in TCP ==> switch back to UDP
+    // We just have sent a METIS stop in TCP
+    // Radio will close the TCP connection, therefore we do this as well
     tmp=tcp_socket;
     tcp_socket=-1;
     usleep(100000);  // give some time to swallow incoming TCP packets
     close(tmp);
     fprintf(stderr,"TCP socket closed\n");
   }
-  if (command == 0x11 && tcp_socket < 0) {
-    // We just have sent a METIS start indicating a switch to TCP
-    tmp=socket(AF_INET, SOCK_STREAM, 0);
-    if (connect(tmp,(const struct sockaddr *)&data_addr,data_addr_length) < 0) {
-      perror("tcp_socket: connect");
-    }
-    int optval = 1;
-    if(setsockopt(tmp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0) {
-      perror("tcp_socket: SO_REUSEADDR");
-    }
-    if(setsockopt(tmp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval))<0) {
-      perror("tcp_socket: SO_REUSEPORT");
-    }
-    optval=0xffff;
-    if (setsockopt(tmp, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval))<0) {
-      perror("tcp_socket: SO_SNDBUF");
-    }
-    if (setsockopt(tmp, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))<0) {
-      perror("tcp_socket: SO_RCVBUF");
-    }
-    //
-    // It seems that no time-out is necessary in TCP
-    //
-    tcp_socket=tmp; // this switches the receive thread to using TCP
-    fprintf(stderr,"TCP socket established: %d\n", tcp_socket);
-  }
 
 #ifdef USBOZY
   }
@@ -1546,6 +1563,7 @@ static void metis_send_buffer(unsigned char* buffer,int length) {
   // Send using either the UDP or TCP socket. Do not use TCP for
   // packets that are not 1032 bytes long
   //
+
   if (tcp_socket >= 0) {
     if (length != 1032) {
        fprintf(stderr,"PROGRAMMING ERROR: TCP LENGTH != 1032\n");
@@ -1554,7 +1572,7 @@ static void metis_send_buffer(unsigned char* buffer,int length) {
       perror("sendto socket failed for TCP metis_send_data\n");
     }
   } else {
-    if(sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,data_addr_length)!=length) {
+    if(sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,sizeof(data_addr))!=length) {
       perror("sendto socket failed for UDP metis_send_data\n");
     }
   }
diff --git a/radio.c b/radio.c
index 471f189378629ce1c07777d3ccb13bb7c5e4d7da..f0044ee94a08aa795ab7b7adcb33e77ad2d3d91a 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -1105,7 +1105,8 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     value=getProperty("filter_board");
     if(value) filter_board=atoi(value);
     value=getProperty("use_tcp");
-    if(value) use_tcp=atoi(value);
+    // 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);
index b0111dabde00260925cabf7649a22b4e4a387dad..f765833aa7f669fd0439c290fe208953938ba600 100644 (file)
@@ -41,8 +41,6 @@ static GtkWidget *menu_b=NULL;
 
 static GtkWidget *dialog=NULL;
 
-static GtkWidget *use_tcp_b=NULL;
-
 static void cleanup() {
   if(dialog!=NULL) {
     gtk_widget_destroy(dialog);
@@ -141,13 +139,9 @@ static void apollo_cb(GtkWidget *widget, gpointer data) {
   }
 }
 
-static void use_tcp_cb(GtkWidget *widget, gpointer data) {
+static void protocol_cb(GtkWidget *widget, gpointer data) {
   if (protocol == ORIGINAL_PROTOCOL) {
-    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
-      use_tcp = 1;
-    } else {
-      use_tcp = 0;
-    }
+    use_tcp=gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
     old_protocol_stop();
     old_protocol_run();
   }
@@ -215,9 +209,6 @@ void radio_menu(GtkWidget *parent) {
 
   GtkWidget *grid=gtk_grid_new();
   gtk_grid_set_column_spacing (GTK_GRID(grid),10);
-  //gtk_grid_set_row_spacing (GTK_GRID(grid),10);
-  //gtk_grid_set_row_homogeneous(GTK_GRID(grid),TRUE);
-  //gtk_grid_set_column_homogeneous(GTK_GRID(grid),TRUE);
 
   GtkWidget *close_b=gtk_button_new_with_label("Close");
   g_signal_connect (close_b, "button_press_event", G_CALLBACK(close_cb), NULL);
@@ -234,17 +225,16 @@ void radio_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),region_combo,2,0,1,1);
   g_signal_connect(region_combo,"changed",G_CALLBACK(region_cb),NULL);
 
-/*
-  GtkWidget *uk_region=gtk_radio_button_new_with_label(NULL,"UK");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uk_region), region==REGION_UK);
-  gtk_grid_attach(GTK_GRID(grid),uk_region,2,0,1,1);
-  g_signal_connect(uk_region,"pressed",G_CALLBACK(region_cb),(gpointer)REGION_UK);
-
-  GtkWidget *other_region=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(uk_region),"Other");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (other_region),region==REGION_OTHER);
-  gtk_grid_attach(GTK_GRID(grid),other_region,3,0,1,1);
-  g_signal_connect(other_region,"pressed",G_CALLBACK(region_cb),(gpointer)REGION_OTHER);
-*/
+  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;
 
@@ -385,18 +375,6 @@ void radio_menu(GtkWidget *parent) {
     g_signal_connect(apollo_b, "toggled", G_CALLBACK(apollo_cb), NULL);
     g_signal_connect(charly25_b, "toggled", G_CALLBACK(charly25_cb), NULL);
 
-#ifdef RADIOBERRY
-    if (protocol == ORIGINAL_PROTOCOL && (device==DEVICE_STEMLAB || device==DEVICE_HERMESLITE)) {
-#else
-    if (protocol == ORIGINAL_PROTOCOL && device==DEVICE_STEMLAB) {
-#endif
-      // Currently, STEMlab supports TCP switching, but RADIOBERRY might do this as well
-      use_tcp_b = gtk_check_button_new_with_label("Use TCP not UDP");
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_tcp_b), use_tcp==1);
-      gtk_grid_attach(GTK_GRID(grid), use_tcp_b, x, 6, 1, 1);
-      g_signal_connect(use_tcp_b, "toggled", G_CALLBACK(use_tcp_cb), NULL);
-    }
-
     x++;
   }
 
index 3db664d0f1b486ff4d240c5a4d3c8c53b096f4e8..63d6aab3c5c049c8fccc92380493c1e2cbb04d48 100644 (file)
@@ -848,7 +848,6 @@ fprintf(stderr,"create_receiver: id=%d buffer_size=%d fft_size=%d pixels=%d fps=
             case DEVICE_METIS:
             case DEVICE_HERMES:
             case DEVICE_HERMES_LITE:                   
-           case DEVICE_STEMLAB:
               rx->adc=0;
               break;
             default:
@@ -1092,7 +1091,7 @@ void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) {
   init_analyzer(rx);
   SetEXTANBSamplerate (rx->id, sample_rate);
   SetEXTNOBSamplerate (rx->id, sample_rate);
-fprintf(stderr,"receiver_change_sample_rate: id=%d rate=%d buffer_size=%d output_samples=%d\n",rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples);
+  fprintf(stderr,"receiver_change_sample_rate: id=%d rate=%d buffer_size=%d output_samples=%d\n",rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples);
   SetChannelState(rx->id,1,0);
 }
 
index 129f9540fa61d4b35f82f3ba3f1503cf5ea3ef1c..528284aa1831daa0decc78b68b30935cea32e105 100644 (file)
--- a/rx_menu.c
+++ b/rx_menu.c
@@ -296,7 +296,6 @@ void rx_menu(GtkWidget *parent) {
           break;
         case DEVICE_HERMES:
         case DEVICE_HERMES_LITE:
-       case DEVICE_STEMLAB:
           n_adc=1;
           break;
         default: