diff --git a/adapter.c b/adapter.c index ec07d56..ade0c02 100644 --- a/adapter.c +++ b/adapter.c @@ -59,6 +59,9 @@ adapter *adapter_alloc() { adapter *ad = malloc1(sizeof(adapter)); memset(ad, 0, sizeof(adapter)); + + mutex_init(&ad->mutex); + /* diseqc setup */ ad->diseqc_param.fast = opts.diseqc_fast; ad->diseqc_param.committed_no = opts.diseqc_committed_no; @@ -127,6 +130,7 @@ int adapter_timeout(sockets *s) return 0; } +#ifndef AXE if (opts.no_threads) { for (i = 0; i < MAX_ADAPTERS; i++) @@ -143,6 +147,7 @@ int adapter_timeout(sockets *s) s->sid, do_close, max_close); if (!do_close) s->rtime = max_close; +#endif return do_close; } @@ -183,7 +188,6 @@ int init_hw(int i) return 2; ad = a[i]; - mutex_init(&ad->mutex); mutex_lock(&ad->mutex); if (is_adapter_disabled(i)) goto NOK; @@ -346,10 +350,12 @@ int close_adapter(int na) ad->sock = -1; ad->strength = 0; ad->snr = 0; +#ifndef AXE ad->old_diseqc = -1; ad->old_hiband = -1; ad->old_pol = -1; - mutex_destroy(&ad->mutex); +#endif + mutex_unlock(&ad->mutex); // if(a[na]->buf)free1(a[na]->buf);a[na]->buf=NULL; LOG("done closing adapter %d", na); return 1; @@ -556,6 +562,19 @@ int set_adapter_for_stream(int sid, int aid) return 0; } +#ifdef AXE +static void free_axe_input(adapter *ad) +{ + int aid; + adapter *ad2; + + for (aid = 0; aid < 4; aid++) { + ad2 = get_adapter2(aid); + ad2->axe_used &= ~(1 << ad->id); + } +} +#endif + void close_adapter_for_stream(int sid, int aid) { adapter *ad; @@ -574,9 +593,12 @@ void close_adapter_for_stream(int sid, int aid) LOG("closed adapter %d for stream %d m:%d s:%d", aid, sid, ad->master_sid, ad->sid_cnt); // delete the attached PIDs as well - if (ad->sid_cnt == 0) + if (ad->sid_cnt == 0) { mark_pids_deleted(aid, -1, NULL); - else +#ifdef AXE + free_axe_input(ad); +#endif + } else mark_pids_deleted(aid, sid, NULL); update_pids(aid); // if (a[aid]->sid_cnt == 0) @@ -672,6 +694,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 { @@ -1003,6 +1026,18 @@ get_adapter1(int aid, char *file, int line) return a[aid]; } +adapter * +get_adapter21(int aid, char *file, int line) +{ + if (aid < 0 || aid >= MAX_ADAPTERS || !a[aid] || disabled[aid]) + { + LOG("%s:%d: get_adapter2 returns NULL for adapter_id %d", file, line, + aid); + return NULL; + } + return a[aid]; +} + char* get_stream_pids(int s_id, char *dest, int max_size); char * describe_adapter(int sid, int aid, char *dad, int ld) @@ -1120,9 +1155,11 @@ void free_all_adapters() { if (a[i]->buf) free1(a[i]->buf); + mutex_destroy(&a[i]->mutex); free(a[i]); a[i] = NULL; } + mutex_destroy(&a_mutex); #ifndef DISABLE_NETCVCLIENT fprintf(stderr, "\n\nREEL: recv_exit\n"); @@ -1375,6 +1412,93 @@ 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] && a[a_id]->slave)) + continue; + if (!a[b_id]) + a[b_id] = adapter_alloc(); + a[b_id]->slave = a_id + 1; + LOGL(0, "Setting adapter %d as master for adapter %d", a_id, b_id); + } +} + +extern int absolute_switch; +extern int absolute_table[32][4]; + +void set_absolute_src(char *o) +{ + int i, la, src, inp, pos; + char buf[100], *arg[20], *inps, *poss; + + strncpy(buf, o, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + la = split(arg, buf, sizeof(arg), ','); + for (i=0; i 31) + continue; + if (inp < 0 || inp > 3) + continue; + if (pos < 0 || pos >= 15) + continue; + LOGL(0, "Setting source %d (src=%d) to input %d position %d", src, src + 1, inp, pos); + absolute_table[src][inp] = pos + 1; + absolute_switch = 1; + } +} + +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; + LOGL(0, "Setting input %d for unicable adapter %d", input, i); + } +} + extern char *fe_delsys[]; void set_adapters_delsys(char *o) { @@ -1643,6 +1767,82 @@ char *get_all_delsys(int aid, char *dest, int max_size) return dest; } +static char *axe_vdevice_read(int aid, char *buf, size_t buflen) +{ + size_t len; + int i, fd; + for (i = 0; i < 10; i++) { + snprintf(buf, buflen, "/proc/STAPI/stpti/PTI%d/vDeviceInfo", aid ^ 1); + fd = open(buf, O_RDONLY); + len = read(fd, buf, buflen-1); + close(fd); + if (len > 200) { + buf[len] = '\0'; + return buf; + } + } + return NULL; +} + +adapter *axe_vdevice_sync(int aid) +{ + adapter *ad = get_adapter_nw(aid); + char buf[1024], *p; + int64_t t; + uint32_t addr, pktc, syncerrc, tperrc, ccerr; + int fd; + + if (!ad) + return NULL; + t = getTickUs(); + if (ad->axe_vdevice_last_sync + 1000000 >= t) + return ad; + ad->axe_vdevice_last_sync = t; + p = axe_vdevice_read(aid, buf, sizeof(buf)); + if (p) p = strchr(p, '\n'); + if (p) { + if (sscanf(p + 1, "#%08x: %08x %08x %08x %08x", + &addr, &pktc, &syncerrc, &tperrc, &ccerr) == 5) { + ad->axe_pktc = pktc; + ad->axe_ccerr = ccerr; + } + } + return ad; +} + +int64_t get_axe_pktc(int aid) +{ + adapter *ad = axe_vdevice_sync(aid); + return ad ? ad->axe_pktc : 0; +} + +int64_t get_axe_ccerr(int aid) +{ + adapter *ad = axe_vdevice_sync(aid); + return ad ? ad->axe_ccerr : 0; +} + +char *get_axe_coax(int aid, char *dest, int max_size) +{ + int i, len; + adapter *ad; + dest[0] = 0; + len = 0; + if (aid < 0 || aid > 3) + return dest; + + for (i = 0; i < 4; i++) { + ad = get_adapter2(i); + if (ad && ad->axe_used & (1< 0) + dest[len - 1] = 0; + + return dest; +} + _symbols adapters_sym[] = { { "ad_enabled", VAR_AARRAY_INT8, a, 1, MAX_ADAPTERS, offsetof(adapter, @@ -1685,4 +1885,7 @@ _symbols adapters_sym[] = { "tuner_c2", VAR_INT, &tuner_c2, 1, 0, 0 }, { "tuner_t", VAR_INT, &tuner_t, 1, 0, 0 }, { "tuner_c", VAR_INT, &tuner_c, 1, 0, 0 }, + { "ad_axe_pktc", VAR_FUNCTION_INT64, (void *) &get_axe_pktc, 0, 0, 0 }, + { "ad_axe_ccerr", VAR_FUNCTION_INT64, (void *) &get_axe_ccerr, 0, 0, 0 }, + { "ad_axe_coax", VAR_FUNCTION_STRING, (void *) &get_axe_coax, 0, 0, 0 }, { NULL, 0, NULL, 0, 0 } }; diff --git a/adapter.h b/adapter.h index 8941f7a..526b38d 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 @@ -62,8 +66,8 @@ typedef struct struct_adapter { char enabled; SMutex mutex; - char type, slow_dev; // available on the system - int fe, dvr, dmx; + char type, slow_dev; // available on the system + int fe, fe2, dvr, dmx; int pa, fn; // physical adapter, physical frontend number fe_delivery_system_t sys[MAX_DELSYS]; @@ -86,6 +90,8 @@ 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 old_diseqc; int old_hiband; int old_pol; @@ -101,6 +107,10 @@ typedef struct struct_adapter Dvb_delsys delsys; Device_signal get_signal; Adapter_commit post_init, close; + + int64_t axe_vdevice_last_sync; + int64_t axe_pktc; + int64_t axe_ccerr; } adapter; extern adapter *a[MAX_ADAPTERS]; @@ -123,6 +133,7 @@ int update_pids(int aid); int tune(int aid, int sid); SPid *find_pid(int aid, int p); adapter * get_adapter1(int aid, char *file, int line); +adapter * get_adapter21(int aid, char *file, int line); char *describe_adapter(int sid, int aid, char *dad, int ld); void dump_pids(int aid); void sort_pids(int aid); @@ -132,6 +143,9 @@ 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_absolute_src(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); @@ -146,6 +160,7 @@ int signal_thread(sockets *s); int compare_tunning_parameters(int aid, transponder * tp); #define get_adapter(a) get_adapter1(a, __FILE__, __LINE__) +#define get_adapter2(a) get_adapter21(a, __FILE__, __LINE__) #define get_adapter_nw(aid) ((aid >= 0 && aid < MAX_ADAPTERS && a[aid] && a[aid]->enabled)?a[aid]:NULL) #define adapter_lock(a) adapter_lock1(__FILE__,__LINE__,a) diff --git a/axe.h b/axe.h new file mode 100644 index 0000000..0bbd074 --- /dev/null +++ b/axe.h @@ -0,0 +1,154 @@ +#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); +} + +static inline int axe_dmxts_stop(int fd) +{ + return ioctl(fd, DMXTS_TRANSFER_STOP); +} + +#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 07195e4..41c678e 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 @@ -369,7 +389,7 @@ int dvb_open_device(adapter *ad) ad->dmx_source); } - +#endif return 0; } @@ -395,6 +415,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; @@ -430,6 +490,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)); @@ -492,6 +555,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)); @@ -539,6 +605,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)); @@ -561,6 +630,55 @@ 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; +} + +adapter *use_adapter(int input) +{ + adapter *ad = input < 4 ? get_adapter2(input) : NULL; + char buf[32]; + if (ad) { + if (ad->fe2 <= 0) { + sprintf (buf, "/dev/axe/frontend-%d", input); + ad->fe2 = open(buf, O_RDONLY | O_NONBLOCK); + LOG("adapter %d force open, fe2: %d", input, ad->fe2); + if (ad->fe2 < 0) + ad = NULL; + } + } + return ad; +} + +int tune_check(adapter *ad, int pol, int hiband, int diseqc) +{ + LOGL(3, "axe: tune check for adapter %d, pol %d/%d, hiband %d/%d, diseqc %d/%d", + ad->id, ad->old_pol, pol, ad->old_hiband, hiband, ad->old_diseqc, diseqc); + if (ad->old_pol != pol) + return 0; + if (ad->old_hiband != hiband) + return 0; + if (ad->old_diseqc != diseqc) + return 0; + return 1; +} + +int absolute_switch; +int absolute_table[32][4]; +#endif + int setup_switch(int frontend_fd, adapter *ad, transponder *tp) { int hiband = 0; @@ -584,15 +702,145 @@ int setup_switch(int frontend_fd, adapter *ad, transponder *tp) hiband = 1; } +#ifdef AXE + adapter *ad2, *adm; + int input = 0, src, aid, pos = 0, equattro = 0, master = -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; + if (absolute_switch && diseqc >= 0 && diseqc < 32) { + /* reuse input */ + for (aid = 0; aid < 4; aid++) { + pos = absolute_table[diseqc][aid]; + if (pos <= 0) continue; + pos--; + ad2 = get_adapter2(aid); + if (!ad2) continue; + if (ad2->fe2 <= 0) continue; + if ((ad2->axe_used & ~(1 << ad->id)) == 0) continue; + if (!tune_check(ad2, pol, hiband, pos)) continue; + break; + } + /* find free input */ + if (aid >= 4) { + for (aid = 0; aid < 4; aid++) { + pos = absolute_table[diseqc][aid]; + if (pos <= 0) continue; + pos--; + ad2 = get_adapter2(aid); + if (!ad2) continue; + LOGL(3, "axe: checking %d used 0x%x in %d", ad->id, ad2->axe_used, ad2->id); + if (ad2->axe_used & ~(1 << ad->id)) continue; + break; + } + } + if (aid >= 4) { + LOGL(0, "unable to find input for diseqc %d (absolute switch), adapter %d", diseqc, input); + return 0; + } + diseqc = pos; + master = aid; + adm = use_adapter(master); + if (adm == NULL) { + LOG("axe_fe: unknown master adapter for input %d", input); + return 0; + } + } else { + master = ad->slave ? ad->slave - 1 : ad->pa; + adm = use_adapter(master); + if (adm == NULL) { + LOG("axe_fe: unknown master adapter for input %d", input); + return 0; + } + if (adm->old_pol >= 0) { + for (aid = 0; aid < 4; aid++) { + ad2 = get_adapter2(aid); + if (!ad2 || ad2->fe2 <= 0 || 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 && !tune_check(adm, pol, hiband, diseqc)) { + LOGL(0, "unable to use slave adapter %d (master %d)", input, adm->pa); + return 0; + } + } + } + adm->axe_used |= (1 << ad->id); + if (master >= 0) { + input = master; + if (!tune_check(adm, pol, hiband, diseqc)) { + send_diseqc(adm->fe2, 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 = use_adapter(input); + if (adm == NULL) { + LOG("axe_fe: unknown master adapter %d", input); + return 0; + } + adm->old_diseqc = diseqc = 0; + if(!tune_check(adm, pol, hiband, 0)) { + send_diseqc(adm->fe2, 0, 0, pol, hiband, + &tp->diseqc_param); + adm->old_pol = pol; + adm->old_hiband = hiband; + adm->old_diseqc = 0; + } + adm->axe_used |= (1 << ad->id); + goto axe; + } + } else { + aid = ad->id & 3; + input = opts.axe_unicinp[aid]; + ad = use_adapter(input); + if (ad == NULL) { + LOGL(3, "axe setup: unable to find adapter %d", input); + return 0; + } + ad->axe_used |= (1 << aid); + } +#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->fe2, 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->fe2, 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) { @@ -615,6 +863,23 @@ int setup_switch(int frontend_fd, adapter *ad, transponder *tp) ad->old_hiband = hiband; ad->old_diseqc = diseqc; +#ifdef AXE +axe: + for (aid = 0; aid < 4; aid++) { + ad2 = get_adapter2(aid); + if (ad2) + LOGL(3, "axe_fe: used[%d] = 0x%x, pol=%d, hiband=%d, diseqc=%d", + aid, ad2->axe_used, ad2->old_pol, ad2->old_hiband, ad2->old_diseqc); + } + LOGL(3, "axe_fe: reset for fd %d adapter %d input %d diseqc %d", frontend_fd, ad ? ad->pa : -1, input, diseqc); + 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 + return freq; } @@ -647,6 +912,15 @@ 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_dmxts_stop(ad->dvr); + 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, @@ -666,8 +940,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 @@ -676,7 +952,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=%jd, ts pol=%jd", 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: @@ -777,29 +1058,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; } @@ -825,10 +1123,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) @@ -837,10 +1147,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; @@ -929,6 +1249,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 } @@ -1041,6 +1362,7 @@ void dvb_get_signal(adapter *ad) ad->max_strength = (strength > 0) ? strength : 1; if (ad->max_snr <= snr) ad->max_snr = (snr > 0) ? snr : 1; +#ifndef AXE if (snr > 4096) new_gs = 0; if (new_gs) @@ -1053,6 +1375,14 @@ void dvb_get_signal(adapter *ad) strength = strength >> 8; snr = snr >> 8; } +#else + strength = strength * 240 / 24000; + if (strength > 240) + strength = 240; + snr = snr * 15 / 54000; + if (snr > 15) + snr = 15; +#endif // keep the assignment at the end for the signal thread to get the right values as no locking is done on the adapter ad->snr = snr; ad->strength = strength; @@ -1065,12 +1395,53 @@ 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_dmxts_stop(a2->fe2); + 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 && c->sock >= 0) + 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->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) @@ -1081,9 +1452,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) @@ -1091,7 +1474,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)) @@ -1122,6 +1506,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/dvbapi.c b/dvbapi.c index ee62007..ea30fc2 100644 --- a/dvbapi.c +++ b/dvbapi.c @@ -978,7 +978,6 @@ int keys_del(int i) enabledKeys = ek; if (!ek && sock > 0) TEST_WRITE(write(sock, buf, sizeof(buf))); - mutex_destroy(&k->mutex); return 0; } @@ -1073,6 +1072,18 @@ void dvbapi_delete_keys_for_adapter(int aid) keys_del(i); } +void free_all_keys(void) +{ + SKey *k; + for (i = 0; i < MAX_KEYS; i++) { + if (key[i]) { + mutex_destroy(&key[i]->mutex); + free(key[i]); + } + } + mutex_destroy(&keys_mutex); +} + _symbols dvbapi_sym[] = { { "key_enabled", VAR_AARRAY_INT8, keys, 1, MAX_KEYS, offsetof(SKey, enabled) }, diff --git a/dvbapi.h b/dvbapi.h index 6c45650..69f1f37 100644 --- a/dvbapi.h +++ b/dvbapi.h @@ -124,5 +124,7 @@ void unregister_dvbapi(); void send_client_info(sockets *s); int set_algo(SKey *k, int algo, int mode); +void free_all_keys(); + #endif #endif diff --git a/html/status.html b/html/status.html index cd000e5..d28a2cc 100644 --- a/html/status.html +++ b/html/status.html @@ -83,6 +83,9 @@ var ad_phyfd = [$ad_phyfd0$, $ad_phyfd1$, $ad_phyfd2$, $ad_phyfd3$, $ad_phyfd4$, var ad_allsys = ["$ad_allsys0$", "$ad_allsys1$", "$ad_allsys2$", "$ad_allsys3$", "$ad_allsys4$", "$ad_allsys5$", "$ad_allsys6$", "$ad_allsys7$", "$ad_allsys8$", "$ad_allsys9$", "$ad_allsys10$", "$ad_allsys11$", "$ad_allsys12$", "$ad_allsys13$", "$ad_allsys14$", "$ad_allsys15$" ]; var ad_pids = ["$ad_pids0$", "$ad_pids1$", "$ad_pids2$", "$ad_pids3$", "$ad_pids4$", "$ad_pids5$", "$ad_pids6$", "$ad_pids7$", "$ad_pids8$", "$ad_pids9$", "$ad_pids10$", "$ad_pids11$", "$ad_pids12$", "$ad_pids13$", "$ad_pids14$", "$ad_pids15$" ]; var ad_satip = ["$ad_satip0$", "$ad_satip1$", "$ad_satip2$", "$ad_satip3$", "$ad_satip4$", "$ad_satip5$", "$ad_satip6$", "$ad_satip7$", "$ad_satip8$", "$ad_satip9$", "$ad_satip10$", "$ad_satip11$", "$ad_satip12$", "$ad_satip13$", "$ad_satip14$", "$ad_satip15$" ]; +var ad_axe_pktc = [$ad_axe_pktc0$, $ad_axe_pktc1$, $ad_axe_pktc2$, $ad_axe_pktc3$]; +var ad_axe_ccerr = [$ad_axe_ccerr0$, $ad_axe_ccerr1$, $ad_axe_ccerr2$, $ad_axe_ccerr3$]; +var ad_axe_coax = ["$ad_axe_coax0$", "$ad_axe_coax1$", "$ad_axe_coax2$", "$ad_axe_coax3$"]; var st_enabled = [$st_enabled0$, $st_enabled1$, $st_enabled2$, $st_enabled3$, $st_enabled4$, $st_enabled5$, $st_enabled6$, $st_enabled7$, $st_enabled8$, $st_enabled9$, $st_enabled10$, $st_enabled11$, $st_enabled12$, $st_enabled13$, $st_enabled14$, $st_enabled15$ ]; var st_adapter = [$st_adapter0$, $st_adapter1$, $st_adapter2$, $st_adapter3$, $st_adapter4$, $st_adapter5$, $st_adapter6$, $st_adapter7$, $st_adapter8$, $st_adapter9$, $st_adapter10$, $st_adapter11$, $st_adapter12$, $st_adapter13$, $st_adapter14$, $st_adapter15$ ]; var st_rport = [$st_rport0$, $st_rport1$, $st_rport2$, $st_rport3$, $st_rport4$, $st_rport5$, $st_rport6$, $st_rport7$, $st_rport8$, $st_rport9$, $st_rport10$, $st_rport11$, $st_rport12$, $st_rport13$, $st_rport14$, $st_rport15$ ]; @@ -112,6 +115,9 @@ myTable += "Status"; myTable += "Frequency"; myTable += "SR/BW"; myTable += "Signal"; +myTable += "Packets"; +myTable += "CC Errors"; +myTable += "Coax Cable"; myTable += "Streams"; myTable += "Cryptinfo"; myTable += ""; @@ -163,16 +169,16 @@ for (var i = 0; i < max_adapters; i++) { var s1 = parseInt(ad_strength[i] / 2.55); signal = "
STR
" + s1 + "%

