aboutsummaryrefslogtreecommitdiffstats
path: root/channels/misdn
diff options
context:
space:
mode:
authornadi <nadi@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-08 18:13:40 +0000
committernadi <nadi@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-08 18:13:40 +0000
commitcc220aaf1a5d0c788f51df0408a0322633d39114 (patch)
tree8b50cb5317dcb65ef5ab86bea451ebcb693576ca /channels/misdn
parent8ca4abf951159eaf3df9b9134bb9b153855936aa (diff)
* first bits of decoding facility information elements
* fail on misdn_cfg_init() if elements in the config enum don't match with the config structs in misdn_config.c * implemented first bits for encoding ISDN facility information elements via ASN.1 descriptions * using unnamed semaphore for syncing in misdn_thread * advanced fax detection: configurable detect timeout and context to jump into git-svn-id: http://svn.digium.com/svn/asterisk/trunk@39378 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/misdn')
-rw-r--r--channels/misdn/Makefile4
-rw-r--r--channels/misdn/asn1.c181
-rw-r--r--channels/misdn/asn1.h72
-rw-r--r--channels/misdn/chan_misdn_config.h4
-rw-r--r--channels/misdn/fac.c492
-rw-r--r--channels/misdn/fac.h10
-rw-r--r--channels/misdn/isdn_lib.c37
-rw-r--r--channels/misdn/isdn_lib.h4
-rw-r--r--channels/misdn/isdn_msg_parser.c7
9 files changed, 528 insertions, 283 deletions
diff --git a/channels/misdn/Makefile b/channels/misdn/Makefile
index ba4a12926..febca51ed 100644
--- a/channels/misdn/Makefile
+++ b/channels/misdn/Makefile
@@ -11,14 +11,14 @@ CFLAGS += -fPIC
endif
SOURCES = isdn_lib.c isdn_msg_parser.c
OBJDIR = .
-OBJS = isdn_lib.o isdn_msg_parser.o fac.o
+OBJS = isdn_lib.o isdn_msg_parser.o fac.o asn1.o
ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libbnec.so),)
CFLAGS+=-DBEROEC_VERSION=1
CFLAGS+=-DWITH_BEROEC
endif
-
+CFLAGS+=-DFACILITY_DEBUG
all: chan_misdn_lib.a
diff --git a/channels/misdn/asn1.c b/channels/misdn/asn1.c
new file mode 100644
index 000000000..80dcacd64
--- /dev/null
+++ b/channels/misdn/asn1.c
@@ -0,0 +1,181 @@
+
+#include "asn1.h"
+#include <string.h>
+
+/*
+** ASN.1 Encoding
+*/
+
+int _enc_null (__u8 *dest, int tag)
+{
+ dest[0] = tag;
+ dest[1] = 0;
+ return 2;
+}
+
+int _enc_bool (__u8 *dest, __u32 i, int tag)
+{
+ dest[0] = tag;
+ dest[1] = 1;
+ dest[2] = i ? 1:0;
+ return 3;
+}
+
+int _enc_int (__u8 *dest, __u32 i, int tag)
+{
+ __u8 *p;
+ dest[0] = tag;
+ p = &dest[2];
+ do {
+ *p++ = i;
+ i >>= 8;
+ } while (i);
+ dest[1] = p - &dest[2];
+ return p - dest;
+}
+
+int _enc_enum (__u8 *dest, __u32 i, int tag)
+{
+ __u8 *p;
+
+ dest[0] = tag;
+ p = &dest[2];
+ do {
+ *p++ = i;
+ i >>= 8;
+ } while (i);
+ dest[1] = p - &dest[2];
+ return p - dest;
+}
+
+int _enc_num_string (__u8 *dest, __u8 *nd, __u8 len, int tag)
+{
+ __u8 *p;
+ int i;
+
+ dest[0] = tag;
+ p = &dest[2];
+ for (i = 0; i < len; i++)
+ *p++ = *nd++;
+ dest[1] = p - &dest[2];
+ return p - dest;
+}
+
+int _enc_sequence_start (__u8 *dest, __u8 **id, int tag)
+{
+ dest[0] = tag;
+ *id = &dest[1];
+ return 2;
+}
+
+int _enc_sequence_end (__u8 *dest, __u8 *id, int tag_dummy)
+{
+ *id = dest - id - 1;
+ return 0;
+}
+
+/*
+** ASN.1 Decoding
+*/
+
+#define CHECK_P \
+ do { \
+ if (p >= end) \
+ return -1; \
+ } while (0)
+
+#define CallASN1(ret, p, end, todo) \
+ do { \
+ ret = todo; \
+ if (ret < 0) { \
+ return -1; \
+ } \
+ p += ret; \
+ } while (0)
+
+#define INIT \
+ int len, ret; \
+ __u8 *begin = p; \
+ if (tag) \
+ *tag = *p; \
+ p++; \
+ CallASN1(ret, p, end, dec_len(p, &len)); \
+ if (len >= 0) { \
+ if (p + len > end) \
+ return -1; \
+ end = p + len; \
+ }
+
+int _dec_null (__u8 *p, __u8 *end, int *tag)
+{
+ INIT;
+ return p - begin;
+}
+
+int _dec_bool (__u8 *p, __u8 *end, int *i, int *tag)
+{
+ INIT;
+ *i = 0;
+ while (len--) {
+ CHECK_P;
+ *i = (*i >> 8) + *p;
+ p++;
+ }
+ return p - begin;
+}
+
+int _dec_int (__u8 *p, __u8 *end, int *i, int *tag)
+{
+ INIT;
+
+ *i = 0;
+ while (len--) {
+ CHECK_P;
+ *i = (*i << 8) + *p;
+ p++;
+ }
+ return p - begin;
+}
+
+int _dec_enum (__u8 *p, __u8 *end, int *i, int *tag)
+{
+ INIT;
+
+ *i = 0;
+ while (len--) {
+ CHECK_P;
+ *i = (*i << 8) + *p;
+ p++;
+ }
+ return p - begin;
+}
+
+int _dec_num_string (__u8 *p, __u8 *end, char *str, int *tag)
+{
+ INIT;
+
+ while (len--) {
+ CHECK_P;
+ *str++ = *p;
+ p++;
+ }
+ *str = 0;
+ return p - begin;
+}
+
+int _dec_octet_string (__u8 *p, __u8 *end, char *str, int *tag)
+{
+ return _dec_num_string(p, end, str, tag);
+}
+
+int _dec_sequence (__u8 *p, __u8 *end, int *tag)
+{
+ INIT;
+ return p - begin;
+}
+
+int dec_len (__u8 *p, int *len)
+{
+ *len = *p;
+ return 1;
+}
diff --git a/channels/misdn/asn1.h b/channels/misdn/asn1.h
new file mode 100644
index 000000000..d3bdae356
--- /dev/null
+++ b/channels/misdn/asn1.h
@@ -0,0 +1,72 @@
+#ifndef __ASN1_H__
+#define __ASN1_H__
+
+#include <asm/types.h>
+
+/*
+** ASN.1 Tags
+*/
+
+#define ASN1_TAG_BOOLEAN (0x01)
+#define ASN1_TAG_INTEGER (0x02)
+#define ASN1_TAG_BIT_STRING (0x03)
+#define ASN1_TAG_OCTET_STRING (0x04)
+#define ASN1_TAG_NULL (0x05)
+#define ASN1_TAG_OBJECT_IDENTIFIER (0x06)
+#define ASN1_TAG_ENUM (0x0a)
+#define ASN1_TAG_SEQUENCE (0x30)
+#define ASN1_TAG_SET (0x31)
+#define ASN1_TAG_NUMERIC_STRING (0x12)
+#define ASN1_TAG_PRINTABLE_STRING (0x13)
+#define ASN1_TAG_IA5_STRING (0x16)
+#define ASN1_TAG_UTC_TIME (0x17)
+#define ASN1_TAG_CONSTRUCTED (0x20)
+#define ASN1_TAG_CONTEXT_SPECIFIC (0x80)
+#define ASN1_TAG_EXPLICIT (0x100)
+#define ASN1_TAG_OPT (0x200)
+#define ASN1_NOT_TAGGED (0x400)
+
+/*
+** ASN.1 Encoding
+*/
+
+#define enc_null(dest) _enc_null(dest,ASN1_TAG_NULL)
+#define enc_bool(dest,i) _enc_bool(dest,i,ASN1_TAG_BOOLEAN)
+#define enc_int(dest,i) _enc_int(dest,i,ASN1_TAG_INTEGER)
+#define enc_enum(dest,i) _enc_enum(dest,i,ASN1_TAG_ENUM)
+#define enc_num_string(dest,num,len) _enc_num_string(dest,num,len,ASN1_TAG_NUMERIC_STRING)
+#define enc_sequence_start(dest,id) _enc_sequence_start(dest,id,ASN1_TAG_SEQUENCE)
+#define enc_sequence_end(dest,id) _enc_sequence_end(dest,id,ASN1_TAG_SEQUENCE)
+
+int _enc_null (__u8 *dest, int tag);
+int _enc_bool (__u8 *dest, __u32 i, int tag);
+int _enc_int (__u8 *dest, __u32 i, int tag);
+int _enc_enum (__u8 *dest, __u32 i, int tag);
+int _enc_num_string (__u8 *dest, __u8 *nd, __u8 len, int tag);
+int _enc_sequence_start (__u8 *dest, __u8 **id, int tag);
+int _enc_sequence_end (__u8 *dest, __u8 *id, int tag_dummy);
+
+/*
+** ASN.1 Decoding
+*/
+
+#define dec_null(p, end) _dec_null (p, end, NULL);
+#define dec_bool(p, end,i) _dec_bool (p, end, i, NULL)
+#define dec_int(p, end,i) _dec_int (p, end, i, NULL)
+#define dec_enum(p, end,i) _dec_enum (p, end, i, NULL)
+#define dec_num_string(p, end,str) _dec_num_string (p, end, str, NULL)
+#define dec_octet_string(p, end,str) _dec_octet_string (p, end, str, NULL)
+#define dec_sequence(p, end) _dec_sequence (p, end, NULL)
+
+int _dec_null (__u8 *p, __u8 *end, int *tag);
+int _dec_bool (__u8 *p, __u8 *end, int *i, int *tag);
+int _dec_int (__u8 *p, __u8 *end, int *i, int *tag);
+int _dec_enum (__u8 *p, __u8 *end, int *i, int *tag);
+int _dec_num_string (__u8 *p, __u8 *end, char *str, int *tag);
+int _dec_octet_string (__u8 *p, __u8 *end, char *str, int *tag);
+int _dec_sequence (__u8 *p, __u8 *end, int *tag);
+
+int dec_len (__u8 *p, int *len);
+
+#endif
+
diff --git a/channels/misdn/chan_misdn_config.h b/channels/misdn/chan_misdn_config.h
index 4828261cd..04376c3cd 100644
--- a/channels/misdn/chan_misdn_config.h
+++ b/channels/misdn/chan_misdn_config.h
@@ -75,6 +75,8 @@ enum misdn_cfg_elements {
MISDN_CFG_OVERLAP_DIAL, /* int (bool)*/
MISDN_CFG_MSNS, /* char[] */
MISDN_CFG_FAXDETECT, /* char[] */
+ MISDN_CFG_FAXDETECT_CONTEXT, /* char[] */
+ MISDN_CFG_FAXDETECT_TIMEOUT, /* int */
MISDN_CFG_PTP, /* int (bool) */
MISDN_CFG_LAST,
@@ -100,7 +102,7 @@ enum misdn_cfg_method {
};
/* you must call misdn_cfg_init before any other function of this header file */
-void misdn_cfg_init(int max_ports);
+int misdn_cfg_init(int max_ports);
void misdn_cfg_reload(void);
void misdn_cfg_destroy(void);
diff --git a/channels/misdn/fac.c b/channels/misdn/fac.c
index 383a60f26..19bfbf729 100644
--- a/channels/misdn/fac.c
+++ b/channels/misdn/fac.c
@@ -1,313 +1,267 @@
-#include "isdn_lib_intern.h"
-#include "isdn_lib.h"
-
-#include "string.h"
-
-
-
-
-#define CENTREX_ID 0xa1
-#define CALLDEFLECT_ID 0xa1
-
-/**
- This file covers the encoding and decoding of facility messages and
- facility information elements.
-
- There will be 2 Functions as Interface:
-
- fac_enc( char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc)
- fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc);
-
- Those will either read the union facility or fill it.
-
- internally, we will have deconding and encoding functions for each facility
- IE.
-
-**/
-
-
-/* support stuff */
-static void strnncpy(unsigned char *dest, unsigned char *src, int len, int dst_len)
+#include "fac.h"
+#include "asn1.h"
+
+#if 0
++-------------------------------
+| IE_IDENTIFIER
++-------------------------------
+| {length}
++-------------------------------
+| +---------------------------
+| | SERVICE_DISCRIMINATOR
+| +---------------------------
+| | COMPONENT_TYPE_TAG
+| +---------------------------
+| | {length}
+| +---------------------------
+| | +-----------------------
+| | | INVOKE_IDENTIFIER_TAG (0x2)
+| | +-----------------------
+| | | {length} (0x1)
+| | +-----------------------
+| | | {value} (odd integer 0-127)
+| | +-----------------------
+| | +-----------------------
+| | | OPERATION_VALUE_TAG (0x2)
+| | +-----------------------
+| | | {length} (0x1)
+| | +-----------------------
+| | | {value}
+| | +-----------------------
+| | +-----------------------
+| | | ASN.1 data
++---+---+-----------------------
+#endif
+
+enum {
+ SUPPLEMENTARY_SERVICE = 0x91,
+} SERVICE_DISCRIMINATOR;
+
+enum {
+ INVOKE = 0xa1,
+ RETURN_RESULT = 0xa2,
+ RETURN_ERROR = 0xa3,
+ REJECT = 0xa4,
+} COMPONENT_TYPE_TAG;
+
+enum {
+ INVOKE_IDENTIFIER = 0x02,
+ LINKED_IDENTIFIER = 0x80,
+ NULL_IDENTIFIER = 0x05,
+} INVOKE_IDENTIFIER_TAG;
+
+enum {
+ OPERATION_VALUE = 0x02,
+} OPERATION_VALUE_TAG;
+
+enum {
+ VALUE_QUERY = 0x8c,
+ SET_VALUE = 0x8d,
+ REQUEST_FEATURE = 0x8f,
+ ABORT = 0xbe,
+ REDIRECT_CALL = 0xce,
+ CALLING_PARTY_TO_HOLD = 0xcf,
+ CALLING_PARTY_FROM_HOLD = 0x50,
+ DROP_TARGET_PARTY = 0xd1,
+ USER_DATA_TRANSFER = 0xd3,
+ APP_SPECIFIC_STATUS = 0xd2,
+
+ /* not from document */
+ CALL_DEFLECT = 0x0d,
+ AOC = 0x22,
+} OPERATION_CODE;
+
+enum {
+ Q931_IE_TAG = 0x40,
+} ARGUMENT_TAG;
+
+#ifdef FACILITY_DEBUG
+#define FAC_DUMP(fac,len,bc) fac_dump(fac,len,bc)
+#include <ctype.h>
+static void fac_dump (__u8 *facility, unsigned int fac_len, struct misdn_bchannel *bc)
{
- if (len > dst_len-1)
- len = dst_len-1;
- strncpy((char *)dest, (char *)src, len);
- dest[len] = '\0';
+ int i;
+ cb_log(0, bc->port, " --- facility dump start. length:%d\n", fac_len);
+ for (i = 0; i < fac_len; ++i)
+ if (isprint(facility[i]))
+ cb_log(0, bc->port, " --- %d: %04p (char:%c)\n", i, facility[i], facility[i]);
+ else
+ cb_log(0, bc->port, " --- %d: %04p\n", i, facility[i]);
+ cb_log(0, bc->port, " --- facility dump end\n");
}
+#else
+#define FAC_DUMP(fac,len,bc)
+#endif
+/*
+** Facility Encoding
+*/
-
-
-/**********************/
-/*** FACILITY STUFF ***/
-/**********************/
-
-
-/* IE_FACILITY */
-void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc)
+static int enc_fac_calldeflect (__u8 *dest, char *number, int pres)
{
- unsigned char *p;
- Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
- int l;
-
-
- if (!facility || facility_len<=0)
- {
- return;
- }
-
+ __u8 *body_len,
+ *p = dest,
+ *seq1, *seq2;
+
+ *p++ = SUPPLEMENTARY_SERVICE;
+ *p++ = INVOKE;
+
+ body_len = p++;
+
+ p += _enc_int(p, 0x1 /* some odd integer in (0..127) */, INVOKE_IDENTIFIER);
+ p += _enc_int(p, CALL_DEFLECT, OPERATION_VALUE);
+ p += enc_sequence_start(p, &seq1);
+ p += enc_sequence_start(p, &seq2);
+ p += _enc_num_string(p, number, strlen(number), ASN1_TAG_CONTEXT_SPECIFIC);
+ p += enc_sequence_end(p, seq2);
+ p += enc_bool(p, pres);
+ p += enc_sequence_end(p, seq1);
- l = facility_len;
- p = msg_put(msg, l+2);
- if (nt)
- *ntmode = p+1;
- else
- qi->QI_ELEMENT(facility) = p - (unsigned char *)qi - sizeof(Q931_info_t);
- p[0] = IE_FACILITY;
- p[1] = l;
- memcpy(p+2, facility, facility_len);
+ *body_len = p - &body_len[1];
+
+ return p - dest;
}
-
-/* facility for siemens CENTEX (known parts implemented only) */
-void enc_ie_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc)
+static void enc_ie_facility (__u8 **ntmode, msg_t *msg, __u8 *facility, int facility_len, struct misdn_bchannel *bc)
{
- unsigned char centrex[256];
- int i = 0;
-
- if (!cnip)
- return;
-
- /* centrex facility */
- centrex[i++] = FACILITY_CENTREX;
- centrex[i++] = CENTREX_ID;
+ __u8 *ie_fac;
+
+ Q931_info_t *qi;
- /* cnip */
- if (strlen((char *)cnip) > 15)
- {
-/* if (options.deb & DEBUG_PORT) */
- cb_log(1,0,"%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__);
- cnip[15] = '\0';
- }
- /* dunno what the 8 bytes mean */
- if (setup)
- {
- centrex[i++] = 0x17;
- centrex[i++] = 0x02;
- centrex[i++] = 0x02;
- centrex[i++] = 0x44;
- centrex[i++] = 0x18;
- centrex[i++] = 0x02;
- centrex[i++] = 0x01;
- centrex[i++] = 0x09;
- } else
- {
- centrex[i++] = 0x18;
- centrex[i++] = 0x02;
- centrex[i++] = 0x02;
- centrex[i++] = 0x81;
- centrex[i++] = 0x09;
- centrex[i++] = 0x02;
- centrex[i++] = 0x01;
- centrex[i++] = 0x0a;
+ ie_fac = msg_put(msg, facility_len + 2);
+ if (bc->nt) {
+ *ntmode = ie_fac + 1;
+ } else {
+ qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
+ qi->QI_ELEMENT(facility) = ie_fac - (__u8 *)qi - sizeof(Q931_info_t);
}
- centrex[i++] = 0x80;
- centrex[i++] = strlen((char *)cnip);
- strcpy((char *)(&centrex[i]), (char *)cnip);
- i += strlen((char *)cnip);
- cb_log(4,0," cnip='%s'\n", cnip);
+ ie_fac[0] = IE_FACILITY;
+ ie_fac[1] = facility_len;
+ memcpy(ie_fac + 2, facility, facility_len);
- /* encode facility */
- enc_ie_facility(ntmode, msg, centrex, i, nt , bc);
+ FAC_DUMP(ie_fac, facility_len + 2, bc);
}
-void dec_ie_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *centrex, int facility_len, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc)
+void fac_enc (__u8 **ntmsg, msg_t *msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc)
{
+ __u8 facility[256];
+ int len;
- int i = 0;
- *cnip = '\0';
-
- if (facility_len >= 2)
- {
- if (centrex[i++] != FACILITY_CENTREX)
- return;
- if (centrex[i++] != CENTREX_ID)
- return;
- }
-
- /* loop sub IEs of facility */
- while(facility_len > i+1)
- {
- if (centrex[i+1]+i+1 > facility_len)
- {
- printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__);
- return;
- }
- switch(centrex[i])
- {
- case 0x80:
- strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
- cb_log(4,0," CENTREX cnip='%s'\n", cnip);
- break;
- }
- i += 1+centrex[i+1];
+ switch (type) {
+ case FACILITY_CALLDEFLECT:
+ len = enc_fac_calldeflect(facility, fac.calldeflect_nr, 1);
+ enc_ie_facility(ntmsg, msg, facility, len, bc);
+ break;
+ case FACILITY_CENTREX:
+ case FACILITY_NONE:
+ break;
}
}
+/*
+** Facility Decoding
+*/
+static int dec_fac_calldeflect (__u8 *p, int len, struct misdn_bchannel *bc)
+{
+ __u8 *end = p + len;
+ int offset,
+ pres;
+ if ((offset = dec_sequence(p, end)) < 0)
+ return -1;
+ p += offset;
-/* facility for CALL Deflect (known parts implemented only) */
-void enc_ie_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc)
-{
- unsigned char fac[256];
+ if ((offset = dec_sequence(p, end)) < 0)
+ return -1;
+ p += offset;
- if (!nr)
- return;
+ if ((offset = dec_num_string(p, end, bc->fac.calldeflect_nr)) < 0)
+ return -1;
+ p += offset;
- int len = strlen(nr);
- /* calldeflect facility */
-
- /* cnip */
- if (strlen((char *)nr) > 15)
- {
-/* if (options.deb & DEBUG_PORT) */
- cb_log(1,0,"%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__);
- nr[15] = '\0';
- }
-
- fac[0]=FACILITY_CALLDEFLECT; // ..
- fac[1]=CALLDEFLECT_ID;
- fac[2]=0x0f + len; // strlen destination + 15 = 26
- fac[3]=0x02;
- fac[4]=0x01;
- //fac[5]=0x70;
- fac[5]=0x09;
- fac[6]=0x02;
- fac[7]=0x01;
- fac[8]=0x0d;
- fac[9]=0x30;
- fac[10]=0x07 + len; // strlen destination + 7 = 18
- fac[11]=0x30; // ...hm 0x30
- fac[12]=0x02+ len; // strlen destination + 2
- fac[13]=0x80; // CLIP
- fac[14]= len; // strlen destination
-
- memcpy((unsigned char *)fac+15,nr,len);
- fac[15+len]=0x01; //sending complete
- fac[16+len]=0x01;
- fac[17+len]=0x80;
-
- enc_ie_facility(ntmode, msg, fac, 17+len +1 , nt , bc);
-}
+ if ((offset = dec_bool(p, end, &pres)) < 0)
+ return -1;
+
+ cb_log(0, 0, "CALLDEFLECT: dest:%s pres:%s (not implemented yet)\n", bc->fac.calldeflect_nr, pres ? "yes" : "no");
+ bc->fac_type = FACILITY_CALLDEFLECT;
+ return 0;
+}
-void dec_ie_facility_calldeflect(unsigned char *p, Q931_info_t *qi, unsigned char *fac, int fac_len, unsigned char *cd_nr, int nt, struct misdn_bchannel *bc)
+void fac_dec (__u8 *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc)
{
- *cd_nr = '\0';
-
- if (fac_len >= 15)
- {
- if (fac[0] != FACILITY_CALLDEFLECT)
- return;
- if (fac[1] != CALLDEFLECT_ID)
- return;
- } else {
- cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
- return ;
- }
-
-
-
- {
- int dest_len=fac[2]-0x0f;
-
- if (dest_len <0 || dest_len > 15) {
- cb_log(1,bc->port, "IE is garbage: FAC_CALLDEFLECT\n");
- return ;
- }
-
- if (fac_len < 15+dest_len) {
- cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
- return ;
- }
-
- memcpy(cd_nr, &fac[15],dest_len);
- cd_nr[dest_len]=0;
-
- cb_log(5,bc->port, "--> IE CALLDEFLECT NR: %s\n",cd_nr);
+ int len,
+ offset,
+ inner_len,
+ invoke_id,
+ op_tag,
+ op_val;
+ __u8 *end,
+ *begin = p;
+
+ if (!bc->nt) {
+ if (qi->QI_ELEMENT(facility))
+ p = (__u8 *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
+ else
+ p = NULL;
}
-}
+ if (!p)
+ return;
+ offset = dec_len (p, &len);
+ if (offset < 0) {
+ cb_log(0, bc->port, "Could not decode FACILITY: dec_len failed!\n");
+ return;
+ }
+ p += offset;
+ end = p + len;
+ FAC_DUMP(p, len, bc);
-void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc)
-{
- switch (type) {
- case FACILITY_CENTREX:
- {
- int setup=0;
- enc_ie_facility_centrex(ntmsg, msg, fac.cnip, setup, bc->nt, bc);
- }
- break;
- case FACILITY_CALLDEFLECT:
- enc_ie_facility_calldeflect(ntmsg, msg, fac.calldeflect_nr, bc->nt, bc);
- break;
- default:
- cb_log(1,0,"Don't know how handle this facility: %d\n", type);
+ if (len < 3 || p[0] != SUPPLEMENTARY_SERVICE || p[1] != INVOKE) {
+ cb_log(0, bc->port, "Could not decode FACILITY: invalid or not supported!\n");
+ return;
}
-}
+ p += 2;
-void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc)
-{
- int i, fac_len=0;
- unsigned char facility[256];
+ offset = dec_len (p, &inner_len);
+ if (offset < 0) {
+ cb_log(0, bc->port, "Could not decode FACILITY: failed parsing inner length!\n");
+ return;
+ }
+ p += offset;
- if (!bc->nt)
- {
- p = NULL;
- if (qi->QI_ELEMENT(facility))
- p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
+ offset = dec_int (p, end, &invoke_id);
+ if (offset < 0) {
+ cb_log(0, bc->port, "Could not decode FACILITY: failed parsing invoke identifier!\n");
+ return;
}
- if (!p)
+ p += offset;
+
+ offset = _dec_int (p, end, &op_val, &op_tag);
+ if (offset < 0) {
+ cb_log(0, bc->port, "Could not decode FACILITY: failed parsing operation value!\n");
return;
-
- fac_len = p[0] & 0xff;
+ }
+ p += offset;
- memcpy(facility, p+1, fac_len);
-
- switch(facility[0]) {
- case FACILITY_CENTREX:
- {
- int cnip_len=15;
-
- dec_ie_facility_centrex(p, qi,facility, fac_len, fac->cnip, cnip_len, bc->nt, bc);
-
- *type=FACILITY_CENTREX;
+ if (op_tag != OPERATION_VALUE || offset != 3) {
+ cb_log(0, bc->port, "Could not decode FACILITY: operation value tag 0x%x unknown!\n", op_tag);
+ return;
}
- break;
- case FACILITY_CALLDEFLECT:
- dec_ie_facility_calldeflect(p, qi,facility, fac_len, fac->calldeflect_nr, bc->nt, bc);
-
- *type=FACILITY_CALLDEFLECT;
+
+ switch (op_val) {
+ case CALL_DEFLECT:
+ cb_log(0, bc->port, "FACILITY: Call Deflect\n");
+ dec_fac_calldeflect(p, len - (p - begin) + 1, bc);
+ break;
+ case AOC:
+ cb_log(0, bc->port, "FACILITY: AOC\n");
break;
default:
- cb_log(3, bc->port, "Unknown Facility received: ");
- i = 0;
- while(i < fac_len)
- {
- cb_log(3, bc->port, " %02x", facility[i]);
- i++;
- }
- cb_log(3, bc->port, " facility\n");
-
- *type=FACILITY_NONE;
+ cb_log(0, bc->port, "FACILITY unknown: operation value 0x%x, ignoring ...\n", op_val);
}
-
-
}
-
-/*** FACILITY END **/
-
diff --git a/channels/misdn/fac.h b/channels/misdn/fac.h
index acc41f17f..da6329967 100644
--- a/channels/misdn/fac.h
+++ b/channels/misdn/fac.h
@@ -1,8 +1,10 @@
-#ifndef FAC_H
-#define FAC_H
+#ifndef __FAC_H__
+#define __FAC_H__
-void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc);
+#include "isdn_lib_intern.h"
-void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc);
+void fac_enc (__u8 **ntmsg, msg_t *msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc);
+void fac_dec (__u8 *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc);
#endif
+
diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c
index 8209df926..8b6e08f5c 100644
--- a/channels/misdn/isdn_lib.c
+++ b/channels/misdn/isdn_lib.c
@@ -2589,6 +2589,7 @@ int handle_frm(msg_t *msg)
bc=find_bc_by_l3id(stack, frm->dinfo);
+handle_frm_bc:
if (bc ) {
enum event_e event = isdn_msg_get_event(msgs_g, msg, 0);
enum event_response_e response=RESPONSE_OK;
@@ -2602,7 +2603,7 @@ int handle_frm(msg_t *msg)
if(!isdn_get_info(msgs_g,event,0))
cb_log(0, stack->port, "Unknown Event Ind: Addr:%x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo);
- else
+ else
response=cb_event(event, bc, glob_mgr->user_data);
#if 1
if (event == EVENT_SETUP) {
@@ -2644,7 +2645,13 @@ int handle_frm(msg_t *msg)
#endif
} else {
- cb_log(0, stack->port, "NO BC FOR STACK\n");
+ cb_log(0, stack->port, " --> Didn't find BC so temporarly creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
+ struct misdn_bchannel dummybc;
+ memset (&dummybc,0,sizeof(dummybc));
+ dummybc.port=stack->port;
+ dummybc.l3_id=frm->dinfo;
+ bc=&dummybc;
+ goto handle_frm_bc;
}
}
@@ -4024,6 +4031,32 @@ void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2)
}
/*
+ * allow live control of channel parameters
+ */
+void isdn_lib_update_rxgain (struct misdn_bchannel *bc)
+{
+ manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
+}
+
+void isdn_lib_update_txgain (struct misdn_bchannel *bc)
+{
+ manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
+}
+
+void isdn_lib_update_ec (struct misdn_bchannel *bc)
+{
+ if (bc->ec_enable)
+ manager_ec_enable(bc);
+ else
+ manager_ec_disable(bc);
+}
+
+void isdn_lib_stop_dtmf (struct misdn_bchannel *bc)
+{
+ manager_ph_control(bc, DTMF_TONE_STOP, 0);
+}
+
+/*
* send control information to the channel (dsp-module)
*/
void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len)
diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h
index 3673baf7d..5bb82d4d5 100644
--- a/channels/misdn/isdn_lib.h
+++ b/channels/misdn/isdn_lib.h
@@ -406,6 +406,10 @@ int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len);
void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2);
+void isdn_lib_update_rxgain (struct misdn_bchannel *bc);
+void isdn_lib_update_txgain (struct misdn_bchannel *bc);
+void isdn_lib_update_ec (struct misdn_bchannel *bc);
+void isdn_lib_stop_dtmf (struct misdn_bchannel *bc);
int misdn_lib_port_restart(int port);
int misdn_lib_get_port_info(int port);
diff --git a/channels/misdn/isdn_msg_parser.c b/channels/misdn/isdn_msg_parser.c
index ae8aa76bf..5ee7f6f49 100644
--- a/channels/misdn/isdn_msg_parser.c
+++ b/channels/misdn/isdn_msg_parser.c
@@ -879,8 +879,7 @@ msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc
void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
{
-//#define FACILITY_DECODE
-#ifdef FACILITY_DECODE
+#ifdef FACILITY_DEBUG
int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
FACILITY_t *facility=(FACILITY_t*)((unsigned long)(msg->data+HEADER_LEN));
Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
@@ -889,9 +888,7 @@ void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *
printf("Parsing FACILITY Msg\n");
#endif
- {
- fac_dec(facility->FACILITY, qi, &bc->fac_type, &bc->fac, bc);
- }
+ fac_dec(facility->FACILITY, qi, &bc->fac_type, &bc->fac, bc);
#endif
}