summaryrefslogtreecommitdiff
path: root/mcast/common/tools.c
diff options
context:
space:
mode:
authorLars Heer <l.heer@gmx.de>2013-09-18 05:50:03 +0200
committerLars Heer <l.heer@gmx.de>2013-09-18 05:50:03 +0200
commitccf6e0f9c6b0481ed13e0f4794e3fbead750f385 (patch)
treeed86efb54f7ee41edfba5c89ca519b5fd10aa0d5 /mcast/common/tools.c
downloadvdr-plugin-mcli-ccf6e0f9c6b0481ed13e0f4794e3fbead750f385.tar.gz
vdr-plugin-mcli-ccf6e0f9c6b0481ed13e0f4794e3fbead750f385.tar.bz2
added vdr-plugin-mcli-0.0.1+svn20120927
Diffstat (limited to 'mcast/common/tools.c')
-rw-r--r--mcast/common/tools.c777
1 files changed, 777 insertions, 0 deletions
diff --git a/mcast/common/tools.c b/mcast/common/tools.c
new file mode 100644
index 0000000..9e05a10
--- /dev/null
+++ b/mcast/common/tools.c
@@ -0,0 +1,777 @@
+/*
+ * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de
+ *
+ * See the COPYING file for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#define DEBUG 1
+#include "headers.h"
+
+#ifdef DEBUG
+const Param inversion_list[] = {
+ {"INVERSION_OFF", INVERSION_OFF},
+ {"INVERSION_ON", INVERSION_ON},
+ {"INVERSION_AUTO", INVERSION_AUTO}
+};
+
+const Param bw_list[] = {
+ {"BANDWIDTH_6_MHZ", BANDWIDTH_6_MHZ},
+ {"BANDWIDTH_7_MHZ", BANDWIDTH_7_MHZ},
+ {"BANDWIDTH_8_MHZ", BANDWIDTH_8_MHZ}
+};
+
+const Param fec_list[] = {
+ {"FEC_1_2", FEC_1_2},
+ {"FEC_2_3", FEC_2_3},
+ {"FEC_3_4", FEC_3_4},
+ {"FEC_4_5", FEC_4_5},
+ {"FEC_5_6", FEC_5_6},
+ {"FEC_6_7", FEC_6_7},
+ {"FEC_7_8", FEC_7_8},
+ {"FEC_8_9", FEC_8_9},
+ {"FEC_AUTO", FEC_AUTO},
+ {"FEC_NONE", FEC_NONE},
+ {"FEC_1_4", FEC_1_4}, // RMM S2 Extension
+ {"FEC_1_3", FEC_1_3},
+ {"FEC_2_5", FEC_2_5},
+ {"FEC_9_10", FEC_9_10}
+};
+
+const Param guard_list[] = {
+ {"GUARD_INTERVAL_1_16", GUARD_INTERVAL_1_16},
+ {"GUARD_INTERVAL_1_32", GUARD_INTERVAL_1_32},
+ {"GUARD_INTERVAL_1_4", GUARD_INTERVAL_1_4},
+ {"GUARD_INTERVAL_1_8", GUARD_INTERVAL_1_8}
+};
+
+const Param hierarchy_list[] = {
+ {"HIERARCHY_1", HIERARCHY_1},
+ {"HIERARCHY_2", HIERARCHY_2},
+ {"HIERARCHY_4", HIERARCHY_4},
+ {"HIERARCHY_NONE", HIERARCHY_NONE}
+};
+
+const Param constellation_list[] = {
+ {"QPSK", QPSK},
+ {"QAM_128", QAM_128},
+ {"QAM_16", QAM_16},
+ {"QAM_256", QAM_256},
+ {"QAM_32", QAM_32},
+ {"QAM_64", QAM_64},
+ {"QPSK_S2", QPSK_S2}, // RMM S2 Extension
+ {"PSK8", PSK8}
+};
+
+const Param transmissionmode_list[] = {
+ {"TRANSMISSION_MODE_2K", TRANSMISSION_MODE_2K},
+ {"TRANSMISSION_MODE_8K", TRANSMISSION_MODE_8K},
+};
+
+const Param capabilities_list[] = {
+ {"Stupid: ", FE_IS_STUPID},
+ {"FE_CAN_INVERSION_AUTO: ", FE_CAN_INVERSION_AUTO},
+ {"CAN_FEC_1_2: ", FE_CAN_FEC_1_2},
+ {"CAN_FEC_2_3: ", FE_CAN_FEC_2_3},
+ {"CAN_FEC_3_4: ", FE_CAN_FEC_3_4},
+ {"CAN_FEC_4_5: ", FE_CAN_FEC_4_5},
+ {"CAN_FEC_6_7: ", FE_CAN_FEC_6_7},
+ {"CAN_FEC_7_8: ", FE_CAN_FEC_7_8},
+ {"CAN_FEC_8_9: ", FE_CAN_FEC_8_9},
+ {"CAN_FEC_AUTO: ", FE_CAN_FEC_AUTO},
+ {"FE_CAN_QPSK: ", FE_CAN_QPSK},
+ {"FE_CAN_QAM_16: ", FE_CAN_QAM_16},
+ {"FE_CAN_QAM_32: ", FE_CAN_QAM_32},
+ {"FE_CAN_QAM_64: ", FE_CAN_QAM_64},
+ {"FE_CAN_QAM_128: ", FE_CAN_QAM_128},
+ {"FE_CAN_QAM_256: ", FE_CAN_QAM_256},
+ {"FE_CAN_QAM_AUTO: ", FE_CAN_QAM_AUTO},
+ {"FE_CAN_TRANSMISSION_MODE_AUTO: ", FE_CAN_TRANSMISSION_MODE_AUTO},
+ {"FE_CAN_BANDWIDTH_AUTO: ", FE_CAN_BANDWIDTH_AUTO},
+ {"FE_CAN_GUARD_INTERVAL_AUTO: ", FE_CAN_GUARD_INTERVAL_AUTO},
+ {"FE_CAN_HIERARCHY_AUTO: ", FE_CAN_HIERARCHY_AUTO},
+ {"FE_CAN_MUTE_TS: ", FE_CAN_MUTE_TS}
+// {"FE_CAN_CLEAN_SETUP: ",FE_CAN_CLEAN_SETUP}
+};
+
+#define LIST_SIZE(x) sizeof(x)/sizeof(Param)
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+void print_fe_info (struct dvb_frontend_info *fe_info)
+{
+ fprintf (stdout, "-------------------------------------------\n");
+ fprintf (stdout, "Tuner name: %s\n", fe_info->name);
+ fprintf (stdout, "Tuner type: %u\n", (unsigned int) fe_info->type);
+ fprintf (stdout, "Frequency min.: %u\n", fe_info->frequency_min);
+ fprintf (stdout, "Frequency max.: %u\n", fe_info->frequency_max);
+ fprintf (stdout, "Frequency stepsize: %u\n", fe_info->frequency_stepsize);
+ fprintf (stdout, "Frequency tolerance: %u\n", fe_info->frequency_tolerance);
+ fprintf (stdout, "Symbol rate min: %u\n", fe_info->symbol_rate_min);
+ fprintf (stdout, "Symbol rate max: %u\n", fe_info->symbol_rate_max);
+ fprintf (stdout, "Symbol rate tolerance: %u\n", fe_info->symbol_rate_tolerance);
+ fprintf (stdout, "Notifier delay: %u\n", fe_info->notifier_delay);
+ fprintf (stdout, "Cpas: 0x%x\n", (unsigned int) fe_info->caps);
+
+ fprintf (stdout, "-------------------------------------------\n");
+ fprintf (stdout, "Frontend Capabilities:\n");
+ int i;
+
+ for (i = 0; i < LIST_SIZE (capabilities_list); i++) {
+ if (fe_info->caps & capabilities_list[i].value)
+ fprintf (stdout, "%syes\n", capabilities_list[i].name);
+ else
+ fprintf (stdout, "%sno\n", capabilities_list[i].name);
+ }
+ fprintf (stdout, "-------------------------------------------\n");
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+void print_frontend_settings (struct dvb_frontend_parameters *frontend_param)
+{
+ int i;
+ fprintf (stdout, "\n----- Front End Settings ----- ");
+ fprintf (stdout, "\nFrequency : %u \n", frontend_param->frequency);
+ for (i = 0; i < LIST_SIZE (inversion_list); i++) {
+ if (inversion_list[i].value == frontend_param->inversion)
+ fprintf (stdout, "Inversion : %s\n", inversion_list[i].name);
+
+ }
+ //
+ for (i = 0; i < LIST_SIZE (bw_list); i++) {
+ if (frontend_param->u.ofdm.bandwidth == bw_list[i].value)
+ fprintf (stdout, "Bandwidth : %s\n", bw_list[i].name);
+
+ }
+ for (i = 0; i < LIST_SIZE (fec_list); i++) {
+ if (fec_list[i].value == frontend_param->u.ofdm.code_rate_HP)
+ fprintf (stdout, "Code Rate HP : %s\n", fec_list[i].name);
+
+ }
+ for (i = 0; i < LIST_SIZE (fec_list); i++) {
+ if (fec_list[i].value == frontend_param->u.ofdm.code_rate_LP)
+ fprintf (stdout, "Code Rate LP : %s\n", fec_list[i].name);
+
+ }
+
+ for (i = 0; i < LIST_SIZE (constellation_list); i++) {
+ if (constellation_list[i].value == frontend_param->u.ofdm.constellation)
+ fprintf (stdout, "Modulation : %s\n", constellation_list[i].name);
+
+ }
+
+ for (i = 0; i < LIST_SIZE (transmissionmode_list); i++) {
+ if (transmissionmode_list[i].value == frontend_param->u.ofdm.transmission_mode)
+ fprintf (stdout, "Transmission mode : %s\n", transmissionmode_list[i].name);
+
+ }
+
+ for (i = 0; i < LIST_SIZE (guard_list); i++) {
+ if (guard_list[i].value == frontend_param->u.ofdm.guard_interval)
+ fprintf (stdout, "Guard interval : %s\n", guard_list[i].name);
+
+ }
+
+ for (i = 0; i < LIST_SIZE (hierarchy_list); i++) {
+ if (hierarchy_list[i].value == frontend_param->u.ofdm.hierarchy_information)
+ fprintf (stdout, "Hierarchy Information : %s\n", hierarchy_list[i].name);
+
+ }
+
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+void print_mcg (struct in6_addr *mcg)
+{
+ char host[80];
+ unsigned int freq;
+ struct in6_addr mc;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ mc.s6_addr16[i] = ntohs (mcg->s6_addr16[i]);
+ }
+
+ freq = mc.s6_addr16[6] | (mc.s6_addr16[7] & NOPID_MASK) << 3;
+
+ inet_ntop (AF_INET6, mcg->s6_addr, (char *) host, INET6_ADDRSTRLEN);
+ fprintf (stdout, "MCG: %s\n", host);
+
+ fprintf (stdout, "\n");
+ fprintf (stdout, "TS-Streaming group\n");
+ fprintf (stdout, "-----------------------------\n");
+ fprintf (stdout, "Streaming Group - 0x%x \n", (mc.s6_addr16[1] >> 12) & 0xf);
+ fprintf (stdout, "Priority - 0x%x \n", (mc.s6_addr16[1] >> 8) & 0xf);
+ fprintf (stdout, "Reception System - 0x%x \n", mc.s6_addr16[1] & 0xff);
+ fprintf (stdout, "CAM Handling - 0x%x \n", mc.s6_addr16[2]);
+ fprintf (stdout, "Polarisation - 0x%x \n", (mc.s6_addr16[3] >> 12) & 0xf);
+ fprintf (stdout, "SATPosition - 0x%x \n", mc.s6_addr16[3] & 0xfff);
+ fprintf (stdout, "Symbol Rate - 0x%x \n", mc.s6_addr16[4]);
+ fprintf (stdout, "Modulation - 0x%x \n", mc.s6_addr16[5]);
+ fprintf (stdout, "Frequency (0x%x) - %d / %d\n\n", freq, freq * (16667 / 8), freq * (250 / 8));
+
+ fprintf (stdout, "PID - 0x%x \n", mc.s6_addr16[7] & PID_MASK);
+}
+#endif
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+/* Frequency 19Bit
+ DVB-T/DVB-C 524288 Steps * (25/12)kHz = 0...1092MHz in 2.083333kHz steps
+ DVB-S 524288 Steps * (1/20) MHz = 0...26.2GHz in 50kHz steps
+*/
+void fe_parms_to_mcg (struct in6_addr *mcg, streaming_group_t StreamingGroup, fe_type_t type, recv_sec_t * sec, struct dvb_frontend_parameters *fep, int vpid)
+{
+ int i;
+ unsigned int Priority = 0;
+ unsigned int ReceptionSystem = 0;
+ unsigned int CAMHandling = 0;
+ unsigned int Polarisation = 0;
+ unsigned int SATPosition = NO_SAT_POS;
+ unsigned int Symbolrate = 0;
+ unsigned int Modulation = 0;
+ unsigned int TransmissionMode = 0;
+ unsigned int Frequency;
+ double fmul;
+
+ // Default for DVB-T and DVB-C
+ fmul = 12.0 * (((double) fep->frequency) + 1041);
+ Frequency = (unsigned int) (fmul / 25000.0);
+
+ switch ((int)type) {
+ case FE_QPSK:
+ case FE_DVBS2:
+ Frequency = (fep->frequency + 24) / 50;
+ //sec->diseqc_cmd currently not used
+ // Fixme: Translation Diseqc->position/LOF-frequency
+ Polarisation = (sec->mini_cmd << 3) | (sec->tone_mode << 2) | sec->voltage;
+ Symbolrate = fep->u.qpsk.symbol_rate / 1000;
+ Modulation |= (fep->u.qpsk.fec_inner) & 0xf;
+
+ // RMM S2 extension: Put Modulation in 23:16 and rolloff in 31:24
+ if (((fep->u.qpsk.fec_inner >> 16) & 0xff) == PSK8)
+ Modulation |= 2 << 4;
+ if (((fep->u.qpsk.fec_inner >> 16) & 0xff) == QPSK_S2)
+ Modulation |= 1 << 4;
+ Modulation |= fep->inversion << 14;
+ break;
+ case FE_QAM:
+ Symbolrate = fep->u.qam.symbol_rate / 200;
+ Modulation |= fep->u.qam.modulation;
+ Modulation |= fep->inversion << 14;
+ break;
+ case FE_OFDM:
+ TransmissionMode = fep->u.ofdm.transmission_mode;
+ Symbolrate = (TransmissionMode & 0x7) << 8 | (fep->u.ofdm.code_rate_HP << 4) | fep->u.ofdm.code_rate_LP;
+ Modulation |= (fep->u.ofdm.constellation & 0xf) | (fep->u.ofdm.hierarchy_information & 3) << 4 | (fep->u.ofdm.bandwidth & 3) << 7 | (fep->u.ofdm.guard_interval & 7) << 9 | (fep->inversion & 3) << 14;
+ break;
+ case FE_ATSC:
+ Modulation |= fep->u.vsb.modulation;
+ Modulation |= fep->inversion << 14;
+ break;
+ }
+
+ if (type == FE_DVBS2 && !(Modulation & 0x30) ){
+ type=FE_QPSK;
+ }
+
+ ReceptionSystem = type;
+
+ mcg->s6_addr16[0] = MC_PREFIX;
+ mcg->s6_addr16[1] = ((StreamingGroup & 0xf) << 12) | ((Priority & 0xf) << 8) | (ReceptionSystem & 0xff);
+ mcg->s6_addr16[2] = CAMHandling;
+ mcg->s6_addr16[3] = ((Polarisation & 0xf) << 12) | (SATPosition & 0xfff);
+ mcg->s6_addr16[4] = Symbolrate;
+ mcg->s6_addr16[5] = Modulation;
+ mcg->s6_addr16[6] = Frequency;
+ mcg->s6_addr16[7] = (vpid & PID_MASK) | ((Frequency >> 16) << 13);
+
+ for (i = 0; i < 8; i++) {
+ mcg->s6_addr16[i] = htons (mcg->s6_addr16[i]);
+ }
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+int mcg_to_all_parms(struct in6_addr *mcg, struct mcg_data * mcd)
+{
+ int ret;
+ mcd->mcg=*mcg;
+ int n;
+
+ ret=mcg_to_fe_parms(mcg, &mcd->type, &mcd->sec, &mcd->fep, &mcd->vpid);
+
+ if (ret)
+ return ret;
+ mcg_get_satpos(mcg, &mcd->satpos);
+
+ for(n=0;n<MAX_TUNER_CACHE;n++) {
+ mcd->sat_cache[n].resolved=NOT_RESOLVED;
+ mcd->sat_cache[n].num=0;
+ mcd->sat_cache[n].component=0;
+ }
+
+ return 0;
+}
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+int mcg_to_fe_parms (struct in6_addr *mcg, fe_type_t * type, recv_sec_t * sec, struct dvb_frontend_parameters *fep, int *vpid)
+{
+ struct in6_addr mc = *mcg;
+ streaming_group_t StreamingGroup;
+ unsigned int freq;
+ double fmul;
+ fe_type_t fetype;
+
+ int i;
+ for (i = 0; i < 8; i++) {
+ mc.s6_addr16[i] = ntohs (mc.s6_addr16[i]);
+ }
+
+ StreamingGroup = (streaming_group_t)((mc.s6_addr16[1] >> 12) & 0xf);
+
+ if (StreamingGroup != STREAMING_PID) {
+ return -1;
+ }
+
+ if (fep) {
+ memset (fep, 0, sizeof (struct dvb_frontend_parameters));
+ }
+ if (sec) {
+ memset (sec, 0, sizeof (recv_sec_t));
+ }
+
+
+ freq = mc.s6_addr16[6] | ((mc.s6_addr16[7] & NOPID_MASK) << 3);
+
+ fmul = 25000.0 * (double) freq;
+
+ fep->frequency = (unsigned int) (fmul / 12.0);
+ fep->inversion = (fe_spectral_inversion_t)((mc.s6_addr16[5] >> 14) & 3);
+ fetype = (fe_type_t)(mc.s6_addr16[1] & 0xff);
+
+ if (type) {
+ *type = fetype;
+ }
+ switch ((int)fetype) {
+ case FE_QPSK:
+ case FE_DVBS2:
+ {
+ int Polarisation = mc.s6_addr16[3] >> 12;
+ fep->frequency = freq * 50;
+ sec->mini_cmd = (fe_sec_mini_cmd_t)((Polarisation >> 3) & 1);
+ sec->tone_mode = (fe_sec_tone_mode_t)((Polarisation >> 2) & 1);
+ sec->voltage = (fe_sec_voltage_t)(Polarisation & 3);
+
+ fep->u.qpsk.symbol_rate = mc.s6_addr16[4] * 1000;
+ fep->u.qpsk.fec_inner = (fe_code_rate_t)(mc.s6_addr16[5] & 0xf);
+
+ unsigned int fec_inner=(unsigned int)fep->u.qpsk.fec_inner;
+
+ // RMM S2 Extension
+ switch (mc.s6_addr16[5] & 0x30) {
+ case 0x10:
+ fec_inner |= QPSK_S2 << 16;
+ fep->u.qpsk.fec_inner=(fe_code_rate_t)fec_inner;
+ *type = (fe_type_t) FE_DVBS2; // force FE type
+ break;
+ case 0x20:
+ fec_inner |= PSK8 << 16;
+ fep->u.qpsk.fec_inner=(fe_code_rate_t)fec_inner;
+ *type = (fe_type_t) FE_DVBS2;
+ break;
+ default:
+ *type = FE_QPSK;
+ }
+ }
+ break;
+ case FE_QAM:
+ fep->u.qam.symbol_rate = mc.s6_addr16[4] * 200;
+ fep->u.qam.modulation = (fe_modulation_t)(mc.s6_addr16[5] & 0xf);
+ // Ignore inversion
+ break;
+ case FE_OFDM:
+ fep->u.ofdm.transmission_mode = (fe_transmit_mode_t)((mc.s6_addr16[4] >> 8) & 3);
+ fep->u.ofdm.code_rate_HP = (fe_code_rate_t)((mc.s6_addr16[4] >> 4) & 0xf);
+ fep->u.ofdm.code_rate_LP = (fe_code_rate_t)(mc.s6_addr16[4] & 0xf);
+
+ fep->u.ofdm.constellation = (fe_modulation_t) (mc.s6_addr16[5] & 0xf);
+ fep->u.ofdm.hierarchy_information = (fe_hierarchy_t)((mc.s6_addr16[5] >> 4) & 3);
+ fep->u.ofdm.bandwidth = (fe_bandwidth_t)((mc.s6_addr16[5] >> 7) & 3);
+ fep->u.ofdm.guard_interval = (fe_guard_interval_t)((mc.s6_addr16[5] >> 9) & 7);
+ break;
+ case FE_ATSC:
+ fep->u.vsb.modulation = (fe_modulation_t)(mc.s6_addr16[5] & 0xf);
+ break;
+ }
+
+ if (vpid) {
+ *vpid = mc.s6_addr16[7] & PID_MASK;
+ }
+ //print_frontend_settings(fep);
+ return 0;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+void mcg_set_streaming_group (struct in6_addr *mcg, streaming_group_t StreamingGroup)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ mcg->s6_addr16[i] = ntohs (mcg->s6_addr16[i]);
+ }
+
+ // Change StreamingGroup
+ mcg->s6_addr16[1] = ((StreamingGroup & 0xf) << 12) | (mcg->s6_addr16[1] & 0x0fff);
+
+ // Remove PID
+ mcg->s6_addr16[7] &= NOPID_MASK;
+
+ // Remove CAID
+ mcg->s6_addr16[2] = 0;
+
+ for (i = 0; i < 8; i++) {
+ mcg->s6_addr16[i] = htons (mcg->s6_addr16[i]);
+ }
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+void mcg_get_streaming_group (struct in6_addr *mcg, streaming_group_t *StreamingGroup)
+{
+ if(StreamingGroup) {
+ *StreamingGroup=(streaming_group_t)((ntohs (mcg->s6_addr16[1]) >> 12) & 0xf);
+ }
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+void mcg_set_pid (struct in6_addr *mcg, int pid)
+{
+
+ mcg->s6_addr16[7] = ntohs (mcg->s6_addr16[7]);
+
+ // Remove PID
+ mcg->s6_addr16[7] &= NOPID_MASK;
+
+ // Set new PID
+ mcg->s6_addr16[7] |= pid;
+
+ mcg->s6_addr16[7] = htons (mcg->s6_addr16[7]);
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+void mcg_get_pid (struct in6_addr *mcg, int *pid)
+{
+ if (pid) {
+ *pid=ntohs (mcg->s6_addr16[7]) & PID_MASK;
+ }
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+void mcg_init_streaming_group (struct in6_addr *mcg, streaming_group_t StreamingGroup)
+{
+ unsigned int Priority = 1;
+ mcg->s6_addr16[0] = MC_PREFIX;
+ mcg->s6_addr16[1] = ((StreamingGroup & 0xf) << 12) | ((Priority & 0xf) << 8) | (0 & 0xff);
+ mcg->s6_addr16[2] = 0;
+ mcg->s6_addr16[3] = 0;
+ mcg->s6_addr16[4] = 0;
+ mcg->s6_addr16[5] = 0;
+ mcg->s6_addr16[6] = 0;
+ mcg->s6_addr16[7] = 0;
+ int i;
+ for (i = 0; i < 8; i++) {
+ mcg->s6_addr16[i] = htons (mcg->s6_addr16[i]);
+ }
+
+}
+
+void mcg_get_priority (struct in6_addr *mcg, int *priority)
+{
+ if (priority) {
+ *priority = (ntohs (mcg->s6_addr16[1])>>8) & 0xf;
+ }
+}
+
+void mcg_set_priority (struct in6_addr *mcg, int priority)
+{
+ mcg->s6_addr16[1] = ntohs (mcg->s6_addr16[1]);
+ mcg->s6_addr16[1] &= 0xf0ff;
+ mcg->s6_addr16[1] |= (priority & 0xf) << 8;
+ mcg->s6_addr16[1] = htons (mcg->s6_addr16[1]);
+}
+
+void mcg_get_satpos (struct in6_addr *mcg, int *satpos)
+{
+ if (satpos) {
+ *satpos = ntohs (mcg->s6_addr16[3]) & 0xfff;
+ }
+}
+
+void mcg_set_satpos (struct in6_addr *mcg, int satpos)
+{
+ mcg->s6_addr16[3] = ntohs (mcg->s6_addr16[3]);
+
+ // Remove SatPos
+ mcg->s6_addr16[3] &= ~NO_SAT_POS;
+
+ // Set new SatPos
+ mcg->s6_addr16[3] |= (satpos & NO_SAT_POS);
+
+ mcg->s6_addr16[3] = htons (mcg->s6_addr16[3]);
+}
+
+void mcg_get_id (struct in6_addr *mcg, int *id)
+{
+ if (id) {
+ *id = ntohs (mcg->s6_addr16[2]);
+ }
+}
+
+void mcg_set_id (struct in6_addr *mcg, int id)
+{
+ mcg->s6_addr16[2] = htons(id);
+}
+
+#if defined LIBRARY || defined SERVER
+#ifndef OS_CODE
+ #define OS_CODE 3
+#endif
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+
+static unsigned char gzip_hdr[] = { 0x1f, 0x8b, Z_DEFLATED, 0 /*flags */ , 0, 0, 0, 0 /*time */ , 0 /*xflags */ , OS_CODE };
+
+int check_header (const Bytef * buf, unsigned int buflen)
+{
+ if (buflen <= 10)
+ return 0;
+
+ if (buf[0] != gzip_hdr[0] || buf[1] != gzip_hdr[1]) {
+ return -1;
+ }
+
+ if (memcmp (buf, gzip_hdr, sizeof (gzip_hdr))) {
+ return -2;
+ }
+ return 10;
+}
+
+unsigned int get32_lsb_first (unsigned char *ptr)
+{
+ int i;
+ unsigned int val = 0;
+ for (i = 3; i >= 0; i--) {
+ val <<= 8;
+ val |= (ptr[i] & 0xff);
+ }
+ return val;
+}
+
+void put32_lsb_first (unsigned char *ptr, unsigned int val)
+{
+ int i;
+ for (i = 0; i < 4; i++) {
+ ptr[i] = val & 0xff;
+ val >>= 8;
+ }
+}
+
+int gzip_ (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen, int level)
+{
+ unsigned int crc = crc32 (0L, Z_NULL, 0);
+ z_stream stream;
+ int err;
+
+ if (*destLen <= 10) {
+ return Z_BUF_ERROR;
+ }
+ memcpy (dest, gzip_hdr, sizeof (gzip_hdr));
+
+ stream.next_in = (Bytef *) source;
+ stream.avail_in = sourceLen;
+
+ stream.next_out = dest + 10;
+ stream.avail_out = *destLen - 10;
+
+ stream.zalloc = (alloc_func) 0;
+ stream.zfree = (free_func) 0;
+ stream.opaque = (voidpf) 0;
+
+ err = deflateInit2 (&stream, level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+
+ if (err != Z_OK)
+ return err;
+
+ err = deflate (&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd (&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out + 10;
+
+ err = deflateEnd (&stream);
+ crc = crc32 (crc, source, sourceLen);
+
+ put32_lsb_first ((unsigned char *) (dest + *destLen), crc);
+ put32_lsb_first ((unsigned char *) (dest + *destLen + 4), sourceLen);
+
+ *destLen += 8;
+ return err;
+}
+
+int gzip (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen, int level)
+{
+ if (!level) {
+ memcpy (dest, source, sourceLen);
+ *destLen = sourceLen;
+ return 0;
+ }
+ return gzip_ (dest, destLen, source, sourceLen,level);
+}
+
+int gunzip_ (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen)
+{
+ unsigned int crc = crc32 (0L, Z_NULL, 0);
+ z_stream stream;
+ int err;
+ int ret = check_header (source, sourceLen);
+ if (ret < 0) {
+ return ret;
+ }
+
+ stream.next_in = (Bytef *) source + ret;
+ stream.avail_in = sourceLen - ret;
+
+ stream.next_out = dest;
+ stream.avail_out = *destLen;
+
+ stream.zalloc = (alloc_func) 0;
+ stream.zfree = (free_func) 0;
+
+ err = inflateInit2 (&stream, -MAX_WBITS);
+ if (err != Z_OK)
+ return err;
+
+ err = inflate (&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd (&stream);
+ if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+ return Z_DATA_ERROR;
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd (&stream);
+ crc = crc32 (crc, dest, stream.total_out);
+
+ int crc_found = get32_lsb_first ((unsigned char *) (stream.next_in));
+ int len_found = get32_lsb_first ((unsigned char *) (stream.next_in + 4));
+
+ if (crc_found == crc && len_found == stream.total_out) {
+ return err;
+ }
+
+ return Z_DATA_ERROR;
+}
+
+int gunzip (Bytef * dest, unsigned int *destLen, const Bytef * source, unsigned int sourceLen)
+{
+ int ret = gunzip_ (dest, destLen, source, sourceLen);
+ if (ret == -1) {
+ memcpy (dest, source, sourceLen);
+ *destLen = sourceLen;
+ return 0;
+ } else if (ret < 0) {
+ return -1;
+ }
+ return 0;
+}
+#endif
+#ifndef BACKTRACE
+ void print_trace (void)
+ {
+ }
+#else
+#include <execinfo.h>
+/* Obtain a backtrace and print it to stdout. */
+void print_trace (void)
+{
+ void *array[10];
+ size_t size;
+ char **strings;
+ size_t i;
+
+ size = backtrace (array, 10);
+ strings = backtrace_symbols (array, size);
+
+ printf ("Obtained %zd stack frames.\n", size);
+
+ for (i = 0; i < size; i++) {
+ printf ("%s\n", strings[i]);
+ }
+ free (strings);
+}
+
+
+void SignalHandlerCrash(int signum)
+{
+ void *array[15];
+ size_t size;
+ char **strings;
+ size_t i;
+ FILE *f;
+ char dtstr[16];
+ time_t t=time(NULL);
+ struct tm *tm=localtime(&t);
+
+ signal(signum,SIG_DFL); // Allow core dump
+
+ f=fopen("/var/log/mcli.crashlog","a");
+ if (f) {
+ strftime(dtstr, sizeof(dtstr), "%b %e %T", tm);
+ size = backtrace (array, 15);
+ strings = backtrace_symbols (array, size);
+ fprintf(f,"%s ### Crash signal %i ###\n",dtstr, signum);
+ for (i = 0; i < size; i++)
+ fprintf (f, "%s Backtrace %i: %s\n", dtstr, i, strings[i]);
+ free (strings);
+ fclose(f);
+ }
+}
+#endif
+
+#ifdef SYSLOG
+pthread_mutex_t _loglock = PTHREAD_MUTEX_INITIALIZER;
+
+UDPContext * syslog_fd = NULL;
+char *_logstr = NULL;
+
+int syslog_init(void)
+{
+ struct in6_addr mcglog;
+ mcg_init_streaming_group (&mcglog, STREAMING_LOG);
+ syslog_fd = server_udp_open (&mcglog, 23000, NULL);
+ if(syslog_fd) {
+ _logstr=(char *)malloc(10240);
+ }
+
+ return syslog_fd?0:-1;
+}
+
+int syslog_write(char *s)
+{
+ return udp_write (syslog_fd, (uint8_t *)s, strlen(s));
+}
+
+void syslog_exit(void)
+{
+ if(syslog_fd) {
+ udp_close(syslog_fd);
+ free(_logstr);
+ }
+}
+#endif