diff recpt1/checksignal.c @ 114:3eccf1ef4853

improve checksignal command: - retries MAX_RETRY times when tuning fails. if device is specified, reties forever. - notifies signal quality by audible beep.
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Fri, 19 Mar 2010 16:42:32 +0900
parents e7b786c42ca0
children 91e71df37095
line wrap: on
line diff
--- a/recpt1/checksignal.c	Fri Mar 19 01:01:35 2010 +0900
+++ b/recpt1/checksignal.c	Fri Mar 19 16:42:32 2010 +0900
@@ -34,6 +34,8 @@
 #include "pt1_dev.h"
 #include "tssplitter_lite.h"
 
+#define MAX_RETRY (2)
+
 /* type definitions */
 typedef int boolean;
 
@@ -46,18 +48,66 @@
 
 /* globals */
 boolean f_exit = FALSE;
+boolean use_bell = FALSE;
 
 /* prototypes */
 int tune(char *channel, thread_data *tdata, char *device);
 int close_tuner(thread_data *tdata);
 
-/* signal handler */
 void
-handler(int dummy)
+cleanup(thread_data *tdata)
 {
     f_exit = TRUE;
 }
 
+/* will be signal handler thread */
+void *
+process_signals(void *data)
+{
+    sigset_t waitset;
+    int sig;
+    thread_data *tdata = (thread_data *)data;
+
+    sigemptyset(&waitset);
+    sigaddset(&waitset, SIGINT);
+    sigaddset(&waitset, SIGTERM);
+    sigaddset(&waitset, SIGUSR1);
+
+    sigwait(&waitset, &sig);
+
+    switch(sig) {
+    case SIGINT:
+        fprintf(stderr, "\nSIGINT received. cleaning up...\n");
+        cleanup(tdata);
+        break;
+    case SIGTERM:
+        fprintf(stderr, "\nSIGTERM received. cleaning up...\n");
+        cleanup(tdata);
+        break;
+    case SIGUSR1: /* normal exit*/
+        cleanup(tdata);
+        break;
+    }
+
+    return NULL; /* dummy */
+}
+
+void
+init_signal_handlers(pthread_t *signal_thread, thread_data *tdata)
+{
+    sigset_t blockset;
+
+    sigemptyset(&blockset);
+    sigaddset(&blockset, SIGINT);
+    sigaddset(&blockset, SIGTERM);
+    sigaddset(&blockset, SIGUSR1);
+
+    if(pthread_sigmask(SIG_BLOCK, &blockset, NULL))
+        fprintf(stderr, "pthread_sigmask() failed.\n");
+
+    pthread_create(signal_thread, NULL, process_signals, tdata);
+}
+
 /* lookup frequency conversion table*/
 ISDB_T_FREQ_CONV_TABLE *
 searchrecoff(char *channel)
@@ -79,7 +129,7 @@
 void
 show_usage(char *cmd)
 {
-    fprintf(stderr, "Usage: \n%s [--device devicefile] [--lnb voltage] channel\n", cmd);
+    fprintf(stderr, "Usage: \n%s [--device devicefile] [--lnb voltage] [--bell] channel\n", cmd);
     fprintf(stderr, "\n");
 }
 
@@ -89,6 +139,7 @@
     fprintf(stderr, "Options:\n");
     fprintf(stderr, "--device devicefile: Specify devicefile to use\n");
     fprintf(stderr, "--lnb voltage:       Specify LNB voltage (0, 11, 15)\n");
+    fprintf(stderr, "--bell:              Notify signal quality by bell\n");
     fprintf(stderr, "--help:              Show this help\n");
     fprintf(stderr, "--version:           Show version\n");
     fprintf(stderr, "--list:              Show channel list\n");
@@ -178,11 +229,22 @@
 }
 
 void
