extractedLnx/linux-2.6.9/drivers/isdn/hardware/eicon/message.c_nl_ind.c
void nl_ind(PLCI * plci)
{
byte ch;
word ncci;
dword Id;
DIVA_CAPI_ADAPTER * a;
word NCCIcode;
APPL * APPLptr;
word count;
word Num;
word i, ncpi_state;
byte len, ncci_state;
word msg;
word info = 0;
word fax_feature_bits;
byte fax_send_edata_ack;
static byte v120_header_buffer[2 + 3];
static word fax_info[] = {
0, /* T30_SUCCESS */
_FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
_FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
_FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
_FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
_FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
_FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
_FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
_FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
_FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
_FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
_FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
_FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
_FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
_FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
_FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
_FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
_FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
_FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
_FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
_FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
0x331e, /* T30_ERR_PWD_UNSUPPORTED */
0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
_FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
_FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
_FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
_FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
_FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
_FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
_FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
_FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
_FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
_FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
_FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
};
byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
static word rtp_info[] = {
GOOD, /* RTP_SUCCESS */
0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
};
static dword udata_forwarding_table[0x100 / sizeof(dword)] =
{
0x0020301e, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
ch = plci->NL.IndCh;
a = plci->adapter;
ncci = a->ch_ncci[ch];
Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
if(plci->tel) Id|=EXT_CONTROLLER;
APPLptr = plci->appl;
dbug(1,dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
/* in the case if no connect_active_Ind was sent to the appl we wait for */
if (plci->nl_remove_id)
{
plci->NL.RNR = 2; /* discard */
dbug(1,dprintf("NL discard while remove pending"));
return;
}
if((plci->NL.Ind &0x0f)==N_CONNECT)
{
if(plci->State==INC_DIS_PENDING
|| plci->State==OUTG_DIS_PENDING
|| plci->State==IDLE)
{
plci->NL.RNR = 2; /* discard */
dbug(1,dprintf("discard n_connect"));
return;
}
if(plci->State < INC_ACT_PENDING)
{
plci->NL.RNR = 1; /* flow control */
channel_x_off (plci, ch, N_XON_CONNECT_IND);
return;
}
}
if(!APPLptr) /* no application or invalid data */
{ /* while reloading the DSP */
dbug(1,dprintf("discard1"));
plci->NL.RNR = 2;
return;
}
if (((plci->NL.Ind &0x0f) == N_UDATA)
&& (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
|| (plci->B2_prot == 7)
|| (plci->B3_prot == 7)) )
{
plci->ncpi_buffer[0] = 0;
ncpi_state = plci->ncpi_state;
if (plci->NL.complete == 1)
{
byte * data = &plci->NL.RBuffer->P[0];
if ((plci->NL.RBuffer->length >= 12)
&&( (*data == DSP_UDATA_INDICATION_DCD_ON)
||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
{
word conn_opt, ncpi_opt = 0x00;
/* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
if (*data == DSP_UDATA_INDICATION_DCD_ON)
plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
if (*data == DSP_UDATA_INDICATION_CTS_ON)
plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
data++; /* indication code */
data += 2; /* timestamp */
if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
data++; /* connected norm */
conn_opt = READ_WORD(data);
data += 2; /* connected options */
WRITE_WORD (&(plci->ncpi_buffer[1]), (word)(READ_DWORD(data) & 0x0000FFFF));
if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
{
ncpi_opt |= MDM_NCPI_ECM_V42;
}
else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
{
ncpi_opt |= MDM_NCPI_ECM_MNP;
}
else
{
ncpi_opt |= MDM_NCPI_TRANSPARENT;
}
if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
{
ncpi_opt |= MDM_NCPI_COMPRESSED;
}
WRITE_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
plci->ncpi_buffer[0] = 4;
plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
}
}
if (plci->B3_prot == 7)
{
if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
&& (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
&& !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
{
a->ncci_state[ncci] = INC_ACT_PENDING;
sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
}
}
if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
& ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
|| !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
|| !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
{
plci->NL.RNR = 2;
return;
}
}
if(plci->NL.complete == 2)
{
if (((plci->NL.Ind &0x0f) == N_UDATA)
&& !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
{
switch(plci->RData[0].P[0])
{
case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
break;
case DTMF_UDATA_INDICATION_ANSWER_TONE:
if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
break;
case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
break;
case DTMF_UDATA_INDICATION_DIGITS_SENT:
dtmf_confirmation (Id, plci);
break;
case UDATA_INDICATION_MIXER_TAP_DATA:
capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
if (i != 0)
{
dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
}
break;
case UDATA_INDICATION_MIXER_COEFS_SET:
mixer_indication_coefs_set (Id, plci);
break;
case UDATA_INDICATION_XCONNECT_FROM:
mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
break;
case UDATA_INDICATION_XCONNECT_TO:
mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
break;
case LEC_UDATA_INDICATION_DISABLE_DETECT:
ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
break;
default:
break;
}
}
else
{
if ((plci->RData[0].PLength != 0)
&& ((plci->B2_prot == B2_V120_ASYNC)
|| (plci->B2_prot == B2_V120_ASYNC_V42BIS)
|| (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
{
sendf(plci->appl,_DATA_B3_I,Id,0,
"dwww",
plci->RData[1].P,
(plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
plci->RNum,
plci->RFlags);
}
else
{
sendf(plci->appl,_DATA_B3_I,Id,0,
"dwww",
plci->RData[0].P,
plci->RData[0].PLength,
plci->RNum,
plci->RFlags);
}
}
return;
}
fax_feature_bits = 0;
if((plci->NL.Ind &0x0f)==N_CONNECT ||
(plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
(plci->NL.Ind &0x0f)==N_DISC ||
(plci->NL.Ind &0x0f)==N_EDATA ||
(plci->NL.Ind &0x0f)==N_DISC_ACK)
{
info = 0;
plci->ncpi_buffer[0] = 0;
switch (plci->B3_prot) {
case 0: /*XPARENT*/
case 1: /*T.90 NL*/
break; /* no network control protocol info - jfr */
case 2: /*ISO8202*/
case 3: /*X25 DCE*/
for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
plci->ncpi_buffer[0] = (byte)(i+3);
plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
plci->ncpi_buffer[2] = 0;
plci->ncpi_buffer[3] = 0;
break;
case 4: /*T.30 - FAX*/
case 5: /*T.30 - FAX*/
if(plci->NL.RLength>=sizeof(T30_INFO))
{
dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
len = 9;
WRITE_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
fax_feature_bits = READ_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
if (plci->B3_prot == 5)
{
if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
i |= 0x8000; /* This is not an ECM connection */
if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
i |= 0x4000; /* This is a connection with MMR compression */
if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
i |= 0x2000; /* This is a connection with MR compression */
if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
i |= 0x0004; /* More documents */
if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
i |= 0x0002; /* Fax-polling indication */
}
dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
WRITE_WORD(&(plci->ncpi_buffer[3]),i);
WRITE_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
plci->ncpi_buffer[len] = 0;
if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
{
plci->ncpi_buffer[len] = 20;
for (i = 0; i < 20; i++)
plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
}
if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
{
if (((T30_INFO *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0]))
info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
else
info = _FAX_PROTOCOL_ERROR;
}
if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
& ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
{
i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
while (i < plci->NL.RBuffer->length)
plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
}
plci->ncpi_buffer[0] = len;
fax_feature_bits = READ_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
WRITE_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
|| (((plci->NL.Ind &0x0f) == N_CONNECT)
&& (fax_feature_bits & T30_FEATURE_BIT_POLLING))
|| (((plci->NL.Ind &0x0f) == N_EDATA)
&& ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
|| (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
|| (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
{
plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
}
if (((plci->NL.Ind &0x0f) == N_DISC)
|| ((plci->NL.Ind &0x0f) == N_DISC_ACK)
|| (((plci->NL.Ind &0x0f) == N_EDATA)
&& (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
{
plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
}
}
break;
case B3_RTP:
if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
{
if (plci->NL.RLength != 0)
{
info = rtp_info[plci->NL.RBuffer->P[0]];
plci->ncpi_buffer[0] = plci->NL.RLength - 1;
for (i = 1; i < plci->NL.RLength; i++)
plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
}
}
break;
}
plci->NL.RNR = 2;
}
switch(plci->NL.Ind &0x0f) {
case N_EDATA:
if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
{
dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
((T30_INFO *)plci->NL.RBuffer->P)->code));
fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
&& (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
&& (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
&& (a->ncci_state[ncci] == OUTG_CON_PENDING)
&& (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
&& !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
{
((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
(byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
fax_send_edata_ack = FALSE;
}
if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
{
switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
{
case EDATA_T30_DIS:
if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
&& !(READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
&& (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
&& !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
{
a->ncci_state[ncci] = INC_ACT_PENDING;
if (plci->B3_prot == 4)
sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
else
sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
}
break;
case EDATA_T30_TRAIN_OK:
if ((a->ncci_state[ncci] == INC_ACT_PENDING)
&& (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
&& !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
{
if (plci->B3_prot == 4)
sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
else
sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
}
break;
case EDATA_T30_EOP_CAPI:
if (a->ncci_state[ncci] == CONNECTED)
{
sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
a->ncci_state[ncci] = INC_DIS_PENDING;
plci->ncpi_state = 0;
fax_send_edata_ack = FALSE;
}
break;
}
}
else
{
switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
{
case EDATA_T30_TRAIN_OK:
if ((a->ncci_state[ncci] == INC_ACT_PENDING)
&& (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
&& !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
{
if (plci->B3_prot == 4)
sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
else
sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
}
break;
}
}
if (fax_send_edata_ack)
{
((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
plci->fax_edata_ack_length = 1;
start_internal_command (Id, plci, fax_edata_ack_command);
}
}
else
{
dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
}
break;
case N_CONNECT:
if (!a->ch_ncci[ch])
{
ncci = get_ncci (plci, ch, 0);
Id = (Id & 0xffff) | (((dword) ncci) << 16);
}
dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
msg = _CONNECT_B3_I;
if (a->ncci_state[ncci] == IDLE)
plci->channels++;
else if (plci->B3_prot == 1)
msg = _CONNECT_B3_T90_ACTIVE_I;
a->ncci_state[ncci] = INC_CON_PENDING;
if(plci->B3_prot == 4)
sendf(plci->appl,msg,Id,0,"s","");
else
sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
break;
case N_CONNECT_ACK:
dbug(1,dprintf("N_connect_Ack"));
if (plci->internal_command_queue[0]
&& ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
|| (plci->adjust_b_state == ADJUST_B_CONNECT_3)
|| (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
{
(*(plci->internal_command_queue[0]))(Id, plci, 0);
if (!plci->internal_command)
next_internal_command (Id, plci);
break;
}
msg = _CONNECT_B3_ACTIVE_I;
if (plci->B3_prot == 1)
{
if (a->ncci_state[ncci] != OUTG_CON_PENDING)
msg = _CONNECT_B3_T90_ACTIVE_I;
a->ncci_state[ncci] = INC_ACT_PENDING;
sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
}
else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
{
if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
&& (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
&& !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
{
a->ncci_state[ncci] = INC_ACT_PENDING;
if (plci->B3_prot == 4)
sendf(plci->appl,msg,Id,0,"s","");
else
sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
}
}
else
{
a->ncci_state[ncci] = INC_ACT_PENDING;
sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
}
if (plci->adjust_b_restore)
{
plci->adjust_b_restore = FALSE;
start_internal_command (Id, plci, adjust_b_restore);
}
break;
case N_DISC:
case N_DISC_ACK:
if (plci->internal_command_queue[0]
&& ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
|| (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
|| (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
{
(*(plci->internal_command_queue[0]))(Id, plci, 0);
if (!plci->internal_command)
next_internal_command (Id, plci);
}
ncci_state = a->ncci_state[ncci];
ncci_remove (plci, ncci, FALSE);
/* with N_DISC or N_DISC_ACK the IDI frees the respective */
/* channel, so we cannot store the state in ncci_state! The */
/* information which channel we received a N_DISC is thus */
/* stored in the inc_dis_ncci_table buffer. */
for(i=0; plci->inc_dis_ncci_table[i]; i++);
plci->inc_dis_ncci_table[i] = (byte) ncci;
/* need a connect_b3_ind before a disconnect_b3_ind with FAX */
if (!plci->channels
&& (plci->B1_resource == 16)
&& (plci->State <= CONNECTED))
{
len = 9;
i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
WRITE_WORD (&plci->ncpi_buffer[1], i);
WRITE_WORD (&plci->ncpi_buffer[3], 0);
i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
WRITE_WORD (&plci->ncpi_buffer[5], i);
WRITE_WORD (&plci->ncpi_buffer[7], 0);
plci->ncpi_buffer[len] = 0;
plci->ncpi_buffer[0] = len;
if(plci->B3_prot == 4)
sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
else
{
if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
& ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
{
plci->ncpi_buffer[++len] = 0;
plci->ncpi_buffer[++len] = 0;
plci->ncpi_buffer[++len] = 0;
plci->ncpi_buffer[0] = len;
}
sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
}
sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
plci->ncpi_state = 0;
sig_req(plci,HANGUP,0);
send_req(plci);
plci->State = OUTG_DIS_PENDING;
/* disc here */
}
else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
&& ((plci->B3_prot == 4) || (plci->B3_prot == 5))
&& ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
{
if (ncci_state == IDLE)
{
if (plci->channels)
plci->channels--;
if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
if(plci->State == SUSPENDING){
sendf(plci->appl,
_FACILITY_I,
Id & 0xffffL,
0,
"ws", (word)3, "\x03\x04\x00\x00");
sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
}
plci_remove(plci);
plci->State=IDLE;
}
}
}
else if (plci->channels)
{
sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
plci->ncpi_state = 0;
if ((ncci_state == OUTG_REJ_PENDING)
&& ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
{
sig_req(plci,HANGUP,0);
send_req(plci);
plci->State = OUTG_DIS_PENDING;
}
}
break;
case N_RESET:
a->ncci_state[ncci] = INC_RES_PENDING;
sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
break;
case N_RESET_ACK:
a->ncci_state[ncci] = CONNECTED;
sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
break;
case N_UDATA:
if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
{
plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
plci->NL.R = plci->RData;
plci->NL.RNum = 1;
return;
}
case N_BDATA:
case N_DATA:
if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
|| (a->ncci_state[ncci] == IDLE)
|| (a->ncci_state[ncci] == INC_DIS_PENDING))
{
plci->NL.RNR = 2;
break;
}
if ((a->ncci_state[ncci] != CONNECTED)
&& (a->ncci_state[ncci] != OUTG_DIS_PENDING)
&& (a->ncci_state[ncci] != OUTG_REJ_PENDING))
{
dbug(1,dprintf("flow control"));
plci->NL.RNR = 1; /* flow control */
channel_x_off (plci, ch, 0);
break;
}
NCCIcode = ncci | (((word)a->Id) << 8);
/* count all buffers within the Application pool */
/* belonging to the same NCCI. If this is below the */
/* number of buffers available per NCCI we accept */
/* this packet, otherwise we reject it */
count = 0;
Num = 0xffff;
for(i=0; i<APPLptr->MaxBuffer; i++) {
if(NCCIcode==APPLptr->DataNCCI[i]) count++;
if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
}
if(count>=APPLptr->MaxNCCIData || Num==0xffff)
{
dbug(3,dprintf("Flow-Control"));
plci->NL.RNR = 1;
if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
(word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
{
plci->NL.RNR = 2;
dbug(3,dprintf("DiscardData"));
} else {
channel_x_off (plci, ch, 0);
}
break;
}
else
{
APPLptr->NCCIDataFlowCtrlTimer = 0;
}
plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
if(!plci->RData[0].P) {
plci->NL.RNR = 1;
channel_x_off (plci, ch, 0);
break;
}
APPLptr->DataNCCI[Num] = NCCIcode;
APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
plci->RNum = Num;
plci->RFlags = plci->NL.Ind>>4;
plci->RData[0].PLength = APPLptr->MaxDataLength;
plci->NL.R = plci->RData;
if ((plci->NL.RLength != 0)
&& ((plci->B2_prot == B2_V120_ASYNC)
|| (plci->B2_prot == B2_V120_ASYNC_V42BIS)
|| (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
{
plci->RData[1].P = plci->RData[0].P;
plci->RData[1].PLength = plci->RData[0].PLength;
plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
plci->RData[0].PLength = 1;
else
plci->RData[0].PLength = 2;
if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
plci->RFlags |= 0x0010;
if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
plci->RFlags |= 0x8000;
plci->NL.RNum = 2;
}
else
{
if((plci->NL.Ind &0x0f)==N_UDATA)
plci->RFlags |= 0x0010;
else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
plci->RFlags |= 0x0001;
plci->NL.RNum = 1;
}
break;
case N_DATA_ACK:
data_ack (plci, ch);
break;
default:
plci->NL.RNR = 2;
break;
}
}
Generated by GNU enscript 1.6.4.