diff --git a/adapter.c b/adapter.c index 285faea..c9bf29c 100755 --- a/adapter.c +++ b/adapter.c @@ -29,10 +29,15 @@ #include #include #include +#include #include "socketworks.h" #include "dvb.h" #include "adapter.h" +#ifdef AXE +#define AXE_MAIN 1 +#include "axe.h" +#endif adapter a[MAX_ADAPTERS]; extern struct struct_opts opts; @@ -49,7 +54,12 @@ find_adapters () for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) { +#ifdef AXE + if (j > 0) continue; + sprintf (buf, "/dev/axe/frontend-%d", i); +#else sprintf (buf, "/dev/dvb/adapter%d/frontend%d", i, j); +#endif fd = open (buf, O_RDONLY | O_NONBLOCK); //LOG("testing device %s -> fd: %d",buf,fd); if (fd >= 0) @@ -61,6 +71,17 @@ find_adapters () if (na == MAX_ADAPTERS) return; } +#ifdef AXE + if (i == 0) + axe_set_network_led(0); + if (i < 4) + axe_set_tuner_led(i + 1, 0); + if (i < 4 && fd < 0) { + LOGL(0, "AXE - cannot open %s: %i", buf, errno); + sleep(60); + exit(239); + } +#endif } for (na; na < MAX_ADAPTERS; na++) a[na].pa = a[na].fn = -1; @@ -69,6 +90,7 @@ find_adapters () // avoid adapter close unless all the adapters can be closed int adapter_timeout(sockets *s) { +#ifndef AXE int do_close = 1, i, max_close = 0; int rtime = getTick(); for (i = 0; i < MAX_ADAPTERS; i++) @@ -84,6 +106,10 @@ int adapter_timeout(sockets *s) s->rtime = max_close; return do_close; +#else + LOG("Requested adapter %d close", s->sid); + return 1; +#endif } int @@ -122,9 +148,22 @@ init_hw () find_adapters (); LOG ("trying to open [%d] adapter %d and frontend %d", i, a[i].pa, a[i].fn); +#ifdef AXE + sprintf (buf, "/dev/axe/frontend-%d", a[i].pa); + if (a[i].fe2 > 0) + a[i].fe = a[i].fe2; + else +#else sprintf (buf, "/dev/dvb/adapter%d/frontend%d", a[i].pa, a[i].fn); - a[i].fe = open (buf, O_RDWR | O_NONBLOCK); +#endif + a[i].fe = a[i].fe2 = open (buf, O_RDWR | O_NONBLOCK); + +#ifdef AXE + a[i].fe2 = a[i].fe; + sprintf (buf, "/dev/axe/demuxts-%d", a[i].pa); +#else sprintf (buf, "/dev/dvb/adapter%d/dvr%d", a[i].pa, a[i].fn); +#endif a[i].dvr = open (buf, O_RDONLY | O_NONBLOCK); if (a[i].fe < 0 || a[i].dvr < 0) { @@ -139,22 +178,24 @@ init_hw () a[i].enabled = 1; if (!a[i].buf) - a[i].buf = malloc1 (ADAPTER_BUFFER + 10); + a[i].buf = malloc1 (opts.dvr + 10); if (!a[i].buf) { LOG ("memory allocation failed for %d bytes failed, adapter %d", - ADAPTER_BUFFER, i); + opts.dvr, i); close_adapter (i); continue; } - memset (a[i].buf, 0, ADAPTER_BUFFER + 1); + //memset (a[i].buf, 0, ADAPTER_BUFFER + 1); num_adapters++; LOG ("opened DVB adapter %d fe:%d dvr:%d", i, a[i].fe, a[i].dvr); +#ifndef AXE if (ioctl (a[i].dvr, DMX_SET_BUFFER_SIZE, opts.dvr) < 0) perror ("couldn't set DVR buffer size"); else LOG ("Done setting DVR buffer to %d bytes", DVR_BUFFER); +#endif init_dvb_parameters (&a[i].tp); mark_pids_deleted (i, -1, NULL); update_pids (i); @@ -165,8 +206,8 @@ init_hw () a[i].sock = sockets_add (a[i].dvr, NULL, i, TYPE_DVR, (socket_action) read_dmx, (socket_action) close_adapter_for_socket, (socket_action ) adapter_timeout); - memset (a[i].buf, 0, ADAPTER_BUFFER + 1); - set_socket_buffer (a[i].sock, a[i].buf, ADAPTER_BUFFER); + //memset (a[i].buf, 0, ADAPTER_BUFFER + 1); + set_socket_buffer (a[i].sock, a[i].buf, opts.dvr); sockets_timeout (a[i].sock, 60000); LOG ("done opening adapter %i fe_sys %d", i, a[i].tp.sys); @@ -179,7 +220,6 @@ init_hw () return num_adapters; } - void close_adapter (int na) { @@ -194,10 +234,47 @@ close_adapter (int na) mark_pids_deleted (na, -1, NULL); update_pids (na); // if(a[na].dmx>0)close(a[na].dmx); +#ifdef AXE + if (a[na].fe > 0) { + int i, j; + a[na].fe = 0; + if (a[na].fe2 > 0) + axe_fe_reset(a[na].fe2); + for (i = j = 0; i < 4; i++) { + a[i].axe_used &= ~(1 << na); + if (a[i].axe_used || a[i].fe > 0) j++; + } + if (j > 0 && opts.axe_power > 1) + goto nostandby; + for (i = 0; i < 4; i++) { + if (opts.axe_power < 2 && i != na && j && a[i].sock >= 0) + continue; + if (a[i].axe_used != 0 || a[i].sid_cnt > 0) { + LOG("AXE standby: adapter %d busy (cnt=%d/used=%04x/fe=%d), keeping", + i, a[i].sid_cnt, a[i].axe_used, a[i].fe); + continue; + } + if (a[i].fe2 < 0) + continue; + LOG("AXE standby: adapter %d", i); + axe_fe_standby(a[i].fe2, -1); + axe_set_tuner_led(i + 1, 0); + ioctl(a[i].fe2, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF); + close(a[i].fe2); + a[i].fe2 = -1; + a[i].tp.old_diseqc = a[i].tp.old_pol = a[i].tp.old_hiband = -1; + } + } +nostandby: + axe_set_tuner_led(na + 1, 0); +#else if (a[na].fe > 0) close (a[na].fe); - if (a[na].sock >= 0) +#endif + if (a[na].sock >= 0) { sockets_del (a[na].sock); + a[na].sock = -1; + } a[na].fe = 0; // if(a[na].buf)free1(a[na].buf);a[na].buf=NULL; LOG ("done closing adapter %d", na); @@ -343,6 +420,7 @@ set_adapter_for_stream (int sid, int aid) if (a[aid].master_sid == -1) a[aid].master_sid = sid; a[aid].sid_cnt++; + sockets_set_poll(a[aid].sock, 1); LOG ("set adapter %d for stream %d m:%d s:%d", aid, sid, a[aid].master_sid, a[aid].sid_cnt); return 0; } @@ -366,8 +444,12 @@ close_adapter_for_stream (int sid, int aid) // delete the attached PIDs as well mark_pids_deleted (aid, sid, NULL); update_pids (aid); -// if (a[aid].sid_cnt == 0) -// close_adapter (aid); + if (a[aid].sid_cnt == 0) { +#ifdef AXE + axe_set_tuner_led(aid + 1, 0); +#endif + sockets_set_poll(a[aid].sock, 0); + } } @@ -410,7 +492,11 @@ update_pids (int aid) int tune (int aid, int sid) { adapter *ad = get_adapter(aid); - int i, rv = 0; + int rv = 0; +#ifdef AXE + ssize_t drv; + char buf[1316]; +#endif if(!ad) return -400; ad->last_sort = getTick (); @@ -419,7 +505,13 @@ int tune (int aid, int sid) ad->tp.switch_type = ad->switch_type; ad->tp.uslot = ad->uslot; ad->tp.ufreq = ad->ufreq; - + +#ifdef AXE + axe_set_tuner_led(aid + 1, 1); + axe_fe_reset(ad->fe); + do { drv = read(ad->dvr, buf, sizeof(buf)); } while (drv > 0); +#endif + sockets_reset(ad->sock); rv = tune_it_s2 (ad->fe, &ad->tp); a[aid].status = 0; a[aid].status_cnt = 0; @@ -428,6 +520,12 @@ int tune (int aid, int sid) close_streams_for_adapter (aid, sid); update_pids (aid); } +#ifdef AXE + //do { drv = read(ad->dvr, buf, sizeof(buf)); } while (drv > 0); + axe_dmxts_start(ad->dvr); + if (rv < 0) + axe_set_tuner_led(aid + 1, 0); +#endif } else LOG ("not tuning for SID %d (do_tune=%d, master_sid=%d)", sid, @@ -659,6 +757,17 @@ 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].force_disable) + { + LOG ("%s:%d: get_adapter2 returns NULL for adapter_id %d", file, line, aid); + return NULL; + } + return &a[aid]; +} + char dad[1000]; char * describe_adapter (int sid, int aid) @@ -684,7 +793,11 @@ describe_adapter (int sid, int aid) memset (dad, 0, sizeof (dad)); x = 0; // do just max 3 signal check 1s after tune +#ifndef AXE if (use_ad && ((ad->status <= 0 && ad->status_cnt<8 && ad->status_cnt++>4) || opts.force_scan)) +#else + if (use_ad && (ad->status_cnt++ & 3) == 0) +#endif { int new_gs = 1; ts = getTick (); @@ -701,11 +814,20 @@ describe_adapter (int sid, int aid) if (ad->max_snr <= ad->snr) ad->max_snr = (ad->snr>0)?ad->snr:1; LOG ("get_signal%s took %d ms for adapter %d handle %d (status: %d, ber: %d, strength:%d, snr: %d, max_strength: %d, max_snr: %d %d)", new_gs?"":"_new", getTick () - ts, aid, ad->fe, ad->status, ad->ber, ad->strength, ad->snr, ad->max_strength, ad->max_snr, opts.force_scan); +#ifndef AXE if(new_gs) { ad->strength = ad->strength * 255 / ad->max_strength; ad->snr = ad->snr * 15 / ad->max_snr; } +#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 } if(use_ad) { @@ -715,14 +837,14 @@ describe_adapter (int sid, int aid) } if (t->sys == SYS_DVBS || t->sys == SYS_DVBS2) sprintf (dad, "ver=1.0;src=%d;tuner=%d,%d,%d,%d,%d,%s,%s,%s,%s,%s,%d,%s;pids=", - t->diseqc, aid, strength, status, snr, t->freq / 1000, get_pol(t->pol), get_modulation(t->mtype), + t->diseqc, aid+1, strength, status, snr, t->freq / 1000, get_pol(t->pol), get_modulation(t->mtype), get_pilot(t->plts), get_rolloff(t->ro), get_delsys(t->sys), t->sr / 1000, get_fec(t->fec)); else if (t->sys == SYS_DVBT || t->sys == SYS_DVBT2) sprintf (dad, "ver=1.1;src=%d;tuner=%d,%d,%d,%d,%.2f,%d,%s,%s,%s,%s,%s,%d,%d,%d;pids=", - t->diseqc, aid, strength, status, snr, (double) t->freq/1000, t->bw, get_delsys(t->sys), get_tmode(t->tmode), get_modulation(t->mtype), get_gi(t->gi), + t->diseqc, aid+1, strength, status, snr, (double) t->freq/1000, t->bw, get_delsys(t->sys), get_tmode(t->tmode), get_modulation(t->mtype), get_gi(t->gi), get_fec(t->fec), t->plp, t->t2id, t->sm); else sprintf (dad, "ver=1.2;src=%d;tuner=%d,%d,%d,%d,%.2f,8,%s,%s,%d,%d,%d,%d,%d;pids=", - t->diseqc, aid, strength, status, snr, (double )t->freq/1000, get_delsys(t->sys), get_modulation(t->mtype), t->sr, + t->diseqc, aid+1, strength, status, snr, (double )t->freq/1000, get_delsys(t->sys), get_modulation(t->mtype), t->sr, t->c2tft, t->ds, t->plp, t->inversion); for (i = 0; i < MAX_PIDS; i++) if (use_ad && ad->pids[i].flags == 1) @@ -825,7 +947,7 @@ void enable_adapters(char *o) void set_unicable_adapters(char *o, int type) { - int i, la, a_id, slot, freq; + int i, la, a_id, slot, freq, o13v; char buf[100], *arg[20], *sep1, *sep2; strncpy(buf, o, sizeof(buf)); @@ -839,17 +961,67 @@ void set_unicable_adapters(char *o, int type) sep2 = strchr(arg[i], '-'); if( !sep1 || !sep2) continue; + o13v = 0; + if(sep2[1] == '*') { + o13v = 1; + sep2++; + } slot = map_intd(sep1 + 1, NULL, -1); freq = map_intd(sep2 + 1, NULL, -1); if( slot < 0 || freq < 0) continue; a[a_id].uslot = slot; - a[a_id].ufreq = freq; + a[a_id].ufreq = o13v ? -freq : freq; a[a_id].switch_type = type; LOG("Setting %s adapter %d slot %d freq %d", type==SWITCH_UNICABLE?"unicable":"jess", a_id, slot, freq); } } +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[b_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); + } +} int delsys_match(adapter *ad, int del_sys) { @@ -866,3 +1038,71 @@ int delsys_match(adapter *ad, int del_sys) return 0; } + +#ifdef AXE + +#define myf(buf, buflen, fmt, ...) do { \ + size_t l = strlen(buf); \ + snprintf(buf + l, buflen - l, fmt, ##__VA_ARGS__); \ +} while (0) + +extern streams st[]; + +#include + +static char *axe_status_pol(int pol) +{ + switch (pol) { + case 0: return "none"; + case 1: return "v"; + case 2: return "h"; + case 3: return "l"; + case 4: return "r"; + default: return "unknown"; + } +} + +void +axe_status(char *buf, size_t buflen) +{ + size_t idx = 0; + int i, k, j, port, t; + char *host; + + t = getTick(); + buf[0] = '\0'; + myf(buf, buflen, "StatusVersion=1\n"); + for (i = 0; i < MAX_ADAPTERS; i++) { + if (!a[i].enabled) continue; + if (a[i].sid_cnt == 0) continue; + myf(buf, buflen, "\nSubscriptions_%d=%d\n", i + 1, a[i].sid_cnt); + myf(buf, buflen, "DiseqC_%d=%d\n", i + 1, a[i].tp.diseqc); + myf(buf, buflen, "Freq_%d=%d\n", i + 1, a[i].tp.freq); + myf(buf, buflen, "Pol_%d=%s\n", i + 1, axe_status_pol(a[i].tp.pol)); + for (k = 0; k < MAX_PIDS; k++) { + if (a[i].pids[k].flags == 0) continue; + if (k == 0) + myf(buf, buflen, "Pids_%d=%d", i + 1, a[i].pids[k].pid); + else + myf(buf, buflen, ",%d", a[i].pids[k].pid); + } + if (k > 0) + myf(buf, buflen, "\n"); + for (k = j = 0; k < MAX_STREAMS; k++) { + streams *s = &st[k]; + if (!s->enabled) continue; + if (s->adapter != i) continue; + port = ntohs(s->sa.sin_port); + host = inet_ntoa(s->sa.sin_addr); + myf(buf, buflen, "Stream_%d_%d=%s:%d\n", i + 1, ++j, host, port); + myf(buf, buflen, "Streaming_%d_%d=%d\n", i + 1, j, s->do_play ? "active" : "inactive"); + if (s->sp > 0) { + myf(buf, buflen, "IOCnt_%d_%d=%zu\n", i + 1, j, s->sp); + myf(buf, buflen, "Bytes_%d_%d=%zu\n", i + 1, j, s->sb); + } + myf(buf, buflen, "LastRTSP_%d_%d=%d\n", i + 1, j, t - s->rtime); + myf(buf, buflen, "TimeoutRTSP_%d_%d=%d\n", i + 1, j, s->timeout); + } + } +} +#endif diff --git a/adapter.h b/adapter.h index 629bd9c..9420f93 100755 --- a/adapter.h +++ b/adapter.h @@ -24,7 +24,7 @@ typedef struct struct_adapter { int enabled; int force_disable; - int fe, dvr; + int fe, fe2, dvr; int pa, fn; // physical adapter, physical frontend number fe_delivery_system_t sys[10]; @@ -45,6 +45,8 @@ typedef struct struct_adapter int switch_type; int uslot; // unicable/jess slot int ufreq; // unicable/jess frequency + int slave; + int axe_used; } adapter; int init_hw (); @@ -60,13 +62,16 @@ void mark_pids_deleted (int aid, int sid, char *pids); int mark_pids_add (int sid, int aid, char *pids); int update_pids (int aid); 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); void dump_pids (int aid); void sort_pids (int aid); void enable_adapters(char *o); void set_unicable_adapters(char *o, int type); - +void set_link_adapters(char *o); +void set_unicable_input(char *o); int delsys_match(adapter *ad, int del_sys); #define get_adapter(a) get_adapter1(a, __FILE__, __LINE__) +#define get_adapter2(a) get_adapter21(a, __FILE__, __LINE__) #endif /* */ diff --git a/axe.h b/axe.h new file mode 100644 index 0000000..cfc1927 --- /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 old mode 100755 new mode 100644 index 5701bd2..bf5c7f2 --- a/dvb.c +++ b/dvb.c @@ -41,6 +41,10 @@ #include #include "dvb.h" #include "minisatip.h" +#ifdef AXE +#include "axe.h" +#include "adapter.h" +#endif extern struct struct_opts opts; @@ -215,6 +219,46 @@ msleep (uint32_t msec) ; } +#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 || a->force_disable) + continue; + if (a->tp.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<force_disable) + continue; + if (ioctl(a->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 pol, int hiband) { struct dvb_diseqc_master_cmd cmd = { @@ -229,6 +273,9 @@ int send_diseqc(int fd, int pos, int pol, int hiband) if (ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1) LOG("send_diseqc: FE_SET_TONE failed for fd %d: %s", fd, strerror(errno)); +#ifdef AXE + axe_wakeup(fd, pol ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13); +#endif if (ioctl(fd, FE_SET_VOLTAGE, pol ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13) == -1) LOG("send_diseqc: FE_SET_VOLTAGE failed for fd %d: %s", fd, strerror(errno)); @@ -252,8 +299,12 @@ int send_unicable(int fd, int freq, int pos, int pol, int hiband, int slot, int struct dvb_diseqc_master_cmd cmd = { {0xe0, 0x11, 0x5a, 0x00, 0x00}, 5 }; - int t; + int t, o13v = 0; + if (ufreq < 0) { + o13v = 1; + ufreq = -ufreq; + } t = (freq + ufreq + 2) / 4 - 350; cmd.msg[3] = ((t & 0x0300) >> 8) | @@ -262,12 +313,15 @@ int send_unicable(int fd, int freq, int pos, int pol, int hiband, int slot, int LOGL(3, "send_unicable fd %d, freq %d, ufreq %d, pos = %d, pol = %d, hiband = %d, slot %d, diseqc => %02x %02x %02x %02x %02x", fd, freq, ufreq, pos, pol, hiband, slot, 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)); msleep(15); if (ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1) LOG("send_unicable: FE_SET_TONE failed for fd %d: %s", fd, strerror(errno)); - if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18) == -1) + if (!o13v && ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18) == -1) LOG("send_unicable: FE_SET_VOLTAGE failed for fd %d: %s", fd, strerror(errno)); msleep(15); if (ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1) @@ -286,21 +340,25 @@ int send_jess(int fd, int freq, int pos, int pol, int hiband, int slot, int ufre }; // int t = (freq / 1000) - 100; int t = freq - 100; + int o13v = ufreq < 0; cmd.msg[1] = slot << 3; - cmd.msg[1] |= ((t << 8) & 0x07); + cmd.msg[1] |= ((t >> 8) & 0x07); cmd.msg[2] = (t & 0xff); cmd.msg[3] = ((pos & 0x3f) << 2) | (pol ? 2 : 0) | (hiband ? 1 : 0); LOGL(3, "send_jess fd %d, freq %d, ufreq %d, pos = %d, pol = %d, hiband = %d, slot %d, diseqc => %02x %02x %02x %02x %02x", fd, freq, ufreq, pos, pol, hiband, slot, 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)); msleep(15); if (ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1) LOG("send_jess: FE_SET_TONE failed for fd %d: %s", fd, strerror(errno)); - if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18) == -1) + if (!o13v && ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18) == -1) LOG("send_jess: FE_SET_VOLTAGE failed for fd %d: %s", fd, strerror(errno)); msleep(15); if (ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1) @@ -312,6 +370,39 @@ int send_jess(int fd, int freq, int pos, int pol, int hiband, int slot, int ufre return 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; +} +#endif + int setup_switch (int frontend_fd, transponder *tp) { int i; @@ -320,7 +411,7 @@ int setup_switch (int frontend_fd, transponder *tp) int diseqc = (tp->diseqc > 0)? tp->diseqc - 1: 0; int freq = tp->freq; int pol = (tp->pol - 1) & 1; - + if (freq < SLOF) { freq = (freq - LOF1); @@ -330,12 +421,108 @@ int setup_switch (int frontend_fd, transponder *tp) hiband = 1; } +#ifdef AXE + adapter *ad, *ad2, *adm; + int input = 0, aid, equattro = 0; + + for (aid = 0; aid < 4; aid++) { + ad = get_adapter(aid); + LOGL(3, "axe adapter %i fe fd %d", aid, ad->fe); + if (ad && ad->fe == frontend_fd) + break; + } + if (aid >= 4) { + LOG("axe_fe: unknown adapter for fd %d", frontend_fd); + return 0; + } + if (tp->switch_type != SWITCH_UNICABLE && tp->switch_type != SWITCH_JESS) { + input = aid; + if (ad && (!opts.quattro || extra_quattro(input, diseqc, &equattro))) { + if (equattro > 0) + diseqc = equattro - 1; + adm = use_adapter(ad->slave ? ad->slave - 1 : ad->pa); + if (adm == NULL) { + LOG("axe_fe: unknown master adapter %d", input); + return 0; + } + if (adm->tp.old_pol >= 0) { + for (aid = 0; aid < 4; aid++) { + ad2 = get_adapter(aid); + if (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->tp.old_pol != pol || + adm->tp.old_hiband != hiband || + adm->tp.old_diseqc != diseqc)) + return 0; + } + adm->axe_used |= (1 << input); + if (ad->slave) { + input = ad->slave - 1; + if(adm->tp.old_pol != pol || + adm->tp.old_hiband != hiband || + adm->tp.old_diseqc != diseqc) { + send_diseqc(adm->fe2, diseqc, pol, hiband); + adm->tp.old_pol = tp->old_pol = pol; + adm->tp.old_hiband = tp->old_hiband = hiband; + adm->tp.old_diseqc = tp->old_diseqc = diseqc; + } + goto axe; + } + } else if (ad && 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; + } + if(adm->tp.old_pol != pol || adm->tp.old_hiband != hiband) { + send_diseqc(adm->fe2, 0, pol, hiband); + adm->tp.old_pol = pol; + adm->tp.old_hiband = hiband; + adm->tp.old_diseqc = 0; + } + adm->axe_used |= (1 << aid); + goto axe; + } + } else { + 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->switch_type == SWITCH_UNICABLE) { +#ifdef AXE + if (ad) + freq = send_unicable(ad->fe2, freq / 1000, diseqc, pol, hiband, tp->uslot, tp->ufreq); +#else freq = send_unicable(frontend_fd, freq / 1000, diseqc, pol, hiband, tp->uslot, tp->ufreq); +#endif }else if(tp->switch_type == SWITCH_JESS) { +#ifdef AXE + if (ad) + freq = send_jess(ad->fe2, freq / 1000, diseqc, pol, hiband, tp->uslot, tp->ufreq); +#else freq = send_jess(frontend_fd, freq / 1000, diseqc, pol, hiband, tp->uslot, tp->ufreq); +#endif }else { if(tp->old_pol != pol || tp->old_hiband != hiband || tp->old_diseqc != diseqc) @@ -343,6 +530,16 @@ int setup_switch (int frontend_fd, transponder *tp) else LOGL(3, "Skip sending diseqc commands since the switch position doesn't need to be changed: pol %d, hiband %d, switch position %d", pol, hiband, 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 tp->old_pol = pol; tp->old_hiband = hiband; @@ -383,8 +580,10 @@ tune_it_s2 (int fd_frontend, transponder * tp) {.cmd = DTV_INVERSION,.u.data = 0}, {.cmd = DTV_SYMBOL_RATE,.u.data = 0}, {.cmd = DTV_INNER_FEC,.u.data = 0}, +#ifndef AXE {.cmd = DTV_PILOT,.u.data = 0}, {.cmd = DTV_ROLLOFF,.u.data = 0}, +#endif {.cmd = DTV_TUNE}, }; static struct dtv_properties dvbs2_cmdseq = @@ -462,11 +661,15 @@ tune_it_s2 (int fd_frontend, transponder * tp) tp->mtype = QPSK; bpol = getTick(); if_freq = setup_switch (fd_frontend, tp); + if (!if_freq) + return -404; p = &dvbs2_cmdseq; p->props[DELSYS].u.data = tp->sys; p->props[MODULATION].u.data = tp->mtype; +#ifndef AXE p->props[PILOT].u.data = tp->plts; p->props[ROLLOFF].u.data = tp->ro; +#endif p->props[INVERSION].u.data = tp->inversion; p->props[SYMBOL_RATE].u.data = tp->sr; p->props[FEC_INNER].u.data = tp->fec; @@ -475,7 +678,12 @@ tune_it_s2 (int fd_frontend, transponder * tp) LOG("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, p->props[FREQUENCY].u.data, get_pol(tp->pol), tp->pol, p->props[SYMBOL_RATE].u.data, fe_fec[p->props[FEC_INNER].u.data], fe_delsys[p->props[DELSYS].u.data], fe_modulation[p->props[MODULATION].u.data], - fe_rolloff[p->props[ROLLOFF].u.data], fe_pilot[p->props[PILOT].u.data], bclear, bpol); +#ifdef AXE + "auto", "auto", +#else + fe_rolloff[p->props[ROLLOFF].u.data], fe_pilot[p->props[PILOT].u.data], +#endif + bclear, bpol); break; @@ -560,6 +768,20 @@ set_pid (int hw, int ad, uint16_t i_pid) char buf[100]; int fd; +#ifdef AXE + adapter *a = get_adapter(hw); + + if ( i_pid > 8192 || a == NULL) + LOG_AND_RETURN(-1, "pid %d > 8192 for ADAPTER %d", i_pid, hw); + + if (axe_dmxts_add_pid(a->dvr, i_pid) < 0) + { + LOG ("failed setting filter on PID %d (%s) for ADAPTER %d", i_pid, strerror (errno), hw); + return -1; + } + LOG ("setting filter on PID %d for ADAPTER %d", i_pid, a->pa); + return (hw << 16) | i_pid; +#else if ( i_pid > 8192 ) LOG_AND_RETURN(-1, "pid %d > 8192 for /dev/dvb/adapter%d/demux%d", i_pid, hw, ad); @@ -585,6 +807,7 @@ set_pid (int hw, int ad, uint16_t i_pid) } LOG ("setting filter on PID %d for fd %d", i_pid, fd); +#endif return fd; } @@ -592,6 +815,17 @@ set_pid (int hw, int ad, uint16_t i_pid) int del_filters (int fd, int pid) { +#ifdef AXE + adapter *a = get_adapter(fd >> 16); + 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) < 0) @@ -599,6 +833,7 @@ int del_filters (int fd, int pid) else LOG ("clearing filters on PID %d FD %d", pid, fd); close (fd); +#endif return 0; } @@ -606,6 +841,15 @@ int del_filters (int fd, int pid) 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; @@ -703,6 +947,7 @@ dvb_delsys (int aid, int fd, fe_delivery_system_t *sys) LOG ("returning default from dvb_delsys => %s (count %d)", fe_delsys[rv] , nsys); return (fe_delivery_system_t) rv; +#endif } diff --git a/minisatip.c b/minisatip.c index d4076ba..9486fae 100755 --- a/minisatip.c +++ b/minisatip.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "socketworks.h" #include "stream.h" #include "adapter.h" @@ -62,10 +63,18 @@ usage () -c X: bandwidth capping for the output to the network (default: unlimited)\n\ -b X: set the DVR buffer to X KB (default: %dKB)\n\ -l increases the verbosity (you can use multiple -l), logging to stdout in foreground mode or in /tmp/log when a daemon\n\ + -g use syslog instead stdout for logging, multiple -g - print to stderr as well\n\ -p url: specify playlist url using X_SATIPM3U header \n\ -u unicable_string: defines the unicable adapters (A) and their slot (S) and frequency (F):\n\ \tThe format is: A1:S1-F1[,A2:S2-F2[,...]] \n\ + \tWhen * character is used before frequency, force 13V for setup\n\ -j jess_string: same format as unicable_string \n\ + -L link adapters (identical src,lo/hi,h/v), the format is M:S (master:slave)\n\ + -Q quattro LNB config (H/H,H/V,L/H,L/V)\n\ + -Z X: enable loband (0) or hiband (1) only for quattro LNB\n\ + -X X[,Y]: AXE unicable/jess input (0-3) for all tuners\n\ + -M X: skip initial MPEG-TS packets for AXE demuxer (default 35)\n\ + -P X: power to all inputs (0 = only active inputs, 1 = all inputs)\n\ ", DVR_BUFFER / 1024); exit (1); @@ -97,11 +106,12 @@ set_options (int argc, char *argv[]) opts.device_id = 0; opts.bootid = 0; opts.force_scan = 0; - opts.dvr = DVR_BUFFER; + opts.dvr = 14*7*DVB_FRAME; opts.file_line = 0; + opts.axe_skippkt = 35; memset(opts.playlist, sizeof(opts.playlist), 0); - while ((opt = getopt (argc, argv, "flr:a:t:d:w:p:shc:b:m:p:e:x:u:j:")) != -1) + while ((opt = getopt (argc, argv, "flr:a:t:d:w:p:shc:b:m:p:e:x:u:j:gL:QZ:X:S:P:")) != -1) { // printf("options %d %c %s\n",opt,opt,optarg); switch (opt) @@ -143,6 +153,12 @@ set_options (int argc, char *argv[]) break; } + case SYSLOG_OPT: + { + opts.slog++; + break; + } + case HELP_OPT: { usage (); @@ -164,6 +180,10 @@ set_options (int argc, char *argv[]) case DVRBUFFER_OPT: { opts.dvr = atoi (optarg) * 1024; +#ifdef AXE + opts.dvr += 7*188 - 1; + opts.dvr -= opts.dvr % (7*188); +#endif break; } @@ -209,6 +229,45 @@ set_options (int argc, char *argv[]) break; } + case LINK_OPT: + { + set_link_adapters(optarg); + break; + } + + case QUATTRO_OPT: + { + opts.quattro = 1; + break; + } + + case QUATTRO_HIBAND_OPT: + { + opts.quattro_hiband = atoi(optarg) + 1; + break; + } + + case AXE_POWER: + { + opts.axe_power = atoi(optarg) + 1; + break; + } + + case AXE_UNICINP_OPT: + { + set_unicable_input(optarg); + 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; + } } } @@ -483,6 +542,11 @@ http_response (sockets *s, int rc, char *ah, char *desc, int cseq, int lr) #define RBUF 4000 +static inline end_of_header(char *buf) +{ + return buf[0] == 0x0d && buf[1] == 0x0a && buf[2] == 0x0d && buf[3] == 0x0a; +} + int read_rtsp (sockets * s) { @@ -507,8 +571,7 @@ read_rtsp (sockets * s) } } - if (s->rlen < 4 - || (htonl (*(uint32_t *) & s->buf[s->rlen - 4]) != 0x0D0A0D0A)) + if (s->rlen < 4 || !end_of_header(s->buf + s->rlen - 4)) { if( s->rlen > RBUF - 10 ) { @@ -524,6 +587,9 @@ read_rtsp (sockets * s) return 0; } +#ifdef AXE + axe_set_network_led(1); +#endif rlen = s->rlen; s->rlen = 0; @@ -726,8 +792,7 @@ read_http (sockets * s) "%s" ""; - if (s->rlen < 5 - || (htonl (*(uint32_t *) & s->buf[s->rlen - 4]) != 0x0D0A0D0A)) + if (s->rlen < 5 || !end_of_header(s->buf + s->rlen - 4)) { if( s->rlen > RBUF - 10 ) { @@ -749,6 +814,9 @@ read_http (sockets * s) return 0; } +#ifdef AXE + axe_set_network_led(1); +#endif rlen = s->rlen; s->rlen = 0; @@ -781,6 +849,15 @@ read_http (sockets * s) return 0; } +#ifdef AXE + if (strncmp (arg[1], "/axe-status.txt", 15) == 0) + { + axe_status(buf, sizeof(buf)); + http_response (s, 200, "CACHE-CONTROL: no-cache\r\nContent-type: text/plain", buf, 0, 0); + return 0; + } +#endif + if (strncmp (arg[1], "/icons/", 7) == 0) { char *ctype = NULL; @@ -904,6 +981,9 @@ ssdp_reply (sockets * s) return 0; } +#ifdef AXE + axe_set_network_led(1); +#endif // not my uuid LOG("Received SSDP packet from %s:%d -> handle %d", inet_ntoa(s->sa.sin_addr), ntohs(s->sa.sin_port), s->sock); LOGL(3, "%s", s->buf); @@ -987,7 +1067,13 @@ main (int argc, char *argv[]) set_options (argc, argv); if (opts.daemon) becomeDaemon (); + if (opts.slog) + openlog ("minisatip", LOG_NDELAY|LOG_NOWAIT|LOG_PID|(opts.slog>1?LOG_PERROR:0), LOG_DAEMON); +#ifdef AXE + LOGL(0, "Starting minisatip version %s, compiled with AXE DVB API, DVR buffer %d bytes",VERSION,opts.dvr); +#else LOGL(0, "Starting minisatip version %s, compiled with dvbapi version: %04X",VERSION, DVBAPIVERSION); +#endif readBootID(); if ((ssdp = udp_bind (NULL, 1900)) < 1) FAIL ("SSDP: Could not bind on udp port 1900"); @@ -1021,7 +1107,9 @@ main (int argc, char *argv[]) select_and_execute (); unlink(PID_FILE); free_all (); - return 0; + if (opts.slog) + closelog(); + return 0; } @@ -1247,12 +1335,16 @@ void _log(int level, char * file, int line, const char *fmt, ...) { idx = 1; else if ( idx < 0) idx = 0; - if(opts.file_line) + if(opts.file_line && !opts.slog) len1 = snprintf(output[idx], sizeof(output[0]), "[%s] %s:%d: ", get_current_timestamp_log(), file, line); - else + else if (!opts.slog) len1 = snprintf(output[idx], sizeof(output[0]), "[%s]: ", get_current_timestamp_log()); + else if (opts.file_line) { + len1 = 0; + output[idx][0] = '\0'; + } /* Write the error message */ - len = len1; + len = len1 = len1 < sizeof(output[0]) ? len1 : sizeof(output[0]) - 1; both = 0; va_start(arg, fmt); len += vsnprintf(output[idx] + len, sizeof(output[0]) - len, fmt, arg); @@ -1271,9 +1363,9 @@ void _log(int level, char * file, int line, const char *fmt, ...) { } if(both){ - puts(output[1-idx]); + if(opts.slog)syslog(LOG_NOTICE, "%s", output[1-idx]); else puts(output[1-idx]); both = 0; } - if(times==0)puts(output[idx]); + if(times==0) if(opts.slog)syslog(LOG_NOTICE, "%s", output[idx]); else puts(output[idx]); fflush(stdout); } diff --git a/minisatip.h b/minisatip.h index 821e756..2794f49 100755 --- a/minisatip.h +++ b/minisatip.h @@ -9,7 +9,7 @@ #define VERSION_BUILD "84" #define CC(a,b,c) #a b #c -#define VERSION CC(0.1.,VERSION_BUILD,) +#define VERSION CC(0.1.,VERSION_BUILD,-axe2) void set_options (int argc, char *argv[]); @@ -30,6 +30,13 @@ void set_options (int argc, char *argv[]); #define ENABLE_ADAPTERS_OPT 'e' #define UNICABLE_OPT 'u' #define JESS_OPT 'j' +#define SYSLOG_OPT 'g' +#define LINK_OPT 'L' +#define QUATTRO_OPT 'Q' +#define QUATTRO_HIBAND_OPT 'Z' +#define AXE_UNICINP_OPT 'X' +#define AXE_SKIP_PKT 'M' +#define AXE_POWER 'P' #define PID_FILE "/var/run/minisatip.pid" struct struct_opts @@ -39,6 +46,7 @@ struct struct_opts char *disc_host; //discover host char mac[13]; unsigned int log, + slog, start_rtp, http_port; int timeout_sec; @@ -50,6 +58,11 @@ struct struct_opts int dvr; int force_scan; int file_line; + int quattro; + int quattro_hiband; + int axe_unicinp[4]; + int axe_skippkt; + int axe_power; char *last_log; char playlist[200]; }; diff --git a/socketworks.c b/socketworks.c index b4891f1..4697f03 100755 --- a/socketworks.c +++ b/socketworks.c @@ -299,6 +299,7 @@ socket_action a, socket_action c, socket_action t) max_sock = i + 1; s[i].buf = NULL; s[i].lbuf = 0; + s[i].skiplen = type == TYPE_DVR ? opts.axe_skippkt * 188 : 0; s[i].close_sec = 0; s[i].sock_id = i; pf[i].fd = sock; @@ -339,6 +340,25 @@ sockets_del (int sock) return 0; } +void +sockets_set_poll (int sock, int enable) +{ + if (sock < 0 || sock > MAX_SOCKS) + return; + pf[sock].events = enable ? (POLLIN | POLLPRI) : 0; +} + +void +sockets_reset (int sock) +{ + int i; + + if (sock < 0 || sock > MAX_SOCKS) + return; + if (s[sock].type == TYPE_DVR) + s[sock].skiplen = opts.axe_skippkt * 188; + s[sock].rlen = 0; +} int run_loop, it = 0, c_time; int bw, bwtt, bwnotify; @@ -348,7 +368,6 @@ uint32_t nsecs, reads; int select_and_execute () { - fd_set io; struct timeval tv; socklen_t slen; int i, @@ -362,7 +381,6 @@ select_and_execute () lt = getTick (); while (run_loop) { - FD_ZERO (&io); i = -1; // LOG("start select"); if ((rv = poll (pf, max_sock, 200)) < 0) @@ -433,6 +451,29 @@ select_and_execute () ss->rtime = c_time; if(rlen>0) ss->rlen += rlen; +#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)) + rlen = 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; @@ -510,8 +551,6 @@ select_and_execute () && ((s[i].close_sec > 0 && lt - s[i].rtime > s[i].close_sec) || (s[i].close_sec == 1))) { - int do_close = 0; - // LOG("Timeout idle connection %d index %d",s[i].sock,i); if (s[i].timeout && s[i].timeout (&s[i])) sockets_del (i); @@ -619,12 +658,13 @@ char * get_current_timestamp_log (void) { static char date_str[200]; + struct timeval tv; time_t date; struct tm *t; - time (&date); - t = localtime (&date); + if (gettimeofday(&tv, NULL)) return "01/01 00:00:20"; + t = localtime (&tv.tv_sec); if(!t) return "01/01 00:00:20"; - snprintf (date_str, sizeof (date_str), "%02d/%02d %02d:%02d:%02d.%03d",t->tm_mday, t->tm_mon + 1, t->tm_hour, t->tm_min, t->tm_sec, getTick()); + snprintf (date_str, sizeof (date_str), "%02d/%02d %02d:%02d:%02d.%03d",t->tm_mday, t->tm_mon + 1, t->tm_hour, t->tm_min, t->tm_sec, (int)(tv.tv_usec / 1000)); return date_str; } diff --git a/socketworks.h b/socketworks.h index 57b25b2..226c689 100755 --- a/socketworks.h +++ b/socketworks.h @@ -18,6 +18,7 @@ typedef struct struct_sockets unsigned char *buf; int lbuf; int rlen; + int skiplen; int close_sec; int sock_id; // socket id int err; @@ -43,6 +44,8 @@ int get_sock_port(int fd); int sockets_add (int sock, struct sockaddr_in *sa, int sid, int type, socket_action a, socket_action c, socket_action t); int sockets_del (int sock); +void sockets_set_poll (int sock, int enable); +void sockets_reset (int sock); int no_action (int s); int select_and_execute (); int get_mac (char *mac); diff --git a/stream.c b/stream.c index db4a46d..8cdd239 100755 --- a/stream.c +++ b/stream.c @@ -54,7 +54,7 @@ getTick () { //ms struct timespec ts; - clock_gettime (CLOCK_REALTIME, &ts); + clock_gettime (CLOCK_MONOTONIC, &ts); theTick = ts.tv_nsec / 1000000; theTick += ts.tv_sec * 1000; ntime = ts.tv_sec * 1000000 + ts.tv_nsec; @@ -320,6 +320,7 @@ int decode_transport (sockets * s, char *arg, char *default_rtp, int start_rtp) if(sid->type == 0) { int i; + socklen_t sl; struct sockaddr_in sa; sid->type = STREAM_RTSP_UDP; @@ -332,6 +333,13 @@ int decode_transport (sockets * s, char *arg, char *default_rtp, int start_rtp) if((sid->rsock = udp_bind_connect (NULL, opts.start_rtp + (sid->sid * 2), p.dest, p.port, &sid->sa)) < 0) LOG_AND_RETURN (-1, "decode_transport failed: UDP connection on rtp port to %s:%d failed", p.dest, p.port); + + i = 512*1024; + if(setsockopt(sid->rsock, SOL_SOCKET, SO_SNDBUF, &i, sizeof(i))) + LOG("unable to set output UDP buffer size to %d", i); + sl = sizeof(int); + if(!getsockopt(sid->rsock, SOL_SOCKET, SO_SNDBUF, &i, &sl)) + LOG("output UDP buffer size is %d bytes", i); if ((sid->rtcp = udp_bind_connect (NULL, opts.start_rtp + (sid->sid * 2) +1, p.dest, p.port + 1, &sa)) < 1) LOG_AND_RETURN (-1, "decode_transport failed: UDP connection on rtcp port to %s:%d failed", p.dest, p.port+1); @@ -582,7 +590,7 @@ send_rtcp (int s_id, int ctime) rtcp[51] = 0; rtcp[52] = 0x80; rtcp[53] = 0xCC; - copy16( rtcp, 54, (la + 16) / 4); + copy16( rtcp, 54, ((la + 16 + 3) / 4) - 1); copy32( rtcp, 56, sid->ssrc); rtcp[60] = 'S'; rtcp[61] = 'E'; @@ -617,13 +625,18 @@ extern uint32_t nsecs, reads; void flush_streamb (streams * sid, char *buf, int rlen, int ctime) { - int i, rv = 0; + int i, remain, rv = 0; if (sid->type == STREAM_HTTP) rv = send (sid->rsock, buf, rlen, MSG_NOSIGNAL); - else - for (i = 0; i < rlen; i += DVB_FRAME * 7) - rv += send_rtpb (sid, &buf[i], DVB_FRAME * 7); + else { + for (i = 0; i < rlen; i += DVB_FRAME * 7) { + remain = rlen - i; + rv += send_rtpb (sid, &buf[i], + remain < DVB_FRAME * 7 ? + remain : DVB_FRAME * 7); + } + } sid->iiov = 0; sid->wtime = ctime; @@ -675,8 +688,9 @@ read_dmx (sockets * s) int pid, flush_all = 0; uint64_t stime; - if (s->rlen % DVB_FRAME != 0) - s->rlen = ((int) s->rlen / DVB_FRAME) * DVB_FRAME; + i = s->rlen % DVB_FRAME; + if (i) + s->rlen -= i; if (s->rlen == s->lbuf) cnt++; else @@ -696,7 +710,7 @@ read_dmx (sockets * s) LOG ("Buffer overrun %d %d", s->rlen, s->lbuf); // LOGL(2, "read_dmx called for adapter %d -> %d bytes read ",s->sid, s->rlen); - + int rlen = s->rlen; ad->rtime = s->rtime; s->rlen = 0; diff --git a/stream.h b/stream.h index 5f1bd6f..5885c59 100755 --- a/stream.h +++ b/stream.h @@ -38,7 +38,7 @@ typedef struct struct_streams *pids; struct iovec iov[MAX_PACK + 2]; int iiov; - int sp,sb; + size_t sp,sb; int timeout; } streams;