From e52384b80d02d6a726dca9f1f343ec6098126c95 Mon Sep 17 00:00:00 2001 From: Joakim Hernberg Date: Wed, 10 Oct 2012 14:24:15 +0200 Subject: [PATCH] [PR-161] Add support for DiSEqC repeat and up to 64 lnbs. Fixes #1319. --- docs/html/config_dvb.html | 4 ++ src/dvb/diseqc.c | 106 ++++++++++++++++++------------------ src/dvb/diseqc.h | 5 +- src/dvb/dvb.h | 6 +- src/dvb/dvb_adapter.c | 17 ++++++ src/dvb/dvb_fe.c | 12 ++-- src/webui/extjs_dvb.c | 11 ++++ src/webui/static/app/dvb.js | 18 +++++- 8 files changed, 115 insertions(+), 64 deletions(-) diff --git a/docs/html/config_dvb.html b/docs/html/config_dvb.html index 5ef40f06..a772da80 100644 --- a/docs/html/config_dvb.html +++ b/docs/html/config_dvb.html @@ -257,6 +257,10 @@
Switchport
Port number to select for this configuration (numbering begins at 0). +
In DiSEqC 1.0/2.0 mode, ports 0-3 are valid. +
In DiSEqC 1.1/2.1 mode, ports 0-63 are valid. +
Use numbers 0-3 for LNBs behind first input on the uncommited switch, + then 4-7 and so on to support up to 64 ports using DiSEqC 1.1/2.1.
LNB type
Select the LNB type from the list of supported LNBs. If your LNB diff --git a/src/dvb/diseqc.c b/src/dvb/diseqc.c index f4468588..1c49ff22 100644 --- a/src/dvb/diseqc.c +++ b/src/dvb/diseqc.c @@ -5,34 +5,6 @@ #include "tvheadend.h" #include "diseqc.h" -//#define DISEQC_TRACE - -struct dvb_diseqc_master_cmd diseqc_commited_cmds[] = { - { { 0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf1, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf2, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf3, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf4, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf5, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf6, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf7, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf8, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xf9, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xfa, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xfb, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xfc, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xfd, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xfe, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x38, 0xff, 0x00, 0x00 }, 4 } -}; - -struct dvb_diseqc_master_cmd diseqc_uncommited_cmds[] = { - { { 0xe0, 0x10, 0x39, 0xf0, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x39, 0xf1, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x39, 0xf2, 0x00, 0x00 }, 4 }, - { { 0xe0, 0x10, 0x39, 0xf3, 0x00, 0x00 }, 4 } -}; - /*--------------------------------------------------------------------------*/ static inline void @@ -45,19 +17,42 @@ msleep(uint32_t msec) } int -diseqc_setup(int fe_fd, int input, int voltage, int band, int diseqc_ver) +diseqc_send_msg(int fe_fd, __u8 framing_byte, __u8 address, __u8 cmd, + __u8 data_1, __u8 data_2, __u8 data_3, __u8 msg_len) { - int i = (input % 4) * 4 + voltage * 2 + (band ? 1 : 0); - int j = input / 4; - int err; + struct dvb_diseqc_master_cmd message; -#ifdef DISEQC_TRACE - tvhlog(LOG_INFO, "diseqc", - "fe_fd %i, input %i, voltage %i, band %i, diseqc_ver %i, i %i, j %i", - fe_fd, input, voltage, band, diseqc_ver, i, j); +#if DISEQC_TRACE + tvhlog(LOG_DEBUG, "diseqc", "sending %X %X %X %X %X %X", + framing_byte, address, cmd, data_1, data_2, data_3); #endif - /* check for invalid input number or diseqc command indexes */ - if(input < 0 || input >=16 || i < 0 || i >= 16 || j < 0 || j >= 4) + + message.msg[0] = framing_byte; + message.msg[1] = address; + message.msg[2] = cmd; + message.msg[3] = data_1; + message.msg[4] = data_2; + message.msg[5] = data_3; + message.msg_len = msg_len; + return ioctl(fe_fd, FE_DISEQC_SEND_MASTER_CMD, &message); +} + +int +diseqc_setup(int fe_fd, int lnb_num, int voltage, int band, + uint32_t version, uint32_t repeats) +{ + int i = (lnb_num % 4) * 4 + voltage * 2 + (band ? 1 : 0); + int j = lnb_num / 4; + int k, err; + +#if DISEQC_TRACE + tvhlog(LOG_DEBUG, "diseqc", + "fe_fd %i, lnb_num %i, voltage %i, band %i, version %i, repeats %i", + fe_fd, lnb_num, voltage, band, version, repeats); +#endif + + /* verify lnb number and diseqc data */ + if(lnb_num < 0 || lnb_num >=64 || i < 0 || i >= 16 || j < 0 || j >= 16) return -1; /* turn off continuous tone */ @@ -70,29 +65,34 @@ diseqc_setup(int fe_fd, int input, int voltage, int band, int diseqc_ver) return err; msleep(15); - /* send uncommited command */ - if ((err = ioctl(fe_fd, FE_DISEQC_SEND_MASTER_CMD, - &diseqc_uncommited_cmds[j]))) - return err; + if (repeats == 0) { /* uncommited msg, wait 15ms, commited msg */ + if ((err = diseqc_send_msg(fe_fd, 0xE0, 0x10, 0x39, 0xF0 | j, 0, 0, 4))) + return err; + msleep(15); + if ((err = diseqc_send_msg(fe_fd, 0xE0, 0x10, 0x38, 0xF0 | i, 0, 0, 4))) + return err; + } else { /* commited msg, 25ms, uncommited msg, 25ms, commited msg, etc */ + if ((err = diseqc_send_msg(fe_fd, 0xE0, 0x10, 0x38, 0xF0 | i, 0, 0, 4))) + return err; + for (k = 0; k < repeats; k++) { + msleep(25); + if ((err = diseqc_send_msg(fe_fd, 0xE0, 0x10, 0x39, 0xF0 | j, 0, 0, 4))) + return err; + msleep(25); + if ((err = diseqc_send_msg(fe_fd, 0xE1, 0x10, 0x38, 0xF0 | i, 0, 0, 4))) + return err; + } + } msleep(15); - /* send commited command */ - if ((err = ioctl(fe_fd, FE_DISEQC_SEND_MASTER_CMD, - &diseqc_commited_cmds[i]))) - return err; -#ifdef DISEQC_TRACE - tvhlog(LOG_INFO, "diseqc", "E0 10 39 F%X - E0 10 38 F%X sent", j, i); -#endif - msleep(15); - - /* send toneburst command */ + /* set toneburst */ if ((err = ioctl(fe_fd, FE_DISEQC_SEND_BURST, (i/4) % 2 ? SEC_MINI_B : SEC_MINI_A))) return err; msleep(15); /* set continuous tone */ - if ((ioctl(fe_fd, FE_SET_TONE, i % 2 ? SEC_TONE_ON : SEC_TONE_OFF))) + if ((err = ioctl(fe_fd, FE_SET_TONE, i % 2 ? SEC_TONE_ON : SEC_TONE_OFF))) return err; return 0; } diff --git a/src/dvb/diseqc.h b/src/dvb/diseqc.h index fdabb6df..852a7948 100644 --- a/src/dvb/diseqc.h +++ b/src/dvb/diseqc.h @@ -7,7 +7,10 @@ /** * set up the switch to position/voltage/tone */ -int diseqc_setup(int fe_fd, int input, int voltage, int band, int diseqc_ver); +int diseqc_send_msg(int fe_fd, __u8 framing_byte, __u8 address, __u8 cmd, + __u8 data_1, __u8 data_2, __u8 data_3, __u8 msg_len); +int diseqc_setup(int fe_fd, int lnb_num, int voltage, int band, + uint32_t version, uint32_t repeats); int diseqc_voltage_off(int fe_fd); #endif diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 60258e7c..25e2ea2a 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -42,7 +42,7 @@ TAILQ_HEAD(dvb_satconf_queue, dvb_satconf); typedef struct dvb_satconf { char *sc_id; TAILQ_ENTRY(dvb_satconf) sc_adapter_link; - int sc_port; // diseqc switchport (0 - 15) + int sc_port; // diseqc switchport (0 - 63) char *sc_name; char *sc_comment; @@ -185,6 +185,7 @@ typedef struct th_dvb_adapter { uint32_t tda_sidtochan; uint32_t tda_nitoid; uint32_t tda_diseqc_version; + uint32_t tda_diseqc_repeats; uint32_t tda_disable_pmt_monitor; char *tda_displayname; @@ -314,6 +315,9 @@ void dvb_adapter_set_nitoid(th_dvb_adapter_t *tda, int nitoid); void dvb_adapter_set_diseqc_version(th_dvb_adapter_t *tda, unsigned int v); +void dvb_adapter_set_diseqc_repeats(th_dvb_adapter_t *tda, + unsigned int repeats); + void dvb_adapter_set_disable_pmt_monitor(th_dvb_adapter_t *tda, int on); void dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src); diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index 6fc42092..ee9e8d49 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -93,6 +93,7 @@ tda_save(th_dvb_adapter_t *tda) htsmsg_add_u32(m, "poweroff", tda->tda_poweroff); htsmsg_add_u32(m, "nitoid", tda->tda_nitoid); htsmsg_add_u32(m, "diseqc_version", tda->tda_diseqc_version); + htsmsg_add_u32(m, "diseqc_repeats", tda->tda_diseqc_repeats); htsmsg_add_u32(m, "extrapriority", tda->tda_extrapriority); htsmsg_add_u32(m, "skip_initialscan", tda->tda_skip_initialscan); htsmsg_add_u32(m, "disable_pmt_monitor", tda->tda_disable_pmt_monitor); @@ -333,6 +334,21 @@ dvb_adapter_set_diseqc_version(th_dvb_adapter_t *tda, unsigned int v) tda_save(tda); } +/** + * sets the number of diseqc repeats to perform + */ +void +dvb_adapter_set_diseqc_repeats(th_dvb_adapter_t *tda, unsigned int repeats) +{ + if(tda->tda_diseqc_repeats == repeats) + return; + lock_assert(&global_lock); + tvhlog(LOG_NOTICE, "dvb", "Adapter \"%s\" DiSEqC repeats set to: %i", + tda->tda_displayname, repeats); + tda->tda_diseqc_repeats = repeats; + tda_save(tda); +} + /** * */ @@ -572,6 +588,7 @@ dvb_adapter_init(uint32_t adapter_mask) htsmsg_get_u32(c, "poweroff", &tda->tda_poweroff); htsmsg_get_u32(c, "nitoid", &tda->tda_nitoid); htsmsg_get_u32(c, "diseqc_version", &tda->tda_diseqc_version); + htsmsg_get_u32(c, "diseqc_repeats", &tda->tda_diseqc_repeats); htsmsg_get_u32(c, "extrapriority", &tda->tda_extrapriority); htsmsg_get_u32(c, "skip_initialscan", &tda->tda_skip_initialscan); htsmsg_get_u32(c, "disable_pmt_monitor", &tda->tda_disable_pmt_monitor); diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 97536abe..4830e2fc 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -507,13 +507,13 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) p->frequency = abs(p->frequency - lowfreq); } - if ((r = diseqc_setup(tda->tda_fe_fd, - port, - pol == POLARISATION_HORIZONTAL || - pol == POLARISATION_CIRCULAR_LEFT, - hiband, tda->tda_diseqc_version)) != 0) + if ((r = diseqc_setup(tda->tda_fe_fd, port, + pol == POLARISATION_HORIZONTAL || + pol == POLARISATION_CIRCULAR_LEFT, + hiband, tda->tda_diseqc_version, + tda->tda_diseqc_repeats)) != 0) tvhlog(LOG_ERR, "dvb", "diseqc setup failed %d\n", r); - } + } dvb_mux_nicename(buf, sizeof(buf), tdmi); diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 94adc399..59760abf 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -162,6 +162,9 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) ((const char *[]){"DiSEqC 1.0 / 2.0", "DiSEqC 1.1 / 2.1"}) [tda->tda_diseqc_version % 2]); + htsmsg_add_str(r, "diseqcrepeats", + ((const char *[]){"0", "1", "3"}) + [tda->tda_diseqc_repeats % 3]); htsmsg_add_u32(r, "extrapriority", tda->tda_extrapriority); out = json_single_record(r, "dvbadapters"); @@ -210,6 +213,14 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) dvb_adapter_set_diseqc_version(tda, 1); } + if((s = http_arg_get(&hc->hc_req_args, "diseqcrepeats")) != NULL) { + if(!strcmp(s, "0")) + dvb_adapter_set_diseqc_repeats(tda, 0); + else if(!strcmp(s, "1")) + dvb_adapter_set_diseqc_repeats(tda, 1); + else if(!strcmp(s, "2")) + dvb_adapter_set_diseqc_repeats(tda, 2); + } if((s = http_arg_get(&hc->hc_req_args, "extrapriority")) != NULL) dvb_adapter_set_extrapriority(tda, atoi(s)); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index a71e7ebb..5667e6f1 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -1087,8 +1087,9 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { var confreader = new Ext.data.JsonReader({ root : 'dvbadapters' }, [ 'name', 'automux', 'skip_initialscan', 'idlescan', 'diseqcversion', - 'qmon', 'skip_checksubscr', 'dumpmux', 'poweroff', 'sidtochan', 'nitoid', - 'extrapriority', 'disable_pmt_monitor', 'idleclose' ]); + 'diseqcrepeats', 'qmon', 'skip_checksubscr', 'dumpmux', + 'poweroff', 'sidtochan', 'nitoid', 'extrapriority', + ,'disable_pmt_monitor', 'idleclose' ]); function saveConfForm() { confform.getForm().submit({ @@ -1169,6 +1170,17 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { }); items.push(v); + v = new Ext.form.ComboBox({ + name : 'diseqcrepeats', + fieldLabel : 'DiSEqC repeats', + editable : false, + allowBlank : false, + mode : 'remote', + triggerAction : 'all', + store : [ '0', '1', '2' ] + }); + items.push(v); + v = new Ext.form.Checkbox({ fieldLabel : 'Turn off LNB when idle', name : 'poweroff' @@ -1293,7 +1305,7 @@ tvheadend.dvb_satconf = function(adapterId, lnbStore) { dataIndex : 'port', editor : new fm.NumberField({ minValue : 0, - maxValue : 15 + maxValue : 63 }) }, { header : "LNB type",