diff --git a/adapter.c b/adapter.c index cd5d8f5..2bb026c 100644 --- a/adapter.c +++ b/adapter.c @@ -117,6 +117,7 @@ int adapter_timeout(sockets *s) return 0; } +#ifndef AXE if (opts.no_threads) { for (i = 0; i < MAX_ADAPTERS; i++) @@ -133,6 +134,7 @@ int adapter_timeout(sockets *s) s->sid, do_close, max_close); if (!do_close) s->rtime = max_close; +#endif return do_close; } @@ -617,6 +619,7 @@ int tune(int aid, int sid) ad->status = -1; ad->status_cnt = 0; set_socket_pos(ad->sock, 0); // flush the existing buffer + set_socket_skip(ad->sock); ad->rlen = 0; if (ad->sid_cnt > 1) // the master changed the frequency { @@ -1304,6 +1307,53 @@ void set_slave_adapters(char *o) } } + +void set_link_adapters(char *o) +{ + int i, la, a_id, b_id; + char buf[100], *arg[20], *sep1; + + strncpy(buf, o, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + la = split(arg, buf, sizeof(arg), ','); + for (i=0; i= MAX_ADAPTERS) + continue; + sep1 = strchr(arg[i], ':'); + if (!sep1) + continue; + b_id=map_intd(sep1 + 1, NULL, -1); + if (b_id < 0 || b_id >= MAX_ADAPTERS) + continue;; + if (a_id == b_id || a[a_id]->slave) + continue; + a[a_id]->slave = a_id + 1; + LOG("Setting adapter %d as master for adapter %d", a_id, b_id); + } +} + +void set_unicable_input(char *o) +{ + int i, la, input, input2; + char buf[100], *arg[20], *sep1; + + strncpy(buf, o, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + la = split(arg, buf, sizeof(arg), ','); + for (i=input=0; i < 4; i++) + { + if (i < la) { + input2=map_intd(arg[i], NULL, -1); + if (input2 >= 0 && input2 < 4) + input = input2; + } + opts.axe_unicinp[i] = input; + LOG("Setting input %d for unicable adapter %d", input, i); + } +} + extern char *fe_delsys[]; void set_adapters_delsys(char *o) { diff --git a/adapter.h b/adapter.h index 39d4d5f..c4eb45f 100644 --- a/adapter.h +++ b/adapter.h @@ -6,7 +6,11 @@ typedef struct ca_device ca_device_t; #define MAX_ADAPTERS 16 +#ifdef AXE +#define DVR_BUFFER 14*7*DVB_FRAME +#else #define DVR_BUFFER 30*1024*188 +#endif #ifdef NO_BACKTRACE #define MAX_STREAMS_PER_PID 8 #else @@ -63,7 +67,7 @@ typedef struct struct_adapter char enabled; SMutex mutex; char type; // available on the system - int fe, dvr, dmx; + int fe, fe2, dvr, dmx; int pa, fn; // physical adapter, physical frontend number fe_delivery_system_t sys[MAX_DELSYS]; @@ -85,6 +89,9 @@ typedef struct struct_adapter uint16_t strength, snr, max_strength, max_snr; uint32_t pid_err, dec_err; // detect pids received but not part of any stream, decrypt errors diseqc diseqc_param; + int slave; + int axe_used; + int axe_feused; int old_diseqc; int old_hiband; int old_pol; @@ -131,6 +138,8 @@ void set_diseqc_adapters(char *o); void set_diseqc_timing(char *o); void set_slave_adapters(char *o); void set_adapter_dmxsource(char *o); +void set_link_adapters(char *o); +void set_unicable_input(char *o); void reset_pids_type(int aid, int clear_pat); void reset_ecm_type_for_key(int aid, int key); int delsys_match(adapter *ad, int del_sys); diff --git a/axe.h b/axe.h new file mode 100644 index 0000000..d8b06bc --- /dev/null +++ b/axe.h @@ -0,0 +1,149 @@ +#ifndef __AXE_H +#define __AXE_H + +#include +#include + +typedef struct fe_frontend_status fe_frontend_status_t; + +struct fe_frontend_status { + __u32 val0; + __u32 val1; + __u32 val2; + __u32 modulation; + __u32 val4; + __u32 frequency; + __u32 val6; + __u32 val7; + __u32 symbol_rate; + __u32 val9; + __u32 fec; + __u32 rolloff; + __u32 val12; + __u32 val13; +} __attribute__ ((packed)); + +#define FE_FRONTEND_STANDBY _IOW('o', 91, __u32) +#define FE_FRONTEND_RESET _IO('o', 93) +#define FE_FRONTEND_STATUS _IOR('o', 96, fe_frontend_status_t) +#define FE_FRONTEND_INPUT _IOW('o', 97, __u8) + +static inline int axe_fe_standby(int fd, __u32 stdby) +{ + return ioctl(fd, FE_FRONTEND_STANDBY, &stdby); +} + +static inline int axe_fe_reset(int fd) +{ + return ioctl(fd, FE_FRONTEND_RESET, 0x54); +} + +static inline int axe_fe_input(int fd, __u8 in) +{ + return ioctl(fd, FE_FRONTEND_INPUT, &in); +} + +typedef struct dmx_stream_params_s { + __u32 srcIp; + __u16 srcPort; + __u16 dstPort; + __u32 dstIp; + __u32 ts; /* timestamp */ + __u32 ssrc; /* synchronization source */ + __u16 seq; +} dmx_stream_params_t; + +typedef struct rtp_state { + __u32 ssrc; + __u32 ts; + __u32 spc; + __u32 soc; + __u16 seq; +} rtp_state_t; + +#define DMXTS_ADD_PID _IOW('o', 1, __u16) +#define DMXTS_REMOVE_PID _IOW('o', 2, __u16) + +#define DMXTS_TRANSFER_START _IO('o', 5) +#define DMXTS_TRANSFER_START_RTP _IOW('o', 6, dmx_stream_params_t) +#define DMXTS_TRANSFER_STOP _IO('o', 7) +#define DMXTS_RTP_SETUP_SSRC _IOW('o', 8, __u32) +#define DMXTS_TRANSFER_PAUSE _IO('o', 9) +#define DMXTS_TRANSFER_RESUME _IO('o', 10) + +#define DMXTS_GET_RTP_STREAM_STATE _IOR('o', 11, rtp_state_t) + +static inline int axe_dmxts_add_pid(int fd, __u16 pid) +{ + return ioctl(fd, DMXTS_ADD_PID, &pid); +} + +static inline int axe_dmxts_remove_pid(int fd, __u16 pid) +{ + return ioctl(fd, DMXTS_REMOVE_PID, &pid); +} + +static inline int axe_dmxts_start(int fd) +{ + return ioctl(fd, DMXTS_TRANSFER_START); +} + +#ifdef AXE_MAIN + +int axe_fp_fd = -1; + +static inline axe_fp_fd_open(void) +{ + if (axe_fp_fd < 0) + axe_fp_fd = open("/dev/axe/fp-0", O_WRONLY); +} + +static inline axe_fp_fd_write(const char *s) +{ + const char *b; + size_t len; + ssize_t r; + + axe_fp_fd_open(); + len = strlen(b = s); + while (len > 0) { + r = write(axe_fp_fd, b, len); + if (r > 0) { + len -= r; + b += r; + } + } +} + +void axe_set_tuner_led(int tuner, int on) +{ + static int state = 0; + char buf[16]; + if (((state >> tuner) & 1) != !!on) { + sprintf(buf, "T%d_LED %d\n", tuner, on ? 1 : 0); + axe_fp_fd_write(buf); + if (on) + state |= 1 << tuner; + else + state &= ~(1 << tuner); + } +} + +void axe_set_network_led(int on) +{ + static int state = -1; + if (state != on) { + axe_fp_fd_write(on ? "NET_LED 1\n" : "NET_LED 0\n"); + state = on; + } +} + +#else + +void axe_set_tuner_led(int tuner, int on); +void axe_set_network_led(int on); +void axe_status(char *buf, size_t buflen); + +#endif + +#endif diff --git a/dvb.c b/dvb.c index 74124fc..bcfc684 100644 --- a/dvb.c +++ b/dvb.c @@ -42,6 +42,11 @@ #include "ca.h" #include "utils.h" +#ifdef AXE +#define AXE_MAIN 1 +#include "axe.h" +#endif + char *fe_pilot[] = { "on", "off", " ", //auto NULL }; @@ -329,25 +334,40 @@ int dvb_open_device(adapter *ad) char buf[100]; LOG("trying to open [%d] adapter %d and frontend %d", ad->id, ad->pa, ad->fn); +#ifdef AXE + sprintf(buf, "/dev/axe/frontend-%d", ad->pa); + if (ad->fe2 > 0) + ad->fe = ad->fe2; + else + ad->fe = ad->fe2 = open(buf, O_RDWR | O_NONBLOCK); + sprintf(buf, "/dev/axe/demuxts-%d", ad->pa); + ad->dvr = open(buf, O_RDONLY | O_NONBLOCK); +#else sprintf(buf, "/dev/dvb/adapter%d/frontend%d", ad->pa, ad->fn); ad->fe = open(buf, O_RDWR | O_NONBLOCK); sprintf(buf, "/dev/dvb/adapter%d/dvr%d", ad->pa, ad->fn); ad->dvr = open(buf, O_RDONLY | O_NONBLOCK); +#endif if (ad->fe < 0 || ad->dvr < 0) { +#ifdef AXE + sprintf(buf, "/dev/axe/frontend-%d", ad->pa); +#else sprintf(buf, "/dev/dvb/adapter%d/frontend%d", ad->pa, ad->fn); +#endif LOGL(0, "Could not open %s in RW mode (fe: %d, dvr: %d)", buf, ad->fe, ad->dvr); if (ad->fe >= 0) close(ad->fe); if (ad->dvr >= 0) close(ad->dvr); - ad->fe = ad->dvr = -1; + ad->fe = ad->fe2 = ad->dvr = -1; return 1; } ad->type = ADAPTER_DVB; ad->dmx = -1; LOG("opened DVB adapter %d fe:%d dvr:%d", ad->id, ad->fe, ad->dvr); +#ifndef AXE if (ioctl(ad->dvr, DMX_SET_BUFFER_SIZE, opts.dvr_buffer) < 0) LOG("couldn't set DVR buffer size error %d: %s", errno, strerror(errno)) else @@ -367,7 +387,7 @@ int dvb_open_device(adapter *ad) LOG("Set DMX_SET_SOURCE for adapter %d to %d", ad->id, ad->dmx_source); } - +#endif return 0; } @@ -393,6 +413,46 @@ void diseqc_cmd(int fd, int times, char *str, struct dvb_diseqc_master_cmd *cmd, } +#ifdef AXE +void axe_wakeup(int fe_fd, int voltage) +{ + int i, mask; + adapter *a; + if (opts.axe_power < 2) + return; + for (i = 0; i < 4; i++) { + a = get_adapter(i); + if (a == NULL || is_adapter_disabled(i)) + continue; + if (a->old_pol >= 0) + return; + } + LOG("AXE wakeup"); + for (i = mask = 0; i < 4; i++) { + /* lowband enabled */ + if (opts.quattro && opts.quattro_hiband == 1 && i < 2) { + mask = 3; + continue; + } + /* hiband enabled */ + if (opts.quattro && opts.quattro_hiband == 2 && i >= 2) { + mask = 3<<2; + continue; + } + mask |= 1<fe, FE_SET_VOLTAGE, voltage) == -1) + LOG("axe_wakeup: FE_SET_VOLTAGE failed fd %d: %s", a->fe, strerror(errno)); + } +} +#endif + int send_diseqc(int fd, int pos, int pos_change, int pol, int hiband, diseqc *d) { int committed_no = d->committed_no; @@ -428,6 +488,9 @@ int send_diseqc(int fd, int pos, int pos_change, int pol, int hiband, diseqc *d) LOGL(3, "send_diseqc fd %d, pos = %d (c %d u %d), pol = %d, hiband = %d", fd, pos, posc, posu, pol, hiband); +#ifdef AXE + axe_wakeup(fd, pol ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13); +#endif if (ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1) LOG("send_diseqc: FE_SET_TONE failed for fd %d: %s", fd, strerror(errno)); @@ -490,6 +553,9 @@ int send_unicable(int fd, int freq, int pos, int pol, int hiband, diseqc *d) "send_unicable fd %d, freq %d, ufreq %d, pos = %d, pol = %d, hiband = %d, slot %d, diseqc => %02x %02x %02x %02x %02x", fd, freq, d->ufreq, pos, pol, hiband, d->uslot, cmd.msg[0], cmd.msg[1], cmd.msg[2], cmd.msg[3], cmd.msg[4]); +#ifdef AXE + axe_wakeup(fd, SEC_VOLTAGE_13); +#endif if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13) == -1) LOG("send_unicable: pre voltage SEC_VOLTAGE_13 failed for fd %d: %s", fd, strerror(errno)); @@ -537,6 +603,9 @@ int send_jess(int fd, int freq, int pos, int pol, int hiband, diseqc *d) fd, freq, d->ufreq, pos, pol, hiband, d->uslot, cmd.msg[0], cmd.msg[1], cmd.msg[2], cmd.msg[3], cmd.msg[4]); +#ifdef AXE + axe_wakeup(fd, SEC_VOLTAGE_13); +#endif if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13) == -1) LOG("send_jess: pre voltage SEC_VOLTAGE_13 failed for fd %d: %s", fd, strerror(errno)); @@ -559,6 +628,23 @@ int send_jess(int fd, int freq, int pos, int pol, int hiband, diseqc *d) return d->ufreq * 1000; } +#ifdef AXE +static inline int extra_quattro(int input, int diseqc, int *equattro) +{ + if (diseqc <= 0) + *equattro = 0; + /* lowband allowed - control the hiband inputs independently for positions src=2+ */ + else if (opts.quattro && opts.quattro_hiband == 1 && input < 2) + *equattro = diseqc; + /* hiband allowed - control the lowband inputs independently for positions src=2+ */ + else if (opts.quattro && opts.quattro_hiband == 2 && input >= 2 && input < 4) + *equattro = diseqc; + else + *equattro = 0; + return *equattro; +} +#endif + int setup_switch(int frontend_fd, adapter *ad, transponder *tp) { int hiband = 0; @@ -582,15 +668,111 @@ int setup_switch(int frontend_fd, adapter *ad, transponder *tp) hiband = 1; } +#ifdef AXE + adapter *ad2, *adm; + int input = 0, aid, equattro = 0; + + ad->axe_feused = 1; + if (tp->diseqc_param.switch_type != SWITCH_UNICABLE && + tp->diseqc_param.switch_type != SWITCH_JESS) { + input = ad->id; + if (!opts.quattro || extra_quattro(input, diseqc, &equattro)) { + if (equattro > 0) + diseqc = equattro - 1; + adm = get_adapter(ad->slave ? ad->slave - 1 : ad->pa); + if (adm == NULL) { + LOG("axe_fe: unknown master adapter %d", input); + return 0; + } + if (adm->old_pol >= 0) { + for (aid = 0; aid < 4; aid++) { + ad2 = get_adapter(aid); + if (!ad2 || ad == ad2) continue; + if (ad2->slave && ad2->slave - 1 != adm->pa) continue; + if (!ad2->slave && ad2 != adm) continue; + if (ad2->sid_cnt > 0) break; + } + if (adm != ad && aid < 4 && + (adm->old_pol != pol || + adm->old_hiband != hiband || + adm->old_diseqc != diseqc)) + return 0; + } + adm->axe_used |= (1 << input); + adm->axe_feused = 1; + if (ad->slave) { + input = ad->slave - 1; + if(adm->old_pol != pol || + adm->old_hiband != hiband || + adm->old_diseqc != diseqc) { + send_diseqc(adm->fe, diseqc, adm->old_diseqc != diseqc, + pol, hiband, &tp->diseqc_param); + adm->old_pol = pol; + adm->old_hiband = hiband; + adm->old_diseqc = diseqc; + } + goto axe; + } + } else if (opts.quattro) { + if (opts.quattro_hiband == 1 && hiband) { + LOG("axe_fe: hiband is not allowed for quattro config (adapter %d)", input); + return 0; + } + if (opts.quattro_hiband == 2 && !hiband) { + LOG("axe_fe: lowband is not allowed for quattro config (adapter %d)", input); + return 0; + } + input = ((hiband ^ 1) << 1) | (pol ^ 1); + adm = get_adapter(input); + if (adm == NULL) { + LOG("axe_fe: unknown master adapter %d", input); + return 0; + } + if(adm->old_pol != pol || adm->old_hiband != hiband) { + send_diseqc(adm->fe, 0, 0, pol, hiband, + &tp->diseqc_param); + adm->old_pol = pol; + adm->old_hiband = hiband; + adm->old_diseqc = diseqc = 0; + } + adm->axe_used |= (1 << ad->id); + adm->axe_feused = 1; + goto axe; + } + } else { + aid = ad->id & 3; + input = opts.axe_unicinp[aid]; + ad = get_adapter(input); + if (ad == NULL) { + LOGL(3, "axe setup: unable to find adapter %d", input); + return 0; + } + ad->axe_used |= (1 << aid); + ad->axe_feused = 1; + } +#endif + if (tp->diseqc_param.switch_type == SWITCH_UNICABLE) { - freq = send_unicable(frontend_fd, freq / 1000, diseqc, pol, hiband, - &tp->diseqc_param); +#ifdef AXE + if (ad) + freq = send_unicable(ad->fe, freq / 1000, diseqc, + pol, hiband, &tp->diseqc_param); +#else + freq = send_unicable(frontend_fd, freq / 1000, diseqc, + pol, hiband, &tp->diseqc_param); +#endif } else if (tp->diseqc_param.switch_type == SWITCH_JESS) { - freq = send_jess(frontend_fd, freq / 1000, diseqc, pol, hiband, - &tp->diseqc_param); +#ifdef AXE + if (ad) + freq = send_jess(ad->fe, freq / 1000, diseqc, + pol, hiband, &tp->diseqc_param); +#else + freq = send_jess(frontend_fd, freq / 1000, diseqc, + pol, hiband, &tp->diseqc_param); +#endif } else if (tp->diseqc_param.switch_type == SWITCH_SLAVE) { @@ -609,6 +791,17 @@ int setup_switch(int frontend_fd, adapter *ad, transponder *tp) diseqc); } +#ifdef AXE +axe: + LOGL(3, "axe_fe: reset for fd %d adapter %d input %d", frontend_fd, ad ? ad->pa : -1, input); + if (axe_fe_reset(frontend_fd) < 0) + LOG("axe_fe: RESET failed for fd %d: %s", frontend_fd, strerror(errno)); + if (axe_fe_input(frontend_fd, input)) + LOG("axe_fe: INPUT failed for fd %d input %d: %s", frontend_fd, input, strerror(errno)); + if (opts.quattro) + return freq; +#endif + ad->old_pol = pol; ad->old_hiband = hiband; ad->old_diseqc = diseqc; @@ -644,6 +837,14 @@ int dvb_tune(int aid, transponder * tp) memset(p_cmd, 0, sizeof(p_cmd)); bclear = getTick(); +#ifdef AXE + ssize_t drv; + char buf[1316]; + axe_set_tuner_led(aid + 1, 1); + axe_fe_reset(ad->fe); + do { drv = read(ad->dvr, buf, sizeof(buf)); } while (drv > 0); +#endif + if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmdseq_clear)) == -1) { LOG("FE_SET_PROPERTY DTV_CLEAR failed for fd %d: %s", fd_frontend, @@ -663,8 +864,10 @@ int dvb_tune(int aid, transponder * tp) ADD_PROP(DTV_SYMBOL_RATE, tp->sr) ADD_PROP(DTV_INNER_FEC, tp->fec) +#ifndef AXE ADD_PROP(DTV_PILOT, tp->plts) ADD_PROP(DTV_ROLLOFF, tp->ro) +#endif #if DVBAPIVERSION >= 0x0502 ADD_PROP(DTV_STREAM_ID, tp->plp) #endif @@ -673,7 +876,12 @@ int dvb_tune(int aid, transponder * tp) "tuning to %d(%d) pol: %s (%d) sr:%d fec:%s delsys:%s mod:%s rolloff:%s pilot:%s, ts clear=%d, ts pol=%d", tp->freq, freq, get_pol(tp->pol), tp->pol, tp->sr, fe_fec[tp->fec], fe_delsys[tp->sys], fe_modulation[tp->mtype], - fe_rolloff[tp->ro], fe_pilot[tp->plts], bclear, bpol) +#ifdef AXE + "auto", "auto", +#else + fe_rolloff[tp->ro], fe_pilot[tp->plts], +#endif + bclear, bpol) break; case SYS_DVBT: @@ -774,29 +982,46 @@ int dvb_tune(int aid, transponder * tp) if (ioctl(fd_frontend, FE_SET_PROPERTY, &p) == -1) { LOG("dvb_tune: set property failed %d %s", errno, strerror(errno)); +#ifdef AXE + axe_set_tuner_led(aid + 1, 0); +#endif return -404; } +#ifdef AXE + axe_dmxts_start(ad->dvr); +#endif + return 0; } int dvb_set_pid(adapter *a, uint16_t i_pid) { +#ifdef AXE + if (i_pid > 8192 || a == NULL) + LOG_AND_RETURN(-1, "pid %d > 8192 for ADAPTER %d", i_pid, a->id); + if (axe_dmxts_add_pid(a->dvr, i_pid) < 0) + { + LOG("failed setting filter on PID %d for ADAPTER %d (%s)", i_pid, a->id, strerror (errno)); + return -1; + } + LOG("setting filter on PID %d for ADAPTER %d", i_pid, a->id); + return ((a->id + 1) << 16) | i_pid; +#else char buf[100]; int fd; int hw, ad; + sprintf(buf, "/dev/dvb/adapter%d/demux%d", hw, ad); + hw = a->pa; ad = a->fn; if (i_pid > 8192) - LOG_AND_RETURN(-1, "pid %d > 8192 for /dev/dvb/adapter%d/demux%d", - i_pid, hw, ad); + LOG_AND_RETURN(-1, "pid %d > 8192 for %s", i_pid, buf); - sprintf(buf, "/dev/dvb/adapter%d/demux%d", hw, ad); if ((fd = open(buf, O_RDWR | O_NONBLOCK)) < 0) { - LOG("Could not open demux device /dev/dvb/adapter%d/demux%d: %s ", hw, - ad, strerror (errno)); + LOG("Could not open demux device %s: %s ", buf, strerror (errno)); return -1; } @@ -822,10 +1047,22 @@ int dvb_set_pid(adapter *a, uint16_t i_pid) LOG("setting filter on PID %d for fd %d", i_pid, fd); return fd; +#endif } int dvb_del_filters(int fd, int pid) { +#ifdef AXE + adapter *a = get_adapter((fd >> 16) - 1); + if (a == NULL) + return 0; /* closed */ + if ((fd & 0xffff) != pid) + LOG_AND_RETURN(0, "AXE PID remove on an invalid handle %d, pid %d", fd, pid); + if (axe_dmxts_remove_pid(a->dvr, pid) < 0) + LOG("AXE PID remove failed on PID %d ADAPTER %d: %s", pid, a->pa, strerror (errno)) + else + LOG("clearing filters on PID %d ADAPTER %d", pid, a->pa); +#else if (fd < 0) LOG_AND_RETURN(0, "DMX_STOP on an invalid handle %d, pid %d", fd, pid); if (ioctl(fd, DMX_STOP, NULL) < 0) @@ -834,10 +1071,20 @@ int dvb_del_filters(int fd, int pid) LOG("clearing filter on PID %d FD %d", pid, fd); close(fd); return 0; +#endif } fe_delivery_system_t dvb_delsys(int aid, int fd, fe_delivery_system_t *sys) { +#ifdef AXE + int i; + LOG ("Delivery System DVB-S/DVB-S2 (AXE)"); + for(i = 0 ; i < 10 ; i ++) + sys[i] = 0; + sys[0] = SYS_DVBS; + sys[1] = SYS_DVBS2; + return SYS_DVBS2; +#else int i, res, rv = 0; struct dvb_frontend_info fe_info; @@ -926,6 +1173,7 @@ fe_delivery_system_t dvb_delsys(int aid, int fd, fe_delivery_system_t *sys) fe_delsys[sys[i]], sys[i]); return (fe_delivery_system_t) rv; +#endif } @@ -1037,6 +1285,7 @@ void dvb_get_signal(adapter *ad) ad->max_strength = (ad->strength > 0) ? ad->strength : 1; if (ad->max_snr <= ad->snr) ad->max_snr = (ad->snr > 0) ? ad->snr : 1; +#ifndef AXE if (ad->snr > 4096) new_gs = 0; if (new_gs) @@ -1049,6 +1298,14 @@ void dvb_get_signal(adapter *ad) ad->strength = ad->strength >> 8; ad->snr = ad->snr >> 8; } +#else + ad->strength = ad->strength * 240 / 24000; + if (ad->strength > 240) + ad->strength = 240; + ad->snr = ad->snr * 15 / 54000; + if (ad->snr > 15) + ad->snr = 15; +#endif } void dvb_commit(adapter *a) @@ -1056,12 +1313,52 @@ void dvb_commit(adapter *a) return; } -void dvb_close(adapter *a) +int dvb_close(adapter *a2) { +#ifdef AXE + adapter *c; + int aid, busy; + if (a2->fe <= 0) + return; + a2->fe = -1; + if (a2->fe2 > 0) + axe_fe_reset(a2->fe2); + for (aid = busy = 0; aid < 4; aid++) { + c = a[aid]; + c->axe_used &= ~(1 << a2->id); + if (c->axe_used || c->fe > 0) busy++; + } + if (busy > 0 && opts.axe_power > 1) + goto nostandby; + for (aid = 0; aid < 4; aid++) { + c = a[aid]; + if (opts.axe_power < 2 && c != a2 && busy) + continue; + if (c->axe_used != 0 || c->sid_cnt > 0) { + LOG("AXE standby: adapter %d busy (cnt=%d/used=%04x/fe=%d), keeping", + aid, c->sid_cnt, c->axe_used, c->fe); + continue; + } + if (c->fe2 < 0) + continue; + LOG("AXE standby: adapter %d", aid); + axe_fe_standby(c->fe2, -1); + axe_set_tuner_led(aid + 1, 0); + ioctl(c->fe2, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF); + close(c->fe2); + c->fe2 = -1; + c->axe_feused = 0; + c->old_diseqc = c->old_pol = c->old_hiband = -1; + } +nostandby: + axe_set_tuner_led(a2->id + 1, 0); + return 0; +#else if (a->dmx >= 0) close(a->dmx); a->dmx = -1; - return; +#endif + return 0; } void find_dvb_adapter(adapter **a) @@ -1072,9 +1369,21 @@ void find_dvb_adapter(adapter **a) int i = 0, j = 0; adapter *ad; +#ifdef AXE + axe_set_network_led(0); +#endif for (i = 0; i < MAX_ADAPTERS; i++) for (j = 0; j < MAX_ADAPTERS; j++) { +#ifdef AXE + if (i < 4 && j == 0) { + axe_set_tuner_led(i + 1, 0); + sprintf(buf, "/dev/axe/frontend-%d", i); + fd = open(buf, O_RDONLY | O_NONBLOCK); + } else { + continue; + } +#else sprintf(buf, "/dev/dvb/adapter%d/frontend%d", i, j); fd = open(buf, O_RDONLY | O_NONBLOCK); if (fd < 0) @@ -1082,7 +1391,8 @@ void find_dvb_adapter(adapter **a) sprintf(buf, "/dev/dvb/adapter%d/ca%d", i, j); fd = open(buf, O_RDONLY | O_NONBLOCK); } - //LOG("testing device %s -> fd: %d",buf,fd); +#endif + LOG("testing device %s -> fd: %d",buf,fd); if (fd >= 0) { // if (is_adapter_disabled(na)) @@ -1113,6 +1423,14 @@ void find_dvb_adapter(adapter **a) if (na == MAX_ADAPTERS) return; } +#ifdef AXE + else { + if (i < 4) { + LOGL(0, "AXE - cannot open %s: %i", buf, errno); + sleep(60); + } + } +#endif } for (; na < MAX_ADAPTERS; na++) if (a[na]) diff --git a/html/status.html b/html/status.html index 15dc0fa..01fe57f 100644 --- a/html/status.html +++ b/html/status.html @@ -16,6 +16,10 @@ font-family: Tahoma, Geneva, sans-serif; font-size: 1em; } + .level { + display: inline; + white-space: nowrap; + } /* .enabled { color: green; @@ -33,12 +37,8 @@ -This page will refresh every 5 seconds.