Enscript Output

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.