+do_bell(int bell)
+{
+    int i;
+    for(i=0; i < bell; i++) {
+        fprintf(stderr, "\a");
+        usleep(400000);
+    }
+}
+
+void
 calc_cn(int fd, int type)
 {
-    int     rc ;
-    double  P ;
+    int     rc;
+    double  P;
     double  CNR;
+    int bell = 0;
 
     if(ioctl(fd, GET_SIGNAL_STRENGTH, &rc) < 0) {
         fprintf(stderr, "Tuner Select Error\n");
@@ -197,7 +259,17 @@
     else {
         CNR = getsignal_isdb_s(rc);
     }
+
+    if(CNR >= 30.0)
+        bell = 3;
+    else if(CNR >= 15.0 && CNR < 30.0)
+        bell = 2;
+    else if(CNR < 15.0)
+        bell = 1;
+
     fprintf(stderr, "\rC/N = %fdB", CNR);
+    if(use_bell)
+        do_bell(bell);
 }
 
 int
@@ -221,7 +293,6 @@
     /* open tuner */
     /* case 1: specified tuner device */
     if(device) {
-        fprintf(stderr, "device = %s\n", device);
         tdata->tfd = open(device, O_RDONLY);
         if(tdata->tfd < 0) {
             fprintf(stderr, "Cannot open tuner device: %s\n", device);
@@ -236,14 +307,16 @@
         }
 
         /* tune to specified channel */
-        if(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) {
-            close(tdata->tfd);
-            fprintf(stderr, "Cannot tune to the specified channel: %s\n", device);
-            return 1;
+        while(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) {
+            if(f_exit) {
+                close_tuner(tdata);
+                return 1;
+            }
+            fprintf(stderr, "No signal. Still trying: %s\n", device);
         }
-        else {
-            tdata->ch = atoi(channel);
-        }
+
+        fprintf(stderr, "device = %s\n", device);
+        tdata->ch = atoi(channel);
     }
     else {
         /* case 2: loop around available devices */
@@ -257,6 +330,8 @@
         }
 
         for(lp = 0; lp < num_devs; lp++) {
+            int count = 0;
+
             tdata->tfd = open(tuner[lp], O_RDONLY);
             if(tdata->tfd >= 0) {
                 /* power on LNB */
@@ -267,9 +342,19 @@
                 }
 
                 /* tune to specified channel */
-                if(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) {
-                    close(tdata->tfd);
-                    tdata->tfd = -1;
+                while(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0 &&
+                      count < MAX_RETRY) {
+                    if(f_exit) {
+                        close_tuner(tdata);
+                        return 1;
+                    }
+                    fprintf(stderr, "No signal. Still trying: %s\n", tuner[lp]);
+                    count++;
+                }
+
+                if(count >= MAX_RETRY) {
+                    close_tuner(tdata);
+                    count = 0;
                     continue;
                 }
 
@@ -296,12 +381,16 @@
 {
     int rv = 0;
 
+    if(tdata->tfd == -1)
+        return rv;
+
     if(tdata->table->type == CHTYPE_SATELLITE) {
         if(ioctl(tdata->tfd, LNB_DISABLE, 0) < 0) {
             rv = 1;
         }
     }
     close(tdata->tfd);
+    tdata->tfd = -1;
 
     return rv;
 }
@@ -309,10 +398,12 @@
 int
 main(int argc, char **argv)
 {
+    pthread_t signal_thread;
     static thread_data tdata;
     int result;
     int option_index;
     struct option long_options[] = {
+        { "bell",      1, NULL, 'b'},
         { "LNB",       1, NULL, 'n'},
         { "lnb",       1, NULL, 'n'},
         { "device",    1, NULL, 'd'},
@@ -326,9 +417,12 @@
     int val;
     char *voltage[] = {"0V", "11V", "15V"};
 
-    while((result = getopt_long(argc, argv, "br:smn:ua:p:d:hvli:",
+    while((result = getopt_long(argc, argv, "bhvln:d:",
                                 long_options, &option_index)) != -1) {
         switch(result) {
+        case 'b':
+            use_bell = TRUE;
+            break;
         case 'h':
             fprintf(stderr, "\n");
             show_usage(argv[0]);
@@ -376,8 +470,8 @@
         return 1;
     }
 
-    /* add signal handler */
-    signal(SIGTERM, handler);
+    /* spawn signal handler thread */
+    init_signal_handlers(&signal_thread, &tdata);
 
     /* tune */
     if(tune(argv[optind], &tdata, device) != 0)
@@ -391,6 +485,10 @@
         sleep(1);
     }
 
+    /* wait for signal thread */
+    pthread_kill(signal_thread, SIGUSR1);
+    pthread_join(signal_thread, NULL);
+
     /* close tuner */
     if(close_tuner(&tdata) != 0)
         return 1;