From 66c6d85f39e2a75f1c8f28e05681e6efebf6866d Mon Sep 17 00:00:00 2001 From: InuSasha Date: Sun, 5 Jan 2014 17:54:49 +0100 Subject: [PATCH 01/11] EN50494: first commit - works with same hardcoded values (needs to setup) - setup via gui is missing --- .gitignore | 1 + Makefile | 3 +- src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 274 +++++++++++++++++++ src/input/mpegts/linuxdvb/linuxdvb_private.h | 17 +- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 106 ++++++- 5 files changed, 380 insertions(+), 21 deletions(-) create mode 100644 src/input/mpegts/linuxdvb/linuxdvb_en50494.c diff --git a/.gitignore b/.gitignore index 217c9961..949dbf66 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ debian/tvheadend debian/tvheadend-dbg debian/tvheadend*substvars debian/tvheadend*.debhelper* +/etc diff --git a/Makefile b/Makefile index 5d7bfb19..a2e5c65c 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ PROG := $(BUILDDIR)/tvheadend CFLAGS += -Wall -Werror -Wwrite-strings -Wno-deprecated-declarations CFLAGS += -Wmissing-prototypes -fms-extensions -CFLAGS += -g -funsigned-char -O2 +CFLAGS += -g -funsigned-char CFLAGS += -D_FILE_OFFSET_BITS=64 CFLAGS += -I${BUILDDIR} -I${ROOTDIR}/src -I${ROOTDIR} LDFLAGS += -lrt -ldl -lpthread -lm @@ -195,6 +195,7 @@ SRCS-${CONFIG_LINUXDVB} += \ src/input/mpegts/linuxdvb/linuxdvb_lnb.c \ src/input/mpegts/linuxdvb/linuxdvb_switch.c \ src/input/mpegts/linuxdvb/linuxdvb_rotor.c \ + src/input/mpegts/linuxdvb/linuxdvb_en50494.c \ src/input/mpegts/linuxdvb/scanfile.c \ # IPTV diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c new file mode 100644 index 00000000..fe073707 --- /dev/null +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -0,0 +1,274 @@ +/* + * Tvheadend - Linux DVB EN50494 + * (known under trademark "UniCable") + * + * Copyright (C) 2013 Sascha "InuSasha" Kuehndel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Open things: + * - make linuxdvb_en50494_tune thread safe + * avoiding self-raised collisions + * - collision dectection + * when a diseqc-command wasn't executed succesful, retry. + * delay time is easly random, but in standard is special (complicated) way described (cap 8). + */ + +#include "tvheadend.h" +#include "linuxdvb_private.h" +#include "settings.h" + +#include +#include + +/* ************************************************************************** + * Static definition + * *************************************************************************/ +#define LINUXDVB_EN50494_NAME "en50494" + +#define LINUXDVB_EN50494_NOPIN 256 + +#define LINUXDVB_EN50494_FRAME 0xE0 +/* adresses 0x00, 0x10 and 0x11 are possible */ +#define LINUXDVB_EN50494_ADDRESS 0x10 + +#define LINUXDVB_EN50494_CMD_NORMAL 0x5A +#define LINUXDVB_EN50494_CMD_NORMAL_MULTIHOME 0x5C +/* special modes not implemented yet */ +#define LINUXDVB_EN50494_CMD_SPECIAL 0x5B +#define LINUXDVB_EN50494_CMD_SPECIAL_MULTIHOME 0x5D + +#define LINUXDVB_EN50494_SAT_A 0x00 +#define LINUXDVB_EN50494_SAT_B 0x01 + + +/* ************************************************************************** + * Class definition + * *************************************************************************/ + +typedef struct linuxdvb_en50494 +{ + linuxdvb_diseqc_t; + + /* en50494 configuration*/ + uint8_t le_position; /* satelitte A(0) or B(1) */ + uint16_t le_frequency; /* user band frequency in MHz */ + uint8_t le_id; /* user band id 0-7 */ + uint16_t le_pin; /* 0-255 or LINUXDVB_EN50494_NOPIN */ + + /* runtime */ + uint32_t (*lnb_freq)(linuxdvb_lnb_t*, linuxdvb_mux_t*); + +} linuxdvb_en50494_t; + +static const char * +linuxdvb_en50494_class_get_title ( idnode_t *o ) +{ + static char buf[256]; + linuxdvb_diseqc_t *ld = (linuxdvb_diseqc_t*)o; + snprintf(buf, sizeof(buf), "%s: %s", LINUXDVB_EN50494_NAME, ld->ld_type); + return buf; +} + +static htsmsg_t * +linuxdvb_en50494_class_position_list ( void *o ) +{ + htsmsg_t *m = htsmsg_create_list(); + htsmsg_add_u32(m, NULL, LINUXDVB_EN50494_SAT_A); + htsmsg_add_u32(m, NULL, LINUXDVB_EN50494_SAT_B); + return m; +} + +static htsmsg_t * +linuxdvb_en50494_class_id_list ( void *o ) +{ + uint32_t i; + + htsmsg_t *m = htsmsg_create_list(); + for (i = 0; i < 8; i++) { + htsmsg_add_u32(m, NULL, i); + } + return m; +} + +static htsmsg_t * +linuxdvb_en50494_class_pin_list ( void *o ) +{ + int32_t i; + + htsmsg_t *m = htsmsg_create_list(); + for (i = -1; i < 256; i++) { + htsmsg_add_s32(m, NULL, i); + } + return m; +} + +extern const idclass_t linuxdvb_diseqc_class; +const idclass_t linuxdvb_en50494_class = +{ + .ic_super = &linuxdvb_diseqc_class, + .ic_class = "linuxdvb_en50494", + .ic_caption = LINUXDVB_EN50494_NAME, + .ic_get_title = linuxdvb_en50494_class_get_title, + .ic_properties = (const property_t[]) { + { + .type = PT_INT, + .id = "position", + .name = "Position", + .off = offsetof(linuxdvb_en50494_t, le_position), + .list = linuxdvb_en50494_class_position_list + }, + { + .type = PT_INT, + .id = "frequency", + .name = "Frequency", + .off = offsetof(linuxdvb_en50494_t, le_frequency), + }, + { + .type = PT_INT, + .id = "id", + .name = "ID", + .off = offsetof(linuxdvb_en50494_t, le_id), + .list = linuxdvb_en50494_class_id_list + }, + { + .type = PT_INT, + .id = "pin", + .name = "Pin", + .off = offsetof(linuxdvb_en50494_t, le_pin), + .list = linuxdvb_en50494_class_pin_list + }, + {} + } +}; + + +/* ************************************************************************** + * Class methods + * *************************************************************************/ + +static int +linuxdvb_en50494_tune + ( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *sc, int fd ) +{ + int ret = 0; + linuxdvb_en50494_t *le = (linuxdvb_en50494_t*) ld; + linuxdvb_lnb_t *lnb = sc->ls_lnb; + + /* band & polarisation */ + uint8_t pol = lnb->lnb_pol(lnb, lm); + uint8_t band = lnb->lnb_band(lnb, lm); + uint32_t freq = lnb->lnb_freq(lnb, lm); + + /* transponder value - t*/ + uint16_t t = round((( (freq / 1000) + 2 + le->le_frequency) / 4) - 350); + if ( t > 1024) { + tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "transponder value bigger then 1024"); + return -1; + } +// uint32_t tunefreq = (t + 350) * 4000 - freq; /* real used en50494 frequency */ + + /* 2 data fields (16bit) */ + uint8_t data1, data2; + data1 = le->le_id << 5; /* 3bit user-band */ + data1 |= le->le_position << 4; /* 1bit position (satelitte A(0)/B(0)) */ + data1 |= pol << 3; /* 1bit polarisation v(0)/h(1) */ + data1 |= band << 2; /* 1bit band lower(0)/upper(1) */ + data1 |= t >> 8; /* 2bit transponder value bit 1-2 */ + data2 = t & 0xFF; /* 8bit transponder value bit 3-10 */ + tvhlog(LOG_INFO, LINUXDVB_EN50494_NAME, + "lnb=%i, id=%i, freq=%i, pin=%i, v/h=%i, l/u=%i, f=%i, data=0x%02X%02X", + le->le_position, le->le_id, le->le_frequency, le->le_pin, pol, band, freq, data1, data2); + + /* use 18V */ + if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_18)) { + tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "error setting lnb voltage to 18V"); + return -1; + } + usleep(15000); /* standard: 4ms < x < 22ms */ + + /* send tune command (with/with pin) */ + if (le->le_pin != LINUXDVB_EN50494_NOPIN) { + ret = linuxdvb_diseqc_send(fd, + LINUXDVB_EN50494_FRAME, + LINUXDVB_EN50494_ADDRESS, + LINUXDVB_EN50494_CMD_NORMAL_MULTIHOME, + 3, + data1, data2, (uint8_t)le->le_pin); + } else { + ret = linuxdvb_diseqc_send(fd, + LINUXDVB_EN50494_FRAME, + LINUXDVB_EN50494_ADDRESS, + LINUXDVB_EN50494_CMD_NORMAL, + 2, + data1, data2); + } + if (ret != 0) { + tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "error send tune command"); + return -1; + } + usleep(50000); /* standard: 2ms < x < 60ms */ + + /* return to 13V */ + if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_13)) { + tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "error setting lnb voltage back to 13V"); + return -1; + } + + return 0; +} + + +/* ************************************************************************** + * Create / Config + * *************************************************************************/ + +htsmsg_t * +linuxdvb_en50494_list ( void *o ) +{ + htsmsg_t *m = htsmsg_create_list(); + htsmsg_add_str(m, NULL, "None"); + htsmsg_add_str(m, NULL, "EN50494/UniCable"); + return m; +} + +linuxdvb_diseqc_t * +linuxdvb_en50494_create0 + ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls) +{ + linuxdvb_diseqc_t *ld; +// linuxdvb_en50494_t *le; + + ld = linuxdvb_diseqc_create0( + calloc(1, sizeof(linuxdvb_en50494_t)), + NULL, + &linuxdvb_en50494_class, + conf, + LINUXDVB_EN50494_NAME, + ls); +// le = (linuxdvb_en50494_t*)ld; + if (ld) { + ld->ld_tune = linuxdvb_en50494_tune; + /* May not needed: ld->ld_grace = linuxdvb_en50494_grace; */ + } + + return (linuxdvb_diseqc_t*)ld; +} + +void +linuxdvb_en50494_destroy ( linuxdvb_diseqc_t *le ) +{ + linuxdvb_diseqc_destroy(le); + free(le); +} diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index 06a44fff..35683d78 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -199,6 +199,7 @@ struct linuxdvb_satconf_ele linuxdvb_lnb_t *ls_lnb; linuxdvb_diseqc_t *ls_switch; linuxdvb_diseqc_t *ls_rotor; + linuxdvb_diseqc_t *ls_en50494; }; struct linuxdvb_diseqc @@ -329,14 +330,18 @@ linuxdvb_diseqc_t *linuxdvb_switch_create0 ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls, int u, int c ); linuxdvb_diseqc_t *linuxdvb_rotor_create0 ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls ); +linuxdvb_diseqc_t *linuxdvb_en50494_create0 + ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls ); -void linuxdvb_lnb_destroy ( linuxdvb_lnb_t *lnb ); -void linuxdvb_switch_destroy ( linuxdvb_diseqc_t *ld ); -void linuxdvb_rotor_destroy ( linuxdvb_diseqc_t *ld ); +void linuxdvb_lnb_destroy ( linuxdvb_lnb_t *lnb ); +void linuxdvb_switch_destroy ( linuxdvb_diseqc_t *ld ); +void linuxdvb_rotor_destroy ( linuxdvb_diseqc_t *ld ); +void linuxdvb_en50494_destroy ( linuxdvb_diseqc_t *ld ); -htsmsg_t *linuxdvb_lnb_list ( void *o ); -htsmsg_t *linuxdvb_switch_list ( void *o ); -htsmsg_t *linuxdvb_rotor_list ( void *o ); +htsmsg_t *linuxdvb_lnb_list ( void *o ); +htsmsg_t *linuxdvb_switch_list ( void *o ); +htsmsg_t *linuxdvb_rotor_list ( void *o ); +htsmsg_t *linuxdvb_en50494_list ( void *o ); int linuxdvb_diseqc_send diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index 99fbaeed..de1b1bbd 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -209,7 +209,7 @@ const idclass_t linuxdvb_satconf_lnbonly_class = .type = PT_STR, .id = "network", .name = "Network", - .get = linuxdvb_satconf_class_network_get0, + .get = linuxdvb_satconf_class_network_get0, .set = linuxdvb_satconf_class_network_set0, .list = linuxdvb_satconf_ele_class_network_enum, .opts = PO_NOSAVE, @@ -231,7 +231,7 @@ const idclass_t linuxdvb_satconf_2port_class = .type = PT_STR, .id = "network_a", .name = "A", - .get = linuxdvb_satconf_class_network_get0, + .get = linuxdvb_satconf_class_network_get0, .set = linuxdvb_satconf_class_network_set0, .list = linuxdvb_satconf_ele_class_network_enum, .opts = PO_NOSAVE, @@ -240,7 +240,7 @@ const idclass_t linuxdvb_satconf_2port_class = .type = PT_STR, .id = "network_b", .name = "B", - .get = linuxdvb_satconf_class_network_get1, + .get = linuxdvb_satconf_class_network_get1, .set = linuxdvb_satconf_class_network_set1, .list = linuxdvb_satconf_ele_class_network_enum, .opts = PO_NOSAVE, @@ -262,7 +262,7 @@ const idclass_t linuxdvb_satconf_4port_class = .type = PT_STR, .id = "network_aa", .name = "AA", - .get = linuxdvb_satconf_class_network_get0, + .get = linuxdvb_satconf_class_network_get0, .set = linuxdvb_satconf_class_network_set0, .list = linuxdvb_satconf_ele_class_network_enum, .opts = PO_NOSAVE, @@ -271,7 +271,7 @@ const idclass_t linuxdvb_satconf_4port_class = .type = PT_STR, .id = "network_ab", .name = "AB", - .get = linuxdvb_satconf_class_network_get1, + .get = linuxdvb_satconf_class_network_get1, .set = linuxdvb_satconf_class_network_set1, .list = linuxdvb_satconf_ele_class_network_enum, .opts = PO_NOSAVE, @@ -280,7 +280,7 @@ const idclass_t linuxdvb_satconf_4port_class = .type = PT_STR, .id = "network_ba", .name = "BA", - .get = linuxdvb_satconf_class_network_get2, + .get = linuxdvb_satconf_class_network_get2, .set = linuxdvb_satconf_class_network_set2, .list = linuxdvb_satconf_ele_class_network_enum, .opts = PO_NOSAVE, @@ -289,7 +289,7 @@ const idclass_t linuxdvb_satconf_4port_class = .type = PT_STR, .id = "network_bb", .name = "BB", - .get = linuxdvb_satconf_class_network_get3, + .get = linuxdvb_satconf_class_network_get3, .set = linuxdvb_satconf_class_network_set3, .list = linuxdvb_satconf_ele_class_network_enum, .opts = PO_NOSAVE, @@ -298,6 +298,37 @@ const idclass_t linuxdvb_satconf_4port_class = } }; +/* + * en50494 + */ +const idclass_t linuxdvb_satconf_en50494_class = +{ + .ic_super = &linuxdvb_satconf_class, + .ic_class = "linuxdvb_satconf_en50494", + .ic_caption = "DVB-S EN50494 (UniCable)", + .ic_properties = (const property_t[]) { + { + .type = PT_STR, + .id = "network_a", + .name = "Network A", + .get = linuxdvb_satconf_class_network_get0, + .set = linuxdvb_satconf_class_network_set0, + .list = linuxdvb_satconf_ele_class_network_enum, + .opts = PO_NOSAVE, + }, + { + .type = PT_STR, + .id = "network_b", + .name = "Netwotk B", + .get = linuxdvb_satconf_class_network_get1, + .set = linuxdvb_satconf_class_network_set1, + .list = linuxdvb_satconf_ele_class_network_enum, + .opts = PO_NOSAVE, + }, + {} + } +}; + /* * Advanced */ @@ -344,6 +375,12 @@ static struct linuxdvb_satconf_type linuxdvb_satconf_types[] = { .idc = &linuxdvb_satconf_4port_class, .ports = 4, }, + { + .type = "en50494", + .name = "EN50494/UniCable Switch (Universal LNB)", + .idc = &linuxdvb_satconf_en50494_class, + .ports = 2, + }, { .type = "advanced", .name = "Advanced", @@ -566,6 +603,26 @@ linuxdvb_satconf_ele_class_lnbtype_get ( void *o ) return &s; } +static int +linuxdvb_satconf_ele_class_en50494type_set ( void *o, const void *p ) +{ + linuxdvb_satconf_ele_t *ls = o; + const char *str = p; + if (ls->ls_en50494) + linuxdvb_en50494_destroy(ls->ls_en50494); + ls->ls_en50494 = linuxdvb_en50494_create0(str, NULL, ls); + return 1; +} + +static const void * +linuxdvb_satconf_ele_class_en50494type_get ( void *o ) +{ + static const char *s; + linuxdvb_satconf_ele_t *ls = o; + s = ls->ls_en50494 ? ls->ls_en50494->ld_type : NULL; + return &s; +} + static int linuxdvb_satconf_ele_class_switchtype_set ( void *o, const void *p ) { @@ -631,6 +688,8 @@ linuxdvb_satconf_ele_class_get_childs ( idnode_t *o ) idnode_set_add(is, &ls->ls_switch->ld_id, NULL); if (ls->ls_rotor) idnode_set_add(is, &ls->ls_rotor->ld_id, NULL); + if (ls->ls_en50494) + idnode_set_add(is, &ls->ls_en50494->ld_id, NULL); return is; } @@ -661,8 +720,8 @@ const idclass_t linuxdvb_satconf_ele_class = .type = PT_STR, .id = "network", .name = "Network", - .get = linuxdvb_satconf_ele_class_network_get, - .set = linuxdvb_satconf_ele_class_network_set, + .get = linuxdvb_satconf_ele_class_network_get, + .set = linuxdvb_satconf_ele_class_network_set, .list = linuxdvb_satconf_ele_class_network_enum, .rend = linuxdvb_satconf_ele_class_network_rend, }, @@ -693,6 +752,15 @@ const idclass_t linuxdvb_satconf_ele_class = .list = linuxdvb_rotor_list, .def.s = "None", }, + { + .type = PT_STR, + .id = "en50494_type", + .name = "EN50494 Type", + .set = linuxdvb_satconf_ele_class_en50494type_set, + .get = linuxdvb_satconf_ele_class_en50494type_get, + .list = linuxdvb_en50494_list, + .def.s = "None", + }, {} } }; @@ -760,6 +828,7 @@ linuxdvb_satconf_ele_tune ( linuxdvb_satconf_ele_t *lse ) lse->ls_rotor ? (linuxdvb_diseqc_t*)lse->ls_switch : NULL, (linuxdvb_diseqc_t*)lse->ls_rotor, (linuxdvb_diseqc_t*)lse->ls_switch, + (linuxdvb_diseqc_t*)lse->ls_en50494, (linuxdvb_diseqc_t*)lse->ls_lnb }; // TODO: really need to understand whether or not we need to pre configure @@ -798,7 +867,8 @@ linuxdvb_satconf_ele_tune ( linuxdvb_satconf_ele_t *lse ) usleep(20000); // Allow LNB to settle before tuning /* Frontend */ - f = lse->ls_lnb->lnb_freq(lse->ls_lnb, lm); + // TODO: get en50494 tuning frequency, not channel frequency + f = 2040500;// lse->ls_lnb->lnb_freq(lse->ls_lnb, lm); return linuxdvb_frontend_tune1(lfe, mmi, f); } @@ -891,6 +961,7 @@ linuxdvb_satconf_ele_get_grace linuxdvb_satconf_ele_t *lse = (linuxdvb_satconf_ele_t*)mi; linuxdvb_satconf_t *ls = lse->ls_parent; linuxdvb_diseqc_t *lds[] = { + (linuxdvb_diseqc_t*)lse->ls_en50494, (linuxdvb_diseqc_t*)lse->ls_switch, (linuxdvb_diseqc_t*)lse->ls_rotor, (linuxdvb_diseqc_t*)lse->ls_lnb @@ -928,9 +999,10 @@ void linuxdvb_satconf_ele_destroy ( linuxdvb_satconf_ele_t *ls ) { TAILQ_REMOVE(&ls->ls_parent->ls_elements, ls, ls_link); - if (ls->ls_lnb) linuxdvb_lnb_destroy(ls->ls_lnb); - if (ls->ls_switch) linuxdvb_switch_destroy(ls->ls_switch); - if (ls->ls_rotor) linuxdvb_rotor_destroy(ls->ls_rotor); + if (ls->ls_lnb) linuxdvb_lnb_destroy(ls->ls_lnb); + if (ls->ls_switch) linuxdvb_switch_destroy(ls->ls_switch); + if (ls->ls_rotor) linuxdvb_rotor_destroy(ls->ls_rotor); + if (ls->ls_en50494) linuxdvb_switch_destroy(ls->ls_en50494); mpegts_input_delete((mpegts_input_t*)ls); } @@ -974,7 +1046,11 @@ linuxdvb_satconf_ele_create0 /* Rotor */ if (lse->ls_rotor && (e = htsmsg_get_map(conf, "rotor_conf"))) idnode_load(&lse->ls_rotor->ld_id, e); - } + + /* EN50494 */ + if (lse->ls_en50494 && (e = htsmsg_get_map(conf, "en50494_conf"))) + idnode_load(&lse->ls_en50494->ld_id, e); +} /* Create default LNB */ if (!lse->ls_lnb) @@ -995,6 +1071,8 @@ linuxdvb_satconf_delete ( linuxdvb_satconf_t *ls ) linuxdvb_switch_destroy(ls->ls_switch); if (ls->ls_rotor) linuxdvb_rotor_destroy(ls->ls_rotor); + if (ls->ls_en50494) + linuxdvb_en50494_destroy(ls->ls_en50494); mpegts_input_delete((mpegts_input_t*)ls); #endif } From 229ef2f48e3dc71ba6fc6bcab143e36f6ab1e477 Mon Sep 17 00:00:00 2001 From: InuSasha Date: Sun, 5 Jan 2014 18:47:55 +0100 Subject: [PATCH 02/11] EN50494: replace hardcoded en50494 tune-freq with calculated one --- src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 29 ++++++++++---------- src/input/mpegts/linuxdvb/linuxdvb_private.h | 15 ++++++++++ src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 6 +++- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index fe073707..ae9f8747 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -57,20 +57,19 @@ * Class definition * *************************************************************************/ -typedef struct linuxdvb_en50494 -{ - linuxdvb_diseqc_t; - - /* en50494 configuration*/ - uint8_t le_position; /* satelitte A(0) or B(1) */ - uint16_t le_frequency; /* user band frequency in MHz */ - uint8_t le_id; /* user band id 0-7 */ - uint16_t le_pin; /* 0-255 or LINUXDVB_EN50494_NOPIN */ - - /* runtime */ - uint32_t (*lnb_freq)(linuxdvb_lnb_t*, linuxdvb_mux_t*); - -} linuxdvb_en50494_t; +//typedef struct linuxdvb_en50494 +//{ +// linuxdvb_diseqc_t; +// +// /* en50494 configuration*/ +// uint8_t le_position; /* satelitte A(0) or B(1) */ +// uint16_t le_frequency; /* user band frequency in MHz */ +// uint8_t le_id; /* user band id 0-7 */ +// uint16_t le_pin; /* 0-255 or LINUXDVB_EN50494_NOPIN */ +// +// /* runtime */ +// uint32_t le_tune_freq; /* the real frequency to tune to */ +//} linuxdvb_en50494_t; static const char * linuxdvb_en50494_class_get_title ( idnode_t *o ) @@ -177,7 +176,7 @@ linuxdvb_en50494_tune tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "transponder value bigger then 1024"); return -1; } -// uint32_t tunefreq = (t + 350) * 4000 - freq; /* real used en50494 frequency */ + le->le_tune_freq = (t + 350) * 4000 - freq; /* real used en50494 frequency */ /* 2 data fields (16bit) */ uint8_t data1, data2; diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index 35683d78..e4bfb2e9 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -35,6 +35,7 @@ typedef struct linuxdvb_diseqc linuxdvb_diseqc_t; typedef struct linuxdvb_lnb linuxdvb_lnb_t; typedef struct linuxdvb_network linuxdvb_network_t; typedef struct linuxdvb_mux linuxdvb_mux_t; +typedef struct linuxdvb_en50494 linuxdvb_en50494_t; typedef LIST_HEAD(,linuxdvb_hardware) linuxdvb_hardware_list_t; typedef TAILQ_HEAD(linuxdvb_satconf_ele_list,linuxdvb_satconf_ele) linuxdvb_satconf_ele_list_t; @@ -220,6 +221,20 @@ struct linuxdvb_lnb int (*lnb_pol) (linuxdvb_lnb_t*, linuxdvb_mux_t*); }; +struct linuxdvb_en50494 +{ + linuxdvb_diseqc_t; + + /* en50494 configuration*/ + uint8_t le_position; /* satelitte A(0) or B(1) */ + uint16_t le_frequency; /* user band frequency in MHz */ + uint8_t le_id; /* user band id 0-7 */ + uint16_t le_pin; /* 0-255 or LINUXDVB_EN50494_NOPIN */ + + /* runtime */ + uint32_t le_tune_freq; /* the real frequency to tune to */ +}; + /* * Methods */ diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index de1b1bbd..973c33e5 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -868,7 +868,11 @@ linuxdvb_satconf_ele_tune ( linuxdvb_satconf_ele_t *lse ) /* Frontend */ // TODO: get en50494 tuning frequency, not channel frequency - f = 2040500;// lse->ls_lnb->lnb_freq(lse->ls_lnb, lm); + if (lse->ls_en50494) { + f = ((linuxdvb_en50494_t*)lse->ls_en50494)->le_tune_freq; + } else { + f = lse->ls_lnb->lnb_freq(lse->ls_lnb, lm); + } return linuxdvb_frontend_tune1(lfe, mmi, f); } From b67b98b7b6c4e9027aeb5389845bdb6ddfd64eaf Mon Sep 17 00:00:00 2001 From: InuSasha Date: Sun, 5 Jan 2014 23:47:12 +0100 Subject: [PATCH 03/11] EN50494: fix subelement creation for multi-port switches --- src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 2 ++ src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index ae9f8747..7b9af649 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -176,6 +176,8 @@ linuxdvb_en50494_tune tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "transponder value bigger then 1024"); return -1; } + + /* tune frequency for the frontend */ le->le_tune_freq = (t + 350) * 4000 - freq; /* real used en50494 frequency */ /* 2 data fields (16bit) */ diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index 973c33e5..a59d9bce 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -471,15 +471,24 @@ linuxdvb_satconf_create TAILQ_FOREACH(lse, &ls->ls_elements, ls_link) { if (!lse->ls_lnb) lse->ls_lnb = linuxdvb_lnb_create0(NULL, NULL, lse); - if (lst->ports > 1 && !lse->ls_switch) - lse->ls_switch = linuxdvb_switch_create0("Generic", NULL, lse, i, -1); + /* create multi port elements (2/4port & en50494) */ + if (lst->ports > 1) { + if( !lse->ls_en50494 && !strcmp("en50494",lst->type)) + lse->ls_en50494 = linuxdvb_en50494_create0("en50494", NULL, lse); + if( !lse->ls_switch && (!strcmp("2port",lst->type) || !strcmp("4port",lst->type))) + lse->ls_switch = linuxdvb_switch_create0("Generic", NULL, lse, i, -1); + } i++; } for (; i < lst->ports; i++) { lse = linuxdvb_satconf_ele_create0(NULL, NULL, ls); lse->ls_lnb = linuxdvb_lnb_create0(NULL, NULL, lse); + /* create multi port elements (2/4port & en50494) */ if (lst->ports > 1) { - lse->ls_switch = linuxdvb_switch_create0("Generic", NULL, lse, i, -1); + if( !strcmp("en50494",lst->type)) + lse->ls_en50494 = linuxdvb_en50494_create0("en50494", NULL, lse); + if( !strcmp("2port",lst->type) || !strcmp("4port",lst->type)) + lse->ls_switch = linuxdvb_switch_create0("Generic", NULL, lse, i, -1); } } From 4a4d7f166e2b1f13c24d7d740c098ad4597f8f99 Mon Sep 17 00:00:00 2001 From: Sascha Date: Mon, 6 Jan 2014 13:58:04 +0100 Subject: [PATCH 04/11] EN50494: fix copy'n'paste misstake --- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index a59d9bce..418c5bad 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -1015,7 +1015,7 @@ linuxdvb_satconf_ele_destroy ( linuxdvb_satconf_ele_t *ls ) if (ls->ls_lnb) linuxdvb_lnb_destroy(ls->ls_lnb); if (ls->ls_switch) linuxdvb_switch_destroy(ls->ls_switch); if (ls->ls_rotor) linuxdvb_rotor_destroy(ls->ls_rotor); - if (ls->ls_en50494) linuxdvb_switch_destroy(ls->ls_en50494); + if (ls->ls_en50494) linuxdvb_en50494_destroy(ls->ls_en50494); mpegts_input_delete((mpegts_input_t*)ls); } From 1673b4a2cdf2d7b843c31089866a3dfc2a67eb0c Mon Sep 17 00:00:00 2001 From: InuSasha Date: Mon, 6 Jan 2014 17:29:19 +0100 Subject: [PATCH 05/11] EN50494: configuration storage - add save configuration - set default values - raise variable length to 16bit (needed by configuration save) --- src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 36 +++++++++++++------- src/input/mpegts/linuxdvb/linuxdvb_private.h | 6 ++-- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 23 +++++++------ 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index 7b9af649..cef56777 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -18,11 +18,11 @@ * along with this program. If not, see . * * Open things: - * - make linuxdvb_en50494_tune thread safe - * avoiding self-raised collisions - * - collision dectection - * when a diseqc-command wasn't executed succesful, retry. - * delay time is easly random, but in standard is special (complicated) way described (cap 8). + * - TODO: make linuxdvb_en50494_tune thread safe + * avoid self-raised collisions + * - TODO: collision dectection + * when a en50494-command wasn't executed succesful, retry. + * delay time is easly random, but in standard is special (complicated) way described (cap. 8). */ #include "tvheadend.h" @@ -122,27 +122,27 @@ const idclass_t linuxdvb_en50494_class = .ic_get_title = linuxdvb_en50494_class_get_title, .ic_properties = (const property_t[]) { { - .type = PT_INT, + .type = PT_U16, .id = "position", .name = "Position", .off = offsetof(linuxdvb_en50494_t, le_position), .list = linuxdvb_en50494_class_position_list }, { - .type = PT_INT, + .type = PT_U16, .id = "frequency", .name = "Frequency", .off = offsetof(linuxdvb_en50494_t, le_frequency), }, { - .type = PT_INT, + .type = PT_U16, .id = "id", .name = "ID", .off = offsetof(linuxdvb_en50494_t, le_id), .list = linuxdvb_en50494_class_id_list }, { - .type = PT_INT, + .type = PT_U16, .id = "pin", .name = "Pin", .off = offsetof(linuxdvb_en50494_t, le_pin), @@ -183,7 +183,7 @@ linuxdvb_en50494_tune /* 2 data fields (16bit) */ uint8_t data1, data2; data1 = le->le_id << 5; /* 3bit user-band */ - data1 |= le->le_position << 4; /* 1bit position (satelitte A(0)/B(0)) */ + data1 |= le->le_position << 4; /* 1bit position (satelitte A(0)/B(1)) */ data1 |= pol << 3; /* 1bit polarisation v(0)/h(1) */ data1 |= band << 2; /* 1bit band lower(0)/upper(1) */ data1 |= t >> 8; /* 2bit transponder value bit 1-2 */ @@ -246,10 +246,15 @@ linuxdvb_en50494_list ( void *o ) linuxdvb_diseqc_t * linuxdvb_en50494_create0 - ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls) + ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls, int port ) { linuxdvb_diseqc_t *ld; -// linuxdvb_en50494_t *le; + linuxdvb_en50494_t *le; + + if (port > 1) { + tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "only 2 ports/positions are posible. given %i", port); + port = 0; + } ld = linuxdvb_diseqc_create0( calloc(1, sizeof(linuxdvb_en50494_t)), @@ -258,10 +263,15 @@ linuxdvb_en50494_create0 conf, LINUXDVB_EN50494_NAME, ls); -// le = (linuxdvb_en50494_t*)ld; + le = (linuxdvb_en50494_t*)ld; if (ld) { ld->ld_tune = linuxdvb_en50494_tune; /* May not needed: ld->ld_grace = linuxdvb_en50494_grace; */ + + le->le_position = port; + le->le_id = 0; + le->le_frequency = 0; + le->le_pin = LINUXDVB_EN50494_NOPIN; } return (linuxdvb_diseqc_t*)ld; diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index e4bfb2e9..251c727d 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -226,9 +226,9 @@ struct linuxdvb_en50494 linuxdvb_diseqc_t; /* en50494 configuration*/ - uint8_t le_position; /* satelitte A(0) or B(1) */ + uint16_t le_position; /* satelitte A(0) or B(1) */ uint16_t le_frequency; /* user band frequency in MHz */ - uint8_t le_id; /* user band id 0-7 */ + uint16_t le_id; /* user band id 0-7 */ uint16_t le_pin; /* 0-255 or LINUXDVB_EN50494_NOPIN */ /* runtime */ @@ -346,7 +346,7 @@ linuxdvb_diseqc_t *linuxdvb_switch_create0 linuxdvb_diseqc_t *linuxdvb_rotor_create0 ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls ); linuxdvb_diseqc_t *linuxdvb_en50494_create0 - ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls ); + ( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls, int port ); void linuxdvb_lnb_destroy ( linuxdvb_lnb_t *lnb ); void linuxdvb_switch_destroy ( linuxdvb_diseqc_t *ld ); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index 418c5bad..4b531bcb 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -422,7 +422,7 @@ linuxdvb_satconf_type_list ( void *p ) void linuxdvb_satconf_destroy ( linuxdvb_satconf_t *ls ) { - // TODO + // TODO: satconf_destroy } linuxdvb_satconf_t * @@ -474,7 +474,7 @@ linuxdvb_satconf_create /* create multi port elements (2/4port & en50494) */ if (lst->ports > 1) { if( !lse->ls_en50494 && !strcmp("en50494",lst->type)) - lse->ls_en50494 = linuxdvb_en50494_create0("en50494", NULL, lse); + lse->ls_en50494 = linuxdvb_en50494_create0("en50494", NULL, lse, i); if( !lse->ls_switch && (!strcmp("2port",lst->type) || !strcmp("4port",lst->type))) lse->ls_switch = linuxdvb_switch_create0("Generic", NULL, lse, i, -1); } @@ -486,7 +486,7 @@ linuxdvb_satconf_create /* create multi port elements (2/4port & en50494) */ if (lst->ports > 1) { if( !strcmp("en50494",lst->type)) - lse->ls_en50494 = linuxdvb_en50494_create0("en50494", NULL, lse); + lse->ls_en50494 = linuxdvb_en50494_create0("en50494", NULL, lse, i); if( !strcmp("2port",lst->type) || !strcmp("4port",lst->type)) lse->ls_switch = linuxdvb_switch_create0("Generic", NULL, lse, i, -1); } @@ -522,6 +522,11 @@ linuxdvb_satconf_save ( linuxdvb_satconf_t *ls, htsmsg_t *m ) idnode_save(&lse->ls_rotor->ld_id, c); htsmsg_add_msg(e, "rotor_conf", c); } + if (lse->ls_en50494) { + c = htsmsg_create_map(); + idnode_save(&lse->ls_en50494->ld_id, c); + htsmsg_add_msg(e, "en50494_conf", c); + } htsmsg_add_msg(l, NULL, e); } htsmsg_add_msg(m, "elements", l); @@ -619,7 +624,7 @@ linuxdvb_satconf_ele_class_en50494type_set ( void *o, const void *p ) const char *str = p; if (ls->ls_en50494) linuxdvb_en50494_destroy(ls->ls_en50494); - ls->ls_en50494 = linuxdvb_en50494_create0(str, NULL, ls); + ls->ls_en50494 = linuxdvb_en50494_create0(str, NULL, ls, 0); return 1; } @@ -876,12 +881,10 @@ linuxdvb_satconf_ele_tune ( linuxdvb_satconf_ele_t *lse ) usleep(20000); // Allow LNB to settle before tuning /* Frontend */ - // TODO: get en50494 tuning frequency, not channel frequency - if (lse->ls_en50494) { - f = ((linuxdvb_en50494_t*)lse->ls_en50494)->le_tune_freq; - } else { - f = lse->ls_lnb->lnb_freq(lse->ls_lnb, lm); - } + /* use en50494 tuning frequency, if needed (not channel frequency) */ + f = lse->ls_en50494 + ? ((linuxdvb_en50494_t*)lse->ls_en50494)->le_tune_freq + : lse->ls_lnb->lnb_freq(lse->ls_lnb, lm); return linuxdvb_frontend_tune1(lfe, mmi, f); } From 8792c5cb42f41398a881b2810bf0bbdc316e85a5 Mon Sep 17 00:00:00 2001 From: InuSasha Date: Mon, 6 Jan 2014 19:05:26 +0100 Subject: [PATCH 06/11] EN50494: add gui interface for configuration - EN50494 configuration - revert drop off compiler optimation --- Makefile | 2 +- src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 2 +- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 135 +++++++++++++++++++ 3 files changed, 137 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a2e5c65c..f05a939b 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ PROG := $(BUILDDIR)/tvheadend CFLAGS += -Wall -Werror -Wwrite-strings -Wno-deprecated-declarations CFLAGS += -Wmissing-prototypes -fms-extensions -CFLAGS += -g -funsigned-char +CFLAGS += -g -funsigned-char -O2 CFLAGS += -D_FILE_OFFSET_BITS=64 CFLAGS += -I${BUILDDIR} -I${ROOTDIR}/src -I${ROOTDIR} LDFLAGS += -lrt -ldl -lpthread -lm diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index cef56777..cc1f5b9b 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -188,7 +188,7 @@ linuxdvb_en50494_tune data1 |= band << 2; /* 1bit band lower(0)/upper(1) */ data1 |= t >> 8; /* 2bit transponder value bit 1-2 */ data2 = t & 0xFF; /* 8bit transponder value bit 3-10 */ - tvhlog(LOG_INFO, LINUXDVB_EN50494_NAME, + tvhlog(LOG_DEBUG, LINUXDVB_EN50494_NAME, "lnb=%i, id=%i, freq=%i, pin=%i, v/h=%i, l/u=%i, f=%i, data=0x%02X%02X", le->le_position, le->le_id, le->le_frequency, le->le_pin, pol, band, freq, data1, data2); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index 4b531bcb..d7aa8c5a 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -163,6 +163,115 @@ linuxdvb_satconf_class_orbitalpos_set return 1; } +static const void * +linuxdvb_satconf_class_en50494_id_get ( void *p ) +{ + linuxdvb_satconf_t *ls = p; + linuxdvb_satconf_ele_t *lse = TAILQ_FIRST(&ls->ls_elements); + linuxdvb_en50494_t *le; + static uint16_t default_value = 0; + + if (!lse && !lse->ls_en50494) + return &default_value; + + le = (linuxdvb_en50494_t*)lse->ls_en50494; + return &le->le_id; +} + +static int +linuxdvb_satconf_class_en50494_id_set + ( void *p, const void *v ) +{ + linuxdvb_satconf_t *ls = p; + linuxdvb_satconf_ele_t *lse; + linuxdvb_en50494_t *le; + uint16_t new_value = *(uint16_t*)v; + + if (new_value < 0 || new_value > 7) + return 1; + + TAILQ_FOREACH(lse, &ls->ls_elements, ls_link) { + if (!lse && !lse->ls_en50494) + continue; + + le = (linuxdvb_en50494_t*)lse->ls_en50494; + le->le_id = new_value; + } + return 0; + +} + +static const void * +linuxdvb_satconf_class_en50494_freq_get ( void *p ) +{ + linuxdvb_satconf_t *ls = p; + linuxdvb_satconf_ele_t *lse = TAILQ_FIRST(&ls->ls_elements); + linuxdvb_en50494_t *le; + static uint16_t default_value = 0; + + if (!lse && !lse->ls_en50494) + return &default_value; + + le = (linuxdvb_en50494_t*)lse->ls_en50494; + return &le->le_frequency; +} + +static int +linuxdvb_satconf_class_en50494_freq_set + ( void *p, const void *v ) +{ + linuxdvb_satconf_t *ls = p; + linuxdvb_satconf_ele_t *lse; + linuxdvb_en50494_t *le; + uint16_t new_value = *(uint16_t*)v; + + TAILQ_FOREACH(lse, &ls->ls_elements, ls_link) { + if (!lse && !lse->ls_en50494) + continue; + + le = (linuxdvb_en50494_t*)lse->ls_en50494; + le->le_frequency = new_value; + } + return 0; +} + +static const void * +linuxdvb_satconf_class_en50494_pin_get ( void *p ) +{ + linuxdvb_satconf_t *ls = p; + linuxdvb_satconf_ele_t *lse = TAILQ_FIRST(&ls->ls_elements); + linuxdvb_en50494_t *le; + static uint16_t default_value = 256; + + if (!lse && !lse->ls_en50494) + return &default_value; + + le = (linuxdvb_en50494_t*)lse->ls_en50494; + return &le->le_pin; +} + +static int +linuxdvb_satconf_class_en50494_pin_set + ( void *p, const void *v ) +{ + linuxdvb_satconf_t *ls = p; + linuxdvb_satconf_ele_t *lse; + linuxdvb_en50494_t *le; + uint16_t new_value = *(uint16_t*)v; + + if (new_value < 0 || new_value > 256) + return 1; + + TAILQ_FOREACH(lse, &ls->ls_elements, ls_link) { + if (!lse && !lse->ls_en50494) + continue; + + le = (linuxdvb_en50494_t*)lse->ls_en50494; + le->le_pin = new_value; + } + return 0; +} + static idnode_set_t * linuxdvb_satconf_class_get_childs ( idnode_t *o ) { @@ -325,6 +434,32 @@ const idclass_t linuxdvb_satconf_en50494_class = .list = linuxdvb_satconf_ele_class_network_enum, .opts = PO_NOSAVE, }, + { + .type = PT_U16, + .id = "id", + .name = "ID (0-7)", + .get = linuxdvb_satconf_class_en50494_id_get, + .set = linuxdvb_satconf_class_en50494_id_set, + .opts = PO_NOSAVE, + // TODO: add id list + }, + { + .type = PT_U16, + .id = "freqency", + .name = "Freqency (MHz)", + .get = linuxdvb_satconf_class_en50494_freq_get, + .set = linuxdvb_satconf_class_en50494_freq_set, + .opts = PO_NOSAVE, + }, + { + .type = PT_U16, + .id = "pin", + .name = "PIN (0-255, 256 for no pin)", + .get = linuxdvb_satconf_class_en50494_pin_get, + .set = linuxdvb_satconf_class_en50494_pin_set, + .opts = PO_NOSAVE, + // TODO: add pin list + }, {} } }; From 5b163273d275f2da235a2a809aa39acfdb572582 Mon Sep 17 00:00:00 2001 From: InuSasha Date: Mon, 6 Jan 2014 22:22:28 +0100 Subject: [PATCH 07/11] EN50494: small fixes --- .gitignore | 1 - src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 949dbf66..217c9961 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,3 @@ debian/tvheadend debian/tvheadend-dbg debian/tvheadend*substvars debian/tvheadend*.debhelper* -/etc diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index cc1f5b9b..8256874e 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -173,7 +173,7 @@ linuxdvb_en50494_tune /* transponder value - t*/ uint16_t t = round((( (freq / 1000) + 2 + le->le_frequency) / 4) - 350); if ( t > 1024) { - tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "transponder value bigger then 1024"); + tvherror(LINUXDVB_EN50494_NAME, "transponder value bigger then 1024"); return -1; } @@ -188,18 +188,18 @@ linuxdvb_en50494_tune data1 |= band << 2; /* 1bit band lower(0)/upper(1) */ data1 |= t >> 8; /* 2bit transponder value bit 1-2 */ data2 = t & 0xFF; /* 8bit transponder value bit 3-10 */ - tvhlog(LOG_DEBUG, LINUXDVB_EN50494_NAME, + tvhdebug(LINUXDVB_EN50494_NAME, "lnb=%i, id=%i, freq=%i, pin=%i, v/h=%i, l/u=%i, f=%i, data=0x%02X%02X", le->le_position, le->le_id, le->le_frequency, le->le_pin, pol, band, freq, data1, data2); /* use 18V */ if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_18)) { - tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "error setting lnb voltage to 18V"); + tvherror(LINUXDVB_EN50494_NAME, "error setting lnb voltage to 18V"); return -1; } usleep(15000); /* standard: 4ms < x < 22ms */ - /* send tune command (with/with pin) */ + /* send tune command (with/without pin) */ if (le->le_pin != LINUXDVB_EN50494_NOPIN) { ret = linuxdvb_diseqc_send(fd, LINUXDVB_EN50494_FRAME, @@ -216,14 +216,14 @@ linuxdvb_en50494_tune data1, data2); } if (ret != 0) { - tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "error send tune command"); + tvherror(LINUXDVB_EN50494_NAME, "error send tune command"); return -1; } usleep(50000); /* standard: 2ms < x < 60ms */ /* return to 13V */ if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_13)) { - tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "error setting lnb voltage back to 13V"); + tvherror(LINUXDVB_EN50494_NAME, "error setting lnb voltage back to 13V"); return -1; } @@ -252,7 +252,7 @@ linuxdvb_en50494_create0 linuxdvb_en50494_t *le; if (port > 1) { - tvhlog(LOG_ERR, LINUXDVB_EN50494_NAME, "only 2 ports/positions are posible. given %i", port); + tvherror(LINUXDVB_EN50494_NAME, "only 2 ports/positions are posible. given %i", port); port = 0; } From 96e3f7b0a4956a6df797ff513fc59c5de55cdae3 Mon Sep 17 00:00:00 2001 From: Sascha InuSasha Kuehndel Date: Wed, 8 Jan 2014 21:31:01 +0100 Subject: [PATCH 08/11] EN50494: convert fields for id and pin to a drop down box, on gui --- src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 36 -------------------- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 35 ++++++++++++++++--- 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index 8256874e..bdaa3bab 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -80,39 +80,6 @@ linuxdvb_en50494_class_get_title ( idnode_t *o ) return buf; } -static htsmsg_t * -linuxdvb_en50494_class_position_list ( void *o ) -{ - htsmsg_t *m = htsmsg_create_list(); - htsmsg_add_u32(m, NULL, LINUXDVB_EN50494_SAT_A); - htsmsg_add_u32(m, NULL, LINUXDVB_EN50494_SAT_B); - return m; -} - -static htsmsg_t * -linuxdvb_en50494_class_id_list ( void *o ) -{ - uint32_t i; - - htsmsg_t *m = htsmsg_create_list(); - for (i = 0; i < 8; i++) { - htsmsg_add_u32(m, NULL, i); - } - return m; -} - -static htsmsg_t * -linuxdvb_en50494_class_pin_list ( void *o ) -{ - int32_t i; - - htsmsg_t *m = htsmsg_create_list(); - for (i = -1; i < 256; i++) { - htsmsg_add_s32(m, NULL, i); - } - return m; -} - extern const idclass_t linuxdvb_diseqc_class; const idclass_t linuxdvb_en50494_class = { @@ -126,7 +93,6 @@ const idclass_t linuxdvb_en50494_class = .id = "position", .name = "Position", .off = offsetof(linuxdvb_en50494_t, le_position), - .list = linuxdvb_en50494_class_position_list }, { .type = PT_U16, @@ -139,14 +105,12 @@ const idclass_t linuxdvb_en50494_class = .id = "id", .name = "ID", .off = offsetof(linuxdvb_en50494_t, le_id), - .list = linuxdvb_en50494_class_id_list }, { .type = PT_U16, .id = "pin", .name = "Pin", .off = offsetof(linuxdvb_en50494_t, le_pin), - .list = linuxdvb_en50494_class_pin_list }, {} } diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index d7aa8c5a..0cfdc0b9 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -163,6 +163,18 @@ linuxdvb_satconf_class_orbitalpos_set return 1; } +static htsmsg_t * +linuxdvb_satconf_class_en50494_id_list ( void *o ) +{ + uint32_t i; + + htsmsg_t *m = htsmsg_create_list(); + for (i = 0; i < 8; i++) { + htsmsg_add_u32(m, NULL, i); + } + return m; +} + static const void * linuxdvb_satconf_class_en50494_id_get ( void *p ) { @@ -235,6 +247,21 @@ linuxdvb_satconf_class_en50494_freq_set return 0; } +/* TODO: Value 256 should shown as "no Pin", and have to set on top" */ +static htsmsg_t * +linuxdvb_satconf_class_en50494_pin_list ( void *o ) +{ + int32_t i; + + htsmsg_t *m = htsmsg_create_list(); + for (i = 0; i < 256; i++) { + htsmsg_add_u32(m, NULL, i); + } + htsmsg_add_u32(m, NULL, 256); + return m; +} + + static const void * linuxdvb_satconf_class_en50494_pin_get ( void *p ) { @@ -440,8 +467,8 @@ const idclass_t linuxdvb_satconf_en50494_class = .name = "ID (0-7)", .get = linuxdvb_satconf_class_en50494_id_get, .set = linuxdvb_satconf_class_en50494_id_set, + .list = linuxdvb_satconf_class_en50494_id_list, .opts = PO_NOSAVE, - // TODO: add id list }, { .type = PT_U16, @@ -454,11 +481,11 @@ const idclass_t linuxdvb_satconf_en50494_class = { .type = PT_U16, .id = "pin", - .name = "PIN (0-255, 256 for no pin)", + .name = "Pin (256 for no pin)", .get = linuxdvb_satconf_class_en50494_pin_get, .set = linuxdvb_satconf_class_en50494_pin_set, + .list = linuxdvb_satconf_class_en50494_pin_list, .opts = PO_NOSAVE, - // TODO: add pin list }, {} } @@ -871,7 +898,7 @@ const idclass_t linuxdvb_satconf_ele_class = .name = "Network", .get = linuxdvb_satconf_ele_class_network_get, .set = linuxdvb_satconf_ele_class_network_set, - .list = linuxdvb_satconf_ele_class_network_enum, + .list = linuxdvb_satconf_ele_class_network_enum, .rend = linuxdvb_satconf_ele_class_network_rend, }, { From 00e9adc3100a2570fb719fc5d54431961f88c1f4 Mon Sep 17 00:00:00 2001 From: "Sascha Kuehndel (InuSasha)" Date: Wed, 8 Jan 2014 22:17:02 +0100 Subject: [PATCH 09/11] EN50494: better pin drop down --- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index 0cfdc0b9..b192d56f 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -247,17 +247,25 @@ linuxdvb_satconf_class_en50494_freq_set return 0; } -/* TODO: Value 256 should shown as "no Pin", and have to set on top" */ static htsmsg_t * linuxdvb_satconf_class_en50494_pin_list ( void *o ) { int32_t i; htsmsg_t *m = htsmsg_create_list(); + htsmsg_t *e; + + e = htsmsg_create_map(); + htsmsg_add_u32(e, "key", 256); + htsmsg_add_str(e, "val", "no Pin"); + htsmsg_add_msg(m, NULL, e); + for (i = 0; i < 256; i++) { - htsmsg_add_u32(m, NULL, i); + e = htsmsg_create_map(); + htsmsg_add_u32(e, "key", i); + htsmsg_add_u32(e, "val", i); + htsmsg_add_msg(m, NULL, e); } - htsmsg_add_u32(m, NULL, 256); return m; } @@ -464,7 +472,7 @@ const idclass_t linuxdvb_satconf_en50494_class = { .type = PT_U16, .id = "id", - .name = "ID (0-7)", + .name = "ID", .get = linuxdvb_satconf_class_en50494_id_get, .set = linuxdvb_satconf_class_en50494_id_set, .list = linuxdvb_satconf_class_en50494_id_list, @@ -481,7 +489,7 @@ const idclass_t linuxdvb_satconf_en50494_class = { .type = PT_U16, .id = "pin", - .name = "Pin (256 for no pin)", + .name = "Pin", .get = linuxdvb_satconf_class_en50494_pin_get, .set = linuxdvb_satconf_class_en50494_pin_set, .list = linuxdvb_satconf_class_en50494_pin_list, From 35a2216eb8b1a79ed64b7993247ddd2d0d82269a Mon Sep 17 00:00:00 2001 From: "Sascha Kuehndel (InuSasha)" Date: Thu, 9 Jan 2014 19:23:33 +0100 Subject: [PATCH 10/11] EN50494: basic collision control - add DiSEqC repeats to en50494 tune, with random delay - avoid parallel tuning on en50494 --- src/input/mpegts/linuxdvb/linuxdvb.c | 3 + src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 90 ++++++++++++-------- src/input/mpegts/linuxdvb/linuxdvb_private.h | 2 + 3 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb.c b/src/input/mpegts/linuxdvb/linuxdvb.c index 33287eb8..cd959400 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb.c +++ b/src/input/mpegts/linuxdvb/linuxdvb.c @@ -32,6 +32,9 @@ void linuxdvb_init ( int adapter_mask ) /* Load list of mux charset global overrides */ dvb_charset_init(); + /* Initialise en50494 locks */ + linuxdvb_en50494_init(); + /* Initialise networks */ linuxdvb_network_init(); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index bdaa3bab..16f1e0f0 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -18,8 +18,6 @@ * along with this program. If not, see . * * Open things: - * - TODO: make linuxdvb_en50494_tune thread safe - * avoid self-raised collisions * - TODO: collision dectection * when a en50494-command wasn't executed succesful, retry. * delay time is easly random, but in standard is special (complicated) way described (cap. 8). @@ -70,6 +68,8 @@ // /* runtime */ // uint32_t le_tune_freq; /* the real frequency to tune to */ //} linuxdvb_en50494_t; +/* prevention of self raised DiSEqC collisions */ +static pthread_mutex_t linuxdvb_en50494_lock; static const char * linuxdvb_en50494_class_get_title ( idnode_t *o ) @@ -126,6 +126,7 @@ linuxdvb_en50494_tune ( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *sc, int fd ) { int ret = 0; + int i; linuxdvb_en50494_t *le = (linuxdvb_en50494_t*) ld; linuxdvb_lnb_t *lnb = sc->ls_lnb; @@ -142,7 +143,7 @@ linuxdvb_en50494_tune } /* tune frequency for the frontend */ - le->le_tune_freq = (t + 350) * 4000 - freq; /* real used en50494 frequency */ + le->le_tune_freq = (t + 350) * 4000 - freq; /* 2 data fields (16bit) */ uint8_t data1, data2; @@ -156,40 +157,53 @@ linuxdvb_en50494_tune "lnb=%i, id=%i, freq=%i, pin=%i, v/h=%i, l/u=%i, f=%i, data=0x%02X%02X", le->le_position, le->le_id, le->le_frequency, le->le_pin, pol, band, freq, data1, data2); - /* use 18V */ - if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_18)) { - tvherror(LINUXDVB_EN50494_NAME, "error setting lnb voltage to 18V"); - return -1; - } - usleep(15000); /* standard: 4ms < x < 22ms */ + pthread_mutex_lock(&linuxdvb_en50494_lock); + for (i = 0; i <= sc->ls_parent->ls_diseqc_repeats; i++) { + /* to avoid repeated collision, wait a random time (5-25ms) */ + if (i != 0) { + int ms = rand()%20 + 5; + usleep(ms*1000); + } - /* send tune command (with/without pin) */ - if (le->le_pin != LINUXDVB_EN50494_NOPIN) { - ret = linuxdvb_diseqc_send(fd, - LINUXDVB_EN50494_FRAME, - LINUXDVB_EN50494_ADDRESS, - LINUXDVB_EN50494_CMD_NORMAL_MULTIHOME, - 3, - data1, data2, (uint8_t)le->le_pin); - } else { - ret = linuxdvb_diseqc_send(fd, - LINUXDVB_EN50494_FRAME, - LINUXDVB_EN50494_ADDRESS, - LINUXDVB_EN50494_CMD_NORMAL, - 2, - data1, data2); - } - if (ret != 0) { - tvherror(LINUXDVB_EN50494_NAME, "error send tune command"); - return -1; - } - usleep(50000); /* standard: 2ms < x < 60ms */ + /* use 18V */ + if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_18)) { + tvherror(LINUXDVB_EN50494_NAME, "error setting lnb voltage to 18V"); + pthread_mutex_unlock(&linuxdvb_en50494_lock); + return -1; + } + usleep(15000); /* standard: 4ms < x < 22ms */ - /* return to 13V */ - if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_13)) { - tvherror(LINUXDVB_EN50494_NAME, "error setting lnb voltage back to 13V"); - return -1; + /* send tune command (with/without pin) */ + if (le->le_pin != LINUXDVB_EN50494_NOPIN) { + ret = linuxdvb_diseqc_send(fd, + LINUXDVB_EN50494_FRAME, + LINUXDVB_EN50494_ADDRESS, + LINUXDVB_EN50494_CMD_NORMAL_MULTIHOME, + 3, + data1, data2, (uint8_t)le->le_pin); + } else { + ret = linuxdvb_diseqc_send(fd, + LINUXDVB_EN50494_FRAME, + LINUXDVB_EN50494_ADDRESS, + LINUXDVB_EN50494_CMD_NORMAL, + 2, + data1, data2); + } + if (ret != 0) { + tvherror(LINUXDVB_EN50494_NAME, "error send tune command"); + pthread_mutex_unlock(&linuxdvb_en50494_lock); + return -1; + } + usleep(50000); /* standard: 2ms < x < 60ms */ + + /* return to 13V */ + if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_13)) { + tvherror(LINUXDVB_EN50494_NAME, "error setting lnb voltage back to 13V"); + pthread_mutex_unlock(&linuxdvb_en50494_lock); + return -1; + } } + pthread_mutex_unlock(&linuxdvb_en50494_lock); return 0; } @@ -199,6 +213,14 @@ linuxdvb_en50494_tune * Create / Config * *************************************************************************/ +void +linuxdvb_en50494_init (void) +{ + if (pthread_mutex_init(&linuxdvb_en50494_lock, NULL) != 0) { + tvherror(LINUXDVB_EN50494_NAME, "failed to init lock mutex"); + } +} + htsmsg_t * linuxdvb_en50494_list ( void *o ) { diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index 251c727d..b1d89e56 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -358,6 +358,8 @@ htsmsg_t *linuxdvb_switch_list ( void *o ); htsmsg_t *linuxdvb_rotor_list ( void *o ); htsmsg_t *linuxdvb_en50494_list ( void *o ); +void linuxdvb_en50494_init (void); + int linuxdvb_diseqc_send (int fd, uint8_t framing, uint8_t addr, uint8_t cmd, uint8_t len, ...); From 88f0dbba2e3558c829a7a82b72da83eb736e82b8 Mon Sep 17 00:00:00 2001 From: "Sascha Kuehndel (InuSasha)" Date: Thu, 9 Jan 2014 20:01:51 +0100 Subject: [PATCH 11/11] EN50494: merge mutex_unlocks after for-loop --- src/input/mpegts/linuxdvb/linuxdvb_en50494.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c index 16f1e0f0..e2ca8678 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_en50494.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_en50494.c @@ -166,10 +166,10 @@ linuxdvb_en50494_tune } /* use 18V */ - if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_18)) { + ret = linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_18); + if (ret) { tvherror(LINUXDVB_EN50494_NAME, "error setting lnb voltage to 18V"); - pthread_mutex_unlock(&linuxdvb_en50494_lock); - return -1; + break; } usleep(15000); /* standard: 4ms < x < 22ms */ @@ -191,21 +191,20 @@ linuxdvb_en50494_tune } if (ret != 0) { tvherror(LINUXDVB_EN50494_NAME, "error send tune command"); - pthread_mutex_unlock(&linuxdvb_en50494_lock); - return -1; + break; } usleep(50000); /* standard: 2ms < x < 60ms */ /* return to 13V */ - if (linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_13)) { + ret = linuxdvb_diseqc_set_volt(fd, SEC_VOLTAGE_13); + if (ret) { tvherror(LINUXDVB_EN50494_NAME, "error setting lnb voltage back to 13V"); - pthread_mutex_unlock(&linuxdvb_en50494_lock); - return -1; + break; } } pthread_mutex_unlock(&linuxdvb_en50494_lock); - return 0; + return ret == 0 ? 0 : -1; }