320 lines
8.6 KiB
C
320 lines
8.6 KiB
C
|
#include "isdnlogin.h"
|
||
|
|
||
|
extern cfg_t cfg;
|
||
|
extern char * prog_logo;
|
||
|
|
||
|
/*******************************************************************
|
||
|
*
|
||
|
*******************************************************************/
|
||
|
call_t *alloc_call(void)
|
||
|
{
|
||
|
call_t *ptrCall;
|
||
|
|
||
|
ptrCall = (call_t *)malloc( sizeof(*ptrCall));
|
||
|
|
||
|
if (!ptrCall) return NULL;
|
||
|
memset( ptrCall, 0, sizeof(*ptrCall));
|
||
|
|
||
|
/*
|
||
|
* open file to transmit
|
||
|
*/
|
||
|
if (cfg.sendfile) {
|
||
|
ptrCall->pFilename = cfg.sendfile;
|
||
|
if (!(ptrCall->txfp=fopen( ptrCall->pFilename, "r"))) {
|
||
|
printf ("Could read from file: <%s>\n", ptrCall->pFilename);
|
||
|
exit ( 1 );
|
||
|
}
|
||
|
if ( cfg.verbose > 2 ) {
|
||
|
printf("Reading from file: <%s>\n", ptrCall->pFilename);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* default call settings */
|
||
|
|
||
|
/* add service and controller to call */
|
||
|
ptrCall->active = 1;
|
||
|
ptrCall->ident = cfg.controller; /* controller */
|
||
|
ptrCall->service= cfg.service;
|
||
|
|
||
|
/* set numbers */
|
||
|
setCalledPartyNumber( ptrCall, cfg.rmttelno);
|
||
|
setCallingPartyNumber( ptrCall, cfg.loctelno, 1);
|
||
|
setCalledPartySubaddress( ptrCall, cfg.rmtsubaddr);
|
||
|
setCallingPartySubaddress( ptrCall, cfg.locsubaddr);
|
||
|
|
||
|
/* adjust protocols */
|
||
|
setBprotocol( ptrCall);
|
||
|
setLLC( ptrCall );
|
||
|
setAdditionalInfo( ptrCall );
|
||
|
|
||
|
return ptrCall;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************
|
||
|
*
|
||
|
*******************************************************************/
|
||
|
void free_call( call_t *ptrCall )
|
||
|
{
|
||
|
if (ptrCall) {
|
||
|
if (ptrCall->txfp) {
|
||
|
fclose( ptrCall->txfp);
|
||
|
}
|
||
|
free(ptrCall);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*******************************************************************
|
||
|
*
|
||
|
*******************************************************************/
|
||
|
struct userdata *setCalledPartyNumber( call_t *ptrCall,
|
||
|
char *szCalledPartyNumber)
|
||
|
{
|
||
|
size_t len = 0;
|
||
|
|
||
|
ptrCall->CalledPartyNumber.length = 0;
|
||
|
if (szCalledPartyNumber) {
|
||
|
len = strlen( szCalledPartyNumber);
|
||
|
len = min(len, CAPI1_MAXMSGLEN-1);
|
||
|
if (len) {
|
||
|
ptrCall->CalledPartyNumber.data[0] = 0x81;
|
||
|
|
||
|
memcpy( &ptrCall->CalledPartyNumber.data[1],
|
||
|
szCalledPartyNumber, len);
|
||
|
ptrCall->CalledPartyNumber.length = len+1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return &ptrCall->CalledPartyNumber;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************
|
||
|
*
|
||
|
*******************************************************************/
|
||
|
struct userdata *setCallingPartyNumber( call_t *ptrCall,
|
||
|
char *szCallingPartyNumber,
|
||
|
int lPresentation)
|
||
|
{
|
||
|
size_t len = 0;
|
||
|
|
||
|
ptrCall->CallingPartyNumber.length = 0;
|
||
|
if (szCallingPartyNumber) {
|
||
|
len = strlen( szCallingPartyNumber);
|
||
|
len = min(len, CAPI1_MAXMSGLEN-1);
|
||
|
if (len) {
|
||
|
ptrCall->CallingPartyNumber.data[0] = 0x01;
|
||
|
ptrCall->CallingPartyNumber.data[1] = lPresentation ? 0x80 : 0xa0;
|
||
|
|
||
|
memcpy( &ptrCall->CallingPartyNumber.data[2],
|
||
|
szCallingPartyNumber, len);
|
||
|
ptrCall->CallingPartyNumber.length = len+2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return &ptrCall->CallingPartyNumber;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************
|
||
|
*
|
||
|
*******************************************************************/
|
||
|
struct userdata *setCalledPartySubaddress( ptrCall, szCalledPartySubaddress)
|
||
|
call_t *ptrCall;
|
||
|
char *szCalledPartySubaddress;
|
||
|
{
|
||
|
size_t len;
|
||
|
|
||
|
ptrCall->CalledPartySubaddress.data[0] = 0x80;
|
||
|
if ((len = strlen(szCalledPartySubaddress))) {
|
||
|
memcpy( &ptrCall->CalledPartySubaddress.data[1],
|
||
|
szCalledPartySubaddress, len);
|
||
|
} else {
|
||
|
ptrCall->CalledPartySubaddress.data[1] = 0;
|
||
|
len = 1;
|
||
|
}
|
||
|
|
||
|
ptrCall->CalledPartySubaddress.length = len + 1;
|
||
|
return &ptrCall->CalledPartySubaddress;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************
|
||
|
*
|
||
|
*******************************************************************/
|
||
|
struct userdata *setCallingPartySubaddress( call_t *ptrCall,
|
||
|
char *szCallingPartySubaddress)
|
||
|
{
|
||
|
size_t len;
|
||
|
|
||
|
ptrCall->CallingPartySubaddress.data[0] = 0x80; /* always there */
|
||
|
|
||
|
if ((len = strlen(szCallingPartySubaddress))) {
|
||
|
/* if subaddress suplied use it */
|
||
|
memcpy( &ptrCall->CallingPartySubaddress.data[1],
|
||
|
szCallingPartySubaddress, len);
|
||
|
} else {
|
||
|
ptrCall->CallingPartySubaddress.data[1] = 0;
|
||
|
len = 1;
|
||
|
}
|
||
|
|
||
|
ptrCall->CallingPartySubaddress.length = len + 1; /* one for the type */
|
||
|
return &ptrCall->CallingPartySubaddress;
|
||
|
}
|
||
|
|
||
|
userdata_t *setBprotocol( call_t *ptrCall)
|
||
|
{
|
||
|
userdata_t *data;
|
||
|
struct bprotocol *bprot;
|
||
|
struct b1config *b1cfg;
|
||
|
struct b1config_modem *b1cfg_mdm;
|
||
|
struct b2config *b2cfg;
|
||
|
struct b3config *b3cfg;
|
||
|
|
||
|
bprot = (struct bprotocol *)&ptrCall->Bprotocol;
|
||
|
|
||
|
/* set layer 1 protocol */
|
||
|
PUT_WORD( bprot->b1proto, ptrCall->service->layer1_mask);
|
||
|
|
||
|
/* depending on service set layer 2 protocol */
|
||
|
switch(ptrCall->service->hw) {
|
||
|
case ISDN_HDLC:
|
||
|
PUT_WORD( bprot->b2proto, B2X75);
|
||
|
break;
|
||
|
case FAX_G3:
|
||
|
PUT_WORD( bprot->b2proto, B2T30);
|
||
|
break;
|
||
|
case ISDN_V42:
|
||
|
PUT_WORD( bprot->b2proto, B2X75V42BIS);
|
||
|
break;
|
||
|
case V110_ASYNC:
|
||
|
case TRANS:
|
||
|
case MODEM:
|
||
|
default:
|
||
|
PUT_WORD( bprot->b2proto, B2TRANS);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* check for layer 2 specific settings */
|
||
|
switch (ptrCall->service->hw) {
|
||
|
case FAX_G3:
|
||
|
PUT_WORD( bprot->b3proto, B3T30);
|
||
|
break;
|
||
|
default:
|
||
|
/* layer 3 is always trans for now */
|
||
|
PUT_WORD( bprot->b3proto, B3TRANS);
|
||
|
break;
|
||
|
}
|
||
|
data = (userdata_t *)&bprot->structlen;
|
||
|
|
||
|
/* check if the service has special layer 2 config */
|
||
|
switch(ptrCall->service->hw) {
|
||
|
case V110_ASYNC:
|
||
|
b1cfg = (struct b1config *) data;
|
||
|
/* v110 specific layer 2 params */
|
||
|
PUT_WORD( b1cfg->rate, cfg.speed);
|
||
|
PUT_WORD( b1cfg->bpc, 8);
|
||
|
PUT_WORD( b1cfg->parity, 0);
|
||
|
PUT_WORD( b1cfg->stopbits, 0);
|
||
|
b1cfg->length = sizeof( struct b1config) - 1;
|
||
|
break;
|
||
|
case MODEM:
|
||
|
/* modem specific params */
|
||
|
b1cfg_mdm = (b1config_modem_t *) data;
|
||
|
PUT_WORD( b1cfg_mdm->rate, cfg.speed); /* 0 = max speed */
|
||
|
PUT_WORD( b1cfg_mdm->bpc, 8);
|
||
|
PUT_WORD( b1cfg_mdm->parity, 0);
|
||
|
PUT_WORD( b1cfg_mdm->stopbits, 0);
|
||
|
PUT_WORD( b1cfg_mdm->options, 0);
|
||
|
PUT_WORD( b1cfg_mdm->negotiation, 1); /* allow autoneg */
|
||
|
b1cfg_mdm->length = sizeof( struct b1config_modem) -1;
|
||
|
break;
|
||
|
case FAX_G3:
|
||
|
/* FAX group 3 params */
|
||
|
b1cfg = (struct b1config *) data;
|
||
|
PUT_WORD( b1cfg->rate, cfg.speed);
|
||
|
PUT_WORD( b1cfg->bpc, 0);
|
||
|
PUT_WORD( b1cfg->parity, 0);
|
||
|
PUT_WORD( b1cfg->stopbits, 0);
|
||
|
b1cfg->length = sizeof( struct b1config) - 1;
|
||
|
break;
|
||
|
default:
|
||
|
data->length = 0;
|
||
|
break;
|
||
|
}
|
||
|
data = (userdata_t *)&data->data[data->length];
|
||
|
|
||
|
b2cfg = (struct b2config *) data;
|
||
|
switch(ptrCall->service->hw) {
|
||
|
case ISDN_HDLC:
|
||
|
b2cfg->addressA = 3;
|
||
|
b2cfg->addressB = 1;
|
||
|
b2cfg->moduloMode = 8;
|
||
|
b2cfg->windowSize = 7;
|
||
|
b2cfg->xidlen = 0;
|
||
|
b2cfg->length = sizeof( struct b2config) - 1;
|
||
|
break;
|
||
|
default:
|
||
|
b2cfg->length = 0;
|
||
|
break;
|
||
|
}
|
||
|
data = (userdata_t *)&data->data[data->length];
|
||
|
|
||
|
/* Layer 3 always transparent */
|
||
|
b3cfg = (struct b3config *) data;
|
||
|
b3cfg->length = 0;
|
||
|
|
||
|
bprot->length = (char *)data - (char *)&bprot->length -1;
|
||
|
#if 0
|
||
|
capi_hexdump((char*) bprot, bprot->length, 16, 2);
|
||
|
printf("b1cfg->length=%d\n", b1cfg->length);
|
||
|
printf("b1cfg_mdm->length=%d\n", b1cfg_mdm->length);
|
||
|
printf("b2cfg->length=%d\n", b2cfg->length);
|
||
|
printf("bprot->length=%d\n", bprot->length);
|
||
|
printf("data->length=%d\n", data->length);
|
||
|
//printf("data->structlen=%d\n", data->structlen);
|
||
|
#endif
|
||
|
|
||
|
return (userdata_t *)bprot;
|
||
|
}
|
||
|
|
||
|
userdata_t *setLLC( call_t *ptrCall ) {
|
||
|
userdata_t *llc;
|
||
|
/* Lower Layer Compatibility */
|
||
|
static char llcs[] = { 0x90, 0x88, 0x90, 0x21, 0x42, 0x00, 0xbb };
|
||
|
|
||
|
llc = &ptrCall->llc;
|
||
|
|
||
|
if (ptrCall->service->rate) {
|
||
|
llc = (userdata_t *)&ptrCall->llc;
|
||
|
|
||
|
llcs[4] = cfg.v110_speed; /* set user rate */
|
||
|
memcpy(&ptrCall->llc, &llcs, sizeof(llcs));
|
||
|
llc->length = sizeof(llcs) - 1;
|
||
|
}
|
||
|
return llc;
|
||
|
}
|
||
|
|
||
|
userdata_t *setAdditionalInfo( call_t *ptrCall )
|
||
|
{
|
||
|
struct userdata *add;
|
||
|
struct userdata *data;
|
||
|
|
||
|
add = (struct userdata *)&ptrCall->AdditionalInfo;
|
||
|
data = (struct userdata *)add->data;
|
||
|
|
||
|
data->length = 0; /* b-channel */
|
||
|
|
||
|
data = (struct userdata *)&data->data[data->length];
|
||
|
data->length = 0; /* keypad */
|
||
|
|
||
|
data = (struct userdata *)&data->data[data->length];
|
||
|
memcpy(&data->data[0], prog_logo, strlen(prog_logo));
|
||
|
|
||
|
data->length = strlen(data->data); /* user user data */
|
||
|
|
||
|
data = (struct userdata *)&data->data[data->length];
|
||
|
data->length = 0; /* facility */
|
||
|
|
||
|
data = (struct userdata *)&data->data[data->length];
|
||
|
add->length = (char *)data - (char *)&add->length - 1;
|
||
|
|
||
|
return (struct userdata *)add;
|
||
|
}
|