Showing error 1802

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/isdn/hardware/eicon/message.c
Line in file: 5980
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-11 08:47:26 UTC


Source:

    1/*
    2 *
    3  Copyright (c) Eicon Networks, 2002.
    4 *
    5  This source file is supplied for the use with
    6  Eicon Networks range of DIVA Server Adapters.
    7 *
    8  Eicon File Revision :    2.1
    9 *
   10  This program is free software; you can redistribute it and/or modify
   11  it under the terms of the GNU General Public License as published by
   12  the Free Software Foundation; either version 2, or (at your option)
   13  any later version.
   14 *
   15  This program is distributed in the hope that it will be useful,
   16  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
   17  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   18  See the GNU General Public License for more details.
   19 *
   20  You should have received a copy of the GNU General Public License
   21  along with this program; if not, write to the Free Software
   22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   23 *
   24 */
   25
   26
   27
   28
   29
   30#include "platform.h"
   31#include "di_defs.h"
   32#include "pc.h"
   33#include "capi20.h"
   34#include "divacapi.h"
   35#include "mdm_msg.h"
   36#include "divasync.h"
   37
   38
   39
   40#define FILE_ "MESSAGE.C"
   41#define dprintf
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51/*------------------------------------------------------------------*/
   52/* This is options supported for all adapters that are server by    */
   53/* XDI driver. Allo it is not necessary to ask it from every adapter*/
   54/* and it is not necessary to save it separate for every adapter    */
   55/* Macrose defined here have only local meaning                     */
   56/*------------------------------------------------------------------*/
   57static dword diva_xdi_extended_features = 0;
   58
   59#define DIVA_CAPI_USE_CMA                 0x00000001
   60#define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
   61#define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
   62#define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
   63
   64/*
   65  CAPI can request to process all return codes self only if:
   66  protocol code supports this && xdi supports this
   67 */
   68#define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
   69
   70/*------------------------------------------------------------------*/
   71/* local function prototypes                                        */
   72/*------------------------------------------------------------------*/
   73
   74static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
   75static void set_group_ind_mask (PLCI   *plci);
   76static void clear_group_ind_mask_bit (PLCI   *plci, word b);
   77static byte test_group_ind_mask_bit (PLCI   *plci, word b);
   78void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
   79word CapiRelease(word);
   80word CapiRegister(word);
   81word api_put(APPL   *, CAPI_MSG   *);
   82static word api_parse(byte   *, word, byte *, API_PARSE *);
   83static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
   84static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
   85
   86word api_remove_start(void);
   87void api_remove_complete(void);
   88
   89static void plci_remove(PLCI   *);
   90static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
   91static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
   92
   93void   callback(ENTITY   *);
   94
   95static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
   96static void data_rc(PLCI   *, byte);
   97static void data_ack(PLCI   *, byte);
   98static void sig_ind(PLCI   *);
   99static void SendInfo(PLCI   *, dword, byte   * *, byte);
  100static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
  101static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
  102
  103static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
  104
  105static void nl_ind(PLCI   *);
  106
  107static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  108static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  109static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  110static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  111static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  112static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  113static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  114static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  115static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  116static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  117static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  118static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  119static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  120static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  121static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  122static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  123static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  124static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  125static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  126static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  127static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  128static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  129static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  130static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  131
  132static word get_plci(DIVA_CAPI_ADAPTER   *);
  133static void add_p(PLCI   *, byte, byte   *);
  134static void add_s(PLCI   * plci, byte code, API_PARSE * p);
  135static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
  136static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
  137static void add_d(PLCI   *, word, byte   *);
  138static void add_ai(PLCI   *, API_PARSE *);
  139static word add_b1(PLCI   *, API_PARSE *, word, word);
  140static word add_b23(PLCI   *, API_PARSE *);
  141static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
  142static void sig_req(PLCI   *, byte, byte);
  143static void nl_req_ncci(PLCI   *, byte, byte);
  144static void send_req(PLCI   *);
  145static void send_data(PLCI   *);
  146static word plci_remove_check(PLCI   *);
  147static void listen_check(DIVA_CAPI_ADAPTER   *);
  148static byte AddInfo(byte   **, byte   **, byte   *, byte *);
  149static byte getChannel(API_PARSE *);
  150static void IndParse(PLCI   *, word *, byte   **, byte);
  151static byte ie_compare(byte   *, byte *);
  152static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
  153static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
  154
  155/*
  156  XON protocol helpers
  157  */
  158static void channel_flow_control_remove (PLCI   * plci);
  159static void channel_x_off (PLCI   * plci, byte ch, byte flag);
  160static void channel_x_on (PLCI   * plci, byte ch);
  161static void channel_request_xon (PLCI   * plci, byte ch);
  162static void channel_xmit_xon (PLCI   * plci);
  163static int channel_can_xon (PLCI   * plci, byte ch);
  164static void channel_xmit_extended_xon (PLCI   * plci);
  165
  166static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
  167static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
  168static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
  169static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
  170static void VoiceChannelOff(PLCI   *plci);
  171static void adv_voice_write_coefs (PLCI   *plci, word write_command);
  172static void adv_voice_clear_config (PLCI   *plci);
  173
  174static word get_b1_facilities (PLCI   * plci, byte b1_resource);
  175static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
  176static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
  177static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
  178static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
  179static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
  180static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
  181static void select_b_command (dword Id, PLCI   *plci, byte Rc);
  182static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
  183static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
  184static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
  185static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
  186static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
  187static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
  188static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
  189static void init_b1_config (PLCI   *plci);
  190static void clear_b1_config (PLCI   *plci);
  191
  192static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
  193static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
  194static void dtmf_confirmation (dword Id, PLCI   *plci);
  195static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
  196static void dtmf_parameter_write (PLCI   *plci);
  197
  198
  199static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
  200static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
  201static void mixer_clear_config (PLCI   *plci);
  202static void mixer_notify_update (PLCI   *plci, byte others);
  203static void mixer_command (dword Id, PLCI   *plci, byte Rc);
  204static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
  205static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
  206static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
  207static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
  208static void mixer_remove (PLCI   *plci);
  209
  210
  211static void ec_command (dword Id, PLCI   *plci, byte Rc);
  212static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
  213static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
  214
  215
  216static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
  217static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
  218
  219
  220static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
  221static void diva_free_dma_descriptor (PLCI   *plci, int nr);
  222
  223/*------------------------------------------------------------------*/
  224/* external function prototypes                                     */
  225/*------------------------------------------------------------------*/
  226
  227extern byte MapController (byte);
  228extern byte UnMapController (byte);
  229#define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
  230#define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
  231
  232void   sendf(APPL   *, word, dword, word, byte *, ...);
  233void   * TransmitBufferSet(APPL   * appl, dword ref);
  234void   * TransmitBufferGet(APPL   * appl, void   * p);
  235void TransmitBufferFree(APPL   * appl, void   * p);
  236void   * ReceiveBufferGet(APPL   * appl, int Num);
  237
  238int fax_head_line_time (char *buffer);
  239
  240
  241/*------------------------------------------------------------------*/
  242/* Global data definitions                                          */
  243/*------------------------------------------------------------------*/
  244extern byte max_adapter;
  245extern byte max_appl;
  246extern DIVA_CAPI_ADAPTER   * adapter;
  247extern APPL   * application;
  248
  249
  250
  251
  252
  253
  254
  255static byte remove_started = false;
  256static PLCI dummy_plci;
  257
  258
  259static struct _ftable {
  260  word command;
  261  byte * format;
  262  byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
  263} ftable[] = {
  264  {_DATA_B3_R,                          "dwww",         data_b3_req},
  265  {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
  266  {_INFO_R,                             "ss",           info_req},
  267  {_INFO_I|RESPONSE,                    "",             info_res},
  268  {_CONNECT_R,                          "wsssssssss",   connect_req},
  269  {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
  270  {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
  271  {_DISCONNECT_R,                       "s",            disconnect_req},
  272  {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
  273  {_LISTEN_R,                           "dddss",        listen_req},
  274  {_ALERT_R,                            "s",            alert_req},
  275  {_FACILITY_R,                         "ws",           facility_req},
  276  {_FACILITY_I|RESPONSE,                "ws",           facility_res},
  277  {_CONNECT_B3_R,                       "s",            connect_b3_req},
  278  {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
  279  {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
  280  {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
  281  {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
  282  {_RESET_B3_R,                         "s",            reset_b3_req},
  283  {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
  284  {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
  285  {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
  286  {_SELECT_B_REQ,                       "s",            select_b_req},
  287  {_MANUFACTURER_R,                     "dws",          manufacturer_req},
  288  {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
  289  {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
  290};
  291
  292static byte * cip_bc[29][2] = {
  293  { "",                     ""                     }, /* 0 */
  294  { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
  295  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
  296  { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
  297  { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
  298  { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
  299  { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
  300  { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
  301  { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
  302  { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
  303  { "",                     ""                     }, /* 10 */
  304  { "",                     ""                     }, /* 11 */
  305  { "",                     ""                     }, /* 12 */
  306  { "",                     ""                     }, /* 13 */
  307  { "",                     ""                     }, /* 14 */
  308  { "",                     ""                     }, /* 15 */
  309
  310  { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
  311  { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
  312  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
  313  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
  314  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
  315  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
  316  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
  317  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
  318  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
  319  { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
  320  { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
  321  { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
  322  { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
  323};
  324
  325static byte * cip_hlc[29] = {
  326  "",                           /* 0 */
  327  "",                           /* 1 */
  328  "",                           /* 2 */
  329  "",                           /* 3 */
  330  "",                           /* 4 */
  331  "",                           /* 5 */
  332  "",                           /* 6 */
  333  "",                           /* 7 */
  334  "",                           /* 8 */
  335  "",                           /* 9 */
  336  "",                           /* 10 */
  337  "",                           /* 11 */
  338  "",                           /* 12 */
  339  "",                           /* 13 */
  340  "",                           /* 14 */
  341  "",                           /* 15 */
  342
  343  "\x02\x91\x81",               /* 16 */
  344  "\x02\x91\x84",               /* 17 */
  345  "\x02\x91\xa1",               /* 18 */
  346  "\x02\x91\xa4",               /* 19 */
  347  "\x02\x91\xa8",               /* 20 */
  348  "\x02\x91\xb1",               /* 21 */
  349  "\x02\x91\xb2",               /* 22 */
  350  "\x02\x91\xb5",               /* 23 */
  351  "\x02\x91\xb8",               /* 24 */
  352  "\x02\x91\xc1",               /* 25 */
  353  "\x02\x91\x81",               /* 26 */
  354  "\x03\x91\xe0\x01",           /* 27 */
  355  "\x03\x91\xe0\x02"            /* 28 */
  356};
  357
  358/*------------------------------------------------------------------*/
  359
  360#define V120_HEADER_LENGTH 1
  361#define V120_HEADER_EXTEND_BIT  0x80
  362#define V120_HEADER_BREAK_BIT   0x40
  363#define V120_HEADER_C1_BIT      0x04
  364#define V120_HEADER_C2_BIT      0x08
  365#define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
  366
  367static byte v120_default_header[] =
  368{
  369
  370  0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
  371
  372};
  373
  374static byte v120_break_header[] =
  375{
  376
  377  0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
  378
  379};
  380
  381
  382/*------------------------------------------------------------------*/
  383/* API_PUT function                                                 */
  384/*------------------------------------------------------------------*/
  385
  386word api_put(APPL   * appl, CAPI_MSG   * msg)
  387{
  388  word i, j, k, l, n;
  389  word ret;
  390  byte c;
  391  byte controller;
  392  DIVA_CAPI_ADAPTER   * a;
  393  PLCI   * plci;
  394  NCCI   * ncci_ptr;
  395  word ncci;
  396  CAPI_MSG   *m;
  397    API_PARSE msg_parms[MAX_MSG_PARMS+1];
  398
  399  if (msg->header.length < sizeof (msg->header) ||
  400      msg->header.length > MAX_MSG_SIZE) {
  401    dbug(1,dprintf("bad len"));
  402    return _BAD_MSG;
  403  }
  404
  405  controller = (byte)((msg->header.controller &0x7f)-1);
  406
  407  /* controller starts with 0 up to (max_adapter - 1) */
  408  if ( controller >= max_adapter )
  409  {
  410    dbug(1,dprintf("invalid ctrl"));
  411    return _BAD_MSG;
  412  }
  413  
  414  a = &adapter[controller];
  415  plci = NULL;
  416  if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
  417  {
  418    dbug(1,dprintf("plci=%x",msg->header.plci));
  419    plci = &a->plci[msg->header.plci-1];
  420    ncci = GET_WORD(&msg->header.ncci);
  421    if (plci->Id
  422     && (plci->appl
  423      || (plci->State == INC_CON_PENDING)
  424      || (plci->State == INC_CON_ALERT)
  425      || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
  426     && ((ncci == 0)
  427      || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
  428      || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
  429    {
  430      i = plci->msg_in_read_pos;
  431      j = plci->msg_in_write_pos;
  432      if (j >= i)
  433      {
  434        if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
  435          i += MSG_IN_QUEUE_SIZE - j;
  436        else
  437          j = 0;
  438      }
  439      else
  440      {
  441
  442        n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
  443
  444        if (i > MSG_IN_QUEUE_SIZE - n)
  445          i = MSG_IN_QUEUE_SIZE - n + 1;
  446        i -= j;
  447      }
  448
  449      if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
  450
  451      {
  452        dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
  453          msg->header.length, plci->msg_in_write_pos,
  454          plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
  455
  456        return _QUEUE_FULL;
  457      }
  458      c = false;
  459      if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
  460       || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
  461      {
  462        if (plci->msg_in_write_pos != plci->msg_in_read_pos)
  463          c = true;
  464      }
  465      if (msg->header.command == _DATA_B3_R)
  466      {
  467        if (msg->header.length < 20)
  468        {
  469          dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
  470          return _BAD_MSG;
  471        }
  472        ncci_ptr = &(a->ncci[ncci]);
  473        n = ncci_ptr->data_pending;
  474        l = ncci_ptr->data_ack_pending;
  475        k = plci->msg_in_read_pos;
  476        while (k != plci->msg_in_write_pos)
  477        {
  478          if (k == plci->msg_in_wrap_pos)
  479            k = 0;
  480          if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
  481           && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
  482          {
  483            n++;
  484            if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
  485              l++;
  486          }
  487
  488          k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
  489            MSG_IN_OVERHEAD + 3) & 0xfffc;
  490
  491        }
  492        if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
  493        {
  494          dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
  495                          ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
  496
  497          return _QUEUE_FULL;
  498        }
  499        if (plci->req_in || plci->internal_command)
  500        {
  501          if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
  502           && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
  503          {
  504            dbug(0,dprintf("Q-FULL3(requeue)"));
  505
  506            return _QUEUE_FULL;
  507          }
  508          c = true;
  509        }
  510      }
  511      else
  512      {
  513        if (plci->req_in || plci->internal_command)
  514          c = true;
  515        else
  516        {
  517          plci->command = msg->header.command;
  518          plci->number = msg->header.number;
  519        }
  520      }
  521      if (c)
  522      {
  523        dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
  524          msg->header.command, plci->req_in, plci->internal_command,
  525          msg->header.length, plci->msg_in_write_pos,
  526          plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
  527        if (j == 0)
  528          plci->msg_in_wrap_pos = plci->msg_in_write_pos;
  529        m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
  530        for (i = 0; i < msg->header.length; i++)
  531          ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
  532        if (m->header.command == _DATA_B3_R)
  533        {
  534
  535          m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
  536
  537        }
  538
  539        j = (j + 3) & 0xfffc;
  540
  541        *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
  542        plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
  543        return 0;
  544      }
  545    }
  546    else
  547    {
  548      plci = NULL;
  549    }
  550  }
  551  dbug(1,dprintf("com=%x",msg->header.command));
  552
  553  for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
  554  for(i=0, ret = _BAD_MSG;
  555      i<(sizeof(ftable)/sizeof(struct _ftable));
  556      i++) {
  557
  558    if(ftable[i].command==msg->header.command) {
  559      /* break loop if the message is correct, otherwise continue scan  */
  560      /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
  561      if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
  562        ret = 0;
  563        break;
  564      }
  565      for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
  566    }
  567  }
  568  if(ret) {
  569    dbug(1,dprintf("BAD_MSG"));
  570    if(plci) plci->command = 0;
  571    return ret;
  572  }
  573
  574
  575  c = ftable[i].function(GET_DWORD(&msg->header.controller),
  576                         msg->header.number,
  577                         a,
  578                         plci,
  579                         appl,
  580                         msg_parms);
  581
  582  channel_xmit_extended_xon (plci);
  583
  584  if(c==1) send_req(plci);
  585  if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
  586  if(plci && !plci->req_in) plci->command = 0;
  587  return 0;
  588}
  589
  590
  591/*------------------------------------------------------------------*/
  592/* api_parse function, check the format of api messages             */
  593/*------------------------------------------------------------------*/
  594
  595word api_parse(byte   * msg, word length, byte * format, API_PARSE * parms)
  596{
  597  word i;
  598  word p;
  599
  600  for(i=0,p=0; format[i]; i++) {
  601    if(parms)
  602    {
  603      parms[i].info = &msg[p];
  604    }
  605    switch(format[i]) {
  606    case 'b':
  607      p +=1;
  608      break;
  609    case 'w':
  610      p +=2;
  611      break;
  612    case 'd':
  613      p +=4;
  614      break;
  615    case 's':
  616      if(msg[p]==0xff) {
  617        parms[i].info +=2;
  618        parms[i].length = msg[p+1] + (msg[p+2]<<8);
  619        p +=(parms[i].length +3);
  620      }
  621      else {
  622        parms[i].length = msg[p];
  623        p +=(parms[i].length +1);
  624      }
  625      break;
  626    }
  627
  628    if(p>length) return true;
  629  }
  630  if(parms) parms[i].info = NULL;
  631  return false;
  632}
  633
  634void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out)
  635{
  636  word i, j, n = 0;
  637  byte   *p;
  638
  639  p = out->info;
  640  for (i = 0; format[i] != '\0'; i++)
  641  {
  642    out->parms[i].info = p;
  643    out->parms[i].length = in[i].length;
  644    switch (format[i])
  645    {
  646    case 'b':
  647      n = 1;
  648      break;
  649    case 'w':
  650      n = 2;
  651      break;
  652    case 'd':
  653      n = 4;
  654      break;
  655    case 's':
  656      n = in[i].length + 1;
  657      break;
  658    }
  659    for (j = 0; j < n; j++)
  660      *(p++) = in[i].info[j];
  661  }
  662  out->parms[i].info = NULL;
  663  out->parms[i].length = 0;
  664}
  665
  666void api_load_msg(API_SAVE   *in, API_PARSE   *out)
  667{
  668  word i;
  669
  670  i = 0;
  671  do
  672  {
  673    out[i].info = in->parms[i].info;
  674    out[i].length = in->parms[i].length;
  675  } while (in->parms[i++].info);
  676}
  677
  678
  679/*------------------------------------------------------------------*/
  680/* CAPI remove function                                             */
  681/*------------------------------------------------------------------*/
  682
  683word api_remove_start(void)
  684{
  685  word i;
  686  word j;
  687
  688  if(!remove_started) {
  689    remove_started = true;
  690    for(i=0;i<max_adapter;i++) {
  691      if(adapter[i].request) {
  692        for(j=0;j<adapter[i].max_plci;j++) {
  693          if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
  694        }
  695      }
  696    }
  697    return 1;
  698  }
  699  else {
  700    for(i=0;i<max_adapter;i++) {
  701      if(adapter[i].request) {
  702        for(j=0;j<adapter[i].max_plci;j++) {
  703          if(adapter[i].plci[j].Sig.Id) return 1;
  704        }
  705      }
  706    }
  707  }
  708  api_remove_complete();
  709  return 0;
  710}
  711
  712
  713/*------------------------------------------------------------------*/
  714/* internal command queue                                           */
  715/*------------------------------------------------------------------*/
  716
  717static void init_internal_command_queue (PLCI   *plci)
  718{
  719  word i;
  720
  721  dbug (1, dprintf ("%s,%d: init_internal_command_queue",
  722    (char   *)(FILE_), __LINE__));
  723
  724  plci->internal_command = 0;
  725  for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
  726    plci->internal_command_queue[i] = NULL;
  727}
  728
  729
  730static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
  731{
  732  word i;
  733
  734  dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
  735    UnMapId (Id), (char   *)(FILE_), __LINE__));
  736
  737  if (plci->internal_command == 0)
  738  {
  739    plci->internal_command_queue[0] = command_function;
  740    (* command_function)(Id, plci, OK);
  741  }
  742  else
  743  {
  744    i = 1;
  745    while (plci->internal_command_queue[i] != NULL)
  746      i++;
  747    plci->internal_command_queue[i] = command_function;
  748  }
  749}
  750
  751
  752static void next_internal_command (dword Id, PLCI   *plci)
  753{
  754  word i;
  755
  756  dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
  757    UnMapId (Id), (char   *)(FILE_), __LINE__));
  758
  759  plci->internal_command = 0;
  760  plci->internal_command_queue[0] = NULL;
  761  while (plci->internal_command_queue[1] != NULL)
  762  {
  763    for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
  764      plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
  765    plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
  766    (*(plci->internal_command_queue[0]))(Id, plci, OK);
  767    if (plci->internal_command != 0)
  768      return;
  769    plci->internal_command_queue[0] = NULL;
  770  }
  771}
  772
  773
  774/*------------------------------------------------------------------*/
  775/* NCCI allocate/remove function                                    */
  776/*------------------------------------------------------------------*/
  777
  778static dword ncci_mapping_bug = 0;
  779
  780static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
  781{
  782  DIVA_CAPI_ADAPTER   *a;
  783  word ncci, i, j, k;
  784
  785  a = plci->adapter;
  786  if (!ch || a->ch_ncci[ch])
  787  {
  788    ncci_mapping_bug++;
  789    dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
  790      ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
  791    ncci = ch;
  792  }
  793  else
  794  {
  795    if (force_ncci)
  796      ncci = force_ncci;
  797    else
  798    {
  799      if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
  800        ncci = ch;
  801      else
  802      {
  803        ncci = 1;
  804        while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
  805          ncci++;
  806        if (ncci == MAX_NCCI+1)
  807        {
  808          ncci_mapping_bug++;
  809          i = 1;
  810          do
  811          {
  812            j = 1;
  813            while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
  814              j++;
  815            k = j;
  816            if (j < MAX_NCCI+1)
  817            {
  818              do
  819              {
  820                j++;
  821              } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
  822            }
  823          } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
  824          if (i < MAX_NL_CHANNEL+1)
  825          {
  826            dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
  827              ncci_mapping_bug, ch, force_ncci, i, k, j));
  828          }
  829          else
  830          {
  831            dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
  832              ncci_mapping_bug, ch, force_ncci));
  833          }
  834          ncci = ch;
  835        }
  836      }
  837      a->ncci_plci[ncci] = plci->Id;
  838      a->ncci_state[ncci] = IDLE;
  839      if (!plci->ncci_ring_list)
  840        plci->ncci_ring_list = ncci;
  841      else
  842        a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
  843      a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
  844    }
  845    a->ncci_ch[ncci] = ch;
  846    a->ch_ncci[ch] = (byte) ncci;
  847    dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
  848      ncci_mapping_bug, ch, force_ncci, ch, ncci));
  849  }
  850  return (ncci);
  851}
  852
  853
  854static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
  855{
  856  DIVA_CAPI_ADAPTER   *a;
  857  APPL   *appl;
  858  word i, ncci_code;
  859  dword Id;
  860
  861  a = plci->adapter;
  862  Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
  863  if (ncci)
  864  {
  865    if (a->ncci_plci[ncci] == plci->Id)
  866    {
  867      if (!plci->appl)
  868      {
  869        ncci_mapping_bug++;
  870        dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
  871          ncci_mapping_bug, Id));
  872      }
  873      else
  874      {
  875        appl = plci->appl;
  876        ncci_code = ncci | (((word) a->Id) << 8);
  877        for (i = 0; i < appl->MaxBuffer; i++)
  878        {
  879          if ((appl->DataNCCI[i] == ncci_code)
  880           && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
  881          {
  882            appl->DataNCCI[i] = 0;
  883          }
  884        }
  885      }
  886    }
  887  }
  888  else
  889  {
  890    for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
  891    {
  892      if (a->ncci_plci[ncci] == plci->Id)
  893      {
  894        if (!plci->appl)
  895        {
  896          ncci_mapping_bug++;
  897          dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
  898            ncci_mapping_bug, Id));
  899        }
  900        else
  901        {
  902          appl = plci->appl;
  903          ncci_code = ncci | (((word) a->Id) << 8);
  904          for (i = 0; i < appl->MaxBuffer; i++)
  905          {
  906            if ((appl->DataNCCI[i] == ncci_code)
  907             && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
  908            {
  909              appl->DataNCCI[i] = 0;
  910            }
  911          }
  912        }
  913      }
  914    }
  915  }
  916}
  917
  918
  919static void cleanup_ncci_data (PLCI   *plci, word ncci)
  920{
  921  NCCI   *ncci_ptr;
  922
  923  if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
  924  {
  925    ncci_ptr = &(plci->adapter->ncci[ncci]);
  926    if (plci->appl)
  927    {
  928      while (ncci_ptr->data_pending != 0)
  929      {
  930        if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
  931          TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
  932        (ncci_ptr->data_out)++;
  933        if (ncci_ptr->data_out == MAX_DATA_B3)
  934          ncci_ptr->data_out = 0;
  935        (ncci_ptr->data_pending)--;
  936      }
  937    }
  938    ncci_ptr->data_out = 0;
  939    ncci_ptr->data_pending = 0;
  940    ncci_ptr->data_ack_out = 0;
  941    ncci_ptr->data_ack_pending = 0;
  942  }
  943}
  944
  945
  946static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
  947{
  948  DIVA_CAPI_ADAPTER   *a;
  949  dword Id;
  950  word i;
  951
  952  a = plci->adapter;
  953  Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
  954  if (!preserve_ncci)
  955    ncci_free_receive_buffers (plci, ncci);
  956  if (ncci)
  957  {
  958    if (a->ncci_plci[ncci] != plci->Id)
  959    {
  960      ncci_mapping_bug++;
  961      dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
  962        ncci_mapping_bug, Id, preserve_ncci));
  963    }
  964    else
  965    {
  966      cleanup_ncci_data (plci, ncci);
  967      dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
  968        ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
  969      a->ch_ncci[a->ncci_ch[ncci]] = 0;
  970      if (!preserve_ncci)
  971      {
  972        a->ncci_ch[ncci] = 0;
  973        a->ncci_plci[ncci] = 0;
  974        a->ncci_state[ncci] = IDLE;
  975        i = plci->ncci_ring_list;
  976        while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
  977          i = a->ncci_next[i];
  978        if ((i != 0) && (a->ncci_next[i] == ncci))
  979        {
  980          if (i == ncci)
  981            plci->ncci_ring_list = 0;
  982          else if (plci->ncci_ring_list == ncci)
  983            plci->ncci_ring_list = i;
  984          a->ncci_next[i] = a->ncci_next[ncci];
  985        }
  986        a->ncci_next[ncci] = 0;
  987      }
  988    }
  989  }
  990  else
  991  {
  992    for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
  993    {
  994      if (a->ncci_plci[ncci] == plci->Id)
  995      {
  996        cleanup_ncci_data (plci, ncci);
  997        dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
  998          ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
  999        a->ch_ncci[a->ncci_ch[ncci]] = 0;
 1000        if (!preserve_ncci)
 1001        {
 1002          a->ncci_ch[ncci] = 0;
 1003          a->ncci_plci[ncci] = 0;
 1004          a->ncci_state[ncci] = IDLE;
 1005          a->ncci_next[ncci] = 0;
 1006        }
 1007      }
 1008    }
 1009    if (!preserve_ncci)
 1010      plci->ncci_ring_list = 0;
 1011  }
 1012}
 1013
 1014
 1015/*------------------------------------------------------------------*/
 1016/* PLCI remove function                                             */
 1017/*------------------------------------------------------------------*/
 1018
 1019static void plci_free_msg_in_queue (PLCI   *plci)
 1020{
 1021  word i;
 1022
 1023  if (plci->appl)
 1024  {
 1025    i = plci->msg_in_read_pos;
 1026    while (i != plci->msg_in_write_pos)
 1027    {
 1028      if (i == plci->msg_in_wrap_pos)
 1029        i = 0;
 1030      if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
 1031      {
 1032
 1033        TransmitBufferFree (plci->appl,
 1034          (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
 1035
 1036      }
 1037
 1038      i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
 1039        MSG_IN_OVERHEAD + 3) & 0xfffc;
 1040
 1041    }
 1042  }
 1043  plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
 1044  plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
 1045  plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
 1046}
 1047
 1048
 1049static void plci_remove(PLCI   * plci)
 1050{
 1051
 1052  if(!plci) {
 1053    dbug(1,dprintf("plci_remove(no plci)"));
 1054    return;
 1055  }
 1056  init_internal_command_queue (plci);
 1057  dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
 1058  if(plci_remove_check(plci))
 1059  {
 1060    return;
 1061  }
 1062  if (plci->Sig.Id == 0xff)
 1063  {
 1064    dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
 1065    if (plci->NL.Id && !plci->nl_remove_id)
 1066    {
 1067      nl_req_ncci(plci,REMOVE,0);
 1068      send_req(plci);
 1069    }
 1070  }
 1071  else
 1072  {
 1073    if (!plci->sig_remove_id
 1074     && (plci->Sig.Id
 1075      || (plci->req_in!=plci->req_out)
 1076      || (plci->nl_req || plci->sig_req)))
 1077    {
 1078      sig_req(plci,HANGUP,0);
 1079      send_req(plci);
 1080    }
 1081  }
 1082  ncci_remove (plci, 0, false);
 1083  plci_free_msg_in_queue (plci);
 1084
 1085  plci->channels = 0;
 1086  plci->appl = NULL;
 1087  if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
 1088    plci->State = OUTG_DIS_PENDING;
 1089}
 1090
 1091/*------------------------------------------------------------------*/
 1092/* Application Group function helpers                               */
 1093/*------------------------------------------------------------------*/
 1094
 1095static void set_group_ind_mask (PLCI   *plci)
 1096{
 1097  word i;
 1098
 1099  for (i = 0; i < C_IND_MASK_DWORDS; i++)
 1100    plci->group_optimization_mask_table[i] = 0xffffffffL;
 1101}
 1102
 1103static void clear_group_ind_mask_bit (PLCI   *plci, word b)
 1104{
 1105  plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
 1106}
 1107
 1108static byte test_group_ind_mask_bit (PLCI   *plci, word b)
 1109{
 1110  return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
 1111}
 1112
 1113/*------------------------------------------------------------------*/
 1114/* c_ind_mask operations for arbitrary MAX_APPL                     */
 1115/*------------------------------------------------------------------*/
 1116
 1117static void clear_c_ind_mask (PLCI   *plci)
 1118{
 1119  word i;
 1120
 1121  for (i = 0; i < C_IND_MASK_DWORDS; i++)
 1122    plci->c_ind_mask_table[i] = 0;
 1123}
 1124
 1125static byte c_ind_mask_empty (PLCI   *plci)
 1126{
 1127  word i;
 1128
 1129  i = 0;
 1130  while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
 1131    i++;
 1132  return (i == C_IND_MASK_DWORDS);
 1133}
 1134
 1135static void set_c_ind_mask_bit (PLCI   *plci, word b)
 1136{
 1137  plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
 1138}
 1139
 1140static void clear_c_ind_mask_bit (PLCI   *plci, word b)
 1141{
 1142  plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
 1143}
 1144
 1145static byte test_c_ind_mask_bit (PLCI   *plci, word b)
 1146{
 1147  return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
 1148}
 1149
 1150static void dump_c_ind_mask (PLCI   *plci)
 1151{
 1152static char hex_digit_table[0x10] =
 1153  {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
 1154  word i, j, k;
 1155  dword d;
 1156    char *p;
 1157    char buf[40];
 1158
 1159  for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
 1160  {
 1161    p = buf + 36;
 1162    *p = '\0';
 1163    for (j = 0; j < 4; j++)
 1164    {
 1165      if (i+j < C_IND_MASK_DWORDS)
 1166      {
 1167        d = plci->c_ind_mask_table[i+j];
 1168        for (k = 0; k < 8; k++)
 1169        {
 1170          *(--p) = hex_digit_table[d & 0xf];
 1171          d >>= 4;
 1172        }
 1173      }
 1174      else if (i != 0)
 1175      {
 1176        for (k = 0; k < 8; k++)
 1177          *(--p) = ' ';
 1178      }
 1179      *(--p) = ' ';
 1180    }
 1181    dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
 1182  }
 1183}
 1184
 1185
 1186
 1187
 1188
 1189#define dump_plcis(a)
 1190
 1191
 1192
 1193/*------------------------------------------------------------------*/
 1194/* translation function for each message                            */
 1195/*------------------------------------------------------------------*/
 1196
 1197byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 1198{
 1199  word ch;
 1200  word i;
 1201  word Info;
 1202  word CIP;
 1203  byte LinkLayer;
 1204  API_PARSE * ai;
 1205  API_PARSE * bp;
 1206    API_PARSE ai_parms[5];
 1207  word channel = 0;
 1208  dword ch_mask;
 1209  byte m;
 1210  static byte esc_chi[35] = {0x02,0x18,0x01};
 1211  static byte lli[2] = {0x01,0x00};
 1212  byte noCh = 0;
 1213  word dir = 0;
 1214  byte   *p_chi = "";
 1215
 1216  for(i=0;i<5;i++) ai_parms[i].length = 0;
 1217
 1218  dbug(1,dprintf("connect_req(%d)",parms->length));
 1219  Info = _WRONG_IDENTIFIER;
 1220  if(a)
 1221  {
 1222    if(a->adapter_disabled)
 1223    {
 1224      dbug(1,dprintf("adapter disabled"));
 1225      Id = ((word)1<<8)|a->Id;
 1226      sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
 1227      sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
 1228      return false;
 1229    }
 1230    Info = _OUT_OF_PLCI;
 1231    if((i=get_plci(a)))
 1232    {
 1233      Info = 0;
 1234      plci = &a->plci[i-1];
 1235      plci->appl = appl;
 1236      plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
 1237      /* check 'external controller' bit for codec support */
 1238      if(Id & EXT_CONTROLLER)
 1239      {
 1240        if(AdvCodecSupport(a, plci, appl, 0) )
 1241        {
 1242          plci->Id = 0;
 1243          sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
 1244          return 2;
 1245        }
 1246      }
 1247      ai = &parms[9];
 1248      bp = &parms[5];
 1249      ch = 0;
 1250      if(bp->length)LinkLayer = bp->info[3];
 1251      else LinkLayer = 0;
 1252      if(ai->length)
 1253      {
 1254        ch=0xffff;
 1255        if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
 1256        {
 1257          ch = 0;
 1258          if(ai_parms[0].length)
 1259          {
 1260            ch = GET_WORD(ai_parms[0].info+1);
 1261            if(ch>4) ch=0; /* safety -> ignore ChannelID */
 1262            if(ch==4) /* explizit CHI in message */
 1263            {
 1264              /* check length of B-CH struct */
 1265              if((ai_parms[0].info)[3]>=1)
 1266              {
 1267                if((ai_parms[0].info)[4]==CHI)
 1268                {
 1269                  p_chi = &((ai_parms[0].info)[5]);
 1270                }
 1271                else
 1272                {
 1273                  p_chi = &((ai_parms[0].info)[3]);
 1274                }
 1275                if(p_chi[0]>35) /* check length of channel ID */
 1276                {
 1277                  Info = _WRONG_MESSAGE_FORMAT;    
 1278                }
 1279              }
 1280              else Info = _WRONG_MESSAGE_FORMAT;    
 1281            }
 1282
 1283            if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
 1284            {
 1285              dir = GET_WORD(ai_parms[0].info+3);
 1286              ch_mask = 0;
 1287              m = 0x3f;
 1288              for(i=0; i+5<=ai_parms[0].length; i++)
 1289              {
 1290                if(ai_parms[0].info[i+5]!=0)
 1291                {
 1292                  if((ai_parms[0].info[i+5] | m) != 0xff)
 1293                    Info = _WRONG_MESSAGE_FORMAT;
 1294                  else
 1295                  {
 1296                    if (ch_mask == 0)
 1297                      channel = i;
 1298                    ch_mask |= 1L << i;
 1299                  }
 1300                }
 1301                m = 0;
 1302              }
 1303              if (ch_mask == 0)
 1304                Info = _WRONG_MESSAGE_FORMAT;
 1305              if (!Info)
 1306              {
 1307                if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
 1308                {
 1309                  esc_chi[0] = (byte)(ai_parms[0].length - 2);
 1310                  for(i=0; i+5<=ai_parms[0].length; i++)
 1311                    esc_chi[i+3] = ai_parms[0].info[i+5];
 1312                }
 1313                else
 1314                  esc_chi[0] = 2;
 1315                esc_chi[2] = (byte)channel;
 1316                plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
 1317                add_p(plci,LLI,lli);
 1318                add_p(plci,ESC,esc_chi);
 1319                plci->State = LOCAL_CONNECT;
 1320                if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
 1321              }
 1322            }
 1323          }
 1324        }
 1325        else  Info = _WRONG_MESSAGE_FORMAT;
 1326      }
 1327
 1328      dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
 1329      plci->command = _CONNECT_R;
 1330      plci->number = Number;
 1331      /* x.31 or D-ch free SAPI in LinkLayer? */
 1332      if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
 1333      if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
 1334      {
 1335        /* B-channel used for B3 connections (ch==0), or no B channel    */
 1336        /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
 1337        if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
 1338        else     Info = add_b1(plci,&parms[5],ch,0); 
 1339        add_s(plci,OAD,&parms[2]);
 1340        add_s(plci,OSA,&parms[4]);
 1341        add_s(plci,BC,&parms[6]);
 1342        add_s(plci,LLC,&parms[7]);
 1343        add_s(plci,HLC,&parms[8]);
 1344        CIP = GET_WORD(parms[0].info);
 1345        if (a->Info_Mask[appl->Id-1] & 0x200)
 1346        {
 1347          /* early B3 connect (CIP mask bit 9) no release after a disc */
 1348          add_p(plci,LLI,"\x01\x01");
 1349        }
 1350        if(GET_WORD(parms[0].info)<29) {
 1351          add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
 1352          add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
 1353        }
 1354        add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 1355        sig_req(plci,ASSIGN,DSIG_ID);
 1356      }
 1357      else if(ch==1) {
 1358
 1359        /* D-Channel used for B3 connections */
 1360        plci->Sig.Id = 0xff;
 1361        Info = 0;
 1362      }
 1363
 1364      if(!Info && ch!=2 && !noCh ) {
 1365        Info = add_b23(plci,&parms[5]);
 1366        if(!Info) {
 1367          if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
 1368        }
 1369      }
 1370
 1371      if(!Info)
 1372      {
 1373        if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
 1374        {
 1375          if(plci->spoofed_msg==SPOOFING_REQUIRED)
 1376          {
 1377            api_save_msg(parms, "wsssssssss", &plci->saved_msg);
 1378            plci->spoofed_msg = CALL_REQ;
 1379            plci->internal_command = BLOCK_PLCI;
 1380            plci->command = 0;
 1381            dbug(1,dprintf("Spoof"));
 1382            send_req(plci);
 1383            return false;
 1384          }
 1385          if(ch==4)add_p(plci,CHI,p_chi);
 1386          add_s(plci,CPN,&parms[1]);
 1387          add_s(plci,DSA,&parms[3]);
 1388          if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
 1389          add_ai(plci,&parms[9]);
 1390          if(!dir)sig_req(plci,CALL_REQ,0);
 1391          else
 1392          {
 1393            plci->command = PERM_LIST_REQ;
 1394            plci->appl = appl;
 1395            sig_req(plci,LISTEN_REQ,0);
 1396            send_req(plci);
 1397            return false;
 1398          }
 1399        }
 1400        send_req(plci);
 1401        return false;
 1402      }
 1403      plci->Id = 0;
 1404    }
 1405  }
 1406  sendf(appl,
 1407        _CONNECT_R|CONFIRM,
 1408        Id,
 1409        Number,
 1410        "w",Info);
 1411  return 2;
 1412}
 1413
 1414byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 1415{
 1416  word i, Info;
 1417  word Reject;
 1418  static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
 1419  static byte esc_t[] = {0x03,0x08,0x00,0x00};
 1420  API_PARSE * ai;
 1421    API_PARSE ai_parms[5];
 1422  word ch=0;
 1423
 1424  if(!plci) {
 1425    dbug(1,dprintf("connect_res(no plci)"));
 1426    return 0;  /* no plci, no send */
 1427  }
 1428
 1429  dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
 1430  for(i=0;i<5;i++) ai_parms[i].length = 0;
 1431  ai = &parms[5];
 1432  dbug(1,dprintf("ai->length=%d",ai->length));
 1433
 1434  if(ai->length)
 1435  {
 1436    if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
 1437    {
 1438      dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
 1439      ch = 0;
 1440      if(ai_parms[0].length)
 1441      {
 1442        ch = GET_WORD(ai_parms[0].info+1);
 1443        dbug(1,dprintf("BCH-I=0x%x",ch));
 1444      }
 1445    }
 1446  }
 1447
 1448  if(plci->State==INC_CON_CONNECTED_ALERT)
 1449  {
 1450    dbug(1,dprintf("Connected Alert Call_Res"));
 1451    if (a->Info_Mask[appl->Id-1] & 0x200)
 1452    {
 1453    /* early B3 connect (CIP mask bit 9) no release after a disc */
 1454      add_p(plci,LLI,"\x01\x01");
 1455    }
 1456    add_s(plci, CONN_NR, &parms[2]);
 1457    add_s(plci, LLC, &parms[4]);
 1458    add_ai(plci, &parms[5]);
 1459    plci->State = INC_CON_ACCEPT;
 1460    sig_req(plci, CALL_RES,0);
 1461    return 1;
 1462  }
 1463  else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
 1464    clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
 1465    dump_c_ind_mask (plci);
 1466    Reject = GET_WORD(parms[0].info);
 1467    dbug(1,dprintf("Reject=0x%x",Reject));
 1468    if(Reject) 
 1469    {
 1470      if(c_ind_mask_empty (plci)) 
 1471      {
 1472        if((Reject&0xff00)==0x3400) 
 1473        {
 1474          esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
 1475          add_p(plci,ESC,esc_t);
 1476          add_ai(plci, &parms[5]);
 1477          sig_req(plci,REJECT,0);
 1478        }      
 1479        else if(Reject==1 || Reject>9) 
 1480        {
 1481          add_ai(plci, &parms[5]);
 1482          sig_req(plci,HANGUP,0);
 1483        }
 1484        else 
 1485        {
 1486          esc_t[2] = cau_t[(Reject&0x000f)];
 1487          add_p(plci,ESC,esc_t);
 1488          add_ai(plci, &parms[5]);
 1489          sig_req(plci,REJECT,0);
 1490        }
 1491        plci->appl = appl;
 1492      }
 1493      else 
 1494      {
 1495        sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
 1496      }
 1497    }
 1498    else {
 1499      plci->appl = appl;
 1500      if(Id & EXT_CONTROLLER){
 1501        if(AdvCodecSupport(a, plci, appl, 0)){
 1502          dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
 1503          sig_req(plci,HANGUP,0);
 1504          return 1;
 1505        }
 1506        if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
 1507        {
 1508          Info = add_b23(plci, &parms[1]);
 1509          if (Info)
 1510          {
 1511            dbug(1,dprintf("connect_res(error from add_b23)"));
 1512            sig_req(plci,HANGUP,0);
 1513            return 1;
 1514          }
 1515          if(plci->adv_nl)
 1516          {
 1517            nl_req_ncci(plci, ASSIGN, 0);
 1518          }
 1519        }
 1520      }
 1521      else
 1522      {
 1523        plci->tel = 0;
 1524        if(ch!=2)
 1525        {
 1526          Info = add_b23(plci, &parms[1]);
 1527          if (Info)
 1528          {
 1529            dbug(1,dprintf("connect_res(error from add_b23 2)"));
 1530            sig_req(plci,HANGUP,0);
 1531            return 1;
 1532          }
 1533        }
 1534        nl_req_ncci(plci, ASSIGN, 0);
 1535      }
 1536
 1537      if(plci->spoofed_msg==SPOOFING_REQUIRED)
 1538      {
 1539        api_save_msg(parms, "wsssss", &plci->saved_msg);
 1540        plci->spoofed_msg = CALL_RES;
 1541        plci->internal_command = BLOCK_PLCI;
 1542        plci->command = 0;
 1543        dbug(1,dprintf("Spoof"));
 1544      }
 1545      else
 1546      {
 1547        add_b1 (plci, &parms[1], ch, plci->B1_facilities);
 1548        if (a->Info_Mask[appl->Id-1] & 0x200)
 1549        {
 1550          /* early B3 connect (CIP mask bit 9) no release after a disc */
 1551          add_p(plci,LLI,"\x01\x01");
 1552        }
 1553        add_s(plci, CONN_NR, &parms[2]);
 1554        add_s(plci, LLC, &parms[4]);
 1555        add_ai(plci, &parms[5]);
 1556        plci->State = INC_CON_ACCEPT;
 1557        sig_req(plci, CALL_RES,0);
 1558      }
 1559
 1560      for(i=0; i<max_appl; i++) {
 1561        if(test_c_ind_mask_bit (plci, i)) {
 1562          sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
 1563        }
 1564      }
 1565    }
 1566  }
 1567  return 1;
 1568}
 1569
 1570byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 1571{
 1572  dbug(1,dprintf("connect_a_res"));
 1573  return false;
 1574}
 1575
 1576byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 1577{
 1578  word Info;
 1579  word i;
 1580
 1581  dbug(1,dprintf("disconnect_req"));
 1582
 1583  Info = _WRONG_IDENTIFIER;
 1584
 1585  if(plci)
 1586  {
 1587    if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
 1588    {
 1589      clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
 1590      plci->appl = appl;
 1591      for(i=0; i<max_appl; i++)
 1592      {
 1593        if(test_c_ind_mask_bit (plci, i))
 1594          sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
 1595      }
 1596      plci->State = OUTG_DIS_PENDING;
 1597    }
 1598    if(plci->Sig.Id && plci->appl)
 1599    {
 1600      Info = 0;
 1601        if(plci->Sig.Id!=0xff)
 1602        {
 1603          if(plci->State!=INC_DIS_PENDING)
 1604          {
 1605            add_ai(plci, &msg[0]);
 1606            sig_req(plci,HANGUP,0);
 1607            plci->State = OUTG_DIS_PENDING;
 1608            return 1;
 1609          }
 1610        }
 1611        else
 1612        {
 1613          if (plci->NL.Id && !plci->nl_remove_id)
 1614          {
 1615            mixer_remove (plci);
 1616            nl_req_ncci(plci,REMOVE,0);
 1617          sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
 1618          sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
 1619          plci->State = INC_DIS_PENDING;
 1620          }
 1621          return 1;
 1622        }
 1623      }
 1624    }
 1625
 1626  if(!appl)  return false;
 1627  sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
 1628  return false;
 1629}
 1630
 1631byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 1632{
 1633  dbug(1,dprintf("disconnect_res"));
 1634  if(plci)
 1635  {
 1636        /* clear ind mask bit, just in case of collsion of          */
 1637        /* DISCONNECT_IND and CONNECT_RES                           */
 1638    clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
 1639    ncci_free_receive_buffers (plci, 0);
 1640    if(plci_remove_check(plci))
 1641    {
 1642      return 0;
 1643    }
 1644    if(plci->State==INC_DIS_PENDING
 1645    || plci->State==SUSPENDING) {
 1646      if(c_ind_mask_empty (plci)) {
 1647        if(plci->State!=SUSPENDING)plci->State = IDLE;
 1648        dbug(1,dprintf("chs=%d",plci->channels));
 1649        if(!plci->channels) {
 1650          plci_remove(plci);
 1651        }
 1652      }
 1653    }
 1654  }
 1655  return 0;
 1656}
 1657
 1658byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 1659{
 1660  word Info;
 1661  byte i;
 1662
 1663  dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
 1664
 1665  Info = _WRONG_IDENTIFIER;
 1666  if(a) {
 1667    Info = 0;
 1668    a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
 1669    a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
 1670    dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
 1671    if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
 1672      a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
 1673    }
 1674
 1675    /* check if external controller listen and switch listen on or off*/
 1676    if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
 1677      if(a->profile.Global_Options & ON_BOARD_CODEC) {
 1678        dummy_plci.State = IDLE;
 1679        a->codec_listen[appl->Id-1] = &dummy_plci;
 1680        a->TelOAD[0] = (byte)(parms[3].length);
 1681        for(i=1;parms[3].length>=i && i<22;i++) {
 1682          a->TelOAD[i] = parms[3].info[i];
 1683        }
 1684        a->TelOAD[i] = 0;
 1685        a->TelOSA[0] = (byte)(parms[4].length);
 1686        for(i=1;parms[4].length>=i && i<22;i++) {
 1687          a->TelOSA[i] = parms[4].info[i];
 1688        }
 1689        a->TelOSA[i] = 0;
 1690      }
 1691      else Info = 0x2002; /* wrong controller, codec not supported */
 1692    }
 1693    else{               /* clear listen */
 1694      a->codec_listen[appl->Id-1] = (PLCI   *)0;
 1695    }
 1696  }
 1697  sendf(appl,
 1698        _LISTEN_R|CONFIRM,
 1699        Id,
 1700        Number,
 1701        "w",Info);
 1702
 1703  if (a) listen_check(a);
 1704  return false;
 1705}
 1706
 1707byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 1708{
 1709  word i;
 1710  API_PARSE * ai;
 1711  PLCI   * rc_plci = NULL;
 1712    API_PARSE ai_parms[5];
 1713  word Info = 0;
 1714
 1715  dbug(1,dprintf("info_req"));
 1716  for(i=0;i<5;i++) ai_parms[i].length = 0;
 1717
 1718  ai = &msg[1];
 1719
 1720  if(ai->length)
 1721  {
 1722    if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
 1723    {
 1724      dbug(1,dprintf("AddInfo wrong"));
 1725      Info = _WRONG_MESSAGE_FORMAT;
 1726    }
 1727  }
 1728  if(!a) Info = _WRONG_STATE;
 1729
 1730  if(!Info && plci)
 1731  {                /* no fac, with CPN, or KEY */
 1732    rc_plci = plci;
 1733    if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
 1734    {
 1735      /* overlap sending option */
 1736      dbug(1,dprintf("OvlSnd"));
 1737      add_s(plci,CPN,&msg[0]);
 1738      add_s(plci,KEY,&ai_parms[1]);
 1739      sig_req(plci,INFO_REQ,0);
 1740      send_req(plci);
 1741      return false;
 1742    }
 1743
 1744    if(plci->State && ai_parms[2].length)
 1745    {
 1746      /* User_Info option */
 1747      dbug(1,dprintf("UUI"));
 1748      add_s(plci,UUI,&ai_parms[2]);
 1749      sig_req(plci,USER_DATA,0);
 1750    }
 1751    else if(plci->State && ai_parms[3].length)
 1752    {
 1753      /* Facility option */
 1754      dbug(1,dprintf("FAC"));
 1755      add_s(plci,CPN,&msg[0]);
 1756      add_ai(plci, &msg[1]);
 1757      sig_req(plci,FACILITY_REQ,0);
 1758    }
 1759    else
 1760    {
 1761      Info = _WRONG_STATE;
 1762    }
 1763  }
 1764  else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
 1765  {
 1766    /* NCR_Facility option -> send UUI and Keypad too */
 1767    dbug(1,dprintf("NCR_FAC"));
 1768    if((i=get_plci(a)))
 1769    {
 1770      rc_plci = &a->plci[i-1];
 1771      appl->NullCREnable  = true;
 1772      rc_plci->internal_command = C_NCR_FAC_REQ;
 1773      rc_plci->appl = appl;
 1774      add_p(rc_plci,CAI,"\x01\x80");
 1775      add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 1776      sig_req(rc_plci,ASSIGN,DSIG_ID);
 1777      send_req(rc_plci);
 1778    }
 1779    else
 1780    {
 1781      Info = _OUT_OF_PLCI;
 1782    }
 1783
 1784    if(!Info)
 1785    {
 1786      add_s(rc_plci,CPN,&msg[0]);
 1787      add_ai(rc_plci, &msg[1]);
 1788      sig_req(rc_plci,NCR_FACILITY,0);
 1789      send_req(rc_plci);
 1790      return false;
 1791     /* for application controlled supplementary services    */
 1792    }
 1793  }
 1794
 1795  if (!rc_plci)
 1796  {
 1797    Info = _WRONG_MESSAGE_FORMAT;
 1798  }
 1799
 1800  if(!Info)
 1801  {
 1802    send_req(rc_plci);
 1803  }
 1804  else
 1805  {  /* appl is not assigned to a PLCI or error condition */
 1806    dbug(1,dprintf("localInfoCon"));
 1807    sendf(appl,
 1808          _INFO_R|CONFIRM,
 1809          Id,
 1810          Number,
 1811          "w",Info);
 1812  }
 1813  return false;
 1814}
 1815
 1816byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 1817{
 1818  dbug(1,dprintf("info_res"));
 1819  return false;
 1820}
 1821
 1822byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 1823{
 1824  word Info;
 1825  byte ret;
 1826
 1827  dbug(1,dprintf("alert_req"));
 1828
 1829  Info = _WRONG_IDENTIFIER;
 1830  ret = false;
 1831  if(plci) {
 1832    Info = _ALERT_IGNORED;
 1833    if(plci->State!=INC_CON_ALERT) {
 1834      Info = _WRONG_STATE;
 1835      if(plci->State==INC_CON_PENDING) {
 1836        Info = 0;
 1837        plci->State=INC_CON_ALERT;
 1838        add_ai(plci, &msg[0]);
 1839        sig_req(plci,CALL_ALERT,0);
 1840        ret = 1;
 1841      }
 1842    }
 1843  }
 1844  sendf(appl,
 1845        _ALERT_R|CONFIRM,
 1846        Id,
 1847        Number,
 1848        "w",Info);
 1849  return ret;
 1850}
 1851
 1852byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 1853{
 1854  word Info = 0;
 1855  word i    = 0;
 1856
 1857  word selector;
 1858  word SSreq;
 1859  long relatedPLCIvalue;
 1860  DIVA_CAPI_ADAPTER   * relatedadapter;
 1861  byte * SSparms  = "";
 1862    byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
 1863    byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
 1864  API_PARSE * parms;
 1865    API_PARSE ss_parms[11];
 1866  PLCI   *rplci;
 1867    byte cai[15];
 1868  dword d;
 1869    API_PARSE dummy;
 1870
 1871  dbug(1,dprintf("facility_req"));
 1872  for(i=0;i<9;i++) ss_parms[i].length = 0;
 1873
 1874  parms = &msg[1];
 1875
 1876  if(!a)
 1877  {
 1878    dbug(1,dprintf("wrong Ctrl"));
 1879    Info = _WRONG_IDENTIFIER;
 1880  }
 1881
 1882  selector = GET_WORD(msg[0].info);
 1883
 1884  if(!Info)
 1885  {
 1886    switch(selector)
 1887    {
 1888      case SELECTOR_HANDSET:
 1889        Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
 1890        break;
 1891
 1892      case SELECTOR_SU_SERV:
 1893        if(!msg[1].length)
 1894        {
 1895          Info = _WRONG_MESSAGE_FORMAT;
 1896          break;
 1897        }
 1898        SSreq = GET_WORD(&(msg[1].info[1]));
 1899        PUT_WORD(&RCparms[1],SSreq);
 1900        SSparms = RCparms;
 1901        switch(SSreq)
 1902        {
 1903          case S_GET_SUPPORTED_SERVICES:
 1904            if((i=get_plci(a)))
 1905            {
 1906              rplci = &a->plci[i-1];
 1907              rplci->appl = appl;
 1908              add_p(rplci,CAI,"\x01\x80");
 1909              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 1910              sig_req(rplci,ASSIGN,DSIG_ID);
 1911              send_req(rplci);
 1912            }
 1913            else
 1914            {
 1915              PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
 1916              SSparms = (byte *)SSstruct;
 1917              break;
 1918            }
 1919            rplci->internal_command = GETSERV_REQ_PEND;
 1920            rplci->number = Number;
 1921            rplci->appl = appl;
 1922            sig_req(rplci,S_SUPPORTED,0);
 1923            send_req(rplci);
 1924            return false;
 1925            break;
 1926
 1927          case S_LISTEN:
 1928            if(parms->length==7)
 1929            {
 1930              if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
 1931              {
 1932                dbug(1,dprintf("format wrong"));
 1933                Info = _WRONG_MESSAGE_FORMAT;
 1934                break;
 1935              }
 1936            }
 1937            else
 1938            {
 1939              Info = _WRONG_MESSAGE_FORMAT;
 1940              break;
 1941            }
 1942            a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
 1943            if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
 1944            {
 1945              if((i=get_plci(a)))
 1946              {
 1947                rplci = &a->plci[i-1];
 1948                rplci->appl = appl;
 1949                add_p(rplci,CAI,"\x01\x80");
 1950                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 1951                sig_req(rplci,ASSIGN,DSIG_ID);
 1952                send_req(rplci);
 1953              }
 1954              else
 1955              {
 1956                break;
 1957              }
 1958              rplci->internal_command = GET_MWI_STATE;
 1959              rplci->number = Number;
 1960              sig_req(rplci,MWI_POLL,0);
 1961              send_req(rplci);
 1962            }
 1963            break;
 1964
 1965          case S_HOLD:
 1966            api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
 1967            if(plci && plci->State && plci->SuppState==IDLE)
 1968            {
 1969              plci->SuppState = HOLD_REQUEST;
 1970              plci->command = C_HOLD_REQ;
 1971              add_s(plci,CAI,&ss_parms[1]);
 1972              sig_req(plci,CALL_HOLD,0);
 1973              send_req(plci);
 1974              return false;
 1975            }
 1976            else Info = 0x3010;                    /* wrong state           */
 1977            break;
 1978          case S_RETRIEVE:
 1979            if(plci && plci->State && plci->SuppState==CALL_HELD)
 1980            {
 1981              if(Id & EXT_CONTROLLER)
 1982              {
 1983                if(AdvCodecSupport(a, plci, appl, 0))
 1984                {
 1985                  Info = 0x3010;                    /* wrong state           */
 1986                  break;
 1987                }
 1988              }
 1989              else plci->tel = 0;
 1990
 1991              plci->SuppState = RETRIEVE_REQUEST;
 1992              plci->command = C_RETRIEVE_REQ;
 1993              if(plci->spoofed_msg==SPOOFING_REQUIRED)
 1994              {
 1995                plci->spoofed_msg = CALL_RETRIEVE;
 1996                plci->internal_command = BLOCK_PLCI;
 1997                plci->command = 0;
 1998                dbug(1,dprintf("Spoof"));
 1999                return false;
 2000              }
 2001              else
 2002              {
 2003                sig_req(plci,CALL_RETRIEVE,0);
 2004                send_req(plci);
 2005                return false;
 2006              }
 2007            }
 2008            else Info = 0x3010;                    /* wrong state           */
 2009            break;
 2010          case S_SUSPEND:
 2011            if(parms->length)
 2012            {
 2013              if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
 2014              {
 2015                dbug(1,dprintf("format wrong"));
 2016                Info = _WRONG_MESSAGE_FORMAT;
 2017                break;
 2018              }
 2019            }
 2020            if(plci && plci->State)
 2021            {
 2022              add_s(plci,CAI,&ss_parms[2]);
 2023              plci->command = SUSPEND_REQ;
 2024              sig_req(plci,SUSPEND,0);
 2025              plci->State = SUSPENDING;
 2026              send_req(plci);
 2027            }
 2028            else Info = 0x3010;                    /* wrong state           */
 2029            break;
 2030
 2031          case S_RESUME:
 2032            if(!(i=get_plci(a)) )
 2033            {
 2034              Info = _OUT_OF_PLCI;
 2035              break;
 2036            }
 2037            rplci = &a->plci[i-1];
 2038            rplci->appl = appl;
 2039            rplci->number = Number;
 2040            rplci->tel = 0;
 2041            rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
 2042            /* check 'external controller' bit for codec support */
 2043            if(Id & EXT_CONTROLLER)
 2044            {
 2045              if(AdvCodecSupport(a, rplci, appl, 0) )
 2046              {
 2047                rplci->Id = 0;
 2048                Info = 0x300A;
 2049                break;
 2050              }
 2051            }
 2052            if(parms->length)
 2053            {
 2054              if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
 2055              {
 2056                dbug(1,dprintf("format wrong"));
 2057                rplci->Id = 0;
 2058                Info = _WRONG_MESSAGE_FORMAT;
 2059                break;
 2060              }
 2061            }
 2062            dummy.length = 0;
 2063            dummy.info = "\x00";
 2064            add_b1(rplci, &dummy, 0, 0);
 2065            if (a->Info_Mask[appl->Id-1] & 0x200)
 2066            {
 2067              /* early B3 connect (CIP mask bit 9) no release after a disc */
 2068              add_p(rplci,LLI,"\x01\x01");
 2069            }
 2070            add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 2071            sig_req(rplci,ASSIGN,DSIG_ID);
 2072            send_req(rplci);
 2073            add_s(rplci,CAI,&ss_parms[2]);
 2074            rplci->command = RESUME_REQ;
 2075            sig_req(rplci,RESUME,0);
 2076            rplci->State = RESUMING;
 2077            send_req(rplci);
 2078            break;
 2079
 2080          case S_CONF_BEGIN: /* Request */
 2081          case S_CONF_DROP:
 2082          case S_CONF_ISOLATE:
 2083          case S_CONF_REATTACH:
 2084            if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
 2085            {
 2086              dbug(1,dprintf("format wrong"));
 2087              Info = _WRONG_MESSAGE_FORMAT;
 2088              break;
 2089            }
 2090            if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
 2091            {
 2092              d = GET_DWORD(ss_parms[2].info);     
 2093              if(d>=0x80)
 2094              {
 2095                dbug(1,dprintf("format wrong"));
 2096                Info = _WRONG_MESSAGE_FORMAT;
 2097                break;
 2098              }
 2099              plci->ptyState = (byte)SSreq;
 2100              plci->command = 0;
 2101              cai[0] = 2;
 2102              switch(SSreq)
 2103              {
 2104              case S_CONF_BEGIN:
 2105                  cai[1] = CONF_BEGIN;
 2106                  plci->internal_command = CONF_BEGIN_REQ_PEND;
 2107                  break;
 2108              case S_CONF_DROP:
 2109                  cai[1] = CONF_DROP;
 2110                  plci->internal_command = CONF_DROP_REQ_PEND;
 2111                  break;
 2112              case S_CONF_ISOLATE:
 2113                  cai[1] = CONF_ISOLATE;
 2114                  plci->internal_command = CONF_ISOLATE_REQ_PEND;
 2115                  break;
 2116              case S_CONF_REATTACH:
 2117                  cai[1] = CONF_REATTACH;
 2118                  plci->internal_command = CONF_REATTACH_REQ_PEND;
 2119                  break;
 2120              }
 2121              cai[2] = (byte)d; /* Conference Size resp. PartyId */
 2122              add_p(plci,CAI,cai);
 2123              sig_req(plci,S_SERVICE,0);
 2124              send_req(plci);
 2125              return false;
 2126            }
 2127            else Info = 0x3010;                    /* wrong state           */
 2128            break;
 2129
 2130          case S_ECT:
 2131          case S_3PTY_BEGIN:
 2132          case S_3PTY_END:
 2133          case S_CONF_ADD:
 2134            if(parms->length==7)
 2135            {
 2136              if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
 2137              {
 2138                dbug(1,dprintf("format wrong"));
 2139                Info = _WRONG_MESSAGE_FORMAT;
 2140                break;
 2141              }
 2142            }
 2143            else if(parms->length==8) /* workaround for the T-View-S */
 2144            {
 2145              if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
 2146              {
 2147                dbug(1,dprintf("format wrong"));
 2148                Info = _WRONG_MESSAGE_FORMAT;
 2149                break;
 2150              }
 2151            }
 2152            else
 2153            {
 2154              Info = _WRONG_MESSAGE_FORMAT;
 2155              break;
 2156            }
 2157            if(!msg[1].length)
 2158            {
 2159              Info = _WRONG_MESSAGE_FORMAT;
 2160              break;
 2161            }
 2162            if (!plci)
 2163            {
 2164              Info = _WRONG_IDENTIFIER;
 2165              break;
 2166            }
 2167            relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
 2168            relatedPLCIvalue &= 0x0000FFFF;
 2169            dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
 2170            /* controller starts with 0 up to (max_adapter - 1) */
 2171            if (((relatedPLCIvalue & 0x7f) == 0)
 2172             || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
 2173             || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
 2174            {
 2175              if(SSreq==S_3PTY_END)
 2176              {
 2177                dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
 2178                rplci = plci;
 2179              }
 2180              else
 2181              {
 2182                Info = 0x3010;                    /* wrong state           */
 2183                break;
 2184              }
 2185            }
 2186            else
 2187            {  
 2188              relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
 2189              relatedPLCIvalue >>=8;
 2190              /* find PLCI PTR*/
 2191              for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
 2192              {
 2193                if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
 2194                {
 2195                  rplci = &relatedadapter->plci[i];
 2196                }
 2197              }
 2198              if(!rplci || !relatedPLCIvalue)
 2199              {
 2200                if(SSreq==S_3PTY_END)
 2201                {
 2202                  dbug(1, dprintf("use 2nd PLCI=PLCI"));
 2203                  rplci = plci;
 2204                }
 2205                else
 2206                {
 2207                  Info = 0x3010;                    /* wrong state           */
 2208                  break;
 2209                }
 2210              }
 2211            }
 2212/*
 2213            dbug(1,dprintf("rplci:%x",rplci));
 2214            dbug(1,dprintf("plci:%x",plci));
 2215            dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
 2216            dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
 2217            dbug(1,dprintf("SSreq:%x",SSreq));
 2218            dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
 2219            dbug(1,dprintf("rplci->appl:%x",rplci->appl));
 2220            dbug(1,dprintf("rplci->Id:%x",rplci->Id));
 2221*/
 2222            /* send PTY/ECT req, cannot check all states because of US stuff */
 2223            if( !rplci->internal_command && rplci->appl )
 2224            {
 2225              plci->command = 0;
 2226              rplci->relatedPTYPLCI = plci;
 2227              plci->relatedPTYPLCI = rplci;
 2228              rplci->ptyState = (byte)SSreq;
 2229              if(SSreq==S_ECT)
 2230              {
 2231                rplci->internal_command = ECT_REQ_PEND;
 2232                cai[1] = ECT_EXECUTE;
 2233
 2234                rplci->vswitchstate=0;
 2235                rplci->vsprot=0;
 2236                rplci->vsprotdialect=0;
 2237                plci->vswitchstate=0;
 2238                plci->vsprot=0;
 2239                plci->vsprotdialect=0;
 2240
 2241              }
 2242              else if(SSreq==S_CONF_ADD)
 2243              {
 2244                rplci->internal_command = CONF_ADD_REQ_PEND;
 2245                cai[1] = CONF_ADD;
 2246              }
 2247              else
 2248              {
 2249                rplci->internal_command = PTY_REQ_PEND;
 2250                cai[1] = (byte)(SSreq-3);
 2251              }
 2252              rplci->number = Number;
 2253              if(plci!=rplci) /* explicit invocation */
 2254              {
 2255                cai[0] = 2;
 2256                cai[2] = plci->Sig.Id;
 2257                dbug(1,dprintf("explicit invocation"));
 2258              }
 2259              else
 2260              {
 2261                dbug(1,dprintf("implicit invocation"));
 2262                cai[0] = 1;
 2263              }
 2264              add_p(rplci,CAI,cai);
 2265              sig_req(rplci,S_SERVICE,0);
 2266              send_req(rplci);
 2267              return false;
 2268            }
 2269            else
 2270            {
 2271              dbug(0,dprintf("Wrong line"));
 2272              Info = 0x3010;                    /* wrong state           */
 2273              break;
 2274            }
 2275            break;
 2276
 2277          case S_CALL_DEFLECTION:
 2278            if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
 2279            {
 2280              dbug(1,dprintf("format wrong"));
 2281              Info = _WRONG_MESSAGE_FORMAT;
 2282              break;
 2283            }
 2284            if (!plci)
 2285            {
 2286              Info = _WRONG_IDENTIFIER;
 2287              break;
 2288            }
 2289            /* reuse unused screening indicator */
 2290            ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
 2291            plci->command = 0;
 2292            plci->internal_command = CD_REQ_PEND;
 2293            appl->CDEnable = true;
 2294            cai[0] = 1;
 2295            cai[1] = CALL_DEFLECTION;
 2296            add_p(plci,CAI,cai);
 2297            add_p(plci,CPN,ss_parms[3].info);
 2298            sig_req(plci,S_SERVICE,0);
 2299            send_req(plci);
 2300            return false;
 2301            break;
 2302
 2303          case S_CALL_FORWARDING_START:
 2304            if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
 2305            {
 2306              dbug(1,dprintf("format wrong"));
 2307              Info = _WRONG_MESSAGE_FORMAT;
 2308              break;
 2309            }
 2310
 2311            if((i=get_plci(a)))
 2312            {
 2313              rplci = &a->plci[i-1];
 2314              rplci->appl = appl;
 2315              add_p(rplci,CAI,"\x01\x80");
 2316              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 2317              sig_req(rplci,ASSIGN,DSIG_ID);
 2318              send_req(rplci);
 2319            }
 2320            else
 2321            {
 2322              Info = _OUT_OF_PLCI;
 2323              break;
 2324            }
 2325
 2326            /* reuse unused screening indicator */
 2327            rplci->internal_command = CF_START_PEND;
 2328            rplci->appl = appl;
 2329            rplci->number = Number;
 2330            appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
 2331            cai[0] = 2;
 2332            cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
 2333            cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
 2334            add_p(rplci,CAI,cai);
 2335            add_p(rplci,OAD,ss_parms[5].info);
 2336            add_p(rplci,CPN,ss_parms[6].info);
 2337            sig_req(rplci,S_SERVICE,0);
 2338            send_req(rplci);
 2339            return false;
 2340            break;
 2341
 2342          case S_INTERROGATE_DIVERSION:
 2343          case S_INTERROGATE_NUMBERS:
 2344          case S_CALL_FORWARDING_STOP:
 2345          case S_CCBS_REQUEST:
 2346          case S_CCBS_DEACTIVATE:
 2347          case S_CCBS_INTERROGATE:
 2348            switch(SSreq)
 2349            {
 2350            case S_INTERROGATE_NUMBERS:
 2351                if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
 2352                {
 2353                  dbug(0,dprintf("format wrong"));
 2354                  Info = _WRONG_MESSAGE_FORMAT;
 2355                }
 2356                break;
 2357            case S_CCBS_REQUEST:
 2358            case S_CCBS_DEACTIVATE:
 2359                if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
 2360                {
 2361                  dbug(0,dprintf("format wrong"));
 2362                  Info = _WRONG_MESSAGE_FORMAT;
 2363                }
 2364                break;
 2365            case S_CCBS_INTERROGATE:
 2366                if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
 2367                {
 2368                  dbug(0,dprintf("format wrong"));
 2369                  Info = _WRONG_MESSAGE_FORMAT;
 2370                }
 2371                break;
 2372            default:
 2373            if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
 2374            {
 2375              dbug(0,dprintf("format wrong"));
 2376              Info = _WRONG_MESSAGE_FORMAT;
 2377              break;
 2378            }
 2379                break;
 2380            }
 2381
 2382            if(Info) break;
 2383            if((i=get_plci(a)))
 2384            {
 2385              rplci = &a->plci[i-1];
 2386              switch(SSreq)
 2387              {
 2388                case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
 2389                  cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
 2390                  rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
 2391                  break;
 2392                case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
 2393                  cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
 2394                  rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
 2395                  break;
 2396                case S_CALL_FORWARDING_STOP:
 2397                  rplci->internal_command = CF_STOP_PEND;
 2398                  cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
 2399                  break;
 2400                case S_CCBS_REQUEST:
 2401                  cai[1] = CCBS_REQUEST;
 2402                  rplci->internal_command = CCBS_REQUEST_REQ_PEND;
 2403                  break;
 2404                case S_CCBS_DEACTIVATE:
 2405                  cai[1] = CCBS_DEACTIVATE;
 2406                  rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
 2407                  break;
 2408                case S_CCBS_INTERROGATE:
 2409                  cai[1] = CCBS_INTERROGATE;
 2410                  rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
 2411                  break;
 2412                default:
 2413                  cai[1] = 0;
 2414                break;
 2415              }
 2416              rplci->appl = appl;
 2417              rplci->number = Number;
 2418              add_p(rplci,CAI,"\x01\x80");
 2419              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 2420              sig_req(rplci,ASSIGN,DSIG_ID);
 2421              send_req(rplci);
 2422            }
 2423            else
 2424            {
 2425              Info = _OUT_OF_PLCI;
 2426              break;
 2427            }
 2428
 2429            appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
 2430            switch(SSreq)
 2431            {
 2432            case S_INTERROGATE_NUMBERS:
 2433                cai[0] = 1;
 2434                add_p(rplci,CAI,cai);
 2435                break;
 2436            case S_CCBS_REQUEST:
 2437            case S_CCBS_DEACTIVATE:
 2438                cai[0] = 3;
 2439                PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
 2440                add_p(rplci,CAI,cai);
 2441                break;
 2442            case S_CCBS_INTERROGATE:
 2443                cai[0] = 3;
 2444                PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
 2445                add_p(rplci,CAI,cai);
 2446                add_p(rplci,OAD,ss_parms[4].info);
 2447                break;
 2448            default:
 2449            cai[0] = 2;
 2450            cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
 2451            add_p(rplci,CAI,cai);
 2452            add_p(rplci,OAD,ss_parms[5].info);
 2453                break;
 2454            }
 2455                        
 2456            sig_req(rplci,S_SERVICE,0);
 2457            send_req(rplci);
 2458            return false;
 2459            break;
 2460
 2461          case S_MWI_ACTIVATE:
 2462            if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
 2463            {
 2464              dbug(1,dprintf("format wrong"));
 2465              Info = _WRONG_MESSAGE_FORMAT;
 2466              break;
 2467            }
 2468            if(!plci)
 2469            {                               
 2470              if((i=get_plci(a)))
 2471              {
 2472                rplci = &a->plci[i-1];
 2473                rplci->appl = appl;
 2474                rplci->cr_enquiry=true;
 2475                add_p(rplci,CAI,"\x01\x80");
 2476                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 2477                sig_req(rplci,ASSIGN,DSIG_ID);
 2478                send_req(rplci);
 2479              }
 2480              else
 2481              {
 2482                Info = _OUT_OF_PLCI;
 2483                break;
 2484              }
 2485            }
 2486            else
 2487            {
 2488              rplci = plci;
 2489              rplci->cr_enquiry=false;
 2490            }
 2491
 2492            rplci->command = 0;
 2493            rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
 2494            rplci->appl = appl;
 2495            rplci->number = Number;
 2496
 2497            cai[0] = 13;
 2498            cai[1] = ACTIVATION_MWI; /* Function */
 2499            PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
 2500            PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
 2501            PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
 2502            PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
 2503            PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
 2504            add_p(rplci,CAI,cai);
 2505            add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
 2506            add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
 2507            add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
 2508            add_p(rplci,UID,ss_parms[10].info); /* Time */
 2509            sig_req(rplci,S_SERVICE,0);
 2510            send_req(rplci);
 2511            return false;
 2512
 2513          case S_MWI_DEACTIVATE:
 2514            if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
 2515            {
 2516              dbug(1,dprintf("format wrong"));
 2517              Info = _WRONG_MESSAGE_FORMAT;
 2518              break;
 2519            }
 2520            if(!plci)
 2521            {                               
 2522              if((i=get_plci(a)))
 2523              {
 2524                rplci = &a->plci[i-1];
 2525                rplci->appl = appl;
 2526                rplci->cr_enquiry=true;
 2527                add_p(rplci,CAI,"\x01\x80");
 2528                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 2529                sig_req(rplci,ASSIGN,DSIG_ID);
 2530                send_req(rplci);
 2531              }
 2532              else
 2533              {
 2534                Info = _OUT_OF_PLCI;
 2535                break;
 2536              }
 2537            }
 2538            else
 2539            {
 2540              rplci = plci;
 2541              rplci->cr_enquiry=false;
 2542            }
 2543
 2544            rplci->command = 0;
 2545            rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
 2546            rplci->appl = appl;
 2547            rplci->number = Number;
 2548
 2549            cai[0] = 5;
 2550            cai[1] = DEACTIVATION_MWI; /* Function */
 2551            PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
 2552            PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
 2553            add_p(rplci,CAI,cai);
 2554            add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
 2555            add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
 2556            sig_req(rplci,S_SERVICE,0);
 2557            send_req(rplci);
 2558            return false;
 2559
 2560          default:
 2561            Info = 0x300E;  /* not supported */
 2562            break;
 2563        }
 2564        break; /* case SELECTOR_SU_SERV: end */
 2565
 2566
 2567      case SELECTOR_DTMF:
 2568        return (dtmf_request (Id, Number, a, plci, appl, msg));
 2569
 2570
 2571
 2572      case SELECTOR_LINE_INTERCONNECT:
 2573        return (mixer_request (Id, Number, a, plci, appl, msg));
 2574
 2575
 2576
 2577      case PRIV_SELECTOR_ECHO_CANCELLER:
 2578        appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
 2579        return (ec_request (Id, Number, a, plci, appl, msg));
 2580
 2581      case SELECTOR_ECHO_CANCELLER:
 2582        appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
 2583        return (ec_request (Id, Number, a, plci, appl, msg));
 2584
 2585
 2586      case SELECTOR_V42BIS:
 2587      default:
 2588        Info = _FACILITY_NOT_SUPPORTED;
 2589        break;
 2590    } /* end of switch(selector) */
 2591  }
 2592
 2593  dbug(1,dprintf("SendFacRc"));
 2594  sendf(appl,
 2595        _FACILITY_R|CONFIRM,
 2596        Id,
 2597        Number,
 2598        "wws",Info,selector,SSparms);
 2599  return false;
 2600}
 2601
 2602byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 2603{
 2604  dbug(1,dprintf("facility_res"));
 2605  return false;
 2606}
 2607
 2608byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 2609{
 2610  word Info = 0;
 2611  byte req;
 2612  byte len;
 2613  word w;
 2614  word fax_control_bits, fax_feature_bits, fax_info_change;
 2615  API_PARSE * ncpi;
 2616    byte pvc[2];
 2617
 2618    API_PARSE fax_parms[9];
 2619  word i;
 2620
 2621
 2622  dbug(1,dprintf("connect_b3_req"));
 2623  if(plci)
 2624  {
 2625    if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
 2626     || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
 2627    {
 2628      Info = _WRONG_STATE;
 2629    }
 2630    else
 2631    {
 2632      /* local reply if assign unsuccessfull
 2633         or B3 protocol allows only one layer 3 connection
 2634           and already connected
 2635             or B2 protocol not any LAPD
 2636               and connect_b3_req contradicts originate/answer direction */
 2637      if (!plci->NL.Id
 2638       || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
 2639        && ((plci->channels != 0)
 2640         || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
 2641          && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
 2642      {
 2643        dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
 2644                       plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
 2645        Info = _WRONG_STATE;
 2646        sendf(appl,                                                        
 2647              _CONNECT_B3_R|CONFIRM,
 2648              Id,
 2649              Number,
 2650              "w",Info);
 2651        return false;
 2652      }
 2653      plci->requested_options_conn = 0;
 2654
 2655      req = N_CONNECT;
 2656      ncpi = &parms[0];
 2657      if(plci->B3_prot==2 || plci->B3_prot==3)
 2658      {
 2659        if(ncpi->length>2)
 2660        {
 2661          /* check for PVC */
 2662          if(ncpi->info[2] || ncpi->info[3])
 2663          {
 2664            pvc[0] = ncpi->info[3];
 2665            pvc[1] = ncpi->info[2];
 2666            add_d(plci,2,pvc);
 2667            req = N_RESET;
 2668          }
 2669          else
 2670          {
 2671            if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
 2672            add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
 2673          }
 2674        }
 2675      }
 2676      else if(plci->B3_prot==5)
 2677      {
 2678        if (plci->NL.Id && !plci->nl_remove_id)
 2679        {
 2680          fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
 2681          fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
 2682          if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
 2683           || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
 2684          {
 2685            len = (byte)(&(((T30_INFO *) 0)->universal_6));
 2686            fax_info_change = false;
 2687            if (ncpi->length >= 4)
 2688            {
 2689              w = GET_WORD(&ncpi->info[3]);
 2690              if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
 2691              {
 2692                ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
 2693                  (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
 2694                  ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
 2695                fax_info_change = true;
 2696              }
 2697              fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
 2698              if (w & 0x0002)  /* Fax-polling request */
 2699                fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
 2700              if ((w & 0x0004) /* Request to send / poll another document */
 2701               && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
 2702              {
 2703                fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
 2704              }
 2705              if (ncpi->length >= 6)
 2706              {
 2707                w = GET_WORD(&ncpi->info[5]);
 2708                if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
 2709                {
 2710                  ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
 2711                  fax_info_change = true;
 2712                }
 2713
 2714                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
 2715                 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
 2716                {
 2717                  plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
 2718                }
 2719                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
 2720                 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
 2721                {
 2722                  plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
 2723                }
 2724                fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
 2725                  T30_CONTROL_BIT_ACCEPT_PASSWORD);
 2726                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
 2727                  & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
 2728                {
 2729                  if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
 2730                    Info = _WRONG_MESSAGE_FORMAT;
 2731                  else
 2732                  {
 2733                    if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
 2734                      & (1L << PRIVATE_FAX_SUB_SEP_PWD))
 2735      {
 2736                    fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
 2737                    if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
 2738                      fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
 2739      }
 2740                    w = fax_parms[4].length;
 2741                    if (w > 20)
 2742                      w = 20;
 2743                    ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
 2744                    for (i = 0; i < w; i++)
 2745                      ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
 2746                    ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
 2747                    len = (byte)(((T30_INFO *) 0)->station_id + 20);
 2748                    w = fax_parms[5].length;
 2749                    if (w > 20)
 2750                      w = 20;
 2751                    plci->fax_connect_info_buffer[len++] = (byte) w;
 2752                    for (i = 0; i < w; i++)
 2753                      plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
 2754                    w = fax_parms[6].length;
 2755                    if (w > 20)
 2756                      w = 20;
 2757                    plci->fax_connect_info_buffer[len++] = (byte) w;
 2758                    for (i = 0; i < w; i++)
 2759                      plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
 2760                    if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
 2761                      & (1L << PRIVATE_FAX_NONSTANDARD))
 2762      {
 2763                      if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
 2764        {
 2765                        dbug(1,dprintf("non-standard facilities info missing or wrong format"));
 2766                        plci->fax_connect_info_buffer[len++] = 0;
 2767        }
 2768                      else
 2769                      {
 2770          if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
 2771            plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
 2772   plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
 2773          for (i = 0; i < fax_parms[7].length; i++)
 2774     plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
 2775                      }
 2776                    }
 2777                  }
 2778                }
 2779                else
 2780                {
 2781                  len = (byte)(&(((T30_INFO *) 0)->universal_6));
 2782                }
 2783                fax_info_change = true;
 2784
 2785              }
 2786              if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
 2787              {
 2788                PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
 2789                fax_info_change = true;
 2790              }
 2791            }
 2792            if (Info == GOOD)
 2793            {
 2794              plci->fax_connect_info_length = len;
 2795              if (fax_info_change)
 2796              {
 2797                if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
 2798                {
 2799                  start_internal_command (Id, plci, fax_connect_info_command);
 2800                  return false;
 2801                }
 2802                else
 2803                {
 2804                  start_internal_command (Id, plci, fax_adjust_b23_command);
 2805                  return false;
 2806                }
 2807              }
 2808            }
 2809          }
 2810          else  Info = _WRONG_STATE;
 2811        }
 2812        else  Info = _WRONG_STATE;
 2813      }
 2814
 2815      else if (plci->B3_prot == B3_RTP)
 2816      {
 2817        plci->internal_req_buffer[0] = ncpi->length + 1;
 2818        plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
 2819        for (w = 0; w < ncpi->length; w++)
 2820          plci->internal_req_buffer[2+w] = ncpi->info[1+w];
 2821        start_internal_command (Id, plci, rtp_connect_b3_req_command);
 2822        return false;
 2823      }
 2824
 2825      if(!Info)
 2826      {
 2827        nl_req_ncci(plci,req,0);
 2828        return 1;
 2829      }
 2830    }
 2831  }
 2832  else Info = _WRONG_IDENTIFIER;
 2833
 2834  sendf(appl,
 2835        _CONNECT_B3_R|CONFIRM,
 2836        Id,
 2837        Number,
 2838        "w",Info);
 2839  return false;
 2840}
 2841
 2842byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 2843{
 2844  word ncci;
 2845  API_PARSE * ncpi;
 2846  byte req;
 2847
 2848  word w;
 2849
 2850
 2851    API_PARSE fax_parms[9];
 2852  word i;
 2853  byte len;
 2854
 2855
 2856  dbug(1,dprintf("connect_b3_res"));
 2857
 2858  ncci = (word)(Id>>16);
 2859  if(plci && ncci) {
 2860    if(a->ncci_state[ncci]==INC_CON_PENDING) {
 2861      if (GET_WORD (&parms[0].info[0]) != 0)
 2862      {
 2863        a->ncci_state[ncci] = OUTG_REJ_PENDING;
 2864        channel_request_xon (plci, a->ncci_ch[ncci]);
 2865        channel_xmit_xon (plci);
 2866        cleanup_ncci_data (plci, ncci);
 2867        nl_req_ncci(plci,N_DISC,(byte)ncci);
 2868        return 1;
 2869      }
 2870      a->ncci_state[ncci] = INC_ACT_PENDING;
 2871
 2872      req = N_CONNECT_ACK;
 2873      ncpi = &parms[1];
 2874      if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
 2875      {
 2876
 2877        if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
 2878          & (1L << PRIVATE_FAX_NONSTANDARD))
 2879 {
 2880   if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
 2881    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
 2882    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
 2883   {
 2884            len = ((byte)(((T30_INFO *) 0)->station_id + 20));
 2885            if (plci->fax_connect_info_length < len)
 2886            {
 2887              ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
 2888              ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
 2889            }
 2890            if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
 2891            {
 2892              dbug(1,dprintf("non-standard facilities info missing or wrong format"));
 2893            }
 2894            else
 2895            {
 2896              if (plci->fax_connect_info_length <= len)
 2897                plci->fax_connect_info_buffer[len] = 0;
 2898              len += 1 + plci->fax_connect_info_buffer[len];
 2899              if (plci->fax_connect_info_length <= len)
 2900                plci->fax_connect_info_buffer[len] = 0;
 2901              len += 1 + plci->fax_connect_info_buffer[len];
 2902              if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
 2903                plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
 2904              plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
 2905              for (i = 0; i < fax_parms[7].length; i++)
 2906                plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
 2907            }
 2908            plci->fax_connect_info_length = len;
 2909            ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
 2910            start_internal_command (Id, plci, fax_connect_ack_command);
 2911     return false;
 2912          }
 2913        }
 2914
 2915        nl_req_ncci(plci,req,(byte)ncci);
 2916        if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
 2917         && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
 2918        {
 2919          if (plci->B3_prot == 4)
 2920            sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
 2921          else
 2922            sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
 2923          plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
 2924        }
 2925      }
 2926
 2927      else if (plci->B3_prot == B3_RTP)
 2928      {
 2929        plci->internal_req_buffer[0] = ncpi->length + 1;
 2930        plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
 2931        for (w = 0; w < ncpi->length; w++)
 2932          plci->internal_req_buffer[2+w] = ncpi->info[1+w];
 2933        start_internal_command (Id, plci, rtp_connect_b3_res_command);
 2934        return false;
 2935      }
 2936
 2937      else
 2938      {
 2939        if(ncpi->length>2) {
 2940          if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
 2941          add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
 2942        }
 2943        nl_req_ncci(plci,req,(byte)ncci);
 2944        sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
 2945        if (plci->adjust_b_restore)
 2946        {
 2947          plci->adjust_b_restore = false;
 2948          start_internal_command (Id, plci, adjust_b_restore);
 2949        }
 2950      }
 2951      return 1;
 2952    }
 2953  }
 2954  return false;
 2955}
 2956
 2957byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 2958{
 2959  word ncci;
 2960
 2961  ncci = (word)(Id>>16);
 2962  dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
 2963
 2964  if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
 2965   && (plci->State != OUTG_DIS_PENDING))
 2966  {
 2967    if(a->ncci_state[ncci]==INC_ACT_PENDING) {
 2968      a->ncci_state[ncci] = CONNECTED;
 2969      if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
 2970      channel_request_xon (plci, a->ncci_ch[ncci]);
 2971      channel_xmit_xon (plci);
 2972    }
 2973  }
 2974  return false;
 2975}
 2976
 2977byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 2978{
 2979  word Info;
 2980  word ncci;
 2981  API_PARSE * ncpi;
 2982
 2983  dbug(1,dprintf("disconnect_b3_req"));
 2984
 2985  Info = _WRONG_IDENTIFIER;
 2986  ncci = (word)(Id>>16);
 2987  if (plci && ncci)
 2988  {
 2989    Info = _WRONG_STATE;
 2990    if ((a->ncci_state[ncci] == CONNECTED)
 2991     || (a->ncci_state[ncci] == OUTG_CON_PENDING)
 2992     || (a->ncci_state[ncci] == INC_CON_PENDING)
 2993     || (a->ncci_state[ncci] == INC_ACT_PENDING))
 2994    {
 2995      a->ncci_state[ncci] = OUTG_DIS_PENDING;
 2996      channel_request_xon (plci, a->ncci_ch[ncci]);
 2997      channel_xmit_xon (plci);
 2998
 2999      if (a->ncci[ncci].data_pending
 3000       && ((plci->B3_prot == B3_TRANSPARENT)
 3001        || (plci->B3_prot == B3_T30)
 3002        || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
 3003      {
 3004        plci->send_disc = (byte)ncci;
 3005        plci->command = 0;
 3006        return false;
 3007      }
 3008      else
 3009      {
 3010        cleanup_ncci_data (plci, ncci);
 3011
 3012        if(plci->B3_prot==2 || plci->B3_prot==3)
 3013        {
 3014          ncpi = &parms[0];
 3015          if(ncpi->length>3)
 3016          {
 3017            add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
 3018          }
 3019        }
 3020        nl_req_ncci(plci,N_DISC,(byte)ncci);
 3021      }
 3022      return 1;
 3023    }
 3024  }
 3025  sendf(appl,
 3026        _DISCONNECT_B3_R|CONFIRM,
 3027        Id,
 3028        Number,
 3029        "w",Info);
 3030  return false;
 3031}
 3032
 3033byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 3034{
 3035  word ncci;
 3036  word i;
 3037
 3038  ncci = (word)(Id>>16);
 3039  dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
 3040  if(plci && ncci) {
 3041    plci->requested_options_conn = 0;
 3042    plci->fax_connect_info_length = 0;
 3043    plci->ncpi_state = 0x00;
 3044    if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
 3045      && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
 3046    {
 3047      plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
 3048    }
 3049    for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
 3050    if(i<MAX_CHANNELS_PER_PLCI) {
 3051      if(plci->channels)plci->channels--;
 3052      for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
 3053      plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
 3054
 3055      ncci_free_receive_buffers (plci, ncci);
 3056
 3057      if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
 3058        if(plci->State == SUSPENDING){
 3059          sendf(plci->appl,
 3060                _FACILITY_I,
 3061                Id & 0xffffL,
 3062                0,
 3063                "ws", (word)3, "\x03\x04\x00\x00");
 3064          sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
 3065        }
 3066        plci_remove(plci);
 3067        plci->State=IDLE;
 3068      }
 3069    }
 3070    else
 3071    {
 3072      if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
 3073       && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
 3074       && (a->ncci_state[ncci] == INC_DIS_PENDING))
 3075      {
 3076        ncci_free_receive_buffers (plci, ncci);
 3077
 3078        nl_req_ncci(plci,N_EDATA,(byte)ncci);
 3079
 3080        plci->adapter->ncci_state[ncci] = IDLE;
 3081        start_internal_command (Id, plci, fax_disconnect_command);
 3082        return 1;
 3083      }
 3084    }
 3085  }
 3086  return false;
 3087}
 3088
 3089byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 3090{
 3091  NCCI   *ncci_ptr;
 3092  DATA_B3_DESC   *data;
 3093  word Info;
 3094  word ncci;
 3095  word i;
 3096
 3097  dbug(1,dprintf("data_b3_req"));
 3098
 3099  Info = _WRONG_IDENTIFIER;
 3100  ncci = (word)(Id>>16);
 3101  dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
 3102
 3103  if (plci && ncci)
 3104  {
 3105    Info = _WRONG_STATE;
 3106    if ((a->ncci_state[ncci] == CONNECTED)
 3107     || (a->ncci_state[ncci] == INC_ACT_PENDING))
 3108    {
 3109        /* queue data */
 3110      ncci_ptr = &(a->ncci[ncci]);
 3111      i = ncci_ptr->data_out + ncci_ptr->data_pending;
 3112      if (i >= MAX_DATA_B3)
 3113        i -= MAX_DATA_B3;
 3114      data = &(ncci_ptr->DBuffer[i]);
 3115      data->Number = Number;
 3116      if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
 3117       && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
 3118      {
 3119
 3120        data->P = (byte *)(long)(*((dword *)(parms[0].info)));
 3121
 3122      }
 3123      else
 3124        data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
 3125      data->Length = GET_WORD(parms[1].info);
 3126      data->Handle = GET_WORD(parms[2].info);
 3127      data->Flags = GET_WORD(parms[3].info);
 3128      (ncci_ptr->data_pending)++;
 3129
 3130        /* check for delivery confirmation */
 3131      if (data->Flags & 0x0004)
 3132      {
 3133        i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
 3134        if (i >= MAX_DATA_ACK)
 3135          i -= MAX_DATA_ACK;
 3136        ncci_ptr->DataAck[i].Number = data->Number;
 3137        ncci_ptr->DataAck[i].Handle = data->Handle;
 3138        (ncci_ptr->data_ack_pending)++;
 3139      }
 3140
 3141      send_data(plci);
 3142      return false;
 3143    }
 3144  }
 3145  if (appl)
 3146  {
 3147    if (plci)
 3148    {
 3149      if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
 3150       && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
 3151      {
 3152
 3153        TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
 3154
 3155      }
 3156    }
 3157    sendf(appl,
 3158          _DATA_B3_R|CONFIRM,
 3159          Id,
 3160          Number,
 3161          "ww",GET_WORD(parms[2].info),Info);
 3162  }
 3163  return false;
 3164}
 3165
 3166byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 3167{
 3168  word n;
 3169  word ncci;
 3170  word NCCIcode;
 3171
 3172  dbug(1,dprintf("data_b3_res"));
 3173
 3174  ncci = (word)(Id>>16);
 3175  if(plci && ncci) {
 3176    n = GET_WORD(parms[0].info);
 3177    dbug(1,dprintf("free(%d)",n));
 3178    NCCIcode = ncci | (((word) a->Id) << 8);
 3179    if(n<appl->MaxBuffer &&
 3180       appl->DataNCCI[n]==NCCIcode &&
 3181       (byte)(appl->DataFlags[n]>>8)==plci->Id) {
 3182      dbug(1,dprintf("found"));
 3183      appl->DataNCCI[n] = 0;
 3184
 3185      if (channel_can_xon (plci, a->ncci_ch[ncci])) {
 3186        channel_request_xon (plci, a->ncci_ch[ncci]);
 3187      }
 3188      channel_xmit_xon (plci);
 3189
 3190      if(appl->DataFlags[n] &4) {
 3191        nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
 3192        return 1;
 3193      }
 3194    }
 3195  }
 3196  return false;
 3197}
 3198
 3199byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 3200{
 3201  word Info;
 3202  word ncci;
 3203
 3204  dbug(1,dprintf("reset_b3_req"));
 3205
 3206  Info = _WRONG_IDENTIFIER;
 3207  ncci = (word)(Id>>16);
 3208  if(plci && ncci)
 3209  {
 3210    Info = _WRONG_STATE;
 3211    switch (plci->B3_prot)
 3212    {
 3213    case B3_ISO8208:
 3214    case B3_X25_DCE:
 3215      if(a->ncci_state[ncci]==CONNECTED)
 3216      {
 3217        nl_req_ncci(plci,N_RESET,(byte)ncci);
 3218        send_req(plci);
 3219        Info = GOOD;
 3220      }
 3221      break;
 3222    case B3_TRANSPARENT:
 3223      if(a->ncci_state[ncci]==CONNECTED)
 3224      {
 3225        start_internal_command (Id, plci, reset_b3_command);
 3226        Info = GOOD;
 3227      }
 3228      break;
 3229    }
 3230  }
 3231  /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
 3232  sendf(appl,
 3233        _RESET_B3_R|CONFIRM,
 3234        Id,
 3235        Number,
 3236        "w",Info);
 3237  return false;
 3238}
 3239
 3240byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 3241{
 3242  word ncci;
 3243
 3244  dbug(1,dprintf("reset_b3_res"));
 3245
 3246  ncci = (word)(Id>>16);
 3247  if(plci && ncci) {
 3248    switch (plci->B3_prot)
 3249    {
 3250    case B3_ISO8208:
 3251    case B3_X25_DCE:
 3252      if(a->ncci_state[ncci]==INC_RES_PENDING)
 3253      {
 3254        a->ncci_state[ncci] = CONNECTED;
 3255        nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
 3256        return true;
 3257      }
 3258    break;
 3259    }
 3260  }
 3261  return false;
 3262}
 3263
 3264byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 3265{
 3266  word ncci;
 3267  API_PARSE * ncpi;
 3268  byte req;
 3269
 3270  dbug(1,dprintf("connect_b3_t90_a_res"));
 3271
 3272  ncci = (word)(Id>>16);
 3273  if(plci && ncci) {
 3274    if(a->ncci_state[ncci]==INC_ACT_PENDING) {
 3275      a->ncci_state[ncci] = CONNECTED;
 3276    }
 3277    else if(a->ncci_state[ncci]==INC_CON_PENDING) {
 3278      a->ncci_state[ncci] = CONNECTED;
 3279
 3280      req = N_CONNECT_ACK;
 3281
 3282        /* parms[0]==0 for CAPI original message definition! */
 3283      if(parms[0].info) {
 3284        ncpi = &parms[1];
 3285        if(ncpi->length>2) {
 3286          if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
 3287          add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
 3288        }
 3289      }
 3290      nl_req_ncci(plci,req,(byte)ncci);
 3291      return 1;
 3292    }
 3293  }
 3294  return false;
 3295}
 3296
 3297
 3298byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 3299{
 3300  word Info=0;
 3301  word i;
 3302  byte tel;
 3303    API_PARSE bp_parms[7];
 3304
 3305  if(!plci || !msg)
 3306  {
 3307    Info = _WRONG_IDENTIFIER;
 3308  }
 3309  else
 3310  {
 3311    dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
 3312                   msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
 3313    dbug(1,dprintf("PlciState=0x%x",plci->State));
 3314    for(i=0;i<7;i++) bp_parms[i].length = 0;
 3315
 3316    /* check if no channel is open, no B3 connected only */
 3317    if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
 3318     || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
 3319    {
 3320      Info = _WRONG_STATE;
 3321    }
 3322    /* check message format and fill bp_parms pointer */
 3323    else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
 3324    {
 3325      Info = _WRONG_MESSAGE_FORMAT;
 3326    }
 3327    else
 3328    {
 3329      if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
 3330      {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
 3331        if(Id & EXT_CONTROLLER)
 3332        {
 3333          sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
 3334          return 0;
 3335        }
 3336        plci->State=INC_CON_CONNECTED_ALERT;
 3337        plci->appl = appl;
 3338        clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
 3339        dump_c_ind_mask (plci);
 3340        for(i=0; i<max_appl; i++) /* disconnect the other appls */
 3341        {                         /* its quasi a connect        */
 3342          if(test_c_ind_mask_bit (plci, i))
 3343            sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
 3344        }
 3345      }
 3346
 3347      api_save_msg(msg, "s", &plci->saved_msg);
 3348      tel = plci->tel;
 3349      if(Id & EXT_CONTROLLER)
 3350      {
 3351        if(tel) /* external controller in use by this PLCI */
 3352        {
 3353          if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
 3354          {
 3355            dbug(1,dprintf("Ext_Ctrl in use 1"));
 3356            Info = _WRONG_STATE;
 3357          }
 3358        }
 3359        else  /* external controller NOT in use by this PLCI ? */
 3360        {
 3361          if(a->AdvSignalPLCI)
 3362          {
 3363            dbug(1,dprintf("Ext_Ctrl in use 2"));
 3364            Info = _WRONG_STATE;
 3365          }
 3366          else /* activate the codec */
 3367          {
 3368            dbug(1,dprintf("Ext_Ctrl start"));
 3369            if(AdvCodecSupport(a, plci, appl, 0) )
 3370            {
 3371              dbug(1,dprintf("Error in codec procedures"));
 3372              Info = _WRONG_STATE;
 3373            }
 3374            else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
 3375            {
 3376              plci->spoofed_msg = AWAITING_SELECT_B;
 3377              plci->internal_command = BLOCK_PLCI; /* lock other commands */
 3378              plci->command = 0;
 3379              dbug(1,dprintf("continue if codec loaded"));
 3380              return false;
 3381            }
 3382          }
 3383        }
 3384      }
 3385      else /* external controller bit is OFF */
 3386      {
 3387        if(tel) /* external controller in use, need to switch off */
 3388        {
 3389          if(a->AdvSignalAppl==appl)
 3390          {
 3391            CodecIdCheck(a, plci);
 3392            plci->tel = 0;
 3393            plci->adv_nl = 0;
 3394            dbug(1,dprintf("Ext_Ctrl disable"));
 3395          }
 3396          else
 3397          {
 3398            dbug(1,dprintf("Ext_Ctrl not requested"));
 3399          }
 3400        }
 3401      }
 3402      if (!Info)
 3403      {
 3404        if (plci->call_dir & CALL_DIR_OUT)
 3405          plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
 3406        else if (plci->call_dir & CALL_DIR_IN)
 3407          plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
 3408        start_internal_command (Id, plci, select_b_command);
 3409        return false;
 3410      }
 3411    }
 3412  }
 3413  sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
 3414  return false;
 3415}
 3416
 3417byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
 3418{
 3419  word command;
 3420  word i;
 3421  word ncci;
 3422  API_PARSE * m;
 3423    API_PARSE m_parms[5];
 3424  word codec;
 3425  byte req;
 3426  byte ch;
 3427  byte dir;
 3428  static byte chi[2] = {0x01,0x00};
 3429  static byte lli[2] = {0x01,0x00};
 3430  static byte codec_cai[2] = {0x01,0x01};
 3431  static byte null_msg = {0};
 3432  static API_PARSE null_parms = { 0, &null_msg };
 3433  PLCI   * v_plci;
 3434  word Info=0;
 3435
 3436  dbug(1,dprintf("manufacturer_req"));
 3437  for(i=0;i<5;i++) m_parms[i].length = 0;
 3438
 3439  if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
 3440    Info = _WRONG_MESSAGE_FORMAT;
 3441  }
 3442  command = GET_WORD(parms[1].info);
 3443  m = &parms[2];
 3444  if (!Info)
 3445  {
 3446    switch(command) {
 3447    case _DI_ASSIGN_PLCI:
 3448      if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
 3449        Info = _WRONG_MESSAGE_FORMAT;
 3450        break;
 3451      }
 3452      codec = GET_WORD(m_parms[0].info);
 3453      ch = m_parms[1].info[0];
 3454      dir = m_parms[2].info[0];
 3455      if((i=get_plci(a))) {
 3456        plci = &a->plci[i-1];
 3457        plci->appl = appl;
 3458        plci->command = _MANUFACTURER_R;
 3459        plci->m_command = command;
 3460        plci->number = Number;
 3461        plci->State = LOCAL_CONNECT;
 3462        Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
 3463        dbug(1,dprintf("ManCMD,plci=0x%x",Id));
 3464
 3465        if((ch==1 || ch==2) && (dir<=2)) {
 3466          chi[1] = (byte)(0x80|ch);
 3467          lli[1] = 0;
 3468          plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
 3469          switch(codec)
 3470          {
 3471          case 0:
 3472            Info = add_b1(plci,&m_parms[3],0,0);
 3473            break;
 3474          case 1:
 3475            add_p(plci,CAI,codec_cai);
 3476            break;
 3477          /* manual 'swich on' to the codec support without signalling */
 3478          /* first 'assign plci' with this function, then use */
 3479          case 2:
 3480            if(AdvCodecSupport(a, plci, appl, 0) ) {
 3481              Info = _RESOURCE_ERROR;
 3482            }
 3483            else {
 3484              Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
 3485              lli[1] = 0x10; /* local call codec stream */
 3486            }
 3487            break;
 3488          }
 3489
 3490          plci->State = LOCAL_CONNECT;
 3491          plci->manufacturer = true;
 3492          plci->command = _MANUFACTURER_R;
 3493          plci->m_command = command;
 3494          plci->number = Number;
 3495
 3496          if(!Info)
 3497          {
 3498            add_p(plci,LLI,lli);
 3499            add_p(plci,CHI,chi);
 3500            add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 3501            sig_req(plci,ASSIGN,DSIG_ID);
 3502
 3503            if(!codec)
 3504            {
 3505              Info = add_b23(plci,&m_parms[3]);
 3506              if(!Info)
 3507              {
 3508                nl_req_ncci(plci,ASSIGN,0);
 3509                send_req(plci);
 3510              }
 3511            }
 3512            if(!Info)
 3513            {
 3514              dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
 3515              if (plci->spoofed_msg==SPOOFING_REQUIRED)
 3516              {
 3517                api_save_msg (m_parms, "wbbs", &plci->saved_msg);
 3518                plci->spoofed_msg = AWAITING_MANUF_CON;
 3519                plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
 3520                plci->command = 0;
 3521                send_req(plci);
 3522                return false;
 3523              }
 3524              if(dir==1) {
 3525                sig_req(plci,CALL_REQ,0);
 3526              }
 3527              else if(!dir){
 3528                sig_req(plci,LISTEN_REQ,0);
 3529              }
 3530              send_req(plci);
 3531            }
 3532            else
 3533            {
 3534              sendf(appl,
 3535                    _MANUFACTURER_R|CONFIRM,
 3536                    Id,
 3537                    Number,
 3538                    "dww",_DI_MANU_ID,command,Info);
 3539              return 2;
 3540            }
 3541          }
 3542        }
 3543      }
 3544      else  Info = _OUT_OF_PLCI;
 3545      break;
 3546
 3547    case _DI_IDI_CTRL:
 3548      if(!plci)
 3549      {
 3550        Info = _WRONG_IDENTIFIER;
 3551        break;
 3552      }
 3553      if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
 3554        Info = _WRONG_MESSAGE_FORMAT;
 3555        break;
 3556      }
 3557      req = m_parms[0].info[0];
 3558      plci->command = _MANUFACTURER_R;
 3559      plci->m_command = command;
 3560      plci->number = Number;
 3561      if(req==CALL_REQ)
 3562      {
 3563        plci->b_channel = getChannel(&m_parms[1]);
 3564        mixer_set_bchannel_id_esc (plci, plci->b_channel);
 3565        if(plci->spoofed_msg==SPOOFING_REQUIRED)
 3566        {
 3567          plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
 3568          plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
 3569          plci->command = 0;
 3570          break;
 3571        }
 3572      }
 3573      else if(req==LAW_REQ)
 3574      {
 3575        plci->cr_enquiry = true;
 3576      }
 3577      add_ss(plci,FTY,&m_parms[1]);
 3578      sig_req(plci,req,0);
 3579      send_req(plci);
 3580      if(req==HANGUP)
 3581      {      
 3582        if (plci->NL.Id && !plci->nl_remove_id)
 3583        {
 3584          if (plci->channels)
 3585          {
 3586            for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
 3587            {
 3588              if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
 3589              {
 3590                a->ncci_state[ncci] = OUTG_DIS_PENDING;
 3591                cleanup_ncci_data (plci, ncci);
 3592                nl_req_ncci(plci,N_DISC,(byte)ncci);
 3593              }
 3594            }
 3595          }
 3596          mixer_remove (plci);
 3597          nl_req_ncci(plci,REMOVE,0);
 3598          send_req(plci);
 3599        }  
 3600      }
 3601      break;
 3602
 3603    case _DI_SIG_CTRL:
 3604    /* signalling control for loop activation B-channel */
 3605      if(!plci)
 3606      {
 3607        Info = _WRONG_IDENTIFIER;
 3608        break;
 3609      }
 3610      if(m->length){
 3611        plci->command = _MANUFACTURER_R;
 3612        plci->number = Number;
 3613        add_ss(plci,FTY,m);
 3614        sig_req(plci,SIG_CTRL,0);
 3615        send_req(plci);
 3616      }
 3617      else Info = _WRONG_MESSAGE_FORMAT;
 3618      break;
 3619
 3620    case _DI_RXT_CTRL:
 3621    /* activation control for receiver/transmitter B-channel */
 3622      if(!plci)
 3623      {
 3624        Info = _WRONG_IDENTIFIER;
 3625        break;
 3626      }
 3627      if(m->length){
 3628        plci->command = _MANUFACTURER_R;
 3629        plci->number = Number;
 3630        add_ss(plci,FTY,m);
 3631        sig_req(plci,DSP_CTRL,0);
 3632        send_req(plci);
 3633      }
 3634      else Info = _WRONG_MESSAGE_FORMAT;
 3635      break;
 3636
 3637    case _DI_ADV_CODEC:
 3638    case _DI_DSP_CTRL:
 3639      /* TEL_CTRL commands to support non standard adjustments: */
 3640      /* Ring on/off, Handset micro volume, external micro vol. */
 3641      /* handset+external speaker volume, receiver+transm. gain,*/
 3642      /* handsfree on (hookinfo off), set mixer command         */
 3643
 3644      if(command == _DI_ADV_CODEC)
 3645      {
 3646        if(!a->AdvCodecPLCI) {
 3647          Info = _WRONG_STATE;
 3648          break;
 3649        }
 3650        v_plci = a->AdvCodecPLCI;
 3651      }
 3652      else
 3653      {
 3654        if (plci
 3655         && (m->length >= 3)
 3656         && (m->info[1] == 0x1c)
 3657         && (m->info[2] >= 1))
 3658        {
 3659          if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
 3660          {
 3661            if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
 3662            {
 3663              Info = _WRONG_STATE;
 3664              break;
 3665            }
 3666            a->adv_voice_coef_length = m->info[2] - 1;
 3667            if (a->adv_voice_coef_length > m->length - 3)
 3668              a->adv_voice_coef_length = (byte)(m->length - 3);
 3669            if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
 3670              a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
 3671            for (i = 0; i < a->adv_voice_coef_length; i++)
 3672              a->adv_voice_coef_buffer[i] = m->info[4 + i];
 3673            if (plci->B1_facilities & B1_FACILITY_VOICE)
 3674              adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
 3675            break;
 3676          }
 3677          else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
 3678          {
 3679            if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
 3680            {
 3681              Info = _FACILITY_NOT_SUPPORTED;
 3682              break;
 3683            }
 3684
 3685            plci->dtmf_parameter_length = m->info[2] - 1;
 3686            if (plci->dtmf_parameter_length > m->length - 3)
 3687              plci->dtmf_parameter_length = (byte)(m->length - 3);
 3688            if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
 3689              plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
 3690            for (i = 0; i < plci->dtmf_parameter_length; i++)
 3691              plci->dtmf_parameter_buffer[i] = m->info[4+i];
 3692            if (plci->B1_facilities & B1_FACILITY_DTMFR)
 3693              dtmf_parameter_write (plci);
 3694            break;
 3695
 3696          }
 3697        }
 3698        v_plci = plci;
 3699      }
 3700
 3701      if(!v_plci)
 3702      {
 3703        Info = _WRONG_IDENTIFIER;
 3704        break;
 3705      }
 3706      if(m->length){
 3707        add_ss(v_plci,FTY,m);
 3708        sig_req(v_plci,TEL_CTRL,0);
 3709        send_req(v_plci);
 3710      }
 3711      else Info = _WRONG_MESSAGE_FORMAT;
 3712
 3713      break;
 3714
 3715    case _DI_OPTIONS_REQUEST:
 3716      if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
 3717        Info = _WRONG_MESSAGE_FORMAT;
 3718        break;
 3719      }
 3720      if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
 3721      {
 3722        Info = _FACILITY_NOT_SUPPORTED;
 3723        break;
 3724      }
 3725      a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
 3726      break;
 3727
 3728
 3729
 3730    default:
 3731      Info = _WRONG_MESSAGE_FORMAT;
 3732      break;
 3733    }
 3734  }
 3735
 3736  sendf(appl,
 3737        _MANUFACTURER_R|CONFIRM,
 3738        Id,
 3739        Number,
 3740        "dww",_DI_MANU_ID,command,Info);
 3741  return false;
 3742}
 3743
 3744
 3745byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 3746{
 3747  word indication;
 3748
 3749    API_PARSE m_parms[3];
 3750  API_PARSE *ncpi;
 3751    API_PARSE fax_parms[9];
 3752  word i;
 3753  byte len;
 3754
 3755
 3756  dbug(1,dprintf("manufacturer_res"));
 3757
 3758  if ((msg[0].length == 0)
 3759   || (msg[1].length == 0)
 3760   || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
 3761  {
 3762    return false;
 3763  }
 3764  indication = GET_WORD(msg[1].info);
 3765  switch (indication)
 3766  {
 3767
 3768  case _DI_NEGOTIATE_B3:
 3769    if(!plci)
 3770      break;
 3771    if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
 3772     || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
 3773    {
 3774      dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
 3775      break;
 3776    }
 3777    if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
 3778    {
 3779      dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
 3780      break;
 3781    }
 3782    ncpi = &m_parms[1];
 3783    len = ((byte)(((T30_INFO *) 0)->station_id + 20));
 3784    if (plci->fax_connect_info_length < len)
 3785    {
 3786      ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
 3787      ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
 3788    }
 3789    if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
 3790    {
 3791      dbug(1,dprintf("non-standard facilities info missing or wrong format"));
 3792    }
 3793    else
 3794    {
 3795      if (plci->fax_connect_info_length <= len)
 3796        plci->fax_connect_info_buffer[len] = 0;
 3797      len += 1 + plci->fax_connect_info_buffer[len];
 3798      if (plci->fax_connect_info_length <= len)
 3799        plci->fax_connect_info_buffer[len] = 0;
 3800      len += 1 + plci->fax_connect_info_buffer[len];
 3801      if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
 3802        plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
 3803      plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
 3804      for (i = 0; i < fax_parms[7].length; i++)
 3805        plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
 3806    }
 3807    plci->fax_connect_info_length = len;
 3808    plci->fax_edata_ack_length = plci->fax_connect_info_length;
 3809    start_internal_command (Id, plci, fax_edata_ack_command);
 3810    break;
 3811
 3812  }
 3813  return false;
 3814}
 3815
 3816/*------------------------------------------------------------------*/
 3817/* IDI callback function                                            */
 3818/*------------------------------------------------------------------*/
 3819
 3820void   callback(ENTITY   * e)
 3821{
 3822  DIVA_CAPI_ADAPTER   * a;
 3823  APPL   * appl;
 3824  PLCI   * plci;
 3825  CAPI_MSG   *m;
 3826  word i, j;
 3827  byte rc;
 3828  byte ch;
 3829  byte req;
 3830  byte global_req;
 3831  int no_cancel_rc;
 3832
 3833  dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
 3834                 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
 3835
 3836  a = &(adapter[(byte)e->user[0]]);
 3837  plci = &(a->plci[e->user[1]]);
 3838  no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
 3839
 3840  /*
 3841     If new protocol code and new XDI is used then CAPI should work
 3842     fully in accordance with IDI cpec an look on callback field instead
 3843     of Rc field for return codes.
 3844   */
 3845  if (((e->complete == 0xff) && no_cancel_rc) ||
 3846      (e->Rc && !no_cancel_rc)) {
 3847    rc = e->Rc;
 3848    ch = e->RcCh;
 3849    req = e->Req;
 3850    e->Rc = 0;
 3851
 3852    if (e->user[0] & 0x8000)
 3853    {
 3854      /*
 3855         If REMOVE request was sent then we have to wait until
 3856         return code with Id set to zero arrives.
 3857         All other return codes should be ignored.
 3858         */
 3859      if (req == REMOVE)
 3860      {
 3861        if (e->Id)
 3862        {
 3863          dbug(1,dprintf("cancel RC in REMOVE state"));
 3864          return;
 3865        }
 3866        channel_flow_control_remove (plci);
 3867        for (i = 0; i < 256; i++)
 3868        {
 3869          if (a->FlowControlIdTable[i] == plci->nl_remove_id)
 3870            a->FlowControlIdTable[i] = 0;
 3871        }
 3872        plci->nl_remove_id = 0;
 3873        if (plci->rx_dma_descriptor > 0) {
 3874          diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
 3875          plci->rx_dma_descriptor = 0;
 3876        }
 3877      }
 3878      if (rc == OK_FC)
 3879      {
 3880        a->FlowControlIdTable[ch] = e->Id;
 3881        a->FlowControlSkipTable[ch] = 0;
 3882
 3883        a->ch_flow_control[ch] |= N_OK_FC_PENDING;
 3884        a->ch_flow_plci[ch] = plci->Id;
 3885        plci->nl_req = 0;
 3886      }
 3887      else
 3888      {
 3889        /*
 3890          Cancel return codes self, if feature was requested
 3891          */
 3892        if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
 3893          a->FlowControlIdTable[ch] = 0;
 3894          if ((rc == OK) && a->FlowControlSkipTable[ch]) {
 3895            dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
 3896            return;
 3897          }
 3898        }
 3899
 3900        if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
 3901        {
 3902          a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
 3903          if (ch == e->ReqCh)
 3904            plci->nl_req = 0;
 3905        }
 3906        else
 3907          plci->nl_req = 0;
 3908      }
 3909      if (plci->nl_req)
 3910        control_rc (plci, 0, rc, ch, 0, true);
 3911      else
 3912      {
 3913        if (req == N_XON)
 3914        {
 3915          channel_x_on (plci, ch);
 3916          if (plci->internal_command)
 3917            control_rc (plci, req, rc, ch, 0, true);
 3918        }
 3919        else
 3920        {
 3921          if (plci->nl_global_req)
 3922          {
 3923            global_req = plci->nl_global_req;
 3924            plci->nl_global_req = 0;
 3925            if (rc != ASSIGN_OK) {
 3926              e->Id = 0;
 3927              if (plci->rx_dma_descriptor > 0) {
 3928                diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
 3929                plci->rx_dma_descriptor = 0;
 3930              }
 3931            }
 3932            channel_xmit_xon (plci);
 3933            control_rc (plci, 0, rc, ch, global_req, true);
 3934          }
 3935          else if (plci->data_sent)
 3936          {
 3937            channel_xmit_xon (plci);
 3938            plci->data_sent = false;
 3939            plci->NL.XNum = 1;
 3940            data_rc (plci, ch);
 3941            if (plci->internal_command)
 3942              control_rc (plci, req, rc, ch, 0, true);
 3943          }
 3944          else
 3945          {
 3946            channel_xmit_xon (plci);
 3947            control_rc (plci, req, rc, ch, 0, true);
 3948          }
 3949        }
 3950      }
 3951    }
 3952    else
 3953    {
 3954      /*
 3955         If REMOVE request was sent then we have to wait until
 3956         return code with Id set to zero arrives.
 3957         All other return codes should be ignored.
 3958         */
 3959      if (req == REMOVE)
 3960      {
 3961        if (e->Id)
 3962        {
 3963          dbug(1,dprintf("cancel RC in REMOVE state"));
 3964          return;
 3965        }
 3966        plci->sig_remove_id = 0;
 3967      }
 3968      plci->sig_req = 0;
 3969      if (plci->sig_global_req)
 3970      {
 3971        global_req = plci->sig_global_req;
 3972        plci->sig_global_req = 0;
 3973        if (rc != ASSIGN_OK)
 3974          e->Id = 0;
 3975        channel_xmit_xon (plci);
 3976        control_rc (plci, 0, rc, ch, global_req, false);
 3977      }
 3978      else
 3979      {
 3980        channel_xmit_xon (plci);
 3981        control_rc (plci, req, rc, ch, 0, false);
 3982      }
 3983    }
 3984    /*
 3985      Again: in accordance with IDI spec Rc and Ind can't be delivered in the
 3986      same callback. Also if new XDI and protocol code used then jump
 3987      direct to finish.
 3988      */
 3989    if (no_cancel_rc) {
 3990      channel_xmit_xon(plci);
 3991      goto capi_callback_suffix;
 3992    }
 3993  }
 3994
 3995  channel_xmit_xon(plci);
 3996
 3997  if (e->Ind) {
 3998    if (e->user[0] &0x8000) {
 3999      byte Ind = e->Ind & 0x0f;
 4000      byte Ch = e->IndCh;
 4001      if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
 4002          (a->ch_flow_plci[Ch] == plci->Id)) {
 4003        if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
 4004          dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
 4005        }
 4006        a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
 4007      }
 4008      nl_ind(plci);
 4009      if ((e->RNR != 1) &&
 4010          (a->ch_flow_plci[Ch] == plci->Id) &&
 4011          (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
 4012        a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
 4013        dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
 4014      }
 4015    } else {
 4016      sig_ind(plci);
 4017    }
 4018    e->Ind = 0;
 4019  }
 4020
 4021capi_callback_suffix:
 4022
 4023  while (!plci->req_in
 4024   && !plci->internal_command
 4025   && (plci->msg_in_write_pos != plci->msg_in_read_pos))
 4026  {
 4027    j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
 4028
 4029    i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
 4030
 4031    m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
 4032    appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
 4033    dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
 4034      m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
 4035    if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
 4036    {
 4037      plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
 4038      plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
 4039    }
 4040    else
 4041    {
 4042      plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
 4043    }
 4044    if (plci->msg_in_read_pos == plci->msg_in_write_pos)
 4045    {
 4046      plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
 4047      plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
 4048    }
 4049    else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
 4050    {
 4051      plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
 4052      plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
 4053    }
 4054    i = api_put (appl, m);
 4055    if (i != 0)
 4056    {
 4057      if (m->header.command == _DATA_B3_R)
 4058
 4059        TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
 4060
 4061      dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
 4062      break;
 4063    }
 4064
 4065    if (plci->li_notify_update)
 4066    {
 4067      plci->li_notify_update = false;
 4068      mixer_notify_update (plci, false);
 4069    }
 4070
 4071  }
 4072  send_data(plci);
 4073  send_req(plci);
 4074}
 4075
 4076
 4077void control_rc(PLCI   * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
 4078{
 4079  dword Id;
 4080  dword rId;
 4081  word Number;
 4082  word Info=0;
 4083  word i;
 4084  word ncci;
 4085  DIVA_CAPI_ADAPTER   * a;
 4086  APPL   * appl;
 4087  PLCI   * rplci;
 4088    byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
 4089    byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
 4090
 4091  if (!plci) {
 4092    dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
 4093    return;
 4094  }
 4095  dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
 4096  if(plci->req_in!=plci->req_out)
 4097  {
 4098    if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
 4099    {
 4100      dbug(1,dprintf("req_1return"));
 4101      return;
 4102    }
 4103    /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
 4104  }
 4105  plci->req_in = plci->req_in_start = plci->req_out = 0;
 4106  dbug(1,dprintf("control_rc"));
 4107
 4108  appl = plci->appl;
 4109  a = plci->adapter;
 4110  ncci = a->ch_ncci[ch];
 4111  if(appl)
 4112  {
 4113    Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
 4114    if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
 4115    Number = plci->number;
 4116    dbug(1,dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x",Id,plci->Id,plci->tel,plci->Sig.Id,plci->command,plci->internal_command));
 4117    dbug(1,dprintf("channels=0x%x",plci->channels));
 4118    if (plci_remove_check(plci))
 4119      return;
 4120    if(req==REMOVE && rc==ASSIGN_OK)
 4121    {
 4122      sig_req(plci,HANGUP,0);
 4123      sig_req(plci,REMOVE,0);
 4124      send_req(plci);
 4125    }
 4126    if(plci->command)
 4127    {
 4128      switch(plci->command)
 4129      {
 4130      case C_HOLD_REQ:
 4131        dbug(1,dprintf("HoldRC=0x%x",rc));
 4132        SSparms[1] = (byte)S_HOLD;
 4133        if(rc!=OK)
 4134        {
 4135          plci->SuppState = IDLE;
 4136          Info = 0x2001;
 4137        }
 4138        sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
 4139        break;
 4140
 4141      case C_RETRIEVE_REQ:
 4142        dbug(1,dprintf("RetrieveRC=0x%x",rc));
 4143        SSparms[1] = (byte)S_RETRIEVE;
 4144        if(rc!=OK)
 4145        {
 4146          plci->SuppState = CALL_HELD;
 4147          Info = 0x2001;
 4148        }
 4149        sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
 4150        break;
 4151
 4152      case _INFO_R:
 4153        dbug(1,dprintf("InfoRC=0x%x",rc));
 4154        if(rc!=OK) Info=_WRONG_STATE;
 4155        sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
 4156        break;
 4157
 4158      case _CONNECT_R:
 4159        dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
 4160        if (plci->State == INC_DIS_PENDING)
 4161          break;
 4162        if(plci->Sig.Id!=0xff)
 4163        {
 4164          if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
 4165           || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
 4166          {
 4167            dbug(1,dprintf("No more IDs/Call_Req failed"));
 4168            sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
 4169            plci_remove(plci);
 4170            plci->State = IDLE;
 4171            break;
 4172          }
 4173          if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
 4174          sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
 4175        }
 4176        else /* D-ch activation */
 4177        {
 4178          if (rc != ASSIGN_OK)
 4179          {
 4180            dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
 4181            sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
 4182            plci_remove(plci);
 4183            plci->State = IDLE;
 4184            break;
 4185          }
 4186          sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
 4187          sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
 4188          plci->State = INC_ACT_PENDING;
 4189        }
 4190        break;
 4191
 4192      case _CONNECT_I|RESPONSE:
 4193        if (plci->State != INC_DIS_PENDING)
 4194          plci->State = INC_CON_ACCEPT;
 4195        break;
 4196
 4197      case _DISCONNECT_R:
 4198        if (plci->State == INC_DIS_PENDING)
 4199          break;
 4200        if(plci->Sig.Id!=0xff)
 4201        {
 4202          plci->State = OUTG_DIS_PENDING;
 4203          sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
 4204        }
 4205        break;
 4206
 4207      case SUSPEND_REQ:
 4208        break;
 4209
 4210      case RESUME_REQ:
 4211        break;
 4212
 4213      case _CONNECT_B3_R:
 4214        if(rc!=OK)
 4215        {
 4216          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
 4217          break;
 4218        }
 4219        ncci = get_ncci (plci, ch, 0);
 4220        Id = (Id & 0xffff) | (((dword) ncci) << 16);
 4221        plci->channels++;
 4222        if(req==N_RESET)
 4223        {
 4224          a->ncci_state[ncci] = INC_ACT_PENDING;
 4225          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
 4226          sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
 4227        }
 4228        else
 4229        {
 4230          a->ncci_state[ncci] = OUTG_CON_PENDING;
 4231          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
 4232        }
 4233        break;
 4234
 4235      case _CONNECT_B3_I|RESPONSE:
 4236        break;
 4237
 4238      case _RESET_B3_R:
 4239/*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
 4240        break;
 4241
 4242      case _DISCONNECT_B3_R:
 4243        sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
 4244        break;
 4245
 4246      case _MANUFACTURER_R:
 4247        break;
 4248
 4249      case PERM_LIST_REQ:
 4250        if(rc!=OK)
 4251        {
 4252          Info = _WRONG_IDENTIFIER;
 4253          sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
 4254          plci_remove(plci);
 4255        }
 4256        else
 4257          sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
 4258        break;
 4259
 4260      default:
 4261        break;
 4262      }
 4263      plci->command = 0;
 4264    }
 4265    else if (plci->internal_command)
 4266    {
 4267      switch(plci->internal_command)
 4268      {
 4269      case BLOCK_PLCI:
 4270        return;
 4271
 4272      case GET_MWI_STATE:
 4273        if(rc==OK) /* command supported, wait for indication */
 4274        {
 4275          return;
 4276        }
 4277        plci_remove(plci);
 4278        break;
 4279
 4280        /* Get Supported Services */
 4281      case GETSERV_REQ_PEND:
 4282        if(rc==OK) /* command supported, wait for indication */
 4283        {
 4284          break;
 4285        }
 4286        PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
 4287        sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
 4288        plci_remove(plci);
 4289        break;
 4290
 4291      case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
 4292      case INTERR_NUMBERS_REQ_PEND:
 4293      case CF_START_PEND:                  /* Call Forwarding Start pending */
 4294      case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
 4295      case CCBS_REQUEST_REQ_PEND:
 4296      case CCBS_DEACTIVATE_REQ_PEND:
 4297      case CCBS_INTERROGATE_REQ_PEND:
 4298        switch(plci->internal_command)
 4299        {
 4300          case INTERR_DIVERSION_REQ_PEND:
 4301            SSparms[1] = S_INTERROGATE_DIVERSION;
 4302            break;
 4303          case INTERR_NUMBERS_REQ_PEND:
 4304            SSparms[1] = S_INTERROGATE_NUMBERS;
 4305            break;
 4306          case CF_START_PEND:
 4307            SSparms[1] = S_CALL_FORWARDING_START;
 4308            break;
 4309          case CF_STOP_PEND:
 4310            SSparms[1] = S_CALL_FORWARDING_STOP;
 4311            break;
 4312          case CCBS_REQUEST_REQ_PEND:
 4313            SSparms[1] = S_CCBS_REQUEST;
 4314            break;
 4315          case CCBS_DEACTIVATE_REQ_PEND:
 4316            SSparms[1] = S_CCBS_DEACTIVATE;
 4317            break;
 4318          case CCBS_INTERROGATE_REQ_PEND:
 4319            SSparms[1] = S_CCBS_INTERROGATE;
 4320            break;
 4321        }
 4322        if(global_req==ASSIGN)
 4323        {
 4324          dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
 4325          return;
 4326        }
 4327        if(!plci->appl) break;
 4328        if(rc==ISDN_GUARD_REJ)
 4329        {
 4330          Info = _CAPI_GUARD_ERROR;
 4331        }
 4332        else if(rc!=OK)
 4333        {
 4334          Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
 4335        }
 4336        sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
 4337              plci->number,"wws",Info,(word)3,SSparms);
 4338        if(Info) plci_remove(plci);
 4339        break;
 4340
 4341        /* 3pty conference pending */
 4342      case PTY_REQ_PEND:
 4343        if(!plci->relatedPTYPLCI) break;
 4344        rplci = plci->relatedPTYPLCI;
 4345        SSparms[1] = plci->ptyState;
 4346        rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
 4347        if(rplci->tel) rId|=EXT_CONTROLLER;
 4348        if(rc!=OK)
 4349        {
 4350          Info = 0x300E; /* not supported */
 4351          plci->relatedPTYPLCI = NULL;
 4352          plci->ptyState = 0;
 4353        }
 4354        sendf(rplci->appl,
 4355              _FACILITY_R|CONFIRM,
 4356              rId,
 4357              plci->number,
 4358              "wws",Info,(word)3,SSparms);
 4359        break;
 4360
 4361        /* Explicit Call Transfer pending */
 4362      case ECT_REQ_PEND:
 4363        dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
 4364        if(!plci->relatedPTYPLCI) break;
 4365        rplci = plci->relatedPTYPLCI;
 4366        SSparms[1] = S_ECT;
 4367        rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
 4368        if(rplci->tel) rId|=EXT_CONTROLLER;
 4369        if(rc!=OK)
 4370        {
 4371          Info = 0x300E; /* not supported */
 4372          plci->relatedPTYPLCI = NULL;
 4373          plci->ptyState = 0;
 4374        }
 4375        sendf(rplci->appl,
 4376              _FACILITY_R|CONFIRM,
 4377              rId,
 4378              plci->number,
 4379              "wws",Info,(word)3,SSparms);
 4380        break;
 4381
 4382      case _MANUFACTURER_R:
 4383        dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
 4384        if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
 4385        {
 4386          dbug(1,dprintf("No more IDs"));
 4387          sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
 4388          plci_remove(plci);  /* after codec init, internal codec commands pending */
 4389        }
 4390        break;
 4391
 4392      case _CONNECT_R:
 4393        dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
 4394        if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
 4395        {
 4396          dbug(1,dprintf("No more IDs"));
 4397          sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
 4398          plci_remove(plci);  /* after codec init, internal codec commands pending */
 4399        }
 4400        break;
 4401
 4402      case PERM_COD_HOOK:                     /* finished with Hook_Ind */
 4403        return;
 4404
 4405      case PERM_COD_CALL:
 4406        dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
 4407        plci->internal_command = PERM_COD_CONN_PEND;
 4408        return;
 4409
 4410      case PERM_COD_ASSIGN:
 4411        dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
 4412        if(rc!=ASSIGN_OK) break;
 4413        sig_req(plci,CALL_REQ,0);
 4414        send_req(plci);
 4415        plci->internal_command = PERM_COD_CALL;
 4416        return;
 4417
 4418        /* Null Call Reference Request pending */
 4419      case C_NCR_FAC_REQ:
 4420        dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
 4421        if(global_req==ASSIGN)
 4422        {
 4423          if(rc==ASSIGN_OK)
 4424          {
 4425            return;
 4426          }
 4427          else
 4428          {
 4429            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
 4430            appl->NullCREnable = false;
 4431            plci_remove(plci);
 4432          }
 4433        }
 4434        else if(req==NCR_FACILITY)
 4435        {
 4436          if(rc==OK)
 4437          {
 4438            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
 4439          }
 4440          else
 4441          {
 4442            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
 4443            appl->NullCREnable = false;
 4444          }
 4445          plci_remove(plci);
 4446        }
 4447        break;
 4448
 4449      case HOOK_ON_REQ:
 4450        if(plci->channels)
 4451        {
 4452          if(a->ncci_state[ncci]==CONNECTED)
 4453          {
 4454            a->ncci_state[ncci] = OUTG_DIS_PENDING;
 4455            cleanup_ncci_data (plci, ncci);
 4456            nl_req_ncci(plci,N_DISC,(byte)ncci);
 4457          }
 4458          break;
 4459        }
 4460        break;
 4461
 4462      case HOOK_OFF_REQ:
 4463        if (plci->State == INC_DIS_PENDING)
 4464          break;
 4465        sig_req(plci,CALL_REQ,0);
 4466        send_req(plci);
 4467        plci->State=OUTG_CON_PENDING;
 4468        break;
 4469
 4470
 4471      case MWI_ACTIVATE_REQ_PEND:
 4472      case MWI_DEACTIVATE_REQ_PEND:
 4473        if(global_req == ASSIGN && rc==ASSIGN_OK)
 4474        {
 4475          dbug(1,dprintf("MWI_REQ assigned"));
 4476          return;
 4477        }
 4478        else if(rc!=OK)
 4479        {                 
 4480          if(rc==WRONG_IE)
 4481          {
 4482            Info = 0x2007; /* Illegal message parameter coding */
 4483            dbug(1,dprintf("MWI_REQ invalid parameter"));
 4484          }
 4485          else
 4486          {
 4487            Info = 0x300B; /* not supported */                      
 4488            dbug(1,dprintf("MWI_REQ not supported"));
 4489          }
 4490          /* 0x3010: Request not allowed in this state */
 4491          PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
 4492                    
 4493        }
 4494        if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
 4495        {
 4496          PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
 4497        }
 4498        else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
 4499
 4500        if(plci->cr_enquiry)
 4501        {
 4502          sendf(plci->appl,
 4503                _FACILITY_R|CONFIRM,
 4504                Id&0xf,
 4505                plci->number,
 4506                "wws",Info,(word)3,SSparms);
 4507          if(rc!=OK) plci_remove(plci);
 4508        }
 4509        else
 4510        {
 4511          sendf(plci->appl,
 4512                _FACILITY_R|CONFIRM,
 4513                Id,
 4514                plci->number,
 4515                "wws",Info,(word)3,SSparms);
 4516        }
 4517        break;
 4518
 4519      case CONF_BEGIN_REQ_PEND:
 4520      case CONF_ADD_REQ_PEND:
 4521      case CONF_SPLIT_REQ_PEND:
 4522      case CONF_DROP_REQ_PEND:
 4523      case CONF_ISOLATE_REQ_PEND:
 4524      case CONF_REATTACH_REQ_PEND:
 4525        dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
 4526        if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
 4527        rplci = plci;
 4528        rId = Id;
 4529        switch(plci->internal_command)
 4530        {
 4531          case CONF_BEGIN_REQ_PEND:
 4532            SSparms[1] = S_CONF_BEGIN;
 4533            break;
 4534          case CONF_ADD_REQ_PEND:
 4535            SSparms[1] = S_CONF_ADD;
 4536            rplci = plci->relatedPTYPLCI;
 4537            rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
 4538            break;
 4539          case CONF_SPLIT_REQ_PEND:
 4540            SSparms[1] = S_CONF_SPLIT;
 4541            break;
 4542          case CONF_DROP_REQ_PEND:
 4543            SSparms[1] = S_CONF_DROP;
 4544            break;
 4545          case CONF_ISOLATE_REQ_PEND:
 4546            SSparms[1] = S_CONF_ISOLATE;
 4547            break;
 4548          case CONF_REATTACH_REQ_PEND:
 4549            SSparms[1] = S_CONF_REATTACH;
 4550            break;
 4551        }
 4552        
 4553        if(rc!=OK)
 4554        {
 4555          Info = 0x300E; /* not supported */
 4556          plci->relatedPTYPLCI = NULL;
 4557          plci->ptyState = 0;
 4558        }
 4559        sendf(rplci->appl,
 4560              _FACILITY_R|CONFIRM,
 4561              rId,
 4562              plci->number,
 4563              "wws",Info,(word)3,SSparms);
 4564        break;
 4565
 4566      case VSWITCH_REQ_PEND:
 4567        if(rc!=OK)
 4568        {
 4569          if(plci->relatedPTYPLCI)
 4570          {
 4571            plci->relatedPTYPLCI->vswitchstate=0;
 4572            plci->relatedPTYPLCI->vsprot=0;
 4573            plci->relatedPTYPLCI->vsprotdialect=0;    
 4574          }
 4575          plci->vswitchstate=0;
 4576          plci->vsprot=0;
 4577          plci->vsprotdialect=0;
 4578        }
 4579        else
 4580        {
 4581          if(plci->relatedPTYPLCI &&
 4582             plci->vswitchstate==1 &&
 4583             plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
 4584            plci->vswitchstate=3;
 4585        }
 4586        break;
 4587
 4588  /* Call Deflection Request pending (SSCT) */
 4589      case CD_REQ_PEND:
 4590        SSparms[1] = S_CALL_DEFLECTION;
 4591        if(rc!=OK)
 4592        {
 4593          Info = 0x300E; /* not supported */
 4594          plci->appl->CDEnable = 0;
 4595        }  
 4596        sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
 4597          plci->number,"wws",Info,(word)3,SSparms);
 4598        break;
 4599
 4600      case RTP_CONNECT_B3_REQ_COMMAND_2:
 4601        if (rc == OK)
 4602        {
 4603          ncci = get_ncci (plci, ch, 0);
 4604          Id = (Id & 0xffff) | (((dword) ncci) << 16);
 4605          plci->channels++;
 4606          a->ncci_state[ncci] = OUTG_CON_PENDING;
 4607        }
 4608
 4609      default:
 4610        if (plci->internal_command_queue[0])
 4611        {
 4612          (*(plci->internal_command_queue[0]))(Id, plci, rc);
 4613          if (plci->internal_command)
 4614            return;
 4615        }
 4616        break;
 4617      }
 4618      next_internal_command (Id, plci);
 4619    }
 4620  }
 4621  else /* appl==0 */
 4622  {
 4623    Id = ((word)plci->Id<<8)|plci->adapter->Id;
 4624    if(plci->tel) Id|=EXT_CONTROLLER;
 4625
 4626    switch(plci->internal_command)
 4627    {
 4628    case BLOCK_PLCI:
 4629      return;
 4630
 4631    case START_L1_SIG_ASSIGN_PEND:
 4632    case REM_L1_SIG_ASSIGN_PEND:
 4633      if(global_req == ASSIGN)
 4634      {
 4635        break;
 4636      }
 4637      else
 4638      {
 4639        dbug(1,dprintf("***L1 Req rem PLCI"));
 4640        plci->internal_command = 0;
 4641        sig_req(plci,REMOVE,0);
 4642        send_req(plci);
 4643      }
 4644      break;
 4645
 4646      /* Call Deflection Request pending, just no appl ptr assigned */
 4647    case CD_REQ_PEND:
 4648      SSparms[1] = S_CALL_DEFLECTION;
 4649      if(rc!=OK)
 4650      {
 4651        Info = 0x300E; /* not supported */
 4652      }
 4653      for(i=0; i<max_appl; i++)
 4654      {
 4655        if(application[i].CDEnable)
 4656        {
 4657          if(!application[i].Id) application[i].CDEnable = 0;
 4658          else
 4659          {
 4660            sendf(&application[i],_FACILITY_R|CONFIRM,Id,
 4661                  plci->number,"wws",Info,(word)3,SSparms);
 4662            if(Info) application[i].CDEnable = 0;
 4663          }
 4664        }
 4665      }
 4666      plci->internal_command = 0;
 4667      break;
 4668
 4669    case PERM_COD_HOOK:                   /* finished with Hook_Ind */
 4670      return;
 4671
 4672    case PERM_COD_CALL:
 4673      plci->internal_command = PERM_COD_CONN_PEND;
 4674      dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
 4675      return;
 4676
 4677    case PERM_COD_ASSIGN:
 4678      dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
 4679      plci->internal_command = 0;
 4680      if(rc!=ASSIGN_OK) break;
 4681      plci->internal_command = PERM_COD_CALL;
 4682      sig_req(plci,CALL_REQ,0);
 4683      send_req(plci);
 4684      return;
 4685
 4686    case LISTEN_SIG_ASSIGN_PEND:
 4687      if(rc == ASSIGN_OK)
 4688      {
 4689        plci->internal_command = 0;
 4690        dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
 4691        add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
 4692        sig_req(plci,INDICATE_REQ,0);
 4693        send_req(plci);
 4694      }
 4695      else
 4696      {
 4697        dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
 4698        a->listen_active--;
 4699        plci_remove(plci);
 4700        plci->State = IDLE;
 4701      }
 4702      break;
 4703
 4704    case USELAW_REQ:
 4705      if(global_req == ASSIGN)
 4706      {
 4707        if (rc==ASSIGN_OK)
 4708      {
 4709        sig_req(plci,LAW_REQ,0);
 4710        send_req(plci);
 4711        dbug(1,dprintf("Auto-Law assigned"));
 4712        }
 4713        else
 4714        {
 4715          dbug(1,dprintf("Auto-Law assign failed"));
 4716          a->automatic_law = 3;
 4717          plci->internal_command = 0;
 4718          a->automatic_lawPLCI = NULL;
 4719        }
 4720        break;
 4721      }
 4722      else if(req == LAW_REQ && rc==OK)
 4723      {
 4724        dbug(1,dprintf("Auto-Law initiated"));
 4725        a->automatic_law = 2;
 4726        plci->internal_command = 0;
 4727      }
 4728      else
 4729      {
 4730        dbug(1,dprintf("Auto-Law not supported"));
 4731        a->automatic_law = 3;
 4732        plci->internal_command = 0;
 4733        sig_req(plci,REMOVE,0);
 4734        send_req(plci);
 4735        a->automatic_lawPLCI = NULL;
 4736      }
 4737      break;
 4738    }
 4739    plci_remove_check(plci);
 4740  }
 4741}
 4742
 4743void data_rc(PLCI   * plci, byte ch)
 4744{
 4745  dword Id;
 4746  DIVA_CAPI_ADAPTER   * a;
 4747  NCCI   *ncci_ptr;
 4748  DATA_B3_DESC   *data;
 4749  word ncci;
 4750
 4751  if (plci->appl)
 4752  {
 4753    TransmitBufferFree (plci->appl, plci->data_sent_ptr);
 4754    a = plci->adapter;
 4755    ncci = a->ch_ncci[ch];
 4756    if (ncci && (a->ncci_plci[ncci] == plci->Id))
 4757    {
 4758      ncci_ptr = &(a->ncci[ncci]);
 4759      dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
 4760      if (ncci_ptr->data_pending)
 4761      {
 4762        data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
 4763        if (!(data->Flags &4) && a->ncci_state[ncci])
 4764        {
 4765          Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
 4766          if(plci->tel) Id|=EXT_CONTROLLER;
 4767          sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
 4768                "ww",data->Handle,0);
 4769        }
 4770        (ncci_ptr->data_out)++;
 4771        if (ncci_ptr->data_out == MAX_DATA_B3)
 4772          ncci_ptr->data_out = 0;
 4773        (ncci_ptr->data_pending)--;
 4774      }
 4775    }
 4776  }
 4777}
 4778
 4779void data_ack(PLCI   * plci, byte ch)
 4780{
 4781  dword Id;
 4782  DIVA_CAPI_ADAPTER   * a;
 4783  NCCI   *ncci_ptr;
 4784  word ncci;
 4785
 4786  a = plci->adapter;
 4787  ncci = a->ch_ncci[ch];
 4788  ncci_ptr = &(a->ncci[ncci]);
 4789  if (ncci_ptr->data_ack_pending)
 4790  {
 4791    if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
 4792    {
 4793      Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
 4794      if(plci->tel) Id|=EXT_CONTROLLER;
 4795      sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
 4796            "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
 4797    }
 4798    (ncci_ptr->data_ack_out)++;
 4799    if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
 4800      ncci_ptr->data_ack_out = 0;
 4801    (ncci_ptr->data_ack_pending)--;
 4802  }
 4803}
 4804
 4805void sig_ind(PLCI   * plci)
 4806{
 4807  dword x_Id;
 4808  dword Id;
 4809  dword rId;
 4810  word Number = 0;
 4811  word i;
 4812  word cip;
 4813  dword cip_mask;
 4814  byte   *ie;
 4815  DIVA_CAPI_ADAPTER   * a;
 4816    API_PARSE saved_parms[MAX_MSG_PARMS+1];
 4817#define MAXPARMSIDS 31
 4818    byte   * parms[MAXPARMSIDS];
 4819    byte   * add_i[4];
 4820    byte   * multi_fac_parms[MAX_MULTI_IE];
 4821    byte   * multi_pi_parms [MAX_MULTI_IE];
 4822    byte   * multi_ssext_parms [MAX_MULTI_IE];
 4823    byte   * multi_CiPN_parms [MAX_MULTI_IE];
 4824
 4825    byte   * multi_vswitch_parms [MAX_MULTI_IE];
 4826
 4827  byte ai_len;
 4828    byte   *esc_chi = "";
 4829    byte   *esc_law = "";
 4830    byte   *pty_cai = "";
 4831    byte   *esc_cr  = "";
 4832    byte   *esc_profile = "";
 4833
 4834    byte facility[256];
 4835  PLCI   * tplci = NULL;
 4836  byte chi[] = "\x02\x18\x01";
 4837  byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
 4838    byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
 4839  /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
 4840  /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
 4841  /* SMSG is situated at the end because its 0 (for compatibility reasons */
 4842  /* (see Info_Mask Bit 4, first IE. then the message type)           */
 4843    word parms_id[] =
 4844         {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
 4845          UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
 4846          RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
 4847          CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
 4848          /* 14 FTY repl by ESC_CHI */
 4849          /* 18 PI  repl by ESC_LAW */
 4850         /* removed OAD changed to 0xff for future use, OAD is multiIE now */
 4851     word multi_fac_id[] = {1, FTY};
 4852     word multi_pi_id[]  = {1, PI};
 4853     word multi_CiPN_id[]  = {1, OAD};
 4854     word multi_ssext_id[]  = {1, ESC_SSEXT};
 4855
 4856     word multi_vswitch_id[]  = {1, ESC_VSWITCH};
 4857
 4858  byte   * cau;
 4859  word ncci;
 4860    byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
 4861    byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
 4862    byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
 4863    byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
 4864  byte force_mt_info = false;
 4865  byte dir;
 4866  dword d;
 4867  word w;
 4868
 4869  a = plci->adapter;
 4870  Id = ((word)plci->Id<<8)|a->Id;
 4871  PUT_WORD(&SS_Ind[4],0x0000);
 4872
 4873  if (plci->sig_remove_id)
 4874  {
 4875    plci->Sig.RNR = 2; /* discard */
 4876    dbug(1,dprintf("SIG discard while remove pending"));
 4877    return;
 4878  }
 4879  if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
 4880  dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
 4881    Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
 4882  if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
 4883  {
 4884    plci->Sig.RNR = 1;
 4885    return;
 4886  }
 4887  if(plci->Sig.Ind==HANGUP && plci->channels)
 4888  {
 4889    plci->Sig.RNR = 1;
 4890    plci->hangup_flow_ctrl_timer++;
 4891    /* recover the network layer after timeout */
 4892    if(plci->hangup_flow_ctrl_timer==100)
 4893    {
 4894      dbug(1,dprintf("Exceptional disc"));
 4895      plci->Sig.RNR = 0;
 4896      plci->hangup_flow_ctrl_timer = 0;
 4897      for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
 4898      {
 4899        if (a->ncci_plci[ncci] == plci->Id)
 4900        {
 4901          cleanup_ncci_data (plci, ncci);
 4902          if(plci->channels)plci->channels--;
 4903          if (plci->appl)
 4904            sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
 4905        }
 4906      }
 4907      if (plci->appl)
 4908        sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
 4909      plci_remove(plci);
 4910      plci->State=IDLE;
 4911    }
 4912    return;
 4913  }
 4914
 4915  /* do first parse the info with no OAD in, because OAD will be converted */
 4916  /* first the multiple facility IE, then mult. progress ind.              */
 4917  /* then the parameters for the info_ind + conn_ind                       */
 4918  IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
 4919  IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
 4920  IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
 4921
 4922  IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
 4923
 4924  IndParse(plci,parms_id,parms,0);
 4925  IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
 4926  esc_chi  = parms[14];
 4927  esc_law  = parms[18];
 4928  pty_cai  = parms[24];
 4929  esc_cr   = parms[25];
 4930  esc_profile = parms[27];
 4931  if(esc_cr[0] && plci)
 4932  {
 4933    if(plci->cr_enquiry && plci->appl)
 4934    {
 4935      plci->cr_enquiry = false;
 4936      /* d = MANU_ID            */
 4937      /* w = m_command          */
 4938      /* b = total length       */
 4939      /* b = indication type    */
 4940      /* b = length of all IEs  */
 4941      /* b = IE1                */
 4942      /* S = IE1 length + cont. */
 4943      /* b = IE2                */
 4944      /* S = IE2 length + cont. */
 4945      sendf(plci->appl,
 4946        _MANUFACTURER_I,
 4947        Id,
 4948        0,
 4949        "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
 4950        2+1+1+esc_cr[0]+1+1+esc_law[0],plci->Sig.Ind,1+1+esc_cr[0]+1+1+esc_law[0],ESC,esc_cr,ESC,esc_law);
 4951    }
 4952  }
 4953  /* create the additional info structure                                  */
 4954  add_i[1] = parms[15]; /* KEY of additional info */
 4955  add_i[2] = parms[11]; /* UUI of additional info */
 4956  ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
 4957
 4958  /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
 4959  /* indication returns by the card if requested by the function           */
 4960  /* AutomaticLaw() after driver init                                      */
 4961  if (a->automatic_law<4)
 4962  {
 4963    if(esc_law[0]){
 4964      if(esc_law[2]){
 4965        dbug(0,dprintf("u-Law selected"));
 4966        a->u_law = 1;
 4967      }
 4968      else {
 4969        dbug(0,dprintf("a-Law selected"));
 4970        a->u_law = 0;
 4971      }
 4972      a->automatic_law = 4;
 4973      if(plci==a->automatic_lawPLCI) {
 4974        plci->internal_command = 0;
 4975        sig_req(plci,REMOVE,0);
 4976        send_req(plci);
 4977        a->automatic_lawPLCI = NULL;
 4978      }
 4979    }
 4980    if (esc_profile[0])
 4981    {
 4982      dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
 4983        UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
 4984        GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
 4985        GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
 4986
 4987      a->profile.Global_Options &= 0x000000ffL;
 4988      a->profile.B1_Protocols &= 0x000003ffL;
 4989      a->profile.B2_Protocols &= 0x00001fdfL;
 4990      a->profile.B3_Protocols &= 0x000000b7L;
 4991
 4992      a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
 4993        GL_BCHANNEL_OPERATION_SUPPORTED;
 4994      a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
 4995      a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
 4996      a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
 4997      a->manufacturer_features = GET_DWORD (&esc_profile[46]);
 4998      a->man_profile.private_options = 0;
 4999
 5000      if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
 5001      {
 5002        a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
 5003        a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
 5004      }
 5005
 5006
 5007      if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
 5008        a->man_profile.private_options |= 1L << PRIVATE_RTP;
 5009      a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
 5010      a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
 5011
 5012
 5013      if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
 5014        a->man_profile.private_options |= 1L << PRIVATE_T38;
 5015
 5016
 5017      if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
 5018        a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
 5019
 5020
 5021      if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
 5022        a->man_profile.private_options |= 1L << PRIVATE_V18;
 5023
 5024
 5025      if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
 5026        a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
 5027
 5028
 5029      if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
 5030        a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
 5031
 5032
 5033      if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
 5034        a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
 5035
 5036
 5037      if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
 5038        a->man_profile.private_options |= 1L << PRIVATE_VOWN;
 5039
 5040
 5041      if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
 5042        a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
 5043
 5044    }
 5045    else
 5046    {
 5047      a->profile.Global_Options &= 0x0000007fL;
 5048      a->profile.B1_Protocols &= 0x000003dfL;
 5049      a->profile.B2_Protocols &= 0x00001adfL;
 5050      a->profile.B3_Protocols &= 0x000000b7L;
 5051      a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
 5052    }
 5053    if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
 5054      MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
 5055    {
 5056      a->profile.Global_Options |= GL_DTMF_SUPPORTED;
 5057    }
 5058    a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
 5059    dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
 5060      UnMapController (a->Id), a->profile.Global_Options,
 5061      a->profile.B1_Protocols, a->profile.B2_Protocols,
 5062      a->profile.B3_Protocols, a->manufacturer_features));
 5063  }
 5064  /* codec plci for the handset/hook state support is just an internal id  */
 5065  if(plci!=a->AdvCodecPLCI)
 5066  {
 5067    force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
 5068    force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
 5069    SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
 5070    SendInfo(plci,Id, parms, force_mt_info);
 5071
 5072    VSwitchReqInd(plci,Id,multi_vswitch_parms);
 5073
 5074  }
 5075
 5076  /* switch the codec to the b-channel                                     */
 5077  if(esc_chi[0] && plci && !plci->SuppState){
 5078    plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
 5079    mixer_set_bchannel_id_esc (plci, plci->b_channel);
 5080    dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
 5081    if(plci->tel==ADV_VOICE && plci->appl) {
 5082      SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
 5083    }
 5084  }
 5085
 5086  if(plci->appl) Number = plci->appl->Number++;
 5087
 5088  switch(plci->Sig.Ind) {
 5089  /* Response to Get_Supported_Services request */
 5090  case S_SUPPORTED:
 5091    dbug(1,dprintf("S_Supported"));
 5092    if(!plci->appl) break;
 5093    if(pty_cai[0]==4)
 5094    {
 5095      PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
 5096    }
 5097    else
 5098    {
 5099      PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
 5100    }
 5101    PUT_WORD (&CF_Ind[1], 0);
 5102    PUT_WORD (&CF_Ind[4], 0);
 5103    sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
 5104    plci_remove(plci);
 5105    break;
 5106                    
 5107  /* Supplementary Service rejected */
 5108  case S_SERVICE_REJ:
 5109    dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
 5110    if(!pty_cai[0]) break;
 5111    switch (pty_cai[5])
 5112    {
 5113    case ECT_EXECUTE:
 5114    case THREE_PTY_END:
 5115    case THREE_PTY_BEGIN:
 5116      if(!plci->relatedPTYPLCI) break;
 5117      tplci = plci->relatedPTYPLCI;
 5118      rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
 5119      if(tplci->tel) rId|=EXT_CONTROLLER;
 5120      if(pty_cai[5]==ECT_EXECUTE)
 5121      {
 5122        PUT_WORD(&SS_Ind[1],S_ECT);
 5123
 5124        plci->vswitchstate=0;
 5125        plci->relatedPTYPLCI->vswitchstate=0;
 5126
 5127      }
 5128      else
 5129      {
 5130        PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
 5131      }
 5132      if(pty_cai[2]!=0xff)
 5133      {
 5134        PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
 5135      }
 5136      else
 5137      {
 5138        PUT_WORD(&SS_Ind[4],0x300E);
 5139      }
 5140      plci->relatedPTYPLCI = NULL;
 5141      plci->ptyState = 0;
 5142      sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
 5143      break;
 5144
 5145    case CALL_DEFLECTION:
 5146      if(pty_cai[2]!=0xff)
 5147      {
 5148        PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
 5149      }
 5150      else
 5151      {
 5152        PUT_WORD(&SS_Ind[4],0x300E);
 5153      }
 5154      PUT_WORD(&SS_Ind[1],pty_cai[5]);
 5155      for(i=0; i<max_appl; i++)
 5156      {
 5157        if(application[i].CDEnable)
 5158        {
 5159          if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
 5160          application[i].CDEnable = false;
 5161        }
 5162      }
 5163      break;
 5164
 5165    case DEACTIVATION_DIVERSION:
 5166    case ACTIVATION_DIVERSION:
 5167    case DIVERSION_INTERROGATE_CFU:
 5168    case DIVERSION_INTERROGATE_CFB:
 5169    case DIVERSION_INTERROGATE_CFNR:
 5170    case DIVERSION_INTERROGATE_NUM:
 5171    case CCBS_REQUEST:
 5172    case CCBS_DEACTIVATE:
 5173    case CCBS_INTERROGATE:
 5174      if(!plci->appl) break;
 5175      if(pty_cai[2]!=0xff)
 5176      {
 5177        PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
 5178      }
 5179      else
 5180      {
 5181        PUT_WORD(&Interr_Err_Ind[4],0x300E);
 5182      }
 5183      switch (pty_cai[5])
 5184      {
 5185        case DEACTIVATION_DIVERSION:
 5186          dbug(1,dprintf("Deact_Div"));
 5187          Interr_Err_Ind[0]=0x9;
 5188          Interr_Err_Ind[3]=0x6;
 5189          PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
 5190          break;
 5191        case ACTIVATION_DIVERSION:
 5192          dbug(1,dprintf("Act_Div"));
 5193          Interr_Err_Ind[0]=0x9;
 5194          Interr_Err_Ind[3]=0x6;
 5195          PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
 5196          break;
 5197        case DIVERSION_INTERROGATE_CFU:
 5198        case DIVERSION_INTERROGATE_CFB:
 5199        case DIVERSION_INTERROGATE_CFNR:
 5200          dbug(1,dprintf("Interr_Div"));
 5201          Interr_Err_Ind[0]=0xa;
 5202          Interr_Err_Ind[3]=0x7;
 5203          PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
 5204          break;
 5205        case DIVERSION_INTERROGATE_NUM:
 5206          dbug(1,dprintf("Interr_Num"));
 5207          Interr_Err_Ind[0]=0xa;
 5208          Interr_Err_Ind[3]=0x7;
 5209          PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
 5210          break;
 5211        case CCBS_REQUEST:
 5212          dbug(1,dprintf("CCBS Request"));
 5213          Interr_Err_Ind[0]=0xd;
 5214          Interr_Err_Ind[3]=0xa;
 5215          PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
 5216          break;
 5217        case CCBS_DEACTIVATE:
 5218          dbug(1,dprintf("CCBS Deactivate"));
 5219          Interr_Err_Ind[0]=0x9;
 5220          Interr_Err_Ind[3]=0x6;
 5221          PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
 5222          break;
 5223        case CCBS_INTERROGATE:
 5224          dbug(1,dprintf("CCBS Interrogate"));
 5225          Interr_Err_Ind[0]=0xb;
 5226          Interr_Err_Ind[3]=0x8;
 5227          PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
 5228          break;
 5229      }
 5230      PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
 5231      sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
 5232      plci_remove(plci);
 5233      break;
 5234    case ACTIVATION_MWI:      
 5235    case DEACTIVATION_MWI:
 5236      if(pty_cai[5]==ACTIVATION_MWI)
 5237      {
 5238        PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
 5239      }
 5240      else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
 5241      
 5242      if(pty_cai[2]!=0xff)
 5243      {
 5244        PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
 5245      }
 5246      else
 5247      {
 5248        PUT_WORD(&SS_Ind[4],0x300E);
 5249      }
 5250
 5251      if(plci->cr_enquiry)
 5252      {
 5253        sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
 5254        plci_remove(plci);
 5255      }
 5256      else
 5257      {
 5258        sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
 5259      }
 5260      break;
 5261    case CONF_ADD: /* ERROR */
 5262    case CONF_BEGIN:
 5263    case CONF_DROP:
 5264    case CONF_ISOLATE:
 5265    case CONF_REATTACH:
 5266      CONF_Ind[0]=9;
 5267      CONF_Ind[3]=6;   
 5268      switch(pty_cai[5])
 5269      {
 5270      case CONF_BEGIN:
 5271          PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
 5272          plci->ptyState = 0;
 5273          break;
 5274      case CONF_DROP:
 5275          CONF_Ind[0]=5;
 5276          CONF_Ind[3]=2;
 5277          PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
 5278          plci->ptyState = CONNECTED;
 5279          break;
 5280      case CONF_ISOLATE:
 5281          CONF_Ind[0]=5;
 5282          CONF_Ind[3]=2;
 5283          PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
 5284          plci->ptyState = CONNECTED;
 5285          break;
 5286      case CONF_REATTACH:
 5287          CONF_Ind[0]=5;
 5288          CONF_Ind[3]=2;
 5289          PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
 5290          plci->ptyState = CONNECTED;
 5291          break;
 5292      case CONF_ADD:
 5293          PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
 5294          plci->relatedPTYPLCI = NULL;
 5295          tplci=plci->relatedPTYPLCI;
 5296          if(tplci) tplci->ptyState = CONNECTED;
 5297          plci->ptyState = CONNECTED;
 5298          break;
 5299      }
 5300          
 5301      if(pty_cai[2]!=0xff)
 5302      {
 5303        PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
 5304      }
 5305      else
 5306      {
 5307        PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
 5308                                            within the required time */
 5309      }
 5310
 5311      PUT_DWORD(&CONF_Ind[6],0x0);
 5312      sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
 5313      break;
 5314    }
 5315    break;
 5316
 5317  /* Supplementary Service indicates success */
 5318  case S_SERVICE:
 5319    dbug(1,dprintf("Service_Ind"));
 5320    PUT_WORD (&CF_Ind[4], 0);
 5321    switch (pty_cai[5])
 5322    {
 5323    case THREE_PTY_END:
 5324    case THREE_PTY_BEGIN:
 5325    case ECT_EXECUTE:
 5326      if(!plci->relatedPTYPLCI) break;
 5327      tplci = plci->relatedPTYPLCI;
 5328      rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
 5329      if(tplci->tel) rId|=EXT_CONTROLLER;
 5330      if(pty_cai[5]==ECT_EXECUTE)
 5331      {
 5332        PUT_WORD(&SS_Ind[1],S_ECT);
 5333
 5334        if(plci->vswitchstate!=3)
 5335        {
 5336
 5337        plci->ptyState = IDLE;
 5338        plci->relatedPTYPLCI = NULL;
 5339        plci->ptyState = 0;
 5340
 5341        }
 5342
 5343        dbug(1,dprintf("ECT OK"));
 5344        sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
 5345
 5346
 5347
 5348      }
 5349      else
 5350      {
 5351        switch (plci->ptyState)
 5352        {
 5353        case S_3PTY_BEGIN:
 5354          plci->ptyState = CONNECTED;
 5355          dbug(1,dprintf("3PTY ON"));
 5356          break;
 5357
 5358        case S_3PTY_END:
 5359          plci->ptyState = IDLE;
 5360          plci->relatedPTYPLCI = NULL;
 5361          plci->ptyState = 0;
 5362          dbug(1,dprintf("3PTY OFF"));
 5363          break;
 5364        }
 5365        PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
 5366        sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
 5367      }
 5368      break;
 5369
 5370    case CALL_DEFLECTION:
 5371      PUT_WORD(&SS_Ind[1],pty_cai[5]);
 5372      for(i=0; i<max_appl; i++)
 5373      {
 5374        if(application[i].CDEnable)
 5375        {
 5376          if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
 5377          application[i].CDEnable = false;
 5378        }
 5379      }
 5380      break;
 5381
 5382    case DEACTIVATION_DIVERSION:
 5383    case ACTIVATION_DIVERSION:
 5384      if(!plci->appl) break;
 5385      PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
 5386      PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
 5387      sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
 5388      plci_remove(plci);
 5389      break;
 5390
 5391    case DIVERSION_INTERROGATE_CFU:
 5392    case DIVERSION_INTERROGATE_CFB:
 5393    case DIVERSION_INTERROGATE_CFNR:
 5394    case DIVERSION_INTERROGATE_NUM:
 5395    case CCBS_REQUEST:
 5396    case CCBS_DEACTIVATE:
 5397    case CCBS_INTERROGATE:
 5398      if(!plci->appl) break;
 5399      switch (pty_cai[5])
 5400      {
 5401        case DIVERSION_INTERROGATE_CFU:
 5402        case DIVERSION_INTERROGATE_CFB:
 5403        case DIVERSION_INTERROGATE_CFNR:
 5404          dbug(1,dprintf("Interr_Div"));
 5405          PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
 5406          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
 5407          break;
 5408        case DIVERSION_INTERROGATE_NUM:
 5409          dbug(1,dprintf("Interr_Num"));
 5410          PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
 5411          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
 5412          break;
 5413        case CCBS_REQUEST:
 5414          dbug(1,dprintf("CCBS Request"));
 5415          PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
 5416          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
 5417          break;
 5418        case CCBS_DEACTIVATE:
 5419          dbug(1,dprintf("CCBS Deactivate"));
 5420          PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
 5421          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
 5422          break;
 5423        case CCBS_INTERROGATE:
 5424          dbug(1,dprintf("CCBS Interrogate"));
 5425          PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
 5426          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
 5427          break;
 5428      }
 5429      PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
 5430      PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
 5431      sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
 5432      plci_remove(plci);
 5433      break;
 5434
 5435    case ACTIVATION_MWI:
 5436    case DEACTIVATION_MWI:
 5437      if(pty_cai[5]==ACTIVATION_MWI)
 5438      {
 5439        PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
 5440      }
 5441      else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
 5442      if(plci->cr_enquiry)
 5443      {
 5444        sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
 5445        plci_remove(plci);
 5446      }
 5447      else
 5448      {
 5449        sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
 5450      }
 5451      break;
 5452    case MWI_INDICATION:
 5453      if(pty_cai[0]>=0x12)
 5454      {
 5455        PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
 5456        pty_cai[2]=pty_cai[0]-2; /* len Parameter */
 5457        pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
 5458        if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
 5459        {
 5460          if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
 5461          {
 5462            sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
 5463            plci_remove(plci);
 5464            return;
 5465          }
 5466          else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
 5467          pty_cai[0]=0;
 5468        }
 5469        else
 5470        {
 5471          for(i=0; i<max_appl; i++)
 5472          {                     
 5473            if(a->Notification_Mask[i]&SMASK_MWI)
 5474            {
 5475              sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
 5476              pty_cai[0]=0;
 5477            }
 5478          }
 5479        }
 5480
 5481        if(!pty_cai[0])
 5482        { /* acknowledge */
 5483          facility[2]= 0; /* returncode */
 5484        }
 5485        else facility[2]= 0xff;
 5486      }
 5487      else
 5488      {
 5489        /* reject */
 5490        facility[2]= 0xff; /* returncode */
 5491      }
 5492      facility[0]= 2;
 5493      facility[1]= MWI_RESPONSE; /* Function */
 5494      add_p(plci,CAI,facility);
 5495      add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
 5496      sig_req(plci,S_SERVICE,0);
 5497      send_req(plci);
 5498      plci->command = 0;
 5499      next_internal_command (Id, plci);
 5500      break;
 5501    case CONF_ADD: /* OK */
 5502    case CONF_BEGIN:
 5503    case CONF_DROP:
 5504    case CONF_ISOLATE:
 5505    case CONF_REATTACH:
 5506    case CONF_PARTYDISC:
 5507      CONF_Ind[0]=9;
 5508      CONF_Ind[3]=6;
 5509      switch(pty_cai[5])
 5510      {
 5511      case CONF_BEGIN:
 5512          PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
 5513          if(pty_cai[0]==6)
 5514          {
 5515              d=pty_cai[6];
 5516              PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
 5517          }
 5518          else
 5519          {
 5520              PUT_DWORD(&CONF_Ind[6],0x0);
 5521          }
 5522          break;
 5523      case CONF_ISOLATE:
 5524          PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
 5525          CONF_Ind[0]=5;
 5526          CONF_Ind[3]=2;
 5527          break;
 5528      case CONF_REATTACH:
 5529          PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
 5530          CONF_Ind[0]=5;
 5531          CONF_Ind[3]=2;
 5532          break;
 5533      case CONF_DROP:
 5534          PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
 5535          CONF_Ind[0]=5;
 5536          CONF_Ind[3]=2;
 5537          break;
 5538      case CONF_ADD:
 5539          PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
 5540          d=pty_cai[6];
 5541          PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
 5542          tplci=plci->relatedPTYPLCI;
 5543          if(tplci) tplci->ptyState = CONNECTED;
 5544          break;
 5545      case CONF_PARTYDISC:
 5546          CONF_Ind[0]=7;
 5547          CONF_Ind[3]=4;          
 5548          PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
 5549          d=pty_cai[6];
 5550          PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
 5551          break;
 5552      }
 5553      plci->ptyState = CONNECTED;
 5554      sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
 5555      break;
 5556    case CCBS_INFO_RETAIN:
 5557    case CCBS_ERASECALLLINKAGEID:
 5558    case CCBS_STOP_ALERTING:
 5559      CONF_Ind[0]=5;
 5560      CONF_Ind[3]=2;
 5561      switch(pty_cai[5])
 5562      {
 5563      case CCBS_INFO_RETAIN:
 5564        PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
 5565        break;
 5566      case CCBS_STOP_ALERTING:
 5567        PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
 5568    break;
 5569      case CCBS_ERASECALLLINKAGEID:
 5570        PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
 5571        CONF_Ind[0]=7;
 5572        CONF_Ind[3]=4;
 5573        CONF_Ind[6]=0;
 5574        CONF_Ind[7]=0;
 5575        break;
 5576      }      
 5577      w=pty_cai[6];
 5578      PUT_WORD(&CONF_Ind[4],w); /* PartyID */
 5579
 5580      if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
 5581      {
 5582        sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
 5583      }
 5584      else
 5585      {
 5586        for(i=0; i<max_appl; i++)
 5587            if(a->Notification_Mask[i]&SMASK_CCBS)
 5588                sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
 5589      }
 5590      break;
 5591    }
 5592    break;
 5593  case CALL_HOLD_REJ:
 5594    cau = parms[7];
 5595    if(cau)
 5596    {
 5597      i = _L3_CAUSE | cau[2];
 5598      if(cau[2]==0) i = 0x3603;
 5599    }
 5600    else
 5601    {
 5602      i = 0x3603;
 5603    }
 5604    PUT_WORD(&SS_Ind[1],S_HOLD);
 5605    PUT_WORD(&SS_Ind[4],i);
 5606    if(plci->SuppState == HOLD_REQUEST)
 5607    {
 5608      plci->SuppState = IDLE;
 5609      sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
 5610    }
 5611    break;
 5612
 5613  case CALL_HOLD_ACK:
 5614    if(plci->SuppState == HOLD_REQUEST)
 5615    {
 5616      plci->SuppState = CALL_HELD;
 5617      CodecIdCheck(a, plci);
 5618      start_internal_command (Id, plci, hold_save_command);
 5619    }
 5620    break;
 5621
 5622  case CALL_RETRIEVE_REJ:
 5623    cau = parms[7];
 5624    if(cau)
 5625    {
 5626      i = _L3_CAUSE | cau[2];
 5627      if(cau[2]==0) i = 0x3603;
 5628    }
 5629    else
 5630    {
 5631      i = 0x3603;
 5632    }
 5633    PUT_WORD(&SS_Ind[1],S_RETRIEVE);
 5634    PUT_WORD(&SS_Ind[4],i);
 5635    if(plci->SuppState == RETRIEVE_REQUEST)
 5636    {
 5637      plci->SuppState = CALL_HELD;
 5638      CodecIdCheck(a, plci);
 5639      sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
 5640    }
 5641    break;
 5642
 5643  case CALL_RETRIEVE_ACK:
 5644    PUT_WORD(&SS_Ind[1],S_RETRIEVE);
 5645    if(plci->SuppState == RETRIEVE_REQUEST)
 5646    {
 5647      plci->SuppState = IDLE;
 5648      plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
 5649      plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
 5650      if(plci->tel)
 5651      {
 5652        mixer_set_bchannel_id_esc (plci, plci->b_channel);
 5653        dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
 5654        SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
 5655        if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
 5656        {
 5657          dbug(1,dprintf("Get B-ch"));
 5658          start_internal_command (Id, plci, retrieve_restore_command);
 5659        }
 5660        else
 5661          sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
 5662      }
 5663      else
 5664        start_internal_command (Id, plci, retrieve_restore_command);
 5665    }
 5666    break;
 5667
 5668  case INDICATE_IND:
 5669    if(plci->State != LISTENING) {
 5670      sig_req(plci,HANGUP,0);
 5671      send_req(plci);
 5672      break;
 5673    }
 5674    cip = find_cip(a,parms[4],parms[6]);
 5675    cip_mask = 1L<<cip;
 5676    dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
 5677    clear_c_ind_mask (plci);
 5678    if (!remove_started && !a->adapter_disabled)
 5679    {
 5680      set_c_ind_mask_bit (plci, MAX_APPL);
 5681      group_optimization(a, plci);
 5682      for(i=0; i<max_appl; i++) {
 5683        if(application[i].Id
 5684        && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
 5685        && CPN_filter_ok(parms[0],a,i)
 5686        && test_group_ind_mask_bit (plci, i) ) {
 5687          dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
 5688          set_c_ind_mask_bit (plci, i);
 5689          dump_c_ind_mask (plci);
 5690          plci->State = INC_CON_PENDING;
 5691          plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
 5692            CALL_DIR_IN | CALL_DIR_ANSWER;
 5693          if(esc_chi[0]) {
 5694            plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
 5695            mixer_set_bchannel_id_esc (plci, plci->b_channel);
 5696          }
 5697          /* if a listen on the ext controller is done, check if hook states */
 5698          /* are supported or if just a on board codec must be activated     */
 5699          if(a->codec_listen[i] && !a->AdvSignalPLCI) {
 5700            if(a->profile.Global_Options & HANDSET)
 5701              plci->tel = ADV_VOICE;
 5702            else if(a->profile.Global_Options & ON_BOARD_CODEC)
 5703              plci->tel = CODEC;
 5704            if(plci->tel) Id|=EXT_CONTROLLER;
 5705            a->codec_listen[i] = plci;
 5706          }
 5707
 5708          sendf(&application[i],_CONNECT_I,Id,0,
 5709                "wSSSSSSSbSSSSS", cip,    /* CIP                 */
 5710                             parms[0],    /* CalledPartyNumber   */
 5711                             multi_CiPN_parms[0],    /* CallingPartyNumber  */
 5712                             parms[2],    /* CalledPartySubad    */
 5713                             parms[3],    /* CallingPartySubad   */
 5714                             parms[4],    /* BearerCapability    */
 5715                             parms[5],    /* LowLC               */
 5716                             parms[6],    /* HighLC              */
 5717                             ai_len,      /* nested struct add_i */
 5718                             add_i[0],    /* B channel info    */
 5719                             add_i[1],    /* keypad facility   */
 5720                             add_i[2],    /* user user data    */
 5721                             add_i[3],    /* nested facility   */
 5722                             multi_CiPN_parms[1]    /* second CiPN(SCR)   */
 5723                             );
 5724          SendSSExtInd(&application[i],
 5725                        plci,
 5726                        Id,
 5727                        multi_ssext_parms);
 5728          SendSetupInfo(&application[i],
 5729                        plci,
 5730                        Id,
 5731                        parms,
 5732                        SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
 5733        }
 5734      }
 5735      clear_c_ind_mask_bit (plci, MAX_APPL);
 5736      dump_c_ind_mask (plci);
 5737    }
 5738    if(c_ind_mask_empty (plci)) {
 5739      sig_req(plci,HANGUP,0);
 5740      send_req(plci);
 5741      plci->State = IDLE;
 5742    }
 5743    plci->notifiedcall = 0;
 5744    a->listen_active--;
 5745    listen_check(a);
 5746    break;
 5747
 5748  case CALL_PEND_NOTIFY:
 5749    plci->notifiedcall = 1;
 5750    listen_check(a);
 5751    break;
 5752
 5753  case CALL_IND:
 5754  case CALL_CON:
 5755    if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
 5756    {
 5757      if(plci->internal_command==PERM_COD_CONN_PEND)
 5758      {
 5759        if(plci->State==ADVANCED_VOICE_NOSIG)
 5760        {
 5761          dbug(1,dprintf("***Codec OK"));
 5762          if(a->AdvSignalPLCI)
 5763          {
 5764            tplci = a->AdvSignalPLCI;
 5765            if(tplci->spoofed_msg)
 5766            {
 5767              dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
 5768              tplci->command = 0;
 5769              tplci->internal_command = 0;
 5770              x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
 5771              switch (tplci->spoofed_msg)
 5772              {
 5773              case CALL_RES:
 5774                tplci->command = _CONNECT_I|RESPONSE;
 5775                api_load_msg (&tplci->saved_msg, saved_parms);
 5776                add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
 5777                if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
 5778                {
 5779                  /* early B3 connect (CIP mask bit 9) no release after a disc */
 5780                  add_p(tplci,LLI,"\x01\x01");
 5781                }
 5782                add_s(tplci, CONN_NR, &saved_parms[2]);
 5783                add_s(tplci, LLC, &saved_parms[4]);
 5784                add_ai(tplci, &saved_parms[5]);
 5785                tplci->State = INC_CON_ACCEPT;
 5786                sig_req(tplci, CALL_RES,0);
 5787                send_req(tplci);
 5788                break;
 5789
 5790              case AWAITING_SELECT_B:
 5791                dbug(1,dprintf("Select_B continue"));
 5792                start_internal_command (x_Id, tplci, select_b_command);
 5793                break;
 5794
 5795              case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
 5796                if(!tplci->Sig.Id)
 5797                {
 5798                  dbug(1,dprintf("No SigID!"));
 5799                  sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
 5800                  plci_remove(tplci);
 5801                  break;
 5802                }
 5803                tplci->command = _MANUFACTURER_R;
 5804                api_load_msg (&tplci->saved_msg, saved_parms);
 5805                dir = saved_parms[2].info[0];
 5806                if(dir==1) {
 5807                  sig_req(tplci,CALL_REQ,0);
 5808                }
 5809                else if(!dir){
 5810                  sig_req(tplci,LISTEN_REQ,0);
 5811                }
 5812                send_req(tplci);
 5813                sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
 5814                break;
 5815
 5816              case (CALL_REQ|AWAITING_MANUF_CON):
 5817                sig_req(tplci,CALL_REQ,0);
 5818                send_req(tplci);
 5819                break;
 5820
 5821              case CALL_REQ:
 5822                if(!tplci->Sig.Id)
 5823                {
 5824                  dbug(1,dprintf("No SigID!"));
 5825                  sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
 5826                  plci_remove(tplci);
 5827                  break;
 5828                }
 5829                tplci->command = _CONNECT_R;
 5830                api_load_msg (&tplci->saved_msg, saved_parms);
 5831                add_s(tplci,CPN,&saved_parms[1]);
 5832                add_s(tplci,DSA,&saved_parms[3]);
 5833                add_ai(tplci,&saved_parms[9]);
 5834                sig_req(tplci,CALL_REQ,0);
 5835                send_req(tplci);
 5836                break;
 5837
 5838              case CALL_RETRIEVE:
 5839                tplci->command = C_RETRIEVE_REQ;
 5840                sig_req(tplci,CALL_RETRIEVE,0);
 5841                send_req(tplci);
 5842                break;
 5843              }
 5844              tplci->spoofed_msg = 0;
 5845              if (tplci->internal_command == 0)
 5846                next_internal_command (x_Id, tplci);
 5847            }
 5848          }
 5849          next_internal_command (Id, plci);
 5850          break;
 5851        }
 5852        dbug(1,dprintf("***Codec Hook Init Req"));
 5853        plci->internal_command = PERM_COD_HOOK;
 5854        add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
 5855        sig_req(plci,TEL_CTRL,0);
 5856        send_req(plci);
 5857      }
 5858    }
 5859    else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
 5860    && plci->State!=INC_ACT_PENDING)
 5861    {
 5862      mixer_set_bchannel_id_esc (plci, plci->b_channel);
 5863      if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
 5864      {
 5865        chi[2] = plci->b_channel;
 5866        SetVoiceChannel(a->AdvCodecPLCI, chi, a);
 5867      }
 5868      sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
 5869      plci->State = INC_ACT_PENDING;
 5870    }
 5871    break;
 5872
 5873  case TEL_CTRL:
 5874    Number = 0;
 5875    ie = multi_fac_parms[0]; /* inspect the facility hook indications */
 5876    if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
 5877      switch (ie[1]&0x91) {
 5878        case 0x80:   /* hook off */
 5879        case 0x81:
 5880          if(plci->internal_command==PERM_COD_HOOK)
 5881          {
 5882            dbug(1,dprintf("init:hook_off"));
 5883            plci->hook_state = ie[1];
 5884            next_internal_command (Id, plci);
 5885            break;
 5886          }
 5887          else /* ignore doubled hook indications */
 5888          {
 5889            if( ((plci->hook_state)&0xf0)==0x80)
 5890            {
 5891              dbug(1,dprintf("ignore hook"));
 5892              break;
 5893            }
 5894            plci->hook_state = ie[1]&0x91;
 5895          }
 5896          /* check for incoming call pending */
 5897          /* and signal '+'.Appl must decide */
 5898          /* with connect_res if call must   */
 5899          /* accepted or not                 */
 5900          for(i=0, tplci=NULL;i<max_appl;i++){
 5901            if(a->codec_listen[i]
 5902            && (a->codec_listen[i]->State==INC_CON_PENDING
 5903              ||a->codec_listen[i]->State==INC_CON_ALERT) ){
 5904              tplci = a->codec_listen[i];
 5905              tplci->appl = &application[i];
 5906            }
 5907          }
 5908          /* no incoming call, do outgoing call */
 5909          /* and signal '+' if outg. setup   */
 5910          if(!a->AdvSignalPLCI && !tplci){
 5911            if((i=get_plci(a))) {
 5912              a->AdvSignalPLCI = &a->plci[i-1];
 5913              tplci = a->AdvSignalPLCI;
 5914              tplci->tel  = ADV_VOICE;
 5915              PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
 5916              if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
 5917                /* early B3 connect (CIP mask bit 9) no release after a disc */
 5918                add_p(tplci,LLI,"\x01\x01");
 5919              }
 5920              add_p(tplci, CAI, voice_cai);
 5921              add_p(tplci, OAD, a->TelOAD);
 5922              add_p(tplci, OSA, a->TelOSA);
 5923              add_p(tplci,SHIFT|6,NULL);
 5924              add_p(tplci,SIN,"\x02\x01\x00");
 5925              add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 5926              sig_req(tplci,ASSIGN,DSIG_ID);
 5927              a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
 5928              a->AdvSignalPLCI->command = 0;
 5929              tplci->appl = a->AdvSignalAppl;
 5930              tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
 5931              send_req(tplci);
 5932            }
 5933
 5934          }
 5935
 5936          if(!tplci) break;
 5937          Id = ((word)tplci->Id<<8)|a->Id;
 5938          Id|=EXT_CONTROLLER;
 5939          sendf(tplci->appl,
 5940                _FACILITY_I,
 5941                Id,
 5942                0,
 5943                "ws", (word)0, "\x01+");
 5944          break;
 5945
 5946        case 0x90:   /* hook on  */
 5947        case 0x91:
 5948          if(plci->internal_command==PERM_COD_HOOK)
 5949          {
 5950            dbug(1,dprintf("init:hook_on"));
 5951            plci->hook_state = ie[1]&0x91;
 5952            next_internal_command (Id, plci);
 5953            break;
 5954          }
 5955          else /* ignore doubled hook indications */
 5956          {
 5957            if( ((plci->hook_state)&0xf0)==0x90) break;
 5958            plci->hook_state = ie[1]&0x91;
 5959          }
 5960          /* hangup the adv. voice call and signal '-' to the appl */
 5961          if(a->AdvSignalPLCI) {
 5962            Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
 5963            if(plci->tel) Id|=EXT_CONTROLLER;
 5964            sendf(a->AdvSignalAppl,
 5965                  _FACILITY_I,
 5966                  Id,
 5967                  0,
 5968                  "ws", (word)0, "\x01-");
 5969            a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
 5970            a->AdvSignalPLCI->command = 0;
 5971            sig_req(a->AdvSignalPLCI,HANGUP,0);
 5972            send_req(a->AdvSignalPLCI);
 5973          }
 5974          break;
 5975      }
 5976    }
 5977    break;
 5978
 5979  case RESUME:
 5980    clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
 5981    PUT_WORD(&resume_cau[4],GOOD);
 5982    sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
 5983    break;
 5984
 5985  case SUSPEND:
 5986    clear_c_ind_mask (plci);
 5987
 5988    if (plci->NL.Id && !plci->nl_remove_id) {
 5989      mixer_remove (plci);
 5990      nl_req_ncci(plci,REMOVE,0);
 5991    }
 5992    if (!plci->sig_remove_id) {
 5993      plci->internal_command = 0;
 5994      sig_req(plci,REMOVE,0);
 5995    }
 5996    send_req(plci);
 5997    if(!plci->channels) {
 5998      sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
 5999      sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
 6000    }
 6001    break;
 6002
 6003  case SUSPEND_REJ:
 6004    break;
 6005
 6006  case HANGUP:
 6007    plci->hangup_flow_ctrl_timer=0;
 6008    if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
 6009    cau = parms[7];
 6010    if(cau) {
 6011      i = _L3_CAUSE | cau[2];
 6012      if(cau[2]==0) i = 0;
 6013      else if(cau[2]==8) i = _L1_ERROR;
 6014      else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
 6015      else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
 6016    }
 6017    else {
 6018      i = _L3_ERROR;
 6019    }
 6020
 6021    if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
 6022    {
 6023      for(i=0; i<max_appl; i++)
 6024      {
 6025        if(test_c_ind_mask_bit (plci, i))
 6026          sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
 6027      }
 6028    }
 6029    else
 6030    {
 6031      clear_c_ind_mask (plci);
 6032    }
 6033    if(!plci->appl)
 6034    {
 6035      if (plci->State == LISTENING)
 6036      {
 6037        plci->notifiedcall=0;
 6038        a->listen_active--;
 6039      }
 6040      plci->State = INC_DIS_PENDING;
 6041      if(c_ind_mask_empty (plci))
 6042      {
 6043        plci->State = IDLE;
 6044        if (plci->NL.Id && !plci->nl_remove_id)
 6045        {
 6046          mixer_remove (plci);
 6047          nl_req_ncci(plci,REMOVE,0);
 6048        }
 6049        if (!plci->sig_remove_id)
 6050        {
 6051          plci->internal_command = 0;
 6052          sig_req(plci,REMOVE,0);
 6053        }
 6054        send_req(plci);
 6055      }
 6056    }
 6057    else
 6058    {
 6059        /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
 6060        /* result in a second HANGUP! Don't generate another        */
 6061        /* DISCONNECT                                               */
 6062      if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
 6063      {
 6064        if(plci->State==RESUMING)
 6065        {
 6066          PUT_WORD(&resume_cau[4],i);
 6067          sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
 6068        }
 6069        plci->State = INC_DIS_PENDING;
 6070        sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
 6071      }
 6072    }
 6073    break;
 6074
 6075  case SSEXT_IND:
 6076    SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
 6077    break;
 6078
 6079  case VSWITCH_REQ:
 6080    VSwitchReqInd(plci,Id,multi_vswitch_parms);
 6081    break;
 6082  case VSWITCH_IND:
 6083 if(plci->relatedPTYPLCI &&
 6084  plci->vswitchstate==3 &&
 6085  plci->relatedPTYPLCI->vswitchstate==3 &&
 6086  parms[MAXPARMSIDS-1][0])
 6087 {
 6088  add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
 6089  sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
 6090  send_req(plci->relatedPTYPLCI);
 6091 }
 6092    else VSwitchReqInd(plci,Id,multi_vswitch_parms);
 6093    break;
 6094
 6095  }
 6096}
 6097
 6098
 6099static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
 6100{
 6101  word i;
 6102  byte   * ie;
 6103  word Info_Number;
 6104  byte   * Info_Element;
 6105  word Info_Mask = 0;
 6106
 6107  dbug(1,dprintf("SetupInfo"));
 6108
 6109  for(i=0; i<MAXPARMSIDS; i++) {
 6110    ie = parms[i];
 6111    Info_Number = 0;
 6112    Info_Element = ie;
 6113    if(ie[0]) {
 6114      switch(i) {
 6115      case 0:
 6116        dbug(1,dprintf("CPN "));
 6117        Info_Number = 0x0070;
 6118        Info_Mask   = 0x80;
 6119        Info_Sent_Flag = true;
 6120        break;
 6121      case 8:  /* display      */
 6122        dbug(1,dprintf("display(%d)",i));
 6123        Info_Number = 0x0028;
 6124        Info_Mask = 0x04;
 6125        Info_Sent_Flag = true;
 6126        break;
 6127      case 16: /* Channel Id */
 6128        dbug(1,dprintf("CHI"));
 6129        Info_Number = 0x0018;
 6130        Info_Mask = 0x100;
 6131        Info_Sent_Flag = true;
 6132        mixer_set_bchannel_id (plci, Info_Element);
 6133        break;
 6134      case 19: /* Redirected Number */
 6135        dbug(1,dprintf("RDN"));
 6136        Info_Number = 0x0074;
 6137        Info_Mask = 0x400;
 6138        Info_Sent_Flag = true;
 6139        break;
 6140      case 20: /* Redirected Number extended */
 6141        dbug(1,dprintf("RDX"));
 6142        Info_Number = 0x0073;
 6143        Info_Mask = 0x400;
 6144        Info_Sent_Flag = true;
 6145        break;
 6146      case 22: /* Redirecing Number  */
 6147        dbug(1,dprintf("RIN"));
 6148        Info_Number = 0x0076;
 6149        Info_Mask = 0x400;
 6150        Info_Sent_Flag = true;
 6151        break;
 6152      default:
 6153        Info_Number = 0;
 6154        break;
 6155      }
 6156    }
 6157
 6158    if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
 6159      Info_Number = 0x8000 |5;
 6160      Info_Mask = 0x10;
 6161      Info_Element = "";
 6162    }
 6163
 6164    if(Info_Sent_Flag && Info_Number){
 6165      if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
 6166        sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
 6167      }
 6168    }
 6169  }
 6170}
 6171
 6172
 6173void SendInfo(PLCI   * plci, dword Id, byte   * * parms, byte iesent)
 6174{
 6175  word i;
 6176  word j;
 6177  word k;
 6178  byte   * ie;
 6179  word Info_Number;
 6180  byte   * Info_Element;
 6181  word Info_Mask = 0;
 6182  static byte charges[5] = {4,0,0,0,0};
 6183  static byte cause[] = {0x02,0x80,0x00};
 6184  APPL   *appl;
 6185
 6186  dbug(1,dprintf("InfoParse "));
 6187
 6188  if(
 6189        !plci->appl
 6190        && !plci->State
 6191        && plci->Sig.Ind!=NCR_FACILITY
 6192      )
 6193  {
 6194    dbug(1,dprintf("NoParse "));
 6195    return;
 6196  }
 6197  cause[2] = 0;
 6198  for(i=0; i<MAXPARMSIDS; i++) {
 6199    ie = parms[i];
 6200    Info_Number = 0;
 6201    Info_Element = ie;
 6202    if(ie[0]) {
 6203      switch(i) {
 6204      case 0:
 6205        dbug(1,dprintf("CPN "));
 6206        Info_Number = 0x0070;
 6207        Info_Mask   = 0x80;
 6208        break;
 6209      case 7: /* ESC_CAU */
 6210        dbug(1,dprintf("cau(0x%x)",ie[2]));
 6211        Info_Number = 0x0008;
 6212        Info_Mask = 0x00;
 6213        cause[2] = ie[2];
 6214        Info_Element = NULL;
 6215        break;
 6216      case 8:  /* display      */
 6217        dbug(1,dprintf("display(%d)",i));
 6218        Info_Number = 0x0028;
 6219        Info_Mask = 0x04;
 6220        break;
 6221      case 9:  /* Date display */
 6222        dbug(1,dprintf("date(%d)",i));
 6223        Info_Number = 0x0029;
 6224        Info_Mask = 0x02;
 6225        break;
 6226      case 10: /* charges */
 6227        for(j=0;j<4;j++) charges[1+j] = 0;
 6228        for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
 6229        for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
 6230        Info_Number = 0x4000;
 6231        Info_Mask = 0x40;
 6232        Info_Element = charges;
 6233        break;
 6234      case 11: /* user user info */
 6235        dbug(1,dprintf("uui"));
 6236        Info_Number = 0x007E;
 6237        Info_Mask = 0x08;
 6238        break;
 6239      case 12: /* congestion receiver ready */
 6240        dbug(1,dprintf("clRDY"));
 6241        Info_Number = 0x00B0;
 6242        Info_Mask = 0x08;
 6243        Info_Element = "";
 6244        break;
 6245      case 13: /* congestion receiver not ready */
 6246        dbug(1,dprintf("clNRDY"));
 6247        Info_Number = 0x00BF;
 6248        Info_Mask = 0x08;
 6249        Info_Element = "";
 6250        break;
 6251      case 15: /* Keypad Facility */
 6252        dbug(1,dprintf("KEY"));
 6253        Info_Number = 0x002C;
 6254        Info_Mask = 0x20;
 6255        break;
 6256      case 16: /* Channel Id */
 6257        dbug(1,dprintf("CHI"));
 6258        Info_Number = 0x0018;
 6259        Info_Mask = 0x100;
 6260        mixer_set_bchannel_id (plci, Info_Element);
 6261        break;
 6262      case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
 6263        dbug(1,dprintf("q9cau(0x%x)",ie[2]));
 6264        if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
 6265        Info_Number = 0x0008;
 6266        Info_Mask = 0x01;
 6267        if(cause[2] != ie[2]) Info_Element = cause;
 6268        break;
 6269      case 19: /* Redirected Number */
 6270        dbug(1,dprintf("RDN"));
 6271        Info_Number = 0x0074;
 6272        Info_Mask = 0x400;
 6273        break;
 6274      case 22: /* Redirecing Number  */
 6275        dbug(1,dprintf("RIN"));
 6276        Info_Number = 0x0076;
 6277        Info_Mask = 0x400;
 6278        break;
 6279      case 23: /* Notification Indicator  */
 6280        dbug(1,dprintf("NI"));
 6281        Info_Number = (word)NI;
 6282        Info_Mask = 0x210;
 6283        break;
 6284      case 26: /* Call State  */
 6285        dbug(1,dprintf("CST"));
 6286        Info_Number = (word)CST;
 6287        Info_Mask = 0x01; /* do with cause i.e. for now */
 6288        break;
 6289      case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
 6290        dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
 6291        Info_Number = 0x8000 |ie[3];
 6292        if(iesent) Info_Mask = 0xffff;
 6293        else  Info_Mask = 0x10;
 6294        Info_Element = "";
 6295        break;
 6296      default:
 6297        Info_Number  = 0;
 6298        Info_Mask    = 0;
 6299        Info_Element = "";
 6300        break;
 6301      }
 6302    }
 6303
 6304    if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
 6305    {
 6306      for(j=0; j<max_appl; j++)
 6307      {
 6308        appl = &application[j];
 6309        if(Info_Number
 6310        && appl->Id
 6311        && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
 6312        {
 6313          dbug(1,dprintf("NCR_Ind"));
 6314          iesent=true;
 6315          sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
 6316        }
 6317      }
 6318    }
 6319    else if(!plci->appl)
 6320    { /* overlap receiving broadcast */
 6321      if(Info_Number==CPN
 6322      || Info_Number==KEY
 6323      || Info_Number==NI
 6324      || Info_Number==DSP
 6325      || Info_Number==UUI )
 6326      {
 6327        for(j=0; j<max_appl; j++)
 6328        {
 6329          if(test_c_ind_mask_bit (plci, j))
 6330          {
 6331            dbug(1,dprintf("Ovl_Ind"));
 6332            iesent=true;
 6333            sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
 6334          }
 6335        }
 6336      }
 6337    }               /* all other signalling states */
 6338    else if(Info_Number
 6339    && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
 6340    {
 6341      dbug(1,dprintf("Std_Ind"));
 6342      iesent=true;
 6343      sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
 6344    }
 6345  }
 6346}
 6347
 6348
 6349byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse)
 6350{
 6351  word i;
 6352  word j;
 6353  byte   * ie;
 6354  word Info_Number;
 6355  byte   * Info_Element;
 6356  APPL   *appl;
 6357  word Info_Mask = 0;
 6358  byte iesent=0;
 6359
 6360  if(
 6361      !plci->appl
 6362      && !plci->State
 6363      && plci->Sig.Ind!=NCR_FACILITY
 6364      && !setupParse
 6365      )
 6366  {
 6367    dbug(1,dprintf("NoM-IEParse "));
 6368    return 0;
 6369  }
 6370  dbug(1,dprintf("M-IEParse "));
 6371
 6372  for(i=0; i<MAX_MULTI_IE; i++)
 6373  {
 6374    ie = parms[i];
 6375    Info_Number = 0;
 6376    Info_Element = ie;
 6377    if(ie[0])
 6378    {
 6379      dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
 6380      Info_Number = (word)ie_type;
 6381      Info_Mask = (word)info_mask;
 6382    }
 6383
 6384    if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
 6385    {
 6386      for(j=0; j<max_appl; j++)
 6387      {
 6388        appl = &application[j];
 6389        if(Info_Number
 6390        && appl->Id
 6391        && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
 6392        {
 6393          iesent = true;
 6394          dbug(1,dprintf("Mlt_NCR_Ind"));
 6395          sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
 6396        }
 6397      }
 6398    }
 6399    else if(!plci->appl && Info_Number)
 6400    {                                        /* overlap receiving broadcast */
 6401      for(j=0; j<max_appl; j++)
 6402      {
 6403        if(test_c_ind_mask_bit (plci, j))
 6404        {
 6405          iesent = true;
 6406          dbug(1,dprintf("Mlt_Ovl_Ind"));
 6407          sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
 6408        }
 6409      }
 6410    }                                        /* all other signalling states */
 6411    else if(Info_Number
 6412    && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
 6413    {
 6414      iesent = true;
 6415      dbug(1,dprintf("Mlt_Std_Ind"));
 6416      sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
 6417    }
 6418  }
 6419  return iesent;
 6420}
 6421
 6422static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
 6423{
 6424  word i;
 6425   /* Format of multi_ssext_parms[i][]:
 6426   0 byte length
 6427   1 byte SSEXTIE
 6428   2 byte SSEXT_REQ/SSEXT_IND
 6429   3 byte length
 6430   4 word SSExtCommand
 6431   6... Params
 6432   */
 6433  if(
 6434   plci
 6435   && plci->State
 6436   && plci->Sig.Ind!=NCR_FACILITY
 6437    )
 6438 for(i=0;i<MAX_MULTI_IE;i++)
 6439    {
 6440      if(parms[i][0]<6) continue;
 6441   if(parms[i][2]==SSEXT_REQ) continue;
 6442
 6443   if(appl)
 6444   {
 6445    parms[i][0]=0; /* kill it */
 6446    sendf(appl,_MANUFACTURER_I,
 6447    Id,
 6448    0,
 6449    "dwS",
 6450    _DI_MANU_ID,
 6451    _DI_SSEXT_CTRL,
 6452    &parms[i][3]);
 6453   }
 6454   else if(plci->appl)
 6455   {
 6456    parms[i][0]=0; /* kill it */
 6457    sendf(plci->appl,_MANUFACTURER_I,
 6458    Id,
 6459    0,
 6460    "dwS",
 6461    _DI_MANU_ID,
 6462    _DI_SSEXT_CTRL,
 6463    &parms[i][3]);
 6464   }
 6465    }
 6466};
 6467
 6468void nl_ind(PLCI   * plci)
 6469{
 6470  byte ch;
 6471  word ncci;
 6472  dword Id;
 6473  DIVA_CAPI_ADAPTER   * a;
 6474  word NCCIcode;
 6475  APPL   * APPLptr;
 6476  word count;
 6477  word Num;
 6478  word i, ncpi_state;
 6479  byte len, ncci_state;
 6480  word msg;
 6481  word info = 0;
 6482  word fax_feature_bits;
 6483  byte fax_send_edata_ack;
 6484  static byte v120_header_buffer[2 + 3];
 6485  static word fax_info[] = {
 6486    0,                     /* T30_SUCCESS                        */
 6487    _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
 6488    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
 6489    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
 6490    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
 6491    _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
 6492    _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
 6493    _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
 6494    _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
 6495    _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
 6496    _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
 6497    _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
 6498    _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
 6499    _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
 6500    _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
 6501    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
 6502    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
 6503    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
 6504    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
 6505    _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
 6506    _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
 6507    _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
 6508    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
 6509    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
 6510    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
 6511    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
 6512    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
 6513    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
 6514    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
 6515    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
 6516    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
 6517    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
 6518    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
 6519    0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
 6520    0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
 6521    0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
 6522    _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
 6523    _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
 6524    _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
 6525    _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
 6526    _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
 6527    _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
 6528    _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
 6529    _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
 6530    _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
 6531    _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
 6532    _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
 6533  };
 6534
 6535    byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
 6536
 6537
 6538  static word rtp_info[] = {
 6539    GOOD,                  /* RTP_SUCCESS                       */
 6540    0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
 6541  };
 6542
 6543  static dword udata_forwarding_table[0x100 / sizeof(dword)] =
 6544  {
 6545    0x0020301e, 0x00000000, 0x00000000, 0x00000000,
 6546    0x00000000, 0x00000000, 0x00000000, 0x00000000
 6547  };
 6548
 6549  ch = plci->NL.IndCh;
 6550  a = plci->adapter;
 6551  ncci = a->ch_ncci[ch];
 6552  Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
 6553  if(plci->tel) Id|=EXT_CONTROLLER;
 6554  APPLptr = plci->appl;
 6555  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",
 6556    plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
 6557
 6558  /* in the case if no connect_active_Ind was sent to the appl we wait for */
 6559
 6560  if (plci->nl_remove_id)
 6561  {
 6562    plci->NL.RNR = 2; /* discard */
 6563    dbug(1,dprintf("NL discard while remove pending"));
 6564    return;
 6565  }
 6566  if((plci->NL.Ind &0x0f)==N_CONNECT)
 6567  {
 6568    if(plci->State==INC_DIS_PENDING
 6569    || plci->State==OUTG_DIS_PENDING
 6570    || plci->State==IDLE)
 6571    {
 6572      plci->NL.RNR = 2; /* discard */
 6573      dbug(1,dprintf("discard n_connect"));
 6574      return;
 6575    }
 6576    if(plci->State < INC_ACT_PENDING)
 6577    {
 6578      plci->NL.RNR = 1; /* flow control */
 6579      channel_x_off (plci, ch, N_XON_CONNECT_IND);
 6580      return;
 6581    }
 6582  }
 6583
 6584  if(!APPLptr)                         /* no application or invalid data */
 6585  {                                    /* while reloading the DSP        */
 6586    dbug(1,dprintf("discard1"));
 6587    plci->NL.RNR = 2;
 6588    return;
 6589  }
 6590
 6591  if (((plci->NL.Ind &0x0f) == N_UDATA)
 6592     && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
 6593        || (plci->B2_prot == 7)
 6594        || (plci->B3_prot == 7)) )
 6595  {
 6596    plci->ncpi_buffer[0] = 0;
 6597
 6598    ncpi_state = plci->ncpi_state;
 6599    if (plci->NL.complete == 1)
 6600    {
 6601      byte  * data = &plci->NL.RBuffer->P[0];
 6602
 6603      if ((plci->NL.RBuffer->length >= 12)
 6604        &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
 6605          ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
 6606      {
 6607        word conn_opt, ncpi_opt = 0x00;
 6608/*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
 6609
 6610        if (*data == DSP_UDATA_INDICATION_DCD_ON)
 6611          plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
 6612        if (*data == DSP_UDATA_INDICATION_CTS_ON)
 6613          plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
 6614
 6615        data++;    /* indication code */
 6616        data += 2; /* timestamp */
 6617        if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
 6618          ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
 6619        data++;    /* connected norm */
 6620        conn_opt = GET_WORD(data);
 6621        data += 2; /* connected options */
 6622
 6623        PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
 6624
 6625        if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
 6626        {
 6627          ncpi_opt |= MDM_NCPI_ECM_V42;
 6628        }
 6629        else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
 6630        {
 6631          ncpi_opt |= MDM_NCPI_ECM_MNP;
 6632        }
 6633        else
 6634        {
 6635          ncpi_opt |= MDM_NCPI_TRANSPARENT;
 6636        }
 6637        if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
 6638        {
 6639          ncpi_opt |= MDM_NCPI_COMPRESSED;
 6640        }
 6641        PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
 6642        plci->ncpi_buffer[0] = 4;
 6643
 6644        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
 6645      }
 6646    }
 6647    if (plci->B3_prot == 7)
 6648    {
 6649      if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
 6650       && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
 6651       && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
 6652      {
 6653        a->ncci_state[ncci] = INC_ACT_PENDING;
 6654        sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
 6655        plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
 6656      }
 6657    }
 6658
 6659    if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
 6660        & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
 6661     || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
 6662     || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
 6663
 6664    {
 6665      plci->NL.RNR = 2;
 6666      return;
 6667    }
 6668  }
 6669
 6670  if(plci->NL.complete == 2)
 6671    {
 6672    if (((plci->NL.Ind &0x0f) == N_UDATA)
 6673     && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
 6674    {
 6675      switch(plci->RData[0].P[0])
 6676      {
 6677
 6678      case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
 6679        if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
 6680          sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
 6681        break;
 6682      case DTMF_UDATA_INDICATION_ANSWER_TONE:
 6683        if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
 6684          sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
 6685        break;
 6686      case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
 6687        dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
 6688        break;
 6689      case DTMF_UDATA_INDICATION_DIGITS_SENT:
 6690        dtmf_confirmation (Id, plci);
 6691        break;
 6692
 6693
 6694      case UDATA_INDICATION_MIXER_TAP_DATA:
 6695        capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
 6696 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
 6697 if (i != 0)
 6698 {
 6699   dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
 6700          dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
 6701 }
 6702        break;
 6703
 6704
 6705      case UDATA_INDICATION_MIXER_COEFS_SET:
 6706        mixer_indication_coefs_set (Id, plci);
 6707        break;
 6708      case UDATA_INDICATION_XCONNECT_FROM:
 6709        mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
 6710        break;
 6711      case UDATA_INDICATION_XCONNECT_TO:
 6712        mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
 6713        break;
 6714
 6715
 6716      case LEC_UDATA_INDICATION_DISABLE_DETECT:
 6717        ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
 6718        break;
 6719
 6720
 6721
 6722      default:
 6723        break;
 6724      }
 6725    }
 6726    else
 6727  {
 6728      if ((plci->RData[0].PLength != 0)
 6729     && ((plci->B2_prot == B2_V120_ASYNC)
 6730      || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
 6731      || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
 6732    {
 6733
 6734      sendf(plci->appl,_DATA_B3_I,Id,0,
 6735            "dwww",
 6736            plci->RData[1].P,
 6737              (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
 6738            plci->RNum,
 6739            plci->RFlags);
 6740
 6741    }
 6742    else
 6743    {
 6744
 6745      sendf(plci->appl,_DATA_B3_I,Id,0,
 6746            "dwww",
 6747            plci->RData[0].P,
 6748            plci->RData[0].PLength,
 6749            plci->RNum,
 6750            plci->RFlags);
 6751
 6752    }
 6753    }
 6754    return;
 6755  }
 6756
 6757  fax_feature_bits = 0;
 6758  if((plci->NL.Ind &0x0f)==N_CONNECT ||
 6759     (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
 6760     (plci->NL.Ind &0x0f)==N_DISC ||
 6761     (plci->NL.Ind &0x0f)==N_EDATA ||
 6762     (plci->NL.Ind &0x0f)==N_DISC_ACK)
 6763  {
 6764    info = 0;
 6765    plci->ncpi_buffer[0] = 0;
 6766    switch (plci->B3_prot) {
 6767    case  0: /*XPARENT*/
 6768    case  1: /*T.90 NL*/
 6769      break;    /* no network control protocol info - jfr */
 6770    case  2: /*ISO8202*/
 6771    case  3: /*X25 DCE*/
 6772      for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
 6773      plci->ncpi_buffer[0] = (byte)(i+3);
 6774      plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
 6775      plci->ncpi_buffer[2] = 0;
 6776      plci->ncpi_buffer[3] = 0;
 6777      break;
 6778    case  4: /*T.30 - FAX*/
 6779    case  5: /*T.30 - FAX*/
 6780      if(plci->NL.RLength>=sizeof(T30_INFO))
 6781      {
 6782        dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
 6783        len = 9;
 6784        PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
 6785        fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
 6786        i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
 6787        if (plci->B3_prot == 5)
 6788        {
 6789          if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
 6790            i |= 0x8000; /* This is not an ECM connection */
 6791          if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
 6792            i |= 0x4000; /* This is a connection with MMR compression */
 6793          if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
 6794            i |= 0x2000; /* This is a connection with MR compression */
 6795          if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
 6796            i |= 0x0004; /* More documents */
 6797          if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
 6798            i |= 0x0002; /* Fax-polling indication */
 6799        }
 6800        dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
 6801        PUT_WORD(&(plci->ncpi_buffer[3]),i);
 6802        PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
 6803        plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
 6804        plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
 6805        plci->ncpi_buffer[len] = 0;
 6806        if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
 6807        {
 6808          plci->ncpi_buffer[len] = 20;
 6809          for (i = 0; i < 20; i++)
 6810            plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
 6811        }
 6812        if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
 6813        {
 6814          if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
 6815            info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
 6816          else
 6817            info = _FAX_PROTOCOL_ERROR;
 6818        }
 6819
 6820        if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
 6821          & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
 6822        {
 6823          i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
 6824          while (i < plci->NL.RBuffer->length)
 6825            plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
 6826        }
 6827
 6828        plci->ncpi_buffer[0] = len;
 6829        fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
 6830        PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
 6831
 6832        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
 6833 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
 6834         || (((plci->NL.Ind &0x0f) == N_CONNECT)
 6835          && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
 6836         || (((plci->NL.Ind &0x0f) == N_EDATA)
 6837          && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
 6838           || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
 6839           || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
 6840 {
 6841          plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
 6842 }
 6843 if (((plci->NL.Ind &0x0f) == N_DISC)
 6844  || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
 6845  || (((plci->NL.Ind &0x0f) == N_EDATA)
 6846   && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
 6847 {
 6848          plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
 6849 }
 6850      }
 6851      break;
 6852
 6853    case B3_RTP:
 6854      if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
 6855      {
 6856        if (plci->NL.RLength != 0)
 6857        {
 6858          info = rtp_info[plci->NL.RBuffer->P[0]];
 6859          plci->ncpi_buffer[0] = plci->NL.RLength - 1;
 6860          for (i = 1; i < plci->NL.RLength; i++)
 6861            plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
 6862        }
 6863      }
 6864      break;
 6865
 6866    }
 6867    plci->NL.RNR = 2;
 6868  }
 6869  switch(plci->NL.Ind &0x0f) {
 6870  case N_EDATA:
 6871    if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
 6872    {
 6873      dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
 6874        ((T30_INFO   *)plci->NL.RBuffer->P)->code));
 6875      fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
 6876
 6877      if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
 6878       && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
 6879       && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
 6880       && (a->ncci_state[ncci] == OUTG_CON_PENDING)
 6881       && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
 6882       && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
 6883      {
 6884        ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
 6885        sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
 6886          (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
 6887        plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
 6888 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
 6889   fax_send_edata_ack = false;
 6890      }
 6891
 6892      if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
 6893      {
 6894        switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
 6895        {
 6896        case EDATA_T30_DIS:
 6897          if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
 6898           && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
 6899           && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
 6900           && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
 6901          {
 6902            a->ncci_state[ncci] = INC_ACT_PENDING;
 6903            if (plci->B3_prot == 4)
 6904              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
 6905            else
 6906              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
 6907            plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
 6908          }
 6909          break;
 6910
 6911        case EDATA_T30_TRAIN_OK:
 6912          if ((a->ncci_state[ncci] == INC_ACT_PENDING)
 6913           && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
 6914           && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
 6915          {
 6916            if (plci->B3_prot == 4)
 6917              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
 6918            else
 6919              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
 6920            plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
 6921          }
 6922          break;
 6923
 6924        case EDATA_T30_EOP_CAPI:
 6925          if (a->ncci_state[ncci] == CONNECTED)
 6926          {
 6927            sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
 6928            a->ncci_state[ncci] = INC_DIS_PENDING;
 6929            plci->ncpi_state = 0;
 6930     fax_send_edata_ack = false;
 6931          }
 6932          break;
 6933        }
 6934      }
 6935      else
 6936      {
 6937        switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
 6938        {
 6939        case EDATA_T30_TRAIN_OK:
 6940          if ((a->ncci_state[ncci] == INC_ACT_PENDING)
 6941           && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
 6942           && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
 6943          {
 6944            if (plci->B3_prot == 4)
 6945              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
 6946            else
 6947              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
 6948            plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
 6949          }
 6950          break;
 6951        }
 6952      }
 6953      if (fax_send_edata_ack)
 6954      {
 6955        ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
 6956 plci->fax_edata_ack_length = 1;
 6957        start_internal_command (Id, plci, fax_edata_ack_command);
 6958      }
 6959    }
 6960    else
 6961    {
 6962      dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
 6963    }
 6964    break;
 6965  case N_CONNECT:
 6966    if (!a->ch_ncci[ch])
 6967    {
 6968      ncci = get_ncci (plci, ch, 0);
 6969      Id = (Id & 0xffff) | (((dword) ncci) << 16);
 6970    }
 6971    dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
 6972      ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
 6973
 6974    msg = _CONNECT_B3_I;
 6975    if (a->ncci_state[ncci] == IDLE)
 6976      plci->channels++;
 6977    else if (plci->B3_prot == 1)
 6978      msg = _CONNECT_B3_T90_ACTIVE_I;
 6979
 6980    a->ncci_state[ncci] = INC_CON_PENDING;
 6981    if(plci->B3_prot == 4)
 6982      sendf(plci->appl,msg,Id,0,"s","");
 6983    else
 6984      sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
 6985    break;
 6986  case N_CONNECT_ACK:
 6987    dbug(1,dprintf("N_connect_Ack"));
 6988    if (plci->internal_command_queue[0]
 6989     && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
 6990      || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
 6991      || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
 6992    {
 6993      (*(plci->internal_command_queue[0]))(Id, plci, 0);
 6994      if (!plci->internal_command)
 6995        next_internal_command (Id, plci);
 6996      break;
 6997    }
 6998    msg = _CONNECT_B3_ACTIVE_I;
 6999    if (plci->B3_prot == 1)
 7000    {
 7001      if (a->ncci_state[ncci] != OUTG_CON_PENDING)
 7002        msg = _CONNECT_B3_T90_ACTIVE_I;
 7003      a->ncci_state[ncci] = INC_ACT_PENDING;
 7004      sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
 7005    }
 7006    else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
 7007    {
 7008      if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
 7009       && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
 7010       && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
 7011      {
 7012        a->ncci_state[ncci] = INC_ACT_PENDING;
 7013        if (plci->B3_prot == 4)
 7014          sendf(plci->appl,msg,Id,0,"s","");
 7015        else
 7016          sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
 7017        plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
 7018      }
 7019    }
 7020    else
 7021    {
 7022      a->ncci_state[ncci] = INC_ACT_PENDING;
 7023      sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
 7024    }
 7025    if (plci->adjust_b_restore)
 7026    {
 7027      plci->adjust_b_restore = false;
 7028      start_internal_command (Id, plci, adjust_b_restore);
 7029    }
 7030    break;
 7031  case N_DISC:
 7032  case N_DISC_ACK:
 7033    if (plci->internal_command_queue[0]
 7034     && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
 7035      || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
 7036      || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
 7037    {
 7038      (*(plci->internal_command_queue[0]))(Id, plci, 0);
 7039      if (!plci->internal_command)
 7040        next_internal_command (Id, plci);
 7041    }
 7042    ncci_state = a->ncci_state[ncci];
 7043    ncci_remove (plci, ncci, false);
 7044
 7045        /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
 7046        /* channel, so we cannot store the state in ncci_state! The */
 7047        /* information which channel we received a N_DISC is thus   */
 7048        /* stored in the inc_dis_ncci_table buffer.                 */
 7049    for(i=0; plci->inc_dis_ncci_table[i]; i++);
 7050    plci->inc_dis_ncci_table[i] = (byte) ncci;
 7051
 7052      /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
 7053    if (!plci->channels
 7054     && (plci->B1_resource == 16)
 7055     && (plci->State <= CONNECTED))
 7056    {
 7057      len = 9;
 7058      i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
 7059      PUT_WORD (&plci->ncpi_buffer[1], i);
 7060      PUT_WORD (&plci->ncpi_buffer[3], 0);
 7061      i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
 7062      PUT_WORD (&plci->ncpi_buffer[5], i);
 7063      PUT_WORD (&plci->ncpi_buffer[7], 0);
 7064      plci->ncpi_buffer[len] = 0;
 7065      plci->ncpi_buffer[0] = len;
 7066      if(plci->B3_prot == 4)
 7067        sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
 7068      else
 7069      {
 7070
 7071        if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
 7072          & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
 7073        {
 7074          plci->ncpi_buffer[++len] = 0;
 7075          plci->ncpi_buffer[++len] = 0;
 7076          plci->ncpi_buffer[++len] = 0;
 7077          plci->ncpi_buffer[0] = len;
 7078        }
 7079
 7080        sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
 7081      }
 7082      sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
 7083      plci->ncpi_state = 0;
 7084      sig_req(plci,HANGUP,0);
 7085      send_req(plci);
 7086      plci->State = OUTG_DIS_PENDING;
 7087      /* disc here */
 7088    }
 7089    else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
 7090     && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
 7091     && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
 7092    {
 7093      if (ncci_state == IDLE)
 7094      {
 7095        if (plci->channels)
 7096          plci->channels--;
 7097        if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
 7098          if(plci->State == SUSPENDING){
 7099            sendf(plci->appl,
 7100                  _FACILITY_I,
 7101                  Id & 0xffffL,
 7102                  0,
 7103                  "ws", (word)3, "\x03\x04\x00\x00");
 7104            sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
 7105          }
 7106          plci_remove(plci);
 7107          plci->State=IDLE;
 7108        }
 7109      }
 7110    }
 7111    else if (plci->channels)
 7112    {
 7113      sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
 7114      plci->ncpi_state = 0;
 7115      if ((ncci_state == OUTG_REJ_PENDING)
 7116       && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
 7117      {
 7118        sig_req(plci,HANGUP,0);
 7119        send_req(plci);
 7120        plci->State = OUTG_DIS_PENDING;
 7121      }
 7122    }
 7123    break;
 7124  case N_RESET:
 7125    a->ncci_state[ncci] = INC_RES_PENDING;
 7126    sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
 7127    break;
 7128  case N_RESET_ACK:
 7129    a->ncci_state[ncci] = CONNECTED;
 7130    sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
 7131    break;
 7132
 7133  case N_UDATA:
 7134    if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
 7135    {
 7136      plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
 7137      plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
 7138      plci->NL.R = plci->RData;
 7139      plci->NL.RNum = 1;
 7140      return;
 7141    }
 7142  case N_BDATA:
 7143  case N_DATA:
 7144    if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
 7145     || (a->ncci_state[ncci] == IDLE)
 7146     || (a->ncci_state[ncci] == INC_DIS_PENDING))
 7147    {
 7148      plci->NL.RNR = 2;
 7149      break;
 7150    }
 7151    if ((a->ncci_state[ncci] != CONNECTED)
 7152     && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
 7153     && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
 7154    {
 7155      dbug(1,dprintf("flow control"));
 7156      plci->NL.RNR = 1; /* flow control  */
 7157      channel_x_off (plci, ch, 0);
 7158      break;
 7159    }
 7160
 7161    NCCIcode = ncci | (((word)a->Id) << 8);
 7162
 7163                /* count all buffers within the Application pool    */
 7164                /* belonging to the same NCCI. If this is below the */
 7165                /* number of buffers available per NCCI we accept   */
 7166                /* this packet, otherwise we reject it              */
 7167    count = 0;
 7168    Num = 0xffff;
 7169    for(i=0; i<APPLptr->MaxBuffer; i++) {
 7170      if(NCCIcode==APPLptr->DataNCCI[i]) count++;
 7171      if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
 7172    }
 7173
 7174    if(count>=APPLptr->MaxNCCIData || Num==0xffff)
 7175    {
 7176      dbug(3,dprintf("Flow-Control"));
 7177      plci->NL.RNR = 1;
 7178      if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
 7179       (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
 7180      {
 7181        plci->NL.RNR = 2;
 7182        dbug(3,dprintf("DiscardData"));
 7183      } else {
 7184        channel_x_off (plci, ch, 0);
 7185      }
 7186      break;
 7187    }
 7188    else
 7189    {
 7190      APPLptr->NCCIDataFlowCtrlTimer = 0;
 7191    }
 7192
 7193    plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
 7194    if(!plci->RData[0].P) {
 7195      plci->NL.RNR = 1;
 7196      channel_x_off (plci, ch, 0);
 7197      break;
 7198    }
 7199
 7200    APPLptr->DataNCCI[Num] = NCCIcode;
 7201    APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
 7202    dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
 7203
 7204    plci->RNum = Num;
 7205    plci->RFlags = plci->NL.Ind>>4;
 7206    plci->RData[0].PLength = APPLptr->MaxDataLength;
 7207    plci->NL.R = plci->RData;
 7208    if ((plci->NL.RLength != 0)
 7209     && ((plci->B2_prot == B2_V120_ASYNC)
 7210      || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
 7211      || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
 7212    {
 7213      plci->RData[1].P = plci->RData[0].P;
 7214      plci->RData[1].PLength = plci->RData[0].PLength;
 7215      plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
 7216      if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
 7217        plci->RData[0].PLength = 1;
 7218      else
 7219        plci->RData[0].PLength = 2;
 7220      if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
 7221        plci->RFlags |= 0x0010;
 7222      if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
 7223        plci->RFlags |= 0x8000;
 7224      plci->NL.RNum = 2;
 7225    }
 7226    else
 7227    {
 7228      if((plci->NL.Ind &0x0f)==N_UDATA)
 7229        plci->RFlags |= 0x0010;
 7230
 7231      else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
 7232        plci->RFlags |= 0x0001;
 7233
 7234      plci->NL.RNum = 1;
 7235    }
 7236    break;
 7237  case N_DATA_ACK:
 7238    data_ack (plci, ch);
 7239    break;
 7240  default:
 7241    plci->NL.RNR = 2;
 7242    break;
 7243  }
 7244}
 7245
 7246/*------------------------------------------------------------------*/
 7247/* find a free PLCI                                                 */
 7248/*------------------------------------------------------------------*/
 7249
 7250word get_plci(DIVA_CAPI_ADAPTER   * a)
 7251{
 7252  word i,j;
 7253  PLCI   * plci;
 7254
 7255  dump_plcis (a);
 7256  for(i=0;i<a->max_plci && a->plci[i].Id;i++);
 7257  if(i==a->max_plci) {
 7258    dbug(1,dprintf("get_plci: out of PLCIs"));
 7259    return 0;
 7260  }
 7261  plci = &a->plci[i];
 7262  plci->Id = (byte)(i+1);
 7263
 7264  plci->Sig.Id = 0;
 7265  plci->NL.Id = 0;
 7266  plci->sig_req = 0;
 7267  plci->nl_req = 0;
 7268
 7269  plci->appl = NULL;
 7270  plci->relatedPTYPLCI = NULL;
 7271  plci->State = IDLE;
 7272  plci->SuppState = IDLE;
 7273  plci->channels = 0;
 7274  plci->tel = 0;
 7275  plci->B1_resource = 0;
 7276  plci->B2_prot = 0;
 7277  plci->B3_prot = 0;
 7278
 7279  plci->command = 0;
 7280  plci->m_command = 0;
 7281  init_internal_command_queue (plci);
 7282  plci->number = 0;
 7283  plci->req_in_start = 0;
 7284  plci->req_in = 0;
 7285  plci->req_out = 0;
 7286  plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
 7287  plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
 7288  plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
 7289
 7290  plci->data_sent = false;
 7291  plci->send_disc = 0;
 7292  plci->sig_global_req = 0;
 7293  plci->sig_remove_id = 0;
 7294  plci->nl_global_req = 0;
 7295  plci->nl_remove_id = 0;
 7296  plci->adv_nl = 0;
 7297  plci->manufacturer = false;
 7298  plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
 7299  plci->spoofed_msg = 0;
 7300  plci->ptyState = 0;
 7301  plci->cr_enquiry = false;
 7302  plci->hangup_flow_ctrl_timer = 0;
 7303
 7304  plci->ncci_ring_list = 0;
 7305  for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
 7306  clear_c_ind_mask (plci);
 7307  set_group_ind_mask (plci);
 7308  plci->fax_connect_info_length = 0;
 7309  plci->nsf_control_bits = 0;
 7310  plci->ncpi_state = 0x00;
 7311  plci->ncpi_buffer[0] = 0;
 7312
 7313  plci->requested_options_conn = 0;
 7314  plci->requested_options = 0;
 7315  plci->notifiedcall = 0;
 7316  plci->vswitchstate = 0;
 7317  plci->vsprot = 0;
 7318  plci->vsprotdialect = 0;
 7319  init_b1_config (plci);
 7320  dbug(1,dprintf("get_plci(%x)",plci->Id));
 7321  return i+1;
 7322}
 7323
 7324/*------------------------------------------------------------------*/
 7325/* put a parameter in the parameter buffer                          */
 7326/*------------------------------------------------------------------*/
 7327
 7328static void add_p(PLCI   * plci, byte code, byte   * p)
 7329{
 7330  word p_length;
 7331
 7332  p_length = 0;
 7333  if(p) p_length = p[0];
 7334  add_ie(plci, code, p, p_length);
 7335}
 7336
 7337/*------------------------------------------------------------------*/
 7338/* put a structure in the parameter buffer                          */
 7339/*------------------------------------------------------------------*/
 7340static void add_s(PLCI   * plci, byte code, API_PARSE * p)
 7341{
 7342  if(p) add_ie(plci, code, p->info, (word)p->length);
 7343}
 7344
 7345/*------------------------------------------------------------------*/
 7346/* put multiple structures in the parameter buffer                  */
 7347/*------------------------------------------------------------------*/
 7348static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
 7349{
 7350  byte i;
 7351
 7352  if(p){
 7353    dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
 7354    for(i=2;i<(byte)p->length;i+=p->info[i]+2){
 7355      dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
 7356      add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
 7357    }
 7358  }
 7359}
 7360
 7361/*------------------------------------------------------------------*/
 7362/* return the channel number sent by the application in a esc_chi   */
 7363/*------------------------------------------------------------------*/
 7364static byte getChannel(API_PARSE * p)
 7365{
 7366  byte i;
 7367
 7368  if(p){
 7369    for(i=2;i<(byte)p->length;i+=p->info[i]+2){
 7370      if(p->info[i]==2){
 7371        if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
 7372      }
 7373    }
 7374  }
 7375  return 0;
 7376}
 7377
 7378
 7379/*------------------------------------------------------------------*/
 7380/* put an information element in the parameter buffer               */
 7381/*------------------------------------------------------------------*/
 7382
 7383static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
 7384{
 7385  word i;
 7386
 7387  if(!(code &0x80) && !p_length) return;
 7388
 7389  if(plci->req_in==plci->req_in_start) {
 7390    plci->req_in +=2;
 7391  }
 7392  else {
 7393    plci->req_in--;
 7394  }
 7395  plci->RBuffer[plci->req_in++] = code;
 7396
 7397  if(p) {
 7398    plci->RBuffer[plci->req_in++] = (byte)p_length;
 7399    for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
 7400  }
 7401
 7402  plci->RBuffer[plci->req_in++] = 0;
 7403}
 7404
 7405/*------------------------------------------------------------------*/
 7406/* put a unstructured data into the buffer                          */
 7407/*------------------------------------------------------------------*/
 7408
 7409void add_d(PLCI   * plci, word length, byte   * p)
 7410{
 7411  word i;
 7412
 7413  if(plci->req_in==plci->req_in_start) {
 7414    plci->req_in +=2;
 7415  }
 7416  else {
 7417    plci->req_in--;
 7418  }
 7419  for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
 7420}
 7421
 7422/*------------------------------------------------------------------*/
 7423/* put parameters from the Additional Info parameter in the         */
 7424/* parameter buffer                                                 */
 7425/*------------------------------------------------------------------*/
 7426
 7427void add_ai(PLCI   * plci, API_PARSE * ai)
 7428{
 7429  word i;
 7430    API_PARSE ai_parms[5];
 7431
 7432  for(i=0;i<5;i++) ai_parms[i].length = 0;
 7433
 7434  if(!ai->length)
 7435    return;
 7436  if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
 7437    return;
 7438
 7439  add_s (plci,KEY,&ai_parms[1]);
 7440  add_s (plci,UUI,&ai_parms[2]);
 7441  add_ss(plci,FTY,&ai_parms[3]);
 7442}
 7443
 7444/*------------------------------------------------------------------*/
 7445/* put parameter for b1 protocol in the parameter buffer            */
 7446/*------------------------------------------------------------------*/
 7447
 7448word add_b1(PLCI   * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
 7449{
 7450    API_PARSE bp_parms[8];
 7451    API_PARSE mdm_cfg[9];
 7452    API_PARSE global_config[2];
 7453    byte cai[256];
 7454  byte resource[] = {5,9,13,12,16,39,9,17,17,18};
 7455  byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
 7456  word i;
 7457
 7458    API_PARSE mdm_cfg_v18[4];
 7459  word j, n, w;
 7460  dword d;
 7461
 7462
 7463  for(i=0;i<8;i++) bp_parms[i]