From acb5931ed0a8881c4b125d7c39c12fdb707993a5 Mon Sep 17 00:00:00 2001 From: drmocm Date: Mon, 8 Mar 2021 14:29:27 +0100 Subject: [PATCH 01/22] added README.md --- lib/README.md | 40 ++++++++++++++++++++++++++++++++++++++++ lib/src/dvb.c | 2 ++ 2 files changed, 42 insertions(+) create mode 100644 lib/README.md diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..13b2eed --- /dev/null +++ b/lib/README.md @@ -0,0 +1,40 @@ +# LIBDDDVB + +In order to install the libdddvb library + +https://github.com/DigitalDevices/dddvb + +you need dvben50221. + + +On an Ubuntu system this would look like this: + +`sudo apt-get install dvb-apps` + +`git clone https://github.com/DigitalDevices/internal_dddvb.git` + +`cd dddvb/lib/; make` + +`sudo make install` + +# DDZAP + +You can now use the example program ddzap for tuning. + +A typical usage example call would be: + + +`ddzap -d S2 -p v -f 10847000 -s 23000000 -c ~/dddvb/lib/config/` + +where you would use the example configuration file for a unicable LNB +given in the sources. If you leave out the `-c` option a standard universal +LNB is assumed to be connected. + +Additionally you can use ddzap to open the /dev/dvb/adaptorX/dvrY device +that corresponds to the tuner that was automatically selected by the library +and pipe it to a media player, e.g. + + +`ddzap -d S2 -p h -f 11494000 -s 22000000 -c /home/dmocm/ddzapconf/ -o|vlc -` + + diff --git a/lib/src/dvb.c b/lib/src/dvb.c index 586a808..2974d9a 100644 --- a/lib/src/dvb.c +++ b/lib/src/dvb.c @@ -750,6 +750,8 @@ int dddvb_fe_tune(struct dddvb_fe *fe, struct dddvb_params *p) memcpy(fe->n_param.param, p->param, sizeof(fe->n_param.param)); fe->n_tune = 1; pthread_mutex_unlock(&fe->mutex); + while(fe->n_tune) usleep(10000); + while(fe->tune != 2) usleep(10000); return ret; } From 04fa5041d3673e3647492380000486ab6a6177a0 Mon Sep 17 00:00:00 2001 From: drmocm Date: Tue, 9 Mar 2021 22:06:10 +0100 Subject: [PATCH 02/22] fixes --- lib/README.md | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/lib/README.md b/lib/README.md index 13b2eed..f764fc5 100644 --- a/lib/README.md +++ b/lib/README.md @@ -1,30 +1,40 @@ # LIBDDDVB - -In order to install the libdddvb library - -https://github.com/DigitalDevices/dddvb - -you need dvben50221. +The libdddvb provides a userspace library to simplify tuning and +CI use. It detects DVB cards and their capabilities and selects +free frontends depending on a given delivery system. -On an Ubuntu system this would look like this: +In order to install the libdddvb library you need the dvben50221. + +On an Ubuntu and other Debian based system you can install it like this: `sudo apt-get install dvb-apps` -`git clone https://github.com/DigitalDevices/internal_dddvb.git` +After that you can build the libdddvb: + +`git clone https://github.com/DigitalDevices/dddvb.git` `cd dddvb/lib/; make` `sudo make install` +If your distribution does not include a dvb-apps package, you can follow the +instructions at + +https://www.linuxtv.org/wiki/index.php/LinuxTV_dvb-apps + +on how to build it yourself. + + # DDZAP -You can now use the example program ddzap for tuning. +You can now use the example program ddzap to see how the library +is used or to test your cards. -A typical usage example call would be: +A typical usage example would be the tuning of a +sattelite channel with a given LNB configuration. - -`ddzap -d S2 -p v -f 10847000 -s 23000000 -c ~/dddvb/lib/config/` +`ddzap -d S2 -p h -f 11494000 -s 22000000 -c ~/dddvb/lib/config/` where you would use the example configuration file for a unicable LNB given in the sources. If you leave out the `-c` option a standard universal @@ -37,4 +47,3 @@ and pipe it to a media player, e.g. `ddzap -d S2 -p h -f 11494000 -s 22000000 -c /home/dmocm/ddzapconf/ -o|vlc -` - From 9269270c7902a817223c7097193b16d6e6651f1f Mon Sep 17 00:00:00 2001 From: mocm Date: Tue, 9 Mar 2021 22:14:14 +0100 Subject: [PATCH 03/22] Added install link --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 8616941..ee2fcf2 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ We can only accept patches which don't break compilation for older kernels (as f Due to this and other changes not approved by us the kernel version of the ddbridge driver might contain incompatiblities to this driver package. +For installation instructions see: + +http://support.digital-devices.eu/index.php?article=152 ### Prepare for Building TBD From 31f36de0d75096ec6646c19085fb06de90c2869e Mon Sep 17 00:00:00 2001 From: none Date: Wed, 10 Mar 2021 16:17:06 +0100 Subject: [PATCH 04/22] set default source to undef --- lib/ddzap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ddzap.c b/lib/ddzap.c index 465452b..9e90acd 100644 --- a/lib/ddzap.c +++ b/lib/ddzap.c @@ -271,7 +271,7 @@ int main(int argc, char **argv) struct dddvb_fe *fe; struct dddvb_params p; uint32_t bandwidth = DDDVB_UNDEF, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF; - uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = 0; + uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = DDDVB_UNDEF; uint32_t mtype= DDDVB_UNDEF; uint32_t verbosity = 0; uint32_t get_ts = 1; From b200ce3596de52f12d9803431982611fecddd418 Mon Sep 17 00:00:00 2001 From: none Date: Wed, 10 Mar 2021 16:19:54 +0100 Subject: [PATCH 05/22] allow source selection in non-unicable mode --- lib/src/dvb.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/src/dvb.c b/lib/src/dvb.c index 2974d9a..9f12042 100644 --- a/lib/src/dvb.c +++ b/lib/src/dvb.c @@ -318,14 +318,15 @@ static int tune_sat(struct dddvb_fe *fe) fe->scif_slot, fe->scif_freq, ds); pthread_mutex_unlock(&fe->dd->uni_lock); } else { - uint32_t input = lnb; + uint32_t input = fe->param.param[PARAM_SRC]; - //if (input != DDDVB_UNDEF) - // input = 3 & (input >> 6); - //set_property(fe->fd, DTV_INPUT, 3 & (lnb >> 6)); + if (input != DDDVB_UNDEF) { + input = 3 & (input >> 6); + printf("input = %u\n", input); + } diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi); - //set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input); - set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, ~(0U)); + set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input); + //set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, DDDVB_UNDEF); } } From eb427a8df2175a5c50d40869013002cf1f1c57d6 Mon Sep 17 00:00:00 2001 From: none Date: Wed, 10 Mar 2021 21:38:19 +0100 Subject: [PATCH 06/22] properly handle flash size limits --- apps/octonet/ddupdate.c | 2 +- apps/octonet/flash.c | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/apps/octonet/ddupdate.c b/apps/octonet/ddupdate.c index 89dee96..d010eab 100644 --- a/apps/octonet/ddupdate.c +++ b/apps/octonet/ddupdate.c @@ -119,7 +119,7 @@ static int update_flash(struct ddflash *ddf) printf("Flash: %s\n", ddf->flash_name); printf("Version: %08x\n", ddf->id.hw); printf("REGMAP : %08x\n", ddf->id.regmap); - if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1) + if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1) stat |= 1; return stat; } diff --git a/apps/octonet/flash.c b/apps/octonet/flash.c index cb0dbc9..8a6fb75 100644 --- a/apps/octonet/flash.c +++ b/apps/octonet/flash.c @@ -968,12 +968,10 @@ static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, return -1; len = off - fw_off; lseek(fs, fw_off, SEEK_SET); -#if 0 if (len > maxlen) { printf("file too big\n"); return -1; } -#endif //printf("flash file len %u, compare to %08x in flash: ", len, addr); for (j = 0; j < len; j += bl, addr += bl) { if (len - j < bl) @@ -1132,9 +1130,15 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off) return -4; } if (devid == ddf->id.device) { - if (version <= (ddf->id.hw & 0xffffff)) { - printf("%s is older or same version as flash\n", fn); - ret = -3; /* same id but no newer version */ + if (version < (ddf->id.hw & 0xffffff)) { + printf("%s is older version than flash\n", fn); + if (!ddf->force) + ret = -3; /* same id but older newer version */ + } + if (version == (ddf->id.hw & 0xffffff)) { + printf("%s is same version as flash\n", fn); + if (!ddf->force) + ret = 2; /* same and same version */ } } else ret = 1; @@ -1147,7 +1151,7 @@ out: } static int update_image(struct ddflash *ddf, char *fn, - uint32_t adr, uint32_t len, + uint32_t adr, uint32_t maxlen, int has_header, int no_change) { int fs, res = 0; @@ -1167,7 +1171,7 @@ static int update_image(struct ddflash *ddf, char *fn, printf("File %s not found \n", fn); return -1; } - res = flashcmp(ddf, fs, adr, len, fw_off); + res = flashcmp(ddf, fs, adr, maxlen, fw_off); if (res == -2) { printf("Flash already identical to %s\n", fn); if (ddf->force) { @@ -1177,9 +1181,9 @@ static int update_image(struct ddflash *ddf, char *fn, } if (res < 0) goto out; - res = flashwrite(ddf, fs, adr, len, fw_off); + res = flashwrite(ddf, fs, adr, maxlen, fw_off); if (res == 0) { - res = flashcmp(ddf, fs, adr, len, fw_off); + res = flashcmp(ddf, fs, adr, maxlen, fw_off); if (res == -2) { res = 1; printf("Flash verify OK!\n"); From 4c96f54ddfb350a80c8d62e04825c49bedf08859 Mon Sep 17 00:00:00 2001 From: none Date: Wed, 10 Mar 2021 21:46:29 +0100 Subject: [PATCH 07/22] increase L-BAND to 3GHz --- lib/src/dvb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/dvb.c b/lib/src/dvb.c index 9f12042..369e0c8 100644 --- a/lib/src/dvb.c +++ b/lib/src/dvb.c @@ -288,7 +288,8 @@ static int tune_sat(struct dddvb_fe *fe) freq = lofs - freq; } #endif - if (freq > 2100000) { + + if (freq > 3000000) { if (lofs) hi = (freq > lofs) ? 1 : 0; if (hi) From cf35c3038b52b57a921038a651ff534acf8b47b9 Mon Sep 17 00:00:00 2001 From: none Date: Wed, 10 Mar 2021 22:03:56 +0100 Subject: [PATCH 08/22] only get status if demod started --- ddbridge/ddbridge-m4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ddbridge/ddbridge-m4.c b/ddbridge/ddbridge-m4.c index 29e0f22..63bb06e 100644 --- a/ddbridge/ddbridge-m4.c +++ b/ddbridge/ddbridge-m4.c @@ -392,10 +392,12 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status) struct m4 *state = fe->demodulator_priv; struct mci_result res; + *status = 0x00; + if (!state->started) + return 0; stat = ddb_mci_get_status(&state->mci, &res); if (stat) return stat; - *status = 0x00; stat = ddb_mci_get_info(&state->mci); if (stat) return stat; From de0e9709992591f2b168e258534d44b012c6d8ed Mon Sep 17 00:00:00 2001 From: none Date: Thu, 11 Mar 2021 22:31:52 +0100 Subject: [PATCH 09/22] change input locked in fmode=4 and do not send emulated sequence as diseqc --- ddbridge/ddbridge-max.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ddbridge/ddbridge-max.c b/ddbridge/ddbridge-max.c index 72b8c80..3cab4ff 100644 --- a/ddbridge/ddbridge-max.c +++ b/ddbridge/ddbridge-max.c @@ -65,7 +65,7 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) return 0; } -static int max_set_input_unlocked(struct dvb_frontend *fe, int in); +static int max_set_input(struct dvb_frontend *fe, int in); static int max_emulate_switch(struct dvb_frontend *fe, u8 *cmd, u32 len) @@ -79,7 +79,7 @@ static int max_emulate_switch(struct dvb_frontend *fe, return -1; input = cmd[3] & 3; - max_set_input_unlocked(fe, input); + max_set_input(fe, input); return 0; } @@ -98,7 +98,8 @@ static int max_send_master_cmd(struct dvb_frontend *fe, return 0; if (fmode == 4) - max_emulate_switch(fe, cmd->msg, cmd->msg_len); + if (!max_emulate_switch(fe, cmd->msg, cmd->msg_len)) + return 0; if (dvb->diseqc_send_master_cmd) dvb->diseqc_send_master_cmd(fe, cmd); From 60646a6b26d6538f62e5ff6be658e787f770f9c1 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 11 Mar 2021 22:33:13 +0100 Subject: [PATCH 10/22] experimental diseqc receive code --- frontends/stv0910.c | 88 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/frontends/stv0910.c b/frontends/stv0910.c index b289ef7..431028d 100644 --- a/frontends/stv0910.c +++ b/frontends/stv0910.c @@ -208,17 +208,35 @@ static int write_field(struct stv *state, u32 field, u8 val) return write_reg(state, field >> 16, new); } +static int read_field(struct stv *state, u32 field, u8 *val) +{ + int status; + u8 shift, mask; + + status = read_reg(state, field >> 16, val); + if (status) + return status; + mask = field & 0xff; + shift = (field >> 12) & 0xf; + *val = (*val & mask) >> shift; + return status; +} + #define set_field(_reg, _val) \ write_field(state, state->nr ? FSTV0910_P2_##_reg : \ FSTV0910_P1_##_reg, _val) +#define get_field(_reg, _val) \ + read_field(state, state->nr ? FSTV0910_P2_##_reg : \ + FSTV0910_P1_##_reg, _val) + #define set_reg(_reg, _val) \ write_reg(state, state->nr ? RSTV0910_P2_##_reg : \ RSTV0910_P1_##_reg, _val) #define get_reg(_reg, _val) \ read_reg(state, state->nr ? RSTV0910_P2_##_reg : \ - RTV0910_P1_##_reg, _val) + RSTV0910_P1_##_reg, _val) static const struct slookup s1_sn_lookup[] = { { 0, 9242 }, /* C/N= 0dB */ @@ -1112,8 +1130,9 @@ static int init_diseqc(struct stv *state) u16 offs = state->nr ? 0x40 : 0; /* Address offset */ u8 freq = ((state->base->mclk + 11000 * 32) / (22000 * 32)); - /* Disable receiver */ - write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x00); + write_reg(state, RSTV0910_P1_DISRXCFG + offs, 0x05); + //write_reg(state, RSTV0910_P1_DISRXF220 + offs, 0x69); 2b? + write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0xBA); /* Reset = 1 */ write_reg(state, RSTV0910_P1_DISTXCFG + offs, 0x3A); /* Reset = 0 */ write_reg(state, RSTV0910_P1_DISTXF22 + offs, freq); @@ -1617,12 +1636,28 @@ static int wait_dis(struct stv *state, u8 flag, u8 val) return -1; } +static int clear_slave(struct dvb_frontend *fe) +{ + struct stv *state = fe->demodulator_priv; + u8 n, d, done; + + get_field(RXEND, &done); + get_reg(DISRXBYTES, &n); + printk("clear: done = %u, %u fifo bytes\n", done, n); + + for (get_reg(DISRXBYTES, &n); n; n--) + get_reg(DISRXFIFO, &d); + return 0; +} + static int send_master_cmd(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) { struct stv *state = fe->demodulator_priv; int i; + clear_slave(fe); + set_field(DISRX_ON, 0); set_reg(DISTXCFG, 0x3e); for (i = 0; i < cmd->msg_len; i++) { wait_dis(state, 0x40, 0x00); @@ -1630,12 +1665,59 @@ static int send_master_cmd(struct dvb_frontend *fe, } set_reg(DISTXCFG, 0x3a); wait_dis(state, 0x20, 0x20); + set_field(DISRX_ON, 1); return 0; } static int recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply) { + struct stv *state = fe->demodulator_priv; + int i, to, flag = 0, max = sizeof(reply->msg); + u8 done, val, n = 0; + + +#if 0 + get_reg(DISRXBYTES, &val); + get_field(RXEND, &done); + printk("slave: done = %u, %u fifo bytes\n", done, val); +#endif + to = reply->timeout; + if (to < 0) { + to = 100; + flag = 1; + } else if (to > 5000) + to = 100; + reply->msg_len = 0; + for (i = 0; i < to; i += 10) { + get_reg(DISRXBYTES, &val); + if (flag && val) + break; + get_field(RXEND, &done); + if (val >= max || done) + break; + msleep(10); + } + get_reg(DISRXBYTES, &val); + printk("done = %u, %u fifo bytes, i=%u\n", done, val, i); + if (i == to && !val) + return -EIO; + if (done && !val) + return -EIO; + for (i = 100; i; i--) { + get_field(RXEND, &done); + + for (get_reg(DISRXBYTES, &n); n; n--) { + if (reply->msg_len == max) + return 0; + get_reg(DISRXFIFO, &reply->msg[reply->msg_len++]); + } + if (!n || done) + break; + msleep(10); + } + if (!i) + return -EIO; return 0; } From f8c97ad3d69a64cedcef46486b77a99cc2cf706d Mon Sep 17 00:00:00 2001 From: none Date: Thu, 11 Mar 2021 22:43:12 +0100 Subject: [PATCH 11/22] remove init dump, cannot access regs directly on all platforms --- ddbridge/ddbridge-mci.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ddbridge/ddbridge-mci.c b/ddbridge/ddbridge-mci.c index 0ae7630..4b5bff4 100644 --- a/ddbridge/ddbridge-mci.c +++ b/ddbridge/ddbridge-mci.c @@ -60,10 +60,6 @@ static int mci_reset(struct ddb_link *link) return -1; } dev_info(link->dev->dev, "MCI port OK, init time %u msecs\n", (40 - timeout) * 50); - - print_hex_dump(KERN_INFO, "ddbridge: MCI INIT INFO: ", DUMP_PREFIX_NONE, 16, 1, - link->dev->regs + regmap->mci_buf->base + MCI_COMMAND_SIZE, - 16, false); return 0; } From f9eb03a065c03baa41ab7c34a994fc9701101750 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 11 Mar 2021 23:20:31 +0100 Subject: [PATCH 12/22] remove unused entries --- ddbridge/ddbridge-sx8.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index b713860..55188c6 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -44,12 +44,10 @@ struct sx8_base { struct mci_base mci_base; u8 tuner_use_count[SX8_TUNER_NUM]; - u32 gain_mode[SX8_TUNER_NUM]; u32 used_ldpc_bitrate[SX8_DEMOD_NUM]; u8 demod_in_use[SX8_DEMOD_NUM]; u32 iq_mode; - u32 burst_size; u32 direct_mode; }; @@ -59,10 +57,6 @@ struct sx8 { int first_time_lock; int started; int iq_started; - - u32 bb_mode; - u32 local_frequency; - }; static const u8 dvbs2_bits_per_symbol[] = { From 8380cb185f24564b245f6ca935e6085761057a43 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 11 Mar 2021 23:22:03 +0100 Subject: [PATCH 13/22] change direct_mode to module parameter --- ddbridge/ddbridge-sx8.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index 55188c6..4bbb3f4 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -30,6 +30,10 @@ static int default_mod = 3; module_param(default_mod, int, 0444); MODULE_PARM_DESC(default_mod, "default modulations enabled, default is 3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)"); +static int direct_mode; +module_param(direct_mode, int, 0444); +MODULE_PARM_DESC(direct_mode, "Ignore LDPC limits and assign high speed demods according to needed symbolrate."); + static const u32 MCLK = (1550000000 / 12); /* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */ @@ -48,7 +52,6 @@ struct sx8_base { u32 used_ldpc_bitrate[SX8_DEMOD_NUM]; u8 demod_in_use[SX8_DEMOD_NUM]; u32 iq_mode; - u32 direct_mode; }; struct sx8 { @@ -281,7 +284,7 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) goto unlock; } - if (sx8_base->direct_mode) { + if (direct_mode) { if (p->symbol_rate >= MCLK / 2) { if (state->mci.nr < 4) i = state->mci.nr; From c3c734b0e8e9f2f597e13a5fd7ee92cdfc06b681 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 11 Mar 2021 23:23:30 +0100 Subject: [PATCH 14/22] remove unsused variables and code --- ddbridge/ddbridge-sx8.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index 4bbb3f4..15b53d1 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -162,14 +162,12 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on, u8 flags, u8 gain) { struct sx8 *state = fe->demodulator_priv; - struct mci_base *mci_base = state->mci.base; - struct sx8_base *sx8_base = (struct sx8_base *) mci_base; struct mci_command cmd; memset(&cmd, 0, sizeof(cmd)); cmd.tuner = state->mci.tuner; cmd.command = on ? SX8_CMD_INPUT_ENABLE : SX8_CMD_INPUT_DISABLE; - cmd.sx8_input_enable.flags = flags;//sx8_base->gain_mode[state->mci.tuner]; + cmd.sx8_input_enable.flags = flags; cmd.sx8_input_enable.rf_gain = gain; return ddb_mci_cmd(&state->mci, &cmd, NULL); } From 2ac970ef8336078415ec26c58148bb15db578ed7 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 18 Mar 2021 10:36:51 +0100 Subject: [PATCH 15/22] typo --- apps/setmod3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/setmod3.c b/apps/setmod3.c index f41491d..fb83015 100644 --- a/apps/setmod3.c +++ b/apps/setmod3.c @@ -113,7 +113,7 @@ int main(int argc, char*argv[]) } } if (optind < argc) { - printf("too man arguments\n"); + printf("too many arguments\n"); exit(1); } From 4b0a0c4ff285549f1b233193d0ce21b0d1f6e7f1 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 18 Mar 2021 10:39:07 +0100 Subject: [PATCH 16/22] allow explicit setting of roll-off --- ddbridge/ddbridge-sx8.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index 15b53d1..cf91cbe 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -255,6 +255,10 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) u32 bits_per_symbol = 0; int i = -1, stat = 0; struct ddb_link *link = state->mci.base->link; + const u8 ro_lut[8] = { + 8 | SX8_ROLLOFF_35, 8 | SX8_ROLLOFF_20, 8 | SX8_ROLLOFF_25, 0, + 8 | SX8_ROLLOFF_15, 8 | SX8_ROLLOFF_10, 8 | SX8_ROLLOFF_05, 0, + }; if (link->ids.device == 0x000b) { /* Mask out higher modulations and MIS for Basic @@ -359,6 +363,7 @@ unlock: cmd.command = MCI_CMD_SEARCH_DVBS; cmd.dvbs2_search.flags = flags; cmd.dvbs2_search.s2_modulation_mask = modmask; + cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7]; cmd.dvbs2_search.retry = 2; cmd.dvbs2_search.frequency = p->frequency * 1000; cmd.dvbs2_search.symbol_rate = p->symbol_rate; From fc9a89c8701d4db87a71332d2cdae5db10bc17e0 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 18 Mar 2021 10:44:11 +0100 Subject: [PATCH 17/22] add per demod lock for more fine-grained locking --- ddbridge/ddbridge-sx8.c | 112 ++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 50 deletions(-) diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index cf91cbe..27ee012 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -56,6 +56,7 @@ struct sx8_base { struct sx8 { struct mci mci; + struct mutex lock; int first_time_lock; int started; @@ -123,38 +124,45 @@ static int ddb_mci_tsconfig(struct mci *state, u32 config) static int read_status(struct dvb_frontend *fe, enum fe_status *status) { - int stat; + int stat = 0; struct sx8 *state = fe->demodulator_priv; struct mci_base *mci_base = state->mci.base; struct sx8_base *sx8_base = (struct sx8_base *) mci_base; struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct mci_result res; + *status = 0x00; + mutex_lock(&state->lock); + if (!state->started && !state->iq_started) + goto unlock; stat = ddb_mci_get_status(&state->mci, &res); if (stat) - return stat; - if (sx8_base->iq_mode >= 2) { - *status = 0x1f; - return stat; - } - *status = 0x00; + goto unlock; ddb_mci_get_info(&state->mci); - if (res.status == SX8_DEMOD_WAIT_MATYPE) - *status = 0x0f; - if (res.status == MCI_DEMOD_LOCKED) { - *status = 0x1f; - if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { + if (stat) + goto unlock; + if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) { + *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | + FE_HAS_CARRIER | FE_HAS_SIGNAL; + if (res.status == MCI_DEMOD_LOCKED) { mutex_lock(&mci_base->tuner_lock); - if (state->started) - sx8_base->used_ldpc_bitrate[state->mci.nr] = - p->symbol_rate * - dvbs2_bits_per_symbol[ - state->mci.signal_info. - dvbs2_signal_info.pls_code]; + if (state->first_time_lock && state->started) { + if (state->mci.signal_info.dvbs2_signal_info.standard == 2) { + sx8_base->used_ldpc_bitrate[state->mci.nr] = + p->symbol_rate * + dvbs2_bits_per_symbol[ + state->mci.signal_info. + dvbs2_signal_info.pls_code]; + } else + sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; + state->first_time_lock = 0; + } mutex_unlock(&mci_base->tuner_lock); - } else - sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; - } + } + else if (res.status >= SX8_DEMOD_WAIT_MATYPE) + *status = FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; +unlock: + mutex_unlock(&state->lock); return stat; } @@ -197,9 +205,9 @@ static int stop_iq(struct dvb_frontend *fe) state->mci.demod = SX8_DEMOD_NONE; } sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; + mutex_unlock(&mci_base->tuner_lock); sx8_base->iq_mode = 0; state->iq_started = 0; - mutex_unlock(&mci_base->tuner_lock); return 0; } @@ -209,12 +217,13 @@ static int stop(struct dvb_frontend *fe) struct mci_base *mci_base = state->mci.base; struct sx8_base *sx8_base = (struct sx8_base *) mci_base; struct mci_command cmd; - u32 input = state->mci.tuner; + u32 input; + input = state->mci.tuner; if (!state->started) return -1; - memset(&cmd, 0, sizeof(cmd)); if (state->mci.demod != SX8_DEMOD_NONE) { + memset(&cmd, 0, sizeof(cmd)); cmd.command = MCI_CMD_STOP; cmd.demod = state->mci.demod; ddb_mci_cmd(&state->mci, &cmd, NULL); @@ -236,8 +245,8 @@ static int stop(struct dvb_frontend *fe) } sx8_base->used_ldpc_bitrate[state->mci.nr] = 0; sx8_base->iq_mode = 0; - mutex_unlock(&mci_base->tuner_lock); state->started = 0; + mutex_unlock(&mci_base->tuner_lock); return 0; } @@ -308,16 +317,15 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) free_ldpc_bitrate = MAX_LDPC_BITRATE - used_ldpc_bitrate; if (free_ldpc_bitrate > MAX_DEMOD_LDPC_BITRATE) free_ldpc_bitrate = MAX_DEMOD_LDPC_BITRATE; - + while (p->symbol_rate * bits_per_symbol > free_ldpc_bitrate) bits_per_symbol--; if (bits_per_symbol < 2) { stat = -EBUSY; goto unlock; } - modmask &= ((1 << (bits_per_symbol - 1)) - 1); - if( ((flags & 0x02) != 0) && (modmask == 0)) { + if (((flags & 0x02) != 0) && (modmask == 0)) { stat = -EBUSY; goto unlock; } @@ -343,11 +351,10 @@ unlock: if (stat) return stat; memset(&cmd, 0, sizeof(cmd)); - if (sx8_base->iq_mode) { cmd.command = SX8_CMD_ENABLE_IQOUTPUT; cmd.demod = state->mci.demod; - cmd.output = p->stream_id & 7; + cmd.output = p->stream_id & 0x0f; ddb_mci_cmd(&state->mci, &cmd, NULL); ddb_mci_tsconfig(&state->mci, ts_config); } @@ -377,6 +384,9 @@ unlock: (p->stream_id & 0x80000000)) cmd.output |= 0x80; stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + state->started = 1; + state->first_time_lock = 1; + state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; if (stat) stop(fe); return stat; @@ -395,8 +405,8 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, u32 input = state->mci.tuner; int i, stat = 0; + mutex_lock(&mci_base->tuner_lock); if (!state->iq_started) { - mutex_lock(&mci_base->tuner_lock); if (sx8_base->iq_mode) { stat = -EBUSY; goto unlock; @@ -409,17 +419,18 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, goto unlock; } state->mci.demod = 0; - /* - if (!sx8_base->tuner_use_count[input]) - mci_set_tuner(fe, input, 1); - */ sx8_base->tuner_use_count[input]++; sx8_base->iq_mode = 2; - unlock: - mutex_unlock(&mci_base->tuner_lock); - if (stat) - return stat; + } else { + if ((state->iq_started & 0x07) != state->mci.nr) { + stat = -EBUSY; + goto unlock; + } } +unlock: + mutex_unlock(&mci_base->tuner_lock); + if (stat) + return stat; mci_set_tuner(fe, input, 1, flags & 0xff, 0); memset(&cmd, 0, sizeof(cmd)); cmd.command = SX8_CMD_START_IQ; @@ -431,6 +442,9 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, cmd.tuner = state->mci.tuner; cmd.demod = state->mci.demod; stat = ddb_mci_cmd(&state->mci, &cmd, NULL); + state->iq_started = 8 | state->mci.nr; + state->first_time_lock = 1; + state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; if (stat) stop_iq(fe); ddb_mci_tsconfig(&state->mci, ts_config); @@ -443,7 +457,6 @@ static int set_lna(struct dvb_frontend *fe) return 0; } - static int set_parameters(struct dvb_frontend *fe) { int stat = 0; @@ -459,6 +472,7 @@ static int set_parameters(struct dvb_frontend *fe) state->mci.input->con = ts_mode << 8; if (iq_mode) ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ); + mutex_lock(&state->lock); stop(fe); if (iq_mode < 2) { u32 mask; @@ -485,19 +499,10 @@ static int set_parameters(struct dvb_frontend *fe) break; } stat = start(fe, 3, mask, ts_config); - if (!stat) { - state->started = 1; - state->first_time_lock = 1; - state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; - } } else { stat = start_iq(fe, isi & 0xffffff, 4, ts_config); - if (!stat) { - state->iq_started = 1; - state->first_time_lock = 1; - state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL; - } } + mutex_unlock(&state->lock); return stat; } @@ -536,16 +541,22 @@ static int set_input(struct dvb_frontend *fe, int input) return -EINVAL; if (state->mci.tuner == input) return 0; + mutex_lock(&state->lock); stop_iq(fe); stop(fe); state->mci.tuner = p->input = input; + mutex_unlock(&state->lock); return 0; } static int sleep(struct dvb_frontend *fe) { + struct sx8 *state = fe->demodulator_priv; + + mutex_lock(&state->lock); stop_iq(fe); stop(fe); + mutex_unlock(&state->lock); return 0; } @@ -591,6 +602,7 @@ static int init(struct mci *mci) state->mci.demod = SX8_DEMOD_NONE; mci->fe.ops.xbar[1] = mci->nr; mci->fe.dtv_property_cache.input = mci->tuner; + mutex_init(&state->lock); return 0; } From dda86985145ba5eb5349033b1d01adf7d23cc325 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 18 Mar 2021 10:45:53 +0100 Subject: [PATCH 18/22] add timeout status --- ddbridge/ddbridge-sx8.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ddbridge/ddbridge-sx8.c b/ddbridge/ddbridge-sx8.c index 27ee012..d419573 100644 --- a/ddbridge/ddbridge-sx8.c +++ b/ddbridge/ddbridge-sx8.c @@ -159,6 +159,8 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status) } mutex_unlock(&mci_base->tuner_lock); } + } else if (res.status == MCI_DEMOD_TIMEOUT) + *status = FE_TIMEDOUT; else if (res.status >= SX8_DEMOD_WAIT_MATYPE) *status = FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; unlock: From 92cd675f5d5801979195100b7fdc21b49b50f239 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 18 Mar 2021 12:39:41 +0100 Subject: [PATCH 19/22] move ddbridge ioctls to separate file --- ddbridge/ddbridge-core.c | 71 +------------------------------------ ddbridge/ddbridge-ioctl.h | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 70 deletions(-) create mode 100644 ddbridge/ddbridge-ioctl.h diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index aeb6c08..4e6dc7f 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -24,6 +24,7 @@ #include "ddbridge.h" #include "ddbridge-i2c.h" #include "ddbridge-io.h" +#include "ddbridge-ioctl.h" #include struct workqueue_struct *ddb_wq; @@ -3187,76 +3188,6 @@ static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg, u32 mdio_base) return ddbreadl(dev, MDIO_VAL_OFF + mdio_base); } -#define DDB_MAGIC 'd' - -struct ddb_flashio { - __u8 *write_buf; - __u32 write_len; - __u8 *read_buf; - __u32 read_len; - __u32 link; -}; - -struct ddb_gpio { - __u32 mask; - __u32 data; -}; - -struct ddb_id { - __u16 vendor; - __u16 device; - __u16 subvendor; - __u16 subdevice; - __u32 hw; - __u32 regmap; -}; - -struct ddb_reg { - __u32 reg; - __u32 val; -}; - -struct ddb_mem { - __u32 off; - __u8 *buf; - __u32 len; -}; - -struct ddb_mdio { - __u8 adr; - __u8 reg; - __u16 val; -}; - -struct ddb_i2c_msg { - __u8 bus; - __u8 adr; - __u8 *hdr; - __u32 hlen; - __u8 *msg; - __u32 mlen; -}; - -struct ddb_mci_msg { - __u32 link; - struct mci_command cmd; - struct mci_result res; -}; - -#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) -#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) -#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) -#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id) -#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg) -#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg) -#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem) -#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem) -#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio) -#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) -#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg) -#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg) -#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg) - #define DDB_NAME "ddbridge" static u32 ddb_num; diff --git a/ddbridge/ddbridge-ioctl.h b/ddbridge/ddbridge-ioctl.h new file mode 100644 index 0000000..332008e --- /dev/null +++ b/ddbridge/ddbridge-ioctl.h @@ -0,0 +1,74 @@ +#ifndef _DDBRIDGE_IOCTL_H_ +#define _DDBRIDGE_IOCTL_H_ + +#define DDB_MAGIC 'd' + +struct ddb_flashio { + __u8 *write_buf; + __u32 write_len; + __u8 *read_buf; + __u32 read_len; + __u32 link; +}; + +struct ddb_gpio { + __u32 mask; + __u32 data; +}; + +struct ddb_id { + __u16 vendor; + __u16 device; + __u16 subvendor; + __u16 subdevice; + __u32 hw; + __u32 regmap; +}; + +struct ddb_reg { + __u32 reg; + __u32 val; +}; + +struct ddb_mem { + __u32 off; + __u8 *buf; + __u32 len; +}; + +struct ddb_mdio { + __u8 adr; + __u8 reg; + __u16 val; +}; + +struct ddb_i2c_msg { + __u8 bus; + __u8 adr; + __u8 *hdr; + __u32 hlen; + __u8 *msg; + __u32 mlen; +}; + +struct ddb_mci_msg { + __u32 link; + struct mci_command cmd; + struct mci_result res; +}; + +#define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) +#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) +#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) +#define IOCTL_DDB_ID _IOR(DDB_MAGIC, 0x03, struct ddb_id) +#define IOCTL_DDB_READ_REG _IOWR(DDB_MAGIC, 0x04, struct ddb_reg) +#define IOCTL_DDB_WRITE_REG _IOW(DDB_MAGIC, 0x05, struct ddb_reg) +#define IOCTL_DDB_READ_MEM _IOWR(DDB_MAGIC, 0x06, struct ddb_mem) +#define IOCTL_DDB_WRITE_MEM _IOR(DDB_MAGIC, 0x07, struct ddb_mem) +#define IOCTL_DDB_READ_MDIO _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio) +#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio) +#define IOCTL_DDB_READ_I2C _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg) +#define IOCTL_DDB_WRITE_I2C _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg) +#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg) + +#endif From e863a2037a531d9daba3080a5e2d7ee542dffd67 Mon Sep 17 00:00:00 2001 From: none Date: Thu, 18 Mar 2021 13:47:45 +0100 Subject: [PATCH 20/22] add byte array to union --- ddbridge/ddbridge-mci.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ddbridge/ddbridge-mci.h b/ddbridge/ddbridge-mci.h index 03e167b..8410ca4 100644 --- a/ddbridge/ddbridge-mci.h +++ b/ddbridge/ddbridge-mci.h @@ -359,6 +359,7 @@ struct mci_result { union { u32 result[27]; + u8 result8[27 * 4]; struct { u8 Rsvd0[3]; u8 Flags; From a6c3b82f833fce82d6c41523af07ef1d87be194a Mon Sep 17 00:00:00 2001 From: none Date: Thu, 18 Mar 2021 13:48:09 +0100 Subject: [PATCH 21/22] make include usable in user space --- ddbridge/ddbridge-mci.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ddbridge/ddbridge-mci.h b/ddbridge/ddbridge-mci.h index 8410ca4..d770a6d 100644 --- a/ddbridge/ddbridge-mci.h +++ b/ddbridge/ddbridge-mci.h @@ -759,6 +759,8 @@ struct mci_result { #define L1POST_STATIC_FLAG(p) (((p)[18] >> 1) & 0x01) #define L1POST_STATIC_PADDING_FLAG(p) (((p)[18] >> 1) & 0x01) +#ifdef __KERNEL__ + struct mci_base { struct list_head mci_list; void *key; @@ -802,5 +804,6 @@ int mci_cmd_val(struct ddb_link *link, uint32_t cmd, uint32_t val); extern struct mci_cfg ddb_max_sx8_cfg; extern struct mci_cfg ddb_max_m4_cfg; +#endif #endif From 91af1be97ea41a2f64b956d5f897827cdc2611db Mon Sep 17 00:00:00 2001 From: none Date: Thu, 18 Mar 2021 14:02:26 +0100 Subject: [PATCH 22/22] simple sx8 status info tool --- apps/sx8info.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 apps/sx8info.c diff --git a/apps/sx8info.c b/apps/sx8info.c new file mode 100644 index 0000000..029524c --- /dev/null +++ b/apps/sx8info.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint32_t u32; +typedef uint64_t u64; + +#include "../ddbridge/ddbridge-mci.h" +#include "../ddbridge/ddbridge-ioctl.h" + +char *Rolloff[8] = { + "0.35", + "0.25", + "0.20", + "0.10", + "0.05", + "0.15", + "rsvd", + "rsvd", +}; + +void print_info(struct mci_result *res) +{ + if (res->status == MCI_DEMOD_STOPPED) { + printf("Demod stopped\n"); + return; + } + + switch (res->mode) { + case 0: + case M4_MODE_DVBSX: + + if (res->dvbs2_signal_info.standard == 2) { + printf("PLS-Code: %u\n", res->dvbs2_signal_info.pls_code); + printf("Roll-Off: %s\n", Rolloff[res->dvbs2_signal_info.roll_off]); + printf("Inversion: %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off"); + printf("Frequency: %u Hz\n", res->dvbs2_signal_info.frequency); + printf("Symbol Rate: %u Symbols/s\n", res->dvbs2_signal_info.symbol_rate); + printf("Channel Power: %.2f dBm\n", (float) res->dvbs2_signal_info.channel_power / 100); + printf("Band Power: %.2f dBm\n", (float) res->dvbs2_signal_info.band_power / 100); + printf("SNR: %.2f dB\n", (float) res->dvbs2_signal_info.signal_to_noise / 100); + printf("Packet Errors: %u\n", res->dvbs2_signal_info.packet_errors); + printf("BER Numerator: %u\n", res->dvbs2_signal_info.ber_numerator); + printf("BER Denom.: %u\n", res->dvbs2_signal_info.ber_denominator); + printf("\n"); + } else { + + } + } +} + +int mci_info(int dev, uint8_t demod) +{ + struct ddb_mci_msg msg = { + .link = 0, + .cmd.command = MCI_CMD_GETSIGNALINFO, + .cmd.demod = demod + }; + int ret; + int i; + + ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); + if (ret < 0) { + printf("%d %d\n", ret, errno); + return ret; + } + + print_info(&msg.res); + return ret; +} + +int main(int argc, char*argv[]) +{ + int fd = -1; + char fn[128]; + uint32_t device = 0; + uint8_t demod = 0; + + while (1) { + int cur_optind = optind ? optind : 1; + int option_index = 0; + int c; + static struct option long_options[] = { + {"device", required_argument, 0, 'd'}, + {"demod", required_argument, 0, 'n'}, + {0, 0, 0, 0} + }; + c = getopt_long(argc, argv, "d:n:", + long_options, &option_index); + if (c == -1) + break; + switch (c) { + case 'd': + device = strtoul(optarg, NULL, 0); + break; + case 'n': + demod = strtoul(optarg, NULL, 0); + break; + default: + break; + } + } + if (optind < argc) { + printf("too many arguments\n"); + exit(1); + } + snprintf(fn, 127, "/dev/ddbridge/card%u", device); + fd = open(fn, O_RDWR); + if (fd < 0) + return -1; + mci_info(fd, demod); +}