"; - if (ad_type[i] == 1 || ad_type[i] == 3) - var s2 = parseInt(ad_snr[i] / 2.55); - else - var s2 = parseInt(ad_snr[i] / 0.15); + var s2 = parseInt(ad_snr[i] / 0.15); signal += "
SNR
" + s2 + "%

"; if (ad_ber[i] > 0) signal += "
BER
" + ad_ber[i] + "

"; } myTable += "" + signal + " "; + myTable += "" + ad_axe_pktc[i] + " "; + myTable += "" + ad_axe_ccerr[i] + " "; + myTable += "" + ad_axe_coax[i] + " "; // STREAMS myTable += ""; diff --git a/minisatip.c b/minisatip.c index 1ffa159..dcc1393 100644 --- a/minisatip.c +++ b/minisatip.c @@ -89,6 +89,14 @@ static const struct option long_options[] = { "xml", required_argument, NULL, 'X' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, +#ifdef AXE + { "link-adapters", required_argument, NULL, 'L' }, + { "free-inputs", required_argument, NULL, 'A' }, + { "quattro", no_argument, NULL, 'Q' }, + { "quattro-hiband", required_argument, NULL, 'Z' }, + { "axe-uinput", required_argument, NULL, 'U' }, + { "skip-mpegts", required_argument, NULL, 'M' }, +#endif { 0, 0, 0, 0 } }; #define RRTP_OPT 'r' @@ -122,6 +130,14 @@ static const struct option long_options[] = #define XML_OPT 'X' #define THREADS_OPT 'T' #define DMXSOURCE_OPT '9' +#define LINK_OPT 'L' +#define QUATTRO_OPT 'Q' +#define QUATTRO_HIBAND_OPT 'Z' +#define AXE_UNICINP_OPT 'U' +#define AXE_SKIP_PKT 'M' +#define AXE_POWER 'P' +#define ABSOLUTE_SRC 'A' + char *built_info[] = { @@ -177,8 +193,11 @@ void print_version(int use_log) char buf[200]; int i, len = 0; memset(buf, 0, sizeof(buf)); - len += sprintf(buf, "%s version %s, compiled with s2api version: %04X", - app_name, version, LOGDVBAPIVERSION); + len += sprintf(buf, "%s version %s, compiled with s2api version: %04X" +#ifdef AXE + " (AXE)" +#endif + , app_name, version, LOGDVBAPIVERSION); if (!use_log) puts(buf); else @@ -191,7 +210,7 @@ void usage() { print_version(0); printf( - "\n\t./%s [-[fgltz]] [-a x:y:z] [-b X:Y] [-c X] [-d A:C-U ] [-D device_id] [-e X-Y,Z] [-i prio] \n\ + "\n\t./%s [-[fgltzQ]] [-a x:y:z] [-b X:Y] [-c X] [-d A:C-U ] [-D device_id] [-e X-Y,Z] [-i prio] \n\ \t[-[uj] A1:S1-F1[-PIN]] [-m mac]" #ifndef DISABLE_DVBAPI "[-o oscam_host:dvbapi_port] " @@ -202,7 +221,8 @@ void usage() "[-s [DELSYS:]host[:port] " #endif "[-u A1:S1-F1[-PIN]] [-w http_server[:port]] \n\ - \t[-x http_port] [-X xml_path] [-y rtsp_port] \n\n\ + \t[-x http_port] [-X xml_path] [-y rtsp_port] [-L M1:S1[,M2:S2]] [-U unicable_adapter] \n\ + \t[-M mpegts_packets] [-A SRC1:INP1:DISEQC1[,SRC2:INP2:DISEQC2]]\n\n\ Help\n\ -------\n\ \n\ @@ -329,7 +349,38 @@ Help\n\ * eg: -y 5544 \n\ - changing this to a port > 1024 removes the requirement for minisatip to run as root\n\ \n\ -", +" +#ifdef AXE +"\ +* -L --link-adapters mapping_string: link adapters (identical src,lo/hi,h/v)\n\ +\t* The format is: M1:S1[,M2:S2] - master:slave\n\ + * eg: 0:1,0:2,0:3 \n\ +\n\ +* -A --free-inputs mapping_string: absolute source mapping for free input mode\n\ +\t* The format is: SRC1:INP1:DISEQC1[,SRC2:INP2:DISEQC2]\n\ + * SRC: source number (src argument for SAT>IP minus 1 - 0-15)\n\ + * INP: coaxial input (0-3)\n\ + * DISEQC: diseqc position (0-15)\n\ + * eg: 13E,19.2E on inputs 0&1 and 23.5E,28.2E on inputs 2&3:\n\ + -A 0:0:0,0:1:0,1:0:0,1:1:1,2:2:0,2:3:0,3:2:1,3:2:2\n\ +\n\ +* -P --power num: power to all inputs (0 = only active inputs, 1 = all inputs)\n\ +\n\ +* -Q --quattro quattro LNB config (H/H,H/V,L/H,L/V)\n\ +\n\ +* -Z --quattro-hiband hiband\n\ + * if hiband is 0, do not allow hiband\n\ + * if hiband is 1, allow hiband\n\ +\n\ +* -U --axe-uinput adapterno[,adapterno2]: AXE unicable/jess input (0-3)\n\ + * eg: 0,0,2,2 (two unicable connections at inputs 0 and 2)\n\ + * (tuners 0,1: unicable input 0, tuners 2,3: unicable input 2)\n\ +\n\ +* -M --skip-mpegts packets: skip initial MPEG-TS packets for AXE demuxer (default 35)\n\ +\n\ +" +#endif +, app_name, ADAPTER_BUFFER, DVR_BUFFER, opts.no_threads ? "DISABLED" : "ENABLED"); @@ -370,9 +421,9 @@ void set_options(int argc, char *argv[]) opts.satip_rtsp_over_tcp = 0; opts.output_buffer = 512 * 1024; opts.satip_servers[0] = 0; - opts.document_root = "html"; + opts.document_root = "/usr/share/minisatip/html"; opts.xml_path = DESC_XML; - opts.no_threads = 0; + opts.no_threads = 1; opts.th_priority = -1; opts.diseqc_before_cmd = 15; opts.diseqc_after_cmd = 54; @@ -384,10 +435,11 @@ void set_options(int argc, char *argv[]) #ifdef NO_BACKTRACE opts.no_threads = 1; #endif + opts.axe_skippkt = 35; memset(opts.playlist, 0, sizeof(opts.playlist)); while ((opt = getopt_long(argc, argv, - "flr:a:td:w:p:s:n:hc:b:m:p:e:x:u:j:o:gy:i:q:D:VR:S:TX:Y:O", + "flr:a:td:w:p:s:n:hc:b:m:p:e:x:u:j:o:gy:i:q:D:VR:S:TX:Y:OL:QZ:U:M:P:A:", long_options, NULL)) != -1) { // printf("options %d %c %s\n",opt,opt,optarg); @@ -459,9 +511,12 @@ void set_options(int argc, char *argv[]) opts.adapter_buffer = (opts.adapter_buffer / 188) * 188; if (opts.adapter_buffer < ADAPTER_BUFFER) opts.adapter_buffer = ADAPTER_BUFFER; +#ifdef AXE + opts.dvr_buffer += 7*188 - 1; + opts.dvr_buffer -= opts.dvr_buffer % (7*188); +#endif if (opts.dvr_buffer == 0) opts.dvr_buffer = DVR_BUFFER; - break; } @@ -629,6 +684,39 @@ void set_options(int argc, char *argv[]) LOGL(0, "Not a valid path for the xml file") ; break; +#ifdef AXE + case LINK_OPT: + set_link_adapters(optarg); + break; + + case ABSOLUTE_SRC: + set_absolute_src(optarg); + break; + + case QUATTRO_OPT: + opts.quattro = 1; + break; + + case QUATTRO_HIBAND_OPT: + opts.quattro_hiband = atoi(optarg) + 1; + break; + + case AXE_UNICINP_OPT: + set_unicable_input(optarg); + break; + + case AXE_POWER: + opts.axe_power = atoi(optarg) + 1; + break; + + case AXE_SKIP_PKT: + opts.axe_skippkt = atoi(optarg); + if (opts.axe_skippkt < 0) + opts.axe_skippkt = 0; + if (opts.axe_skippkt > 200) + opts.axe_skippkt = 200; + break; +#endif } } @@ -1154,6 +1242,9 @@ int ssdp_reply(sockets * s) return 0; } +#ifdef AXE + axe_set_network_led(1); +#endif // not my uuid LOGL(4, "Received SSDP packet from %s:%d -> handle %d", get_socket_rhost(s->id, ra, sizeof(ra)), get_socket_rport(s->id), @@ -1289,7 +1380,11 @@ int main(int argc, char *argv[]) if (!opts.no_threads) set_socket_thread(sock_signal, start_new_thread("signal")); +#ifdef AXE + sockets_timeout(sock_signal, 400); +#else sockets_timeout(sock_signal, 1000); +#endif if (0 > (sock_bw = sockets_add(SOCK_TIMEOUT, NULL, -1, TYPE_UDP, NULL, NULL, (socket_action) calculate_bw))) diff --git a/minisatip.h b/minisatip.h old mode 100644 new mode 100755 index ab893df..e9bc48c --- a/minisatip.h +++ b/minisatip.h @@ -10,7 +10,7 @@ #define VERSION_BUILD "54" #define CC(a,b,c) #a b #c -#define VERSION CC(0.5.,VERSION_BUILD,) +#define VERSION CC(0.5.,VERSION_BUILD,-axe102) void set_options (int argc, char *argv[]); @@ -53,6 +53,11 @@ struct struct_opts int force_scan; int clean_psi; int file_line; + int quattro; + int quattro_hiband; + int axe_unicinp[4]; + int axe_skippkt; + int axe_power; char *last_log; int dvbapi_port; char *dvbapi_host; diff --git a/socketworks.c b/socketworks.c index 94a7035..add39d8 100644 --- a/socketworks.c +++ b/socketworks.c @@ -437,6 +437,7 @@ int sockets_add(int sock, struct sockaddr_in *sa, int sid, int type, ss->buf = NULL; ss->lbuf = 0; ss->timeout_ms = 0; + ss->skiplen = type == TYPE_DVR ? opts.axe_skippkt * 188 : 0; ss->id = i; ss->read = (read_action) sockets_read; ss->lock = NULL; @@ -464,15 +465,16 @@ int sockets_del(int sock) if (sock < 0 || sock > MAX_SOCKS || !s[sock] || !s[sock]->enabled) return 0; + mutex_lock(&s_mutex); ss = s[sock]; mutex_lock(&ss->mutex); if (!ss->enabled) { mutex_unlock(&ss->mutex); + mutex_unlock(&s_mutex); return 0; } - mutex_lock(&s_mutex); ss->enabled = 0; so = ss->sock; ss->sock = -1; // avoid infinite loop @@ -497,7 +499,7 @@ int sockets_del(int sock) LOG("sockets_del: %d Last open socket is at index %d current_handle %d", sock, i, so); - mutex_destroy(&ss->mutex); + mutex_unlock(&ss->mutex); mutex_unlock(&s_mutex); return 0; } @@ -637,6 +639,29 @@ void *select_and_execute(void *arg) ss->rlen += rlen; else ss->rlen = 0; +#ifdef AXE + if (ss->type == TYPE_DVR) { + while (rlen > 0 && ss->lbuf - ss->rlen >= 1316) { + rlen = read (ss->sock, &ss->buf[ss->rlen], ss->lbuf - ss->rlen); + if (rlen > 0) + ss->rlen += rlen; + } + if (rlen == 0 || (rlen < 0 || errno == -EAGAIN)) + read_ok = 1; + if (ss->skiplen > 0 && ss->rlen > 0) { + LOG("AXE skip: before rlen %d skiplen %d", ss->rlen, ss->skiplen); + if (ss->skiplen >= ss->rlen) { + ss->skiplen -= ss->rlen; + ss->rlen = 0; + } else { + memmove(ss->buf, &ss->buf[ss->skiplen], ss->rlen - ss->skiplen); + ss->rlen = ss->rlen - ss->skiplen; + ss->skiplen = 0; + } + LOG("AXE skip: after rlen %d skiplen %d", ss->rlen, ss->skiplen); + } + } +#endif //force 0 at the end of the string if (ss->lbuf >= ss->rlen) ss->buf[ss->rlen] = 0; @@ -886,6 +911,7 @@ void set_socket_buffer(int sid, unsigned char *buf, int len) void free_all_streams(); void free_all_adapters(); +void free_all_keys(); void free_all() { @@ -895,12 +921,17 @@ void free_all() { if (s[i] && s[i]->enabled) sockets_del(i); - if (s[i]) + if (s[i]) { + mutex_destroy(&s[i]->mutex); free(s[i]); + } s[i] = NULL; } free_all_streams(); free_all_adapters(); +#ifndef DISABLE_DVBAPI + free_all_keys(); +#endif } void set_socket_send_buffer(int sock, int len) @@ -953,6 +984,14 @@ void set_socket_pos(int sock, int pos) ss->rlen = pos; } +void set_socket_skip(int sock) +{ + sockets *ss = get_sockets(sock); + if (!ss) + return; + ss->skiplen = opts.axe_skippkt * 188; +} + char *get_socket_rhost(int s_id, char *dest, int ld) { sockets *ss = get_sockets(s_id); diff --git a/socketworks.h b/socketworks.h old mode 100644 new mode 100755 index 0782477..723821a --- a/socketworks.h +++ b/socketworks.h @@ -24,6 +24,7 @@ typedef struct struct_sockets { int lbuf; int rlen; int timeout_ms; + int skiplen; int id; // socket id int err; int flags; // 1 - buf is allocated dynamically @@ -72,6 +73,7 @@ void set_socket_send_buffer(int sock, int len); void set_socket_receive_buffer(int sock, int len); sockets *get_sockets(int i); void set_socket_pos(int sock, int pos); +void set_socket_skip(int sock); char *get_socket_rhost(int s_id, char *dest, int ld); int get_socket_rport(int s_id); void set_sock_lock(int i, SMutex *m); diff --git a/stream.c b/stream.c index 53492d8..408ce20 100644 --- a/stream.c +++ b/stream.c @@ -297,14 +297,15 @@ int close_stream(int i) return 0; sid = st[i]; + mutex_lock(&st_mutex); mutex_lock(&sid->mutex); if (!sid->enabled) { adapter_unlock(sid->adapter); mutex_unlock(&sid->mutex); + mutex_unlock(&st_mutex); return 0; } - mutex_lock(&st_mutex); sid->enabled = 0; sid->timeout = 0; ad = sid->adapter; @@ -319,7 +320,6 @@ int close_stream(int i) if(sid->buf)free(sid->buf); sid->pids = sid->apids = sid->dpids = sid->buf = NULL; */ - mutex_destroy(&sid->mutex); if (sid->rtcp_sock > 0 || sid->rtcp > 0) { @@ -339,6 +339,7 @@ int close_stream(int i) sockets_del_for_sid (i); + mutex_unlock(&sid->mutex); mutex_unlock(&st_mutex); LOG("closed stream %d", i); return 0; @@ -1140,8 +1141,10 @@ void free_all_streams() for (i = 0; i < MAX_STREAMS; i++) { - if (st[i]) + if (st[i]) { + mutex_destroy(&st[i]->mutex); free1(st[i]); + } st[i] = NULL; } diff --git a/utils.c b/utils.c index 689b8f3..5a5f1d3 100644 --- a/utils.c +++ b/utils.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #include @@ -749,6 +751,14 @@ void * get_var_address(char *var, float *multiplier, int * type, void *storage, *multiplier = 1; return storage; } + else if (sym[i][j].type == VAR_FUNCTION_INT64) + { + off = map_intd(var + strlen(sym[i][j].name), NULL, 0); + get_data_int64 fun64 = (get_data_int64) sym[i][j].addr; + *(int64_t *) storage = fun64(off); + *multiplier = 1; + return storage; + } else if (sym[i][j].type == VAR_FUNCTION_STRING) { off = map_intd(var + strlen(sym[i][j].name), NULL, 0); @@ -1043,12 +1053,12 @@ int mutex_destroy(SMutex* mutex) __FUNCTION__, mutex, rv, strerror(rv)); LOGL(4, "Destroying mutex %p", mutex); -// if ((rv = pthread_mutex_destroy(&mutex->mtx))) -// { -// LOG("mutex destroy %p failed with error %d %s", mutex, rv, strerror(rv)); -// mutex->enabled = 1; -// return 1; -// } + if ((rv = pthread_mutex_destroy(&mutex->mtx))) + { + LOG("mutex destroy %p failed with error %d %s", mutex, rv, strerror(rv)); + mutex->enabled = 1; + return 1; + } return 0; } @@ -1093,6 +1103,7 @@ pthread_t start_new_thread(char *name) void set_thread_prio(pthread_t tid, int prio) { +#if 0 int rv; struct sched_param param; memset(¶m, 0, sizeof(struct sched_param)); @@ -1100,6 +1111,12 @@ void set_thread_prio(pthread_t tid, int prio) if ((rv = pthread_setschedparam(pthread_self(), SCHED_RR, ¶m))) LOG("pthread_setschedparam failed with error %d", rv); return; +#else + pid_t xtid; + xtid = syscall(SYS_gettid); + if (setpriority(PRIO_PROCESS, xtid, prio)) + LOG("setpriority(%d) failed with error %d", prio, errno); +#endif } struct struct_array @@ -1124,8 +1141,8 @@ int add_new_lock(void **arr, int count, int size, SMutex *mutex) LOG_AND_RETURN(-1, "Could not allocate memory for %p index %d", arr, i); memset(sa[i], 0, size); + mutex_init(&sa[i]->mutex); } - mutex_init(&sa[i]->mutex); mutex_lock(&sa[i]->mutex); sa[i]->enabled = 1; mutex_unlock(mutex); diff --git a/utils.h b/utils.h index fd5d578..70fa61f 100644 --- a/utils.h +++ b/utils.h @@ -39,9 +39,11 @@ #define VAR_AARRAY_PSTRING (VAR_AARRAY + VAR_PSTRING) #define VAR_FUNCTION 48 #define VAR_FUNCTION_INT (VAR_FUNCTION + VAR_INT) +#define VAR_FUNCTION_INT64 (VAR_FUNCTION + VAR_INT64) #define VAR_FUNCTION_STRING (VAR_FUNCTION + VAR_STRING) typedef int (*get_data_int)(int p); +typedef int64_t (*get_data_int64)(int p); typedef char * (*get_data_string)(int p, char *dest, int max_len); typedef struct struct_symbols