#define LINUXDVB_EN50494_SAT_A 0x00
#define LINUXDVB_EN50494_SAT_B 0x01
+/* EN50607 */
+#define LINUXDVB_EN50607_FRAME_NORMAL 0x70
+#define LINUXDVB_EN50607_FRAME_MULTIHOME 0x71
/* **************************************************************************
* Class definition
static const char *
linuxdvb_en50494_class_get_title ( idnode_t *o, const char *lang )
{
- static const char *title = N_("Unicable");
+ static const char *title = N_("Unicable I (EN50494)");
+ return tvh_gettext_lang(lang, title);
+}
+
+static const char *
+linuxdvb_en50607_class_get_title ( idnode_t *o, const char *lang )
+{
+ static const char *title = N_("Unicable II (EN50607)");
return tvh_gettext_lang(lang, title);
}
}
htsmsg_t *
+linuxdvb_en50607_id_list ( void *o, const char *lang )
+{
+ uint32_t i;
+ htsmsg_t *m = htsmsg_create_list();
+ for (i = 0; i < 32; i++) {
+ htsmsg_add_u32(m, NULL, i);
+ }
+ return m;
+}
+
+static htsmsg_t *
linuxdvb_en50494_pin_list ( void *o, const char *lang )
{
int32_t i;
}
extern const idclass_t linuxdvb_diseqc_class;
+
const idclass_t linuxdvb_en50494_class =
{
.ic_super = &linuxdvb_diseqc_class,
}
};
+const idclass_t linuxdvb_en50607_class =
+{
+ .ic_super = &linuxdvb_diseqc_class,
+ .ic_class = "linuxdvb_en50607",
+ .ic_caption = N_("en50607"),
+ .ic_get_title = linuxdvb_en50607_class_get_title,
+ .ic_properties = (const property_t[]) {
+ {
+ .type = PT_U16,
+ .id = "position",
+ .name = N_("Position"),
+ .off = offsetof(linuxdvb_en50494_t, le_position),
+ .list = linuxdvb_en50494_position_list,
+ },
+ {
+ .type = PT_U16,
+ .id = "frequency",
+ .name = N_("Frequency"),
+ .off = offsetof(linuxdvb_en50494_t, le_frequency),
+ },
+ {
+ .type = PT_U16,
+ .id = "id",
+ .name = N_("SCR (ID)"),
+ .off = offsetof(linuxdvb_en50494_t, le_id),
+ .list = linuxdvb_en50607_id_list,
+ },
+ {
+ .type = PT_U16,
+ .id = "pin",
+ .name = N_("PIN"),
+ .off = offsetof(linuxdvb_en50494_t, le_pin),
+ .list = linuxdvb_en50494_pin_list,
+ },
+ {}
+ }
+};
+
/* **************************************************************************
* Class methods
* *************************************************************************/
int vol, int pol, int band, int freq )
{
int ret = 0, i, fd = linuxdvb_satconf_fe_fd(lsp), rfreq;
+ int ver2 = linuxdvb_unicable_is_en50607(ld->ld_type);
linuxdvb_en50494_t *le = (linuxdvb_en50494_t*) ld;
+ uint8_t data1, data2, data3;
uint16_t t;
/* tune frequency for the frontend */
return -1;
le->le_tune_freq = rfreq;
- /* 2 data fields (16bit) */
- uint8_t data1, data2;
- data1 = (le->le_id & 7) << 5; /* 3bit user-band */
- data1 |= (le->le_position & 1) << 4; /* 1bit position (satellite A(0)/B(1)) */
- data1 |= (pol & 1) << 3; /* 1bit polarization v(0)/h(1) */
- data1 |= (band & 1) << 2; /* 1bit band lower(0)/upper(1) */
- data1 |= (t >> 8) & 3; /* 2bit transponder value bit 1-2 */
- data2 = t & 0xFF; /* 8bit transponder value bit 3-10 */
+ if (!ver2) {
+ /* 2 data fields (16bit) */
+ data1 = (le->le_id & 7) << 5; /* 3bit user-band */
+ data1 |= (le->le_position & 1) << 4; /* 1bit position (satellite A(0)/B(1)) */
+ data1 |= (pol & 1) << 3; /* 1bit polarization v(0)/h(1) */
+ data1 |= (band & 1) << 2; /* 1bit band lower(0)/upper(1) */
+ data1 |= (t >> 8) & 3; /* 2bit transponder value bit 1-2 */
+ data2 = t & 0xff; /* 8bit transponder value bit 3-10 */
+ data3 = 0;
+ } else {
+ /* 3 data fields (24bit) */
+ data1 = (le->le_id & 0x1f) << 3; /* 5bit user-band */
+ data1 |= (t >> 8) & 7; /* 3bit transponder value bit 1-3 */
+ data2 = t & 0xff; /* 8bit transponder value bit 4-11 */
+ data3 = (le->le_position & 0x3f) << 2; /* 6bit position */
+ data3 |= (pol & 1) << 1; /* 1bit polarization v(0)/h(1) */
+ data3 |= band & 1; /* 1bit band lower(0)/upper(1) */
+ }
/* wait until no other thread is setting up switch.
* when an other thread was blocking, waiting 20ms.
/* send tune command (with/without pin) */
tvhdebug(LS_EN50494,
- "lnb=%i id=%i freq=%i pin=%i v/h=%i l/u=%i f=%i, data=0x%02X%02X",
+ "lnb=%i id=%i freq=%i pin=%i v/h=%i l/u=%i f=%i, data=0x%02X%02X%02X",
le->le_position, le->le_id, le->le_frequency, le->le_pin, pol,
- band, freq, data1, data2);
- if (le->le_pin != LINUXDVB_EN50494_NOPIN) {
+ band, freq, data1, data2, data3);
+ if (!ver2 && 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 {
+ } else if (!ver2) {
ret = linuxdvb_diseqc_send(fd,
LINUXDVB_EN50494_FRAME,
LINUXDVB_EN50494_ADDRESS,
LINUXDVB_EN50494_CMD_NORMAL,
2,
data1, data2);
+ } else if (ver2 && le->le_pin != LINUXDVB_EN50494_NOPIN) {
+ ret = linuxdvb_diseqc_raw_send(fd,
+ LINUXDVB_EN50607_FRAME_MULTIHOME,
+ 4,
+ data1, data2, data3, (uint8_t)le->le_pin);
+ } else if (ver2) {
+ ret = linuxdvb_diseqc_raw_send(fd,
+ LINUXDVB_EN50607_FRAME_NORMAL,
+ 3,
+ data1, data2, data3);
}
if (ret != 0) {
tvherror(LS_EN50494, "error send tune command");
{
htsmsg_t *m = htsmsg_create_list();
htsmsg_add_str(m, NULL, tvh_gettext_lang(lang, N_("None")));
- htsmsg_add_str(m, NULL, tvh_gettext_lang(lang, N_("Generic")));
+ htsmsg_add_str(m, NULL, tvh_gettext_lang(lang, N_(UNICABLE_I_NAME)));
+ htsmsg_add_str(m, NULL, tvh_gettext_lang(lang, N_(UNICABLE_II_NAME)));
return m;
}
linuxdvb_diseqc_t *ld;
linuxdvb_en50494_t *le;
- if (strcmp(name ?: "", "Generic"))
+ if (strcmp(name ?: "", "Generic") &&
+ strcmp(name ?: "", UNICABLE_I_NAME) &&
+ strcmp(name ?: "", UNICABLE_II_NAME))
return NULL;
- if (port > 1) {
+ if (linuxdvb_unicable_is_en50494(name) && port > 1) {
tvherror(LS_EN50494, "only 2 ports/positions are possible. given %i", port);
port = 0;
}
+ if (linuxdvb_unicable_is_en50607(name) && port > 63) {
+ tvherror(LS_EN50494, "only 64 ports/positions are possible. given %i", port);
+ port = 0;
+ }
+
le = calloc(1, sizeof(linuxdvb_en50494_t));
if (le == NULL)
return NULL;
le->ld_match = linuxdvb_en50494_match;
ld = linuxdvb_diseqc_create0((linuxdvb_diseqc_t *)le,
- NULL, &linuxdvb_en50494_class, conf,
- "Generic", ls);
+ NULL,
+ linuxdvb_unicable_is_en50607(name) ?
+ &linuxdvb_en50607_class :
+ &linuxdvb_en50494_class,
+ conf, name, ls);
if (ld) {
- ld->ld_tune = linuxdvb_en50494_tune;
+ ld->ld_tune = linuxdvb_en50494_tune;
/* May not needed: ld->ld_grace = linuxdvb_en50494_grace; */
}
int (*lnb_pol) (linuxdvb_lnb_t*, dvb_mux_t*);
};
+#define UNICABLE_EN50494 50494
+#define UNICABLE_EN50607 50607
+
struct linuxdvb_en50494
{
linuxdvb_diseqc_t;
( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls, int c, int u );
linuxdvb_diseqc_t *linuxdvb_rotor_create0
( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls );
+
+#define UNICABLE_I_NAME "Unicable I (EN50494)"
+#define UNICABLE_II_NAME "Unicable II (EN50607)"
+
linuxdvb_diseqc_t *linuxdvb_en50494_create0
( const char *name, htsmsg_t *conf, linuxdvb_satconf_ele_t *ls, int port );
htsmsg_t *linuxdvb_rotor_list ( void *o, const char *lang );
htsmsg_t *linuxdvb_en50494_list ( void *o, const char *lang );
-htsmsg_t *linuxdvb_en50494_id_list ( void *o, const char *lang );
+htsmsg_t *linuxdvb_en50494_id_list ( void *o, const char *lang );
+htsmsg_t *linuxdvb_en50607_id_list ( void *o, const char *lang );
htsmsg_t *linuxdvb_en50494_pin_list ( void *o, const char *lang );
+static inline int linuxdvb_unicable_is_en50607( const char *str )
+ { return strcmp(str, UNICABLE_II_NAME) == 0; }
+static inline int linuxdvb_unicable_is_en50494( const char *str )
+ { return !linuxdvb_unicable_is_en50607(str); }
+
void linuxdvb_en50494_init (void);
+int linuxdvb_diseqc_raw_send (int fd, uint8_t len, ...);
int
linuxdvb_diseqc_send
(int fd, uint8_t framing, uint8_t addr, uint8_t cmd, uint8_t len, ...);
.ic_super = &linuxdvb_satconf_class,
.ic_class = "linuxdvb_satconf_en50494",
.ic_doc = tvh_doc_linuxdvb_satconf_class,
- .ic_caption = N_("TV Adapters - SatConfig - EN50494/UniCable (experimental)"),
+ .ic_caption = N_("TV Adapters - SatConfig - EN50494/UniCable I"),
.ic_properties = (const property_t[]) {
{
.type = PT_U16,
}
};
+const idclass_t linuxdvb_satconf_en50607_class =
+{
+ .ic_super = &linuxdvb_satconf_class,
+ .ic_class = "linuxdvb_satconf_en50607",
+ .ic_doc = tvh_doc_linuxdvb_satconf_class,
+ .ic_caption = N_("TV Adapters - SatConfig - EN50607/UniCable II"),
+ .ic_properties = (const property_t[]) {
+ {
+ .type = PT_U16,
+ .id = "id",
+ .name = N_("SCR (ID)"),
+ .desc = N_("SCR (Satellite Channel Router) ID."),
+ .get = linuxdvb_satconf_class_en50494_id_get,
+ .set = linuxdvb_satconf_class_en50494_id_set,
+ .list = linuxdvb_en50607_id_list,
+ .opts = PO_NOSAVE,
+ },
+ {
+ .type = PT_U16,
+ .id = "pin",
+ .name = N_("PIN"),
+ .desc = N_("PIN."),
+ .get = linuxdvb_satconf_class_en50494_pin_get,
+ .set = linuxdvb_satconf_class_en50494_pin_set,
+ .list = linuxdvb_en50494_pin_list,
+ .opts = PO_NOSAVE,
+ },
+ {
+ .type = PT_U16,
+ .id = "frequency",
+ .name = N_("Frequency (MHz)"),
+ .desc = N_("Frequency (in MHz)."),
+ .get = linuxdvb_satconf_class_en50494_freq_get,
+ .set = linuxdvb_satconf_class_en50494_freq_set,
+ .opts = PO_NOSAVE,
+ },
+ {
+ .type = PT_STR,
+ .id = "network_a",
+ .name = N_("Network A"),
+ .desc = N_("Network for port A."),
+ .islist = 1,
+ .get = linuxdvb_satconf_class_network_get0,
+ .set = linuxdvb_satconf_class_network_set0,
+ .list = linuxdvb_satconf_class_network_enum,
+ .rend = linuxdvb_satconf_class_network_rend0,
+ .opts = PO_NOSAVE,
+ },
+ {
+ .type = PT_STR,
+ .id = "network_b",
+ .name = N_("Network B"),
+ .desc = N_("Network for port B."),
+ .islist = 1,
+ .get = linuxdvb_satconf_class_network_get1,
+ .set = linuxdvb_satconf_class_network_set1,
+ .list = linuxdvb_satconf_class_network_enum,
+ .rend = linuxdvb_satconf_class_network_rend1,
+ .opts = PO_NOSAVE,
+ },
+ {
+ .type = PT_STR,
+ .id = "network_c",
+ .name = N_("Network C"),
+ .desc = N_("Network for port C."),
+ .islist = 1,
+ .get = linuxdvb_satconf_class_network_get2,
+ .set = linuxdvb_satconf_class_network_set2,
+ .list = linuxdvb_satconf_class_network_enum,
+ .rend = linuxdvb_satconf_class_network_rend2,
+ .opts = PO_NOSAVE,
+ },
+ {
+ .type = PT_STR,
+ .id = "network_d",
+ .name = N_("Network D"),
+ .desc = N_("Network for port D."),
+ .islist = 1,
+ .get = linuxdvb_satconf_class_network_get3,
+ .set = linuxdvb_satconf_class_network_set3,
+ .list = linuxdvb_satconf_class_network_enum,
+ .rend = linuxdvb_satconf_class_network_rend3,
+ .opts = PO_NOSAVE,
+ },
+ {}
+ }
+};
+
/*
* Advanced
*/
},
{
.type = "en50494",
- .name = N_("Unicable switch (universal LNB, experimental)"),
+ .name = N_("Unicable I switch (universal LNB)"),
.idc = &linuxdvb_satconf_en50494_class,
.ports = 2,
},
+ {
+ .type = "en50607",
+ .name = N_("Unicable II switch (universal LNB)"),
+ .idc = &linuxdvb_satconf_en50607_class,
+ .ports = 4,
+ },
{
.type = "advanced",
.name = N_("Advanced (non-universal LNBs, rotors, etc.)"),
if (lst->ports > 1) {
if (!strcmp(lst->type, "en50494")) {
if (!lse->lse_en50494)
- lse->lse_en50494 = linuxdvb_en50494_create0("Generic", NULL, lse, i);
+ lse->lse_en50494 = linuxdvb_en50494_create0(UNICABLE_I_NAME, NULL, lse, i);
+ } else if (!strcmp(lst->type, "en50607")) {
+ if (!lse->lse_en50494)
+ lse->lse_en50494 = linuxdvb_en50494_create0(UNICABLE_II_NAME, NULL, lse, i);
} else {
if (!lse->lse_switch)
lse->lse_switch = linuxdvb_switch_create0("Generic", NULL, lse, i, -1);
free((void *)ld->ld_type);
}
+int
+linuxdvb_diseqc_raw_send
+ (int fd, uint8_t len, ...)
+{
+ int i;
+ va_list ap;
+ struct dvb_diseqc_master_cmd message;
+ char buf[256];
+ size_t c = 0;
+
+ /* Build message */
+ message.msg_len = len;
+ va_start(ap, len);
+ for (i = 0; i < len; i++) {
+ message.msg[i] = (uint8_t)va_arg(ap, int);
+ if (tvhtrace_enabled())
+ tvh_strlcatf(buf, sizeof(buf), c, "%02X ", message.msg[3 + i]);
+ }
+ va_end(ap);
+
+ if (tvhtrace_enabled())
+ tvhtrace(LS_DISEQC, "sending raw diseqc (len %d) %s", len, buf);
+
+ /* Send */
+ if (ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &message)) {
+ tvherror(LS_DISEQC, "failed to send diseqc cmd (e=%s)", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
int
linuxdvb_diseqc_send
(int fd, uint8_t framing, uint8_t addr, uint8_t cmd, uint8_t len, ...)
struct dvb_diseqc_master_cmd message;
char buf[256];
size_t c = 0;
- int tr = tvhtrace_enabled();
/* Build message */
message.msg_len = len + 3;
va_start(ap, len);
for (i = 0; i < len; i++) {
message.msg[3 + i] = (uint8_t)va_arg(ap, int);
- if (tr)
+ if (tvhtrace_enabled())
tvh_strlcatf(buf, sizeof(buf), c, "%02X ", message.msg[3 + i]);
}
va_end(ap);
- if (tr)
+ if (tvhtrace_enabled())
tvhtrace(LS_DISEQC, "sending diseqc (len %d) %02X %02X %02X %s",
len + 3, framing, addr, cmd, buf);