mirror of https://github.com/asterisk/asterisk
he 1.2 branch. These changes include the new mISDN mqueue interface which makes it possible to compile chan_misdn against the current cvs version of mISDN/mISDNuser. These changes also contain various additions and numerous bugfixes to chan_misdn . Each change is documented in the commit logs in the team/crichter/0.3.0 branch. git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@40306 65c4cc65-6c06-0410-ace0-fbb531ad65f31.2
parent
2f5c21ded7
commit
71b348be1c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,313 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
if (len > dst_len-1)
|
||||
len = dst_len-1;
|
||||
strncpy((char *)dest, (char *)src, len);
|
||||
dest[len] = '\0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************/
|
||||
/*** 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)
|
||||
{
|
||||
unsigned char *p;
|
||||
Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
|
||||
int l;
|
||||
|
||||
|
||||
if (!facility || facility_len<=0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
unsigned char centrex[256];
|
||||
int i = 0;
|
||||
|
||||
if (!cnip)
|
||||
return;
|
||||
|
||||
/* centrex facility */
|
||||
centrex[i++] = FACILITY_CENTREX;
|
||||
centrex[i++] = CENTREX_ID;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
centrex[i++] = 0x80;
|
||||
centrex[i++] = strlen((char *)cnip);
|
||||
strcpy((char *)(¢rex[i]), (char *)cnip);
|
||||
i += strlen((char *)cnip);
|
||||
cb_log(4,0," cnip='%s'\n", cnip);
|
||||
|
||||
/* encode facility */
|
||||
enc_ie_facility(ntmode, msg, centrex, i, nt , 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)
|
||||
{
|
||||
|
||||
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, ¢rex[i+2], centrex[i+1], cnip_len);
|
||||
cb_log(4,0," CENTREX cnip='%s'\n", cnip);
|
||||
break;
|
||||
}
|
||||
i += 1+centrex[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* 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 (!nr)
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
*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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
if (!bc->nt)
|
||||
{
|
||||
p = NULL;
|
||||
if (qi->QI_ELEMENT(facility))
|
||||
p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
|
||||
}
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
fac_len = p[0] & 0xff;
|
||||
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case FACILITY_CALLDEFLECT:
|
||||
dec_ie_facility_calldeflect(p, qi,facility, fac_len, fac->calldeflect_nr, bc->nt, bc);
|
||||
|
||||
*type=FACILITY_CALLDEFLECT;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*** FACILITY END **/
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
#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);
|
||||
|
||||
void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,197 +0,0 @@
|
||||
|
||||
|
||||
#include "isdn_lib.h"
|
||||
|
||||
|
||||
/*
|
||||
* global function to show all available isdn ports
|
||||
*/
|
||||
void isdn_port_info(void)
|
||||
{
|
||||
int err;
|
||||
int i, ii, p;
|
||||
int useable, nt, pri;
|
||||
unsigned char buff[1025];
|
||||
iframe_t *frm = (iframe_t *)buff;
|
||||
stack_info_t *stinf;
|
||||
int device;
|
||||
|
||||
/* open mISDN */
|
||||
if ((device = mISDN_open()) < 0)
|
||||
{
|
||||
fprintf(stderr, "mISDN_open() failed: ret=%d errno=%d (%s) Check for mISDN modules and device.\n", device, errno, strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* get number of stacks */
|
||||
i = 1;
|
||||
ii = mISDN_get_stack_count(device);
|
||||
printf("\n");
|
||||
if (ii <= 0)
|
||||
{
|
||||
printf("Found no card. Please be sure to load card drivers.\n");
|
||||
}
|
||||
|
||||
/* loop the number of cards and get their info */
|
||||
while(i <= ii)
|
||||
{
|
||||
err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
|
||||
if (err <= 0)
|
||||
{
|
||||
fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err);
|
||||
break;
|
||||
}
|
||||
stinf = (stack_info_t *)&frm->data.p;
|
||||
|
||||
nt = pri = 0;
|
||||
useable = 1;
|
||||
|
||||
/* output the port info */
|
||||
printf("Port %2d: ", i);
|
||||
switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
|
||||
{
|
||||
case ISDN_PID_L0_TE_S0:
|
||||
printf("TE-mode BRI S/T interface line (for phone lines)");
|
||||
#if 0
|
||||
if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK)
|
||||
printf(" HFC multiport card");
|
||||
#endif
|
||||
break;
|
||||
case ISDN_PID_L0_NT_S0:
|
||||
nt = 1;
|
||||
printf("NT-mode BRI S/T interface port (for phones)");
|
||||
#if 0
|
||||
if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK)
|
||||
printf(" HFC multiport card");
|
||||
#endif
|
||||
break;
|
||||
case ISDN_PID_L0_TE_U:
|
||||
printf("TE-mode BRI U interface line");
|
||||
break;
|
||||
case ISDN_PID_L0_NT_U:
|
||||
nt = 1;
|
||||
printf("NT-mode BRI U interface port");
|
||||
break;
|
||||
case ISDN_PID_L0_TE_UP2:
|
||||
printf("TE-mode BRI Up2 interface line");
|
||||
break;
|
||||
case ISDN_PID_L0_NT_UP2:
|
||||
nt = 1;
|
||||
printf("NT-mode BRI Up2 interface port");
|
||||
break;
|
||||
case ISDN_PID_L0_TE_E1:
|
||||
pri = 1;
|
||||
printf("TE-mode PRI E1 interface line (for phone lines)");
|
||||
#if 0
|
||||
if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK)
|
||||
printf(" HFC-E1 card");
|
||||
#endif
|
||||
break;
|
||||
case ISDN_PID_L0_NT_E1:
|
||||
nt = 1;
|
||||
pri = 1;
|
||||
printf("NT-mode PRI E1 interface port (for phones)");
|
||||
#if 0
|
||||
if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK)
|
||||
printf(" HFC-E1 card");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
useable = 0;
|
||||
printf("unknown type 0x%08x",stinf->pid.protocol[0]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (nt)
|
||||
{
|
||||
if (stinf->pid.protocol[1] == 0)
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Missing layer 1 NT-mode protocol.\n");
|
||||
}
|
||||
p = 2;
|
||||
while(p <= MAX_LAYER_NR) {
|
||||
if (stinf->pid.protocol[p])
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for NT lib.\n", p, stinf->pid.protocol[p]);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (useable)
|
||||
{
|
||||
if (pri)
|
||||
printf(" -> Interface is Point-To-Point (PRI).\n");
|
||||
else
|
||||
printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (stinf->pid.protocol[1] == 0)
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Missing layer 1 protocol.\n");
|
||||
}
|
||||
if (stinf->pid.protocol[2] == 0)
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Missing layer 2 protocol.\n");
|
||||
}
|
||||
if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
|
||||
{
|
||||
printf(" -> Interface is Poin-To-Point.\n");
|
||||
}
|
||||
if (stinf->pid.protocol[3] == 0)
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Missing layer 3 protocol.\n");
|
||||
} else
|
||||
{
|
||||
printf(" -> Protocol: ");
|
||||
switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
|
||||
{
|
||||
case ISDN_PID_L3_DSS1USER:
|
||||
printf("DSS1 (Euro ISDN)");
|
||||
break;
|
||||
|
||||
default:
|
||||
useable = 0;
|
||||
printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
p = 4;
|
||||
while(p <= MAX_LAYER_NR) {
|
||||
if (stinf->pid.protocol[p])
|
||||
{
|
||||
useable = 0;
|
||||
printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for TE lib.\n", p, stinf->pid.protocol[p]);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
printf(" -> childcnt: %d\n",stinf->childcnt);
|
||||
}
|
||||
|
||||
if (!useable)
|
||||
printf(" * Port NOT useable for PBX\n");
|
||||
|
||||
printf("--------\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* close mISDN */
|
||||
if ((err = mISDN_close(device)))
|
||||
{
|
||||
fprintf(stderr, "mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
isdn_port_info();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in new issue