utils/dvb: add a prototype for a dvb scan based on APIv5
authorMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 8 Oct 2011 19:40:50 +0000 (16:40 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 7 Jan 2012 13:12:11 +0000 (11:12 -0200)
For now, it does nothing but get device capabilities, and
identify the supported delivery systems.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
utils/dvb/Makefile
utils/dvb/dvb-v5-std.h
utils/dvb/dvbv5_scan.c [new file with mode: 0644]

index 8d4a201..7f6d48f 100644 (file)
@@ -1,9 +1,11 @@
-TARGETS = dvb-v5.h
+TARGETS = dvbv5_scan
 
 all: $(TARGETS)
 
 -include *.d
 
+dvb5_scan: dvb5_scan.c
+
 dvb-v5.h:
        ./gen_dvb_structs.pl $(KERNEL_DIR)/include/
 
index f255a04..4008dab 100644 (file)
@@ -130,7 +130,7 @@ const unsigned int sys_isdbs_props[] = {
        0
 };
 
-const unsigned int *delivery_system_name[] = {
+const unsigned int *dvb_v5_delivery_system[] = {
        [SYS_ATSC] =          sys_atsc_props,
        [SYS_DVBC_ANNEX_AC] = sys_dvbc_annex_ac_props,
        [SYS_DVBC_ANNEX_B] =  sys_dvbc_annex_b_props,
diff --git a/utils/dvb/dvbv5_scan.c b/utils/dvb/dvbv5_scan.c
new file mode 100644 (file)
index 0000000..b81edce
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2011 - Mauro Carvalho Chehab <mchehab@redhat.com>
+ */
+
+#include "dvb-v5.h"
+#include "dvb-v5-std.h"
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <string.h>
+
+#define ARRAY_SIZE(x)  (sizeof(x)/sizeof((x)[0]))
+
+struct dvb_v5_fe_parms {
+       int                             fd;
+       char                            *fname;
+       unsigned                        verbose;
+       struct dvb_frontend_info        info;
+       uint32_t                        version;
+       fe_delivery_system_t            current_sys;
+       int                             num_systems;
+       fe_delivery_system_t            systems[ARRAY_SIZE(dvb_v5_delivery_system)];
+       int                             n_props;
+       struct dtv_property             dvb_prop[DTV_MAX_COMMAND];
+       int                             legacy_fe;
+};
+
+static void dvb_v5_free(struct dvb_v5_fe_parms *parms)
+{
+       if (parms->fname)
+               free(parms->fname);
+
+       free(parms);
+}
+
+static struct dvb_v5_fe_parms *dvb_fe_open(int adapter, int frontend, unsigned verbose)
+{
+       int fd, i;
+       char *fname;
+       struct dtv_properties dtv_prop;
+       struct dvb_v5_fe_parms *parms = NULL;
+
+       asprintf(&fname, "/dev/dvb/adapter%i/frontend%i", adapter, frontend);
+       if (!fname) {
+               perror("fname malloc");
+               return NULL;
+       }
+
+       fd = open(fname, O_RDWR, 0);
+       if (fd == -1) {
+               fprintf(stderr, "%s while opening %s\n", strerror(errno), fname);
+               return NULL;
+       }
+       parms = calloc(sizeof(*parms), 1);
+       if (!parms) {
+               perror("parms calloc");
+               return NULL;
+       }
+       parms->fname = fname;
+       parms->verbose = verbose;
+
+       if (ioctl(fd, FE_GET_INFO, &parms->info)) {
+               perror("FE_GET_INFO");
+               dvb_v5_free(parms);
+               return NULL;
+       }
+
+       if (verbose) {
+               fe_caps_t caps = parms->info.caps;
+
+               printf("Device %s (%s) capabilities:\n\t",
+                       parms->info.name, fname);
+               for (i = 0; i < ARRAY_SIZE(fe_caps_name); i++) {
+                       if (caps & fe_caps_name[i].idx)
+                               printf ("%s ", fe_caps_name[i].name);
+               }
+               printf("\n");
+       }
+
+       parms->dvb_prop[0].cmd = DTV_API_VERSION;
+       parms->dvb_prop[1].cmd = DTV_DELIVERY_SYSTEM;
+
+       dtv_prop.num = 2;
+       dtv_prop.props = parms->dvb_prop;
+
+       /* Detect a DVBv3 device */
+       if (ioctl(fd, FE_GET_PROPERTY, &dtv_prop) == -1) {
+               parms->dvb_prop[0].u.data = 0x300;
+               parms->dvb_prop[1].u.data = SYS_UNDEFINED;
+       }
+       parms->version = parms->dvb_prop[0].u.data;
+       parms->current_sys = parms->dvb_prop[1].u.data;
+       if (verbose)
+               printf ("DVB API Version %d.%d, Current v5 delivery system: %s\n",
+                       parms->version / 256,
+                       parms->version % 256,
+                       delivery_system_name[parms->current_sys]);
+
+       if (parms->current_sys == SYS_UNDEFINED) {
+               parms->legacy_fe = 1;
+               switch(parms->info.type) {
+               case FE_QPSK:
+                       parms->current_sys = SYS_DVBS;
+                       parms->systems[parms->num_systems++] = parms->current_sys;
+                       if (parms->info.caps & FE_CAN_2G_MODULATION) {
+                               parms->systems[parms->num_systems++] = SYS_DVBS2;
+                       }
+                       break;
+               case FE_QAM:
+                       parms->current_sys = SYS_DVBC_ANNEX_AC;
+                       parms->systems[parms->num_systems++] = parms->current_sys;
+                       break;
+               case FE_OFDM:
+                       parms->current_sys = SYS_DVBT;
+                       parms->systems[parms->num_systems++] = parms->current_sys;
+                       if (parms->info.caps & FE_CAN_2G_MODULATION) {
+                               parms->systems[parms->num_systems++] = SYS_DVBT2;
+                       }
+                       break;
+               case FE_ATSC:
+                       if (parms->info.caps & (FE_CAN_8VSB | FE_CAN_16VSB))
+                               parms->systems[parms->num_systems++] = SYS_ATSC;
+                       if (parms->info.caps & (FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO))
+                               parms->systems[parms->num_systems++] = SYS_DVBC_ANNEX_B;
+                       parms->current_sys = parms->systems[0];
+                       break;
+               }
+               if (!parms->num_systems) {
+                       fprintf(stderr, "delivery system not detected\n");
+                       dvb_v5_free(parms);
+                       return NULL;
+               }
+       } else {
+               for (i = 0; i < ARRAY_SIZE(dvb_v5_delivery_system); i++) {
+                       if (!dvb_v5_delivery_system[i])
+                               continue;
+
+                       dtv_prop.num = 1;
+                       parms->dvb_prop[0].cmd = DTV_DELIVERY_SYSTEM;
+                       parms->dvb_prop[0].u.data = i;
+                       if (ioctl(fd, FE_SET_PROPERTY, &dtv_prop) == -1)
+                               continue;
+                       if (ioctl(fd, FE_GET_PROPERTY, &dtv_prop) == -1)
+                               continue;
+                       if (parms->dvb_prop[0].u.data == i)
+                               parms->systems[parms->num_systems++] = i;
+               }
+               if (parms->num_systems == 0) {
+                       fprintf(stderr, "driver died while trying to set the delivery system\n");
+                       dvb_v5_free(parms);
+                       return NULL;
+               }
+               if (parms->num_systems == 1 && parms->systems[0] != parms->current_sys) {
+                       fprintf(stderr, "failed to detect all delivery systems\n");
+                       dvb_v5_free(parms);
+                       return NULL;
+               } else {
+                       /* Return back to the default delivery system */
+                       dtv_prop.num = 1;
+                       parms->dvb_prop[0].cmd = DTV_DELIVERY_SYSTEM;
+                       parms->dvb_prop[0].u.data = parms->current_sys;
+                       if (ioctl(fd, FE_SET_PROPERTY, &dtv_prop) == -1) {
+                               fprintf(stderr, "failed to return to default delivery system\n");
+                               dvb_v5_free(parms);
+                               return NULL;
+                       }
+                       if (parms->dvb_prop[0].u.data == i)
+                               parms->systems[parms->num_systems++] = i;
+               }
+       }
+
+       if (verbose) {
+               printf("Supported delivery system%s: ",
+                      (parms->num_systems > 1) ? "s" : "");
+               for (i = 0; i < parms->num_systems; i++) {
+                       if (parms->systems[i] == parms->current_sys)
+                               printf ("[%s] ",
+                                       delivery_system_name[parms->systems[i]]);
+                       else
+                               printf ("%s ",
+                                       delivery_system_name[parms->systems[i]]);
+               }
+               printf("\n");
+       }
+
+       return parms;
+}
+
+static void dvb_fe_close(struct dvb_v5_fe_parms *parms)
+{
+       if (!parms)
+               return;
+
+
+       if (parms->fd < 0)
+               return;
+}
+
+int main(void)
+{
+       struct dvb_v5_fe_parms *parms;
+
+       parms = dvb_fe_open(0, 0, 1);
+       dvb_fe_close(parms);
+
+       return 0;
+}
\ No newline at end of file