Showing error 1803

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: 617
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].length = 0;
 7464  for(i=0;i<2;i++) global_config[i].length = 0;
 7465
 7466  dbug(1,dprintf("add_b1"));
 7467  api_save_msg(bp, "s", &plci->B_protocol);
 7468
 7469  if(b_channel_info==2){
 7470    plci->B1_resource = 0;
 7471    adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
 7472    add_p(plci, CAI, "\x01\x00");
 7473    dbug(1,dprintf("Cai=1,0 (no resource)"));
 7474    return 0;
 7475  }
 7476
 7477  if(plci->tel == CODEC_PERMANENT) return 0;
 7478  else if(plci->tel == CODEC){
 7479    plci->B1_resource = 1;
 7480    adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
 7481    add_p(plci, CAI, "\x01\x01");
 7482    dbug(1,dprintf("Cai=1,1 (Codec)"));
 7483    return 0;
 7484  }
 7485  else if(plci->tel == ADV_VOICE){
 7486    plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
 7487    adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
 7488    voice_cai[1] = plci->B1_resource;
 7489    PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
 7490    add_p(plci, CAI, voice_cai);
 7491    dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
 7492    return 0;
 7493  }
 7494  plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
 7495  if (plci->call_dir & CALL_DIR_OUT)
 7496    plci->call_dir |= CALL_DIR_ORIGINATE;
 7497  else if (plci->call_dir & CALL_DIR_IN)
 7498    plci->call_dir |= CALL_DIR_ANSWER;
 7499
 7500  if(!bp->length){
 7501    plci->B1_resource = 0x5;
 7502    adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
 7503    add_p(plci, CAI, "\x01\x05");
 7504    return 0;
 7505  }
 7506
 7507  dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
 7508  if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
 7509  if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
 7510  {
 7511    bp_parms[6].length = 0;
 7512    if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
 7513    {
 7514      dbug(1,dprintf("b-form.!"));
 7515      return _WRONG_MESSAGE_FORMAT;
 7516    }
 7517  }
 7518  else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
 7519  {
 7520    dbug(1,dprintf("b-form.!"));
 7521    return _WRONG_MESSAGE_FORMAT;
 7522  }
 7523
 7524  if(bp_parms[6].length)
 7525  {
 7526    if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
 7527    {
 7528      return _WRONG_MESSAGE_FORMAT;
 7529    }
 7530    switch(GET_WORD(global_config[0].info))
 7531    {
 7532    case 1:
 7533      plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
 7534      break;
 7535    case 2:
 7536      plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
 7537      break;
 7538    }
 7539  }
 7540  dbug(1,dprintf("call_dir=%04x", plci->call_dir));
 7541
 7542
 7543  if ((GET_WORD(bp_parms[0].info) == B1_RTP)
 7544   && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
 7545  {
 7546    plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
 7547    adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
 7548    cai[1] = plci->B1_resource;
 7549    cai[2] = 0;
 7550    cai[3] = 0;
 7551    cai[4] = 0;
 7552    PUT_WORD(&cai[5],plci->appl->MaxDataLength);
 7553    for (i = 0; i < bp_parms[3].length; i++)
 7554      cai[7+i] = bp_parms[3].info[1+i];
 7555    cai[0] = 6 + bp_parms[3].length;
 7556    add_p(plci, CAI, cai);
 7557    return 0;
 7558  }
 7559
 7560
 7561  if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
 7562   && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
 7563  {
 7564    plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
 7565    adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
 7566    cai[1] = plci->B1_resource;
 7567    cai[2] = 0;
 7568    cai[3] = 0;
 7569    cai[4] = 0;
 7570    PUT_WORD(&cai[5],plci->appl->MaxDataLength);
 7571    cai[0] = 6;
 7572    add_p(plci, CAI, cai);
 7573    return 0;
 7574  }
 7575
 7576
 7577  if ((GET_WORD(bp_parms[0].info) >= 32)
 7578   || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
 7579    && ((GET_WORD(bp_parms[0].info) != 3)
 7580     || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
 7581     || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
 7582  {
 7583    return _B1_NOT_SUPPORTED;
 7584  }
 7585  plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
 7586    (word)(b1_facilities & ~B1_FACILITY_VOICE));
 7587  adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
 7588  cai[0] = 6;
 7589  cai[1] = plci->B1_resource;
 7590  for (i=2;i<sizeof(cai);i++) cai[i] = 0;
 7591
 7592  if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
 7593   || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
 7594   || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
 7595  { /* B1 - modem */
 7596    for (i=0;i<7;i++) mdm_cfg[i].length = 0;
 7597
 7598    if (bp_parms[3].length)
 7599    {
 7600      if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
 7601      {
 7602        return (_WRONG_MESSAGE_FORMAT);
 7603      }
 7604        
 7605      cai[2] = 0; /* Bit rate for adaptation */
 7606
 7607      dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
 7608
 7609      PUT_WORD (&cai[13], 0);                          /* Min Tx speed */
 7610      PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
 7611      PUT_WORD (&cai[17], 0);                          /* Min Rx speed */
 7612      PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
 7613
 7614      cai[3] = 0; /* Async framing parameters */
 7615      switch (GET_WORD (mdm_cfg[2].info))
 7616      {       /* Parity     */
 7617      case 1: /* odd parity */
 7618        cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
 7619        dbug(1,dprintf("MDM: odd parity"));
 7620        break;
 7621
 7622      case 2: /* even parity */
 7623        cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
 7624        dbug(1,dprintf("MDM: even parity"));
 7625        break;
 7626
 7627      default:
 7628        dbug(1,dprintf("MDM: no parity"));
 7629        break;
 7630      }
 7631
 7632      switch (GET_WORD (mdm_cfg[3].info))
 7633      {       /* stop bits   */
 7634      case 1: /* 2 stop bits */
 7635        cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
 7636        dbug(1,dprintf("MDM: 2 stop bits"));
 7637        break;
 7638
 7639      default:
 7640        dbug(1,dprintf("MDM: 1 stop bit"));
 7641        break;
 7642      }
 7643
 7644      switch (GET_WORD (mdm_cfg[1].info))
 7645      {     /* char length */
 7646      case 5:
 7647        cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
 7648        dbug(1,dprintf("MDM: 5 bits"));
 7649        break;
 7650
 7651      case 6:
 7652        cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
 7653        dbug(1,dprintf("MDM: 6 bits"));
 7654        break;
 7655
 7656      case 7:
 7657        cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
 7658        dbug(1,dprintf("MDM: 7 bits"));
 7659        break;
 7660
 7661      default:
 7662        dbug(1,dprintf("MDM: 8 bits"));
 7663        break;
 7664      }
 7665
 7666      cai[7] = 0; /* Line taking options */
 7667      cai[8] = 0; /* Modulation negotiation options */
 7668      cai[9] = 0; /* Modulation options */
 7669
 7670      if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
 7671      {
 7672        cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
 7673        dbug(1, dprintf("MDM: Reverse direction"));
 7674      }
 7675
 7676      if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
 7677      {
 7678        cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
 7679        dbug(1, dprintf("MDM: Disable retrain"));
 7680      }
 7681
 7682      if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
 7683      {
 7684        cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
 7685        dbug(1, dprintf("MDM: Disable ring tone"));
 7686      }
 7687
 7688      if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
 7689      {
 7690        cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
 7691        dbug(1, dprintf("MDM: 1800 guard tone"));
 7692      }
 7693      else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
 7694      {
 7695        cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
 7696        dbug(1, dprintf("MDM: 550 guard tone"));
 7697      }
 7698
 7699      if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
 7700      {
 7701        cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
 7702        dbug(1, dprintf("MDM: V100"));
 7703      }
 7704      else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
 7705      {
 7706        cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
 7707        dbug(1, dprintf("MDM: IN CLASS"));
 7708      }
 7709      else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
 7710      {
 7711        cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
 7712        dbug(1, dprintf("MDM: DISABLED"));
 7713      }
 7714      cai[0] = 20;
 7715
 7716      if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
 7717       && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
 7718      {
 7719        plci->requested_options |= 1L << PRIVATE_V18;
 7720      }
 7721      if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
 7722        plci->requested_options |= 1L << PRIVATE_VOWN;
 7723
 7724      if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
 7725        & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
 7726      {
 7727        if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
 7728        {
 7729          i = 27;
 7730          if (mdm_cfg[6].length >= 4)
 7731          {
 7732            d = GET_DWORD(&mdm_cfg[6].info[1]);
 7733            cai[7] |= (byte) d;          /* line taking options */
 7734            cai[9] |= (byte)(d >> 8);    /* modulation options */
 7735            cai[++i] = (byte)(d >> 16);  /* vown modulation options */
 7736            cai[++i] = (byte)(d >> 24);
 7737            if (mdm_cfg[6].length >= 8)
 7738            {
 7739              d = GET_DWORD(&mdm_cfg[6].info[5]);
 7740              cai[10] |= (byte) d;        /* disabled modulations mask */
 7741              cai[11] |= (byte)(d >> 8);
 7742              if (mdm_cfg[6].length >= 12)
 7743              {
 7744                d = GET_DWORD(&mdm_cfg[6].info[9]);
 7745                cai[12] = (byte) d;          /* enabled modulations mask */
 7746                cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
 7747                cai[++i] = (byte)(d >> 16);
 7748                cai[++i] = (byte)(d >> 24);
 7749                cai[++i] = 0;
 7750                if (mdm_cfg[6].length >= 14)
 7751                {
 7752                  w = GET_WORD(&mdm_cfg[6].info[13]);
 7753                  if (w != 0)
 7754                    PUT_WORD(&cai[13], w);  /* min tx speed */
 7755                  if (mdm_cfg[6].length >= 16)
 7756                  {
 7757                    w = GET_WORD(&mdm_cfg[6].info[15]);
 7758                    if (w != 0)
 7759                      PUT_WORD(&cai[15], w);  /* max tx speed */
 7760                    if (mdm_cfg[6].length >= 18)
 7761                    {
 7762                      w = GET_WORD(&mdm_cfg[6].info[17]);
 7763                      if (w != 0)
 7764                        PUT_WORD(&cai[17], w);  /* min rx speed */
 7765                      if (mdm_cfg[6].length >= 20)
 7766                      {
 7767                        w = GET_WORD(&mdm_cfg[6].info[19]);
 7768                        if (w != 0)
 7769                          PUT_WORD(&cai[19], w);  /* max rx speed */
 7770                        if (mdm_cfg[6].length >= 22)
 7771                        {
 7772                          w = GET_WORD(&mdm_cfg[6].info[21]);
 7773                          cai[23] = (byte)(-((short) w));  /* transmit level */
 7774                          if (mdm_cfg[6].length >= 24)
 7775                          {
 7776                            w = GET_WORD(&mdm_cfg[6].info[23]);
 7777                            cai[22] |= (byte) w;        /* info options mask */
 7778                            cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
 7779                          }
 7780                        }
 7781                      }
 7782                    }
 7783                  }
 7784                }
 7785              }
 7786            }
 7787          }
 7788          cai[27] = i - 27;
 7789          i++;
 7790          if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
 7791          {
 7792            if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
 7793            {
 7794              for (n = 0; n < 3; n++)
 7795              {
 7796                cai[i] = (byte)(mdm_cfg_v18[n].length);
 7797                for (j = 1; j < ((word)(cai[i] + 1)); j++)
 7798                  cai[i+j] = mdm_cfg_v18[n].info[j];
 7799                i += cai[i] + 1;
 7800              }
 7801            }
 7802          }
 7803          cai[0] = (byte)(i - 1);
 7804        }
 7805      }
 7806
 7807    }
 7808  }
 7809  if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */
 7810     GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */
 7811  {
 7812    if(bp_parms[3].length){
 7813      dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
 7814      switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */
 7815        case 0:
 7816        case 56000:
 7817          if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */
 7818            dbug(1,dprintf("56k sync HSCX"));
 7819            cai[1] = 8;
 7820            cai[2] = 0;
 7821            cai[3] = 0;
 7822          }
 7823          else if(GET_WORD(bp_parms[0].info)==2){
 7824            dbug(1,dprintf("56k async DSP"));
 7825            cai[2] = 9;
 7826          }
 7827          break;
 7828        case 50:     cai[2] = 1;  break;
 7829        case 75:     cai[2] = 1;  break;
 7830        case 110:    cai[2] = 1;  break;
 7831        case 150:    cai[2] = 1;  break;
 7832        case 200:    cai[2] = 1;  break;
 7833        case 300:    cai[2] = 1;  break;
 7834        case 600:    cai[2] = 1;  break;
 7835        case 1200:   cai[2] = 2;  break;
 7836        case 2400:   cai[2] = 3;  break;
 7837        case 4800:   cai[2] = 4;  break;
 7838        case 7200:   cai[2] = 10; break;
 7839        case 9600:   cai[2] = 5;  break;
 7840        case 12000:  cai[2] = 13; break;
 7841        case 24000:  cai[2] = 0;  break;
 7842        case 14400:  cai[2] = 11; break;
 7843        case 19200:  cai[2] = 6;  break;
 7844        case 28800:  cai[2] = 12; break;
 7845        case 38400:  cai[2] = 7;  break;
 7846        case 48000:  cai[2] = 8;  break;
 7847        case 76:     cai[2] = 15; break;  /* 75/1200     */
 7848        case 1201:   cai[2] = 14; break;  /* 1200/75     */
 7849        case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
 7850
 7851        default:
 7852          return _B1_PARM_NOT_SUPPORTED;
 7853      }
 7854      cai[3] = 0;
 7855      if (cai[1] == 13)                                        /* v.110 async */
 7856      {
 7857        if (bp_parms[3].length >= 8)
 7858        {
 7859          switch (GET_WORD (&bp_parms[3].info[3]))
 7860          {       /* char length */
 7861          case 5:
 7862            cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
 7863            break;
 7864          case 6:
 7865            cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
 7866            break;
 7867          case 7:
 7868            cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
 7869            break;
 7870          }
 7871          switch (GET_WORD (&bp_parms[3].info[5]))
 7872          {       /* Parity     */
 7873          case 1: /* odd parity */
 7874            cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
 7875            break;
 7876          case 2: /* even parity */
 7877            cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
 7878            break;
 7879          }
 7880          switch (GET_WORD (&bp_parms[3].info[7]))
 7881          {       /* stop bits   */
 7882          case 1: /* 2 stop bits */
 7883            cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
 7884            break;
 7885          }
 7886        }
 7887      }
 7888    }
 7889    else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
 7890      dbug(1,dprintf("V.110 default 56k sync"));
 7891      cai[1] = 8;
 7892      cai[2] = 0;
 7893      cai[3] = 0;
 7894    }
 7895    else {
 7896      dbug(1,dprintf("V.110 default 9600 async"));
 7897      cai[2] = 5;
 7898    }
 7899  }
 7900  PUT_WORD(&cai[5],plci->appl->MaxDataLength);
 7901  dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
 7902/* HexDump ("CAI", sizeof(cai), &cai[0]); */
 7903
 7904  add_p(plci, CAI, cai);
 7905  return 0;
 7906}
 7907
 7908/*------------------------------------------------------------------*/
 7909/* put parameter for b2 and B3  protocol in the parameter buffer    */
 7910/*------------------------------------------------------------------*/
 7911
 7912word add_b23(PLCI   * plci, API_PARSE * bp)
 7913{
 7914  word i, fax_control_bits;
 7915  byte pos, len;
 7916  byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
 7917    API_PARSE bp_parms[8];
 7918  API_PARSE * b1_config;
 7919  API_PARSE * b2_config;
 7920    API_PARSE b2_config_parms[8];
 7921  API_PARSE * b3_config;
 7922    API_PARSE b3_config_parms[6];
 7923    API_PARSE global_config[2];
 7924
 7925  static byte llc[3] = {2,0,0};
 7926  static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 7927  static byte nlc[256];
 7928  static byte lli[12] = {1,1};
 7929
 7930  const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
 7931  const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
 7932
 7933  const byte llc3[] = {4,3,2,2,6,6,0};
 7934  const byte header[] = {0,2,3,3,0,0,0};
 7935
 7936  for(i=0;i<8;i++) bp_parms[i].length = 0;
 7937  for(i=0;i<6;i++) b2_config_parms[i].length = 0;
 7938  for(i=0;i<5;i++) b3_config_parms[i].length = 0;
 7939
 7940  lli[0] = 1;
 7941  lli[1] = 1;
 7942  if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
 7943    lli[1] |= 2;
 7944  if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
 7945    lli[1] |= 4;
 7946
 7947  if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
 7948    lli[1] |= 0x10;
 7949    if (plci->rx_dma_descriptor <= 0) {
 7950      plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
 7951      if (plci->rx_dma_descriptor >= 0)
 7952        plci->rx_dma_descriptor++;
 7953    }
 7954    if (plci->rx_dma_descriptor > 0) {
 7955      lli[0] = 6;
 7956      lli[1] |= 0x40;
 7957      lli[2] = (byte)(plci->rx_dma_descriptor - 1);
 7958      lli[3] = (byte)plci->rx_dma_magic;
 7959      lli[4] = (byte)(plci->rx_dma_magic >>  8);
 7960      lli[5] = (byte)(plci->rx_dma_magic >> 16);
 7961      lli[6] = (byte)(plci->rx_dma_magic >> 24);
 7962    }
 7963  }
 7964
 7965  if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
 7966    lli[1] |= 0x20;
 7967  }
 7968
 7969  dbug(1,dprintf("add_b23"));
 7970  api_save_msg(bp, "s", &plci->B_protocol);
 7971
 7972  if(!bp->length && plci->tel)
 7973  {
 7974    plci->adv_nl = true;
 7975    dbug(1,dprintf("Default adv.Nl"));
 7976    add_p(plci,LLI,lli);
 7977    plci->B2_prot = 1 /*XPARENT*/;
 7978    plci->B3_prot = 0 /*XPARENT*/;
 7979    llc[1] = 2;
 7980    llc[2] = 4;
 7981    add_p(plci, LLC, llc);
 7982    dlc[0] = 2;
 7983    PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
 7984    add_p(plci, DLC, dlc);
 7985    return 0;
 7986  }
 7987
 7988  if(!bp->length) /*default*/
 7989  {   
 7990    dbug(1,dprintf("ret default"));
 7991    add_p(plci,LLI,lli);
 7992    plci->B2_prot = 0 /*X.75   */;
 7993    plci->B3_prot = 0 /*XPARENT*/;
 7994    llc[1] = 1;
 7995    llc[2] = 4;
 7996    add_p(plci, LLC, llc);
 7997    dlc[0] = 2;
 7998    PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
 7999    add_p(plci, DLC, dlc);
 8000    return 0;
 8001  }
 8002  dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
 8003  if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
 8004
 8005  if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
 8006  {
 8007    bp_parms[6].length = 0;
 8008    if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
 8009    {
 8010      dbug(1,dprintf("b-form.!"));
 8011      return _WRONG_MESSAGE_FORMAT;
 8012    }
 8013  }
 8014  else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
 8015  {
 8016    dbug(1,dprintf("b-form.!"));
 8017    return _WRONG_MESSAGE_FORMAT;
 8018  }
 8019
 8020  if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
 8021  {  
 8022    if(GET_WORD(bp_parms[1].info)!=1
 8023    || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
 8024    plci->adv_nl = true;
 8025  }
 8026  else if(plci->tel) return _B2_NOT_SUPPORTED;
 8027
 8028
 8029  if ((GET_WORD(bp_parms[1].info) == B2_RTP)
 8030   && (GET_WORD(bp_parms[2].info) == B3_RTP)
 8031   && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
 8032  {
 8033    add_p(plci,LLI,lli);
 8034    plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
 8035    plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
 8036    llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
 8037    llc[2] = 4;
 8038    add_p(plci, LLC, llc);
 8039    dlc[0] = 2;
 8040    PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
 8041    dlc[3] = 3; /* Addr A */
 8042    dlc[4] = 1; /* Addr B */
 8043    dlc[5] = 7; /* modulo mode */
 8044    dlc[6] = 7; /* window size */
 8045    dlc[7] = 0; /* XID len Lo  */
 8046    dlc[8] = 0; /* XID len Hi  */
 8047    for (i = 0; i < bp_parms[4].length; i++)
 8048      dlc[9+i] = bp_parms[4].info[1+i];
 8049    dlc[0] = (byte)(8 + bp_parms[4].length);
 8050    add_p(plci, DLC, dlc);
 8051    for (i = 0; i < bp_parms[5].length; i++)
 8052      nlc[1+i] = bp_parms[5].info[1+i];
 8053    nlc[0] = (byte)(bp_parms[5].length);
 8054    add_p(plci, NLC, nlc);
 8055    return 0;
 8056  }
 8057
 8058
 8059
 8060  if ((GET_WORD(bp_parms[1].info) >= 32)
 8061   || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
 8062    && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
 8063     || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
 8064
 8065  {
 8066    return _B2_NOT_SUPPORTED;
 8067  }
 8068  if ((GET_WORD(bp_parms[2].info) >= 32)
 8069   || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
 8070  {
 8071    return _B3_NOT_SUPPORTED;
 8072  }
 8073  if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
 8074   && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
 8075    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
 8076    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
 8077  {
 8078    return (add_modem_b23 (plci, bp_parms));
 8079  }
 8080
 8081  add_p(plci,LLI,lli);
 8082
 8083  plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
 8084  plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
 8085  if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
 8086
 8087  if(bp_parms[6].length)
 8088  {
 8089    if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
 8090    {
 8091      return _WRONG_MESSAGE_FORMAT;
 8092    }
 8093    switch(GET_WORD(global_config[0].info))
 8094    {
 8095    case 1:
 8096      plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
 8097      break;
 8098    case 2:
 8099      plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
 8100      break;
 8101    }
 8102  }
 8103  dbug(1,dprintf("call_dir=%04x", plci->call_dir));
 8104
 8105
 8106  if (plci->B2_prot == B2_PIAFS)
 8107    llc[1] = PIAFS_CRC;
 8108  else
 8109/* IMPLEMENT_PIAFS */
 8110  {
 8111    llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
 8112             llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
 8113  }
 8114  llc[2] = llc3[GET_WORD(bp_parms[2].info)];
 8115
 8116  add_p(plci, LLC, llc);
 8117
 8118  dlc[0] = 2;
 8119  PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
 8120                      header[GET_WORD(bp_parms[2].info)]);
 8121
 8122  b1_config = &bp_parms[3];
 8123  nlc[0] = 0;
 8124  if(plci->B3_prot == 4
 8125  || plci->B3_prot == 5)
 8126  {
 8127    for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
 8128    nlc[0] = sizeof(T30_INFO);
 8129    if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
 8130      ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
 8131    ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
 8132    if(b1_config->length>=2)
 8133    {
 8134      ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
 8135    }
 8136  }
 8137  b2_config = &bp_parms[4];
 8138
 8139
 8140  if (llc[1] == PIAFS_CRC)
 8141  {
 8142    if (plci->B3_prot != B3_TRANSPARENT)
 8143    {
 8144      return _B_STACK_NOT_SUPPORTED;
 8145    }
 8146    if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
 8147      return _WRONG_MESSAGE_FORMAT;
 8148    }
 8149    PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
 8150    dlc[3] = 0; /* Addr A */
 8151    dlc[4] = 0; /* Addr B */
 8152    dlc[5] = 0; /* modulo mode */
 8153    dlc[6] = 0; /* window size */
 8154    if (b2_config->length >= 7){
 8155      dlc[ 7] = 7; 
 8156      dlc[ 8] = 0; 
 8157      dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
 8158      dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
 8159      dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
 8160      dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
 8161      dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
 8162      dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
 8163      dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
 8164      dlc[ 0] = 15;
 8165      if(b2_config->length >= 8) { /* PIAFS control abilities */
 8166        dlc[ 7] = 10; 
 8167        dlc[16] = 2; /* Length of PIAFS extention */
 8168        dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
 8169        dlc[18] = b2_config_parms[4].info[0]; /* value */
 8170        dlc[ 0] = 18;
 8171      }
 8172    }
 8173    else /* default values, 64K, variable, no compression */
 8174    {
 8175      dlc[ 7] = 7; 
 8176      dlc[ 8] = 0; 
 8177      dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
 8178      dlc[10] = 0x03; /* V.42bis P0 */
 8179      dlc[11] = 0;    /* V.42bis P0 */
 8180      dlc[12] = 0;    /* V.42bis P1 */
 8181      dlc[13] = 0;    /* V.42bis P1 */
 8182      dlc[14] = 0;    /* V.42bis P2 */
 8183      dlc[15] = 0;    /* V.42bis P2 */
 8184    dlc[ 0] = 15;
 8185    }
 8186    add_p(plci, DLC, dlc);
 8187  }
 8188  else
 8189
 8190  if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
 8191  {
 8192    if (plci->B3_prot != B3_TRANSPARENT)
 8193      return _B_STACK_NOT_SUPPORTED;
 8194
 8195    dlc[0] = 6;
 8196    PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
 8197    dlc[3] = 0x08;
 8198    dlc[4] = 0x01;
 8199    dlc[5] = 127;
 8200    dlc[6] = 7;
 8201    if (b2_config->length != 0)
 8202    {
 8203      if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
 8204        return _WRONG_MESSAGE_FORMAT;
 8205      }
 8206      dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
 8207      dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
 8208      if (b2_config->info[3] != 128)
 8209      {
 8210        dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
 8211        return _B2_PARM_NOT_SUPPORTED;
 8212      }
 8213      dlc[5] = (byte)(b2_config->info[3] - 1);
 8214      dlc[6] = b2_config->info[4];
 8215      if(llc[1]==V120_V42BIS){
 8216        if (b2_config->length >= 10){
 8217          dlc[ 7] = 6; 
 8218          dlc[ 8] = 0; 
 8219          dlc[ 9] = b2_config_parms[4].info[0];
 8220          dlc[10] = b2_config_parms[4].info[1];
 8221          dlc[11] = b2_config_parms[5].info[0];
 8222          dlc[12] = b2_config_parms[5].info[1];
 8223          dlc[13] = b2_config_parms[6].info[0];
 8224          dlc[14] = b2_config_parms[6].info[1];
 8225          dlc[ 0] = 14;
 8226          dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
 8227          dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
 8228          dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
 8229        }
 8230        else {
 8231          dlc[ 6] = 14;
 8232        }
 8233      }
 8234    }
 8235  }
 8236  else
 8237  {
 8238    if(b2_config->length)
 8239    {
 8240      dbug(1,dprintf("B2-Config"));
 8241      if(llc[1]==X75_V42BIS){
 8242        if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
 8243        {
 8244          return _WRONG_MESSAGE_FORMAT;
 8245        }
 8246      }
 8247      else {
 8248        if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
 8249        {
 8250          return _WRONG_MESSAGE_FORMAT;
 8251        }
 8252      }
 8253          /* if B2 Protocol is LAPD, b2_config structure is different */
 8254      if(llc[1]==6)
 8255      {
 8256        dlc[0] = 4;
 8257        if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
 8258        else dlc[2] = 0x01;
 8259        if( (b2_config->length>=2) && (plci->B2_prot==12) )
 8260        {
 8261          SAPI = b2_config->info[2];    /* SAPI */
 8262        }
 8263        dlc[1] = SAPI;
 8264        if( (b2_config->length>=3) && (b2_config->info[3]==128) )
 8265        {
 8266          dlc[3] = 127;      /* Mode */
 8267        }
 8268        else
 8269        {
 8270          dlc[3] = 7;        /* Mode */
 8271        }
 8272   
 8273        if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
 8274        else dlc[4] = 1;
 8275        dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
 8276        if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
 8277      }
 8278      else
 8279      {
 8280        dlc[0] = (byte)(b2_config_parms[4].length+6);
 8281        dlc[3] = b2_config->info[1];
 8282        dlc[4] = b2_config->info[2];
 8283        if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
 8284          dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
 8285          return _B2_PARM_NOT_SUPPORTED;
 8286        }
 8287
 8288        dlc[5] = (byte)(b2_config->info[3]-1);
 8289        dlc[6] = b2_config->info[4];
 8290        if(dlc[6]>dlc[5]){
 8291          dbug(1,dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
 8292          return _B2_PARM_NOT_SUPPORTED;
 8293        }
 8294 
 8295        if(llc[1]==X75_V42BIS) {
 8296          if (b2_config->length >= 10){
 8297            dlc[ 7] = 6; 
 8298            dlc[ 8] = 0; 
 8299            dlc[ 9] = b2_config_parms[4].info[0];
 8300            dlc[10] = b2_config_parms[4].info[1];
 8301            dlc[11] = b2_config_parms[5].info[0];
 8302            dlc[12] = b2_config_parms[5].info[1];
 8303            dlc[13] = b2_config_parms[6].info[0];
 8304            dlc[14] = b2_config_parms[6].info[1];
 8305            dlc[ 0] = 14;
 8306            dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
 8307            dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
 8308            dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
 8309          }
 8310          else {
 8311            dlc[ 6] = 14;
 8312          }
 8313
 8314        }
 8315        else {
 8316          PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
 8317          for(i=0; i<b2_config_parms[4].length; i++)
 8318            dlc[11+i] = b2_config_parms[4].info[1+i];
 8319        }
 8320      }
 8321    }
 8322  }
 8323  add_p(plci, DLC, dlc);
 8324
 8325  b3_config = &bp_parms[5];
 8326  if(b3_config->length)
 8327  {
 8328    if(plci->B3_prot == 4 
 8329    || plci->B3_prot == 5)
 8330    {
 8331      if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
 8332      {
 8333        return _WRONG_MESSAGE_FORMAT;
 8334      }
 8335      i = GET_WORD((byte   *)(b3_config_parms[0].info));
 8336      ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
 8337        ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
 8338      ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info));
 8339      fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
 8340      if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
 8341        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
 8342      if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
 8343      {
 8344
 8345        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
 8346          & (1L << PRIVATE_FAX_PAPER_FORMATS))
 8347        {
 8348          ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
 8349            T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
 8350            T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
 8351        }
 8352
 8353 ((T30_INFO *)&nlc[1])->recording_properties =
 8354   T30_RECORDING_WIDTH_ISO_A3 |
 8355   (T30_RECORDING_LENGTH_UNLIMITED << 2) |
 8356   (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
 8357      }
 8358      if(plci->B3_prot == 5)
 8359      {
 8360        if (i & 0x0002) /* Accept incoming fax-polling requests */
 8361          fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
 8362        if (i & 0x2000) /* Do not use MR compression */
 8363          fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
 8364        if (i & 0x4000) /* Do not use MMR compression */
 8365          fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
 8366        if (i & 0x8000) /* Do not use ECM */
 8367          fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
 8368        if (plci->fax_connect_info_length != 0)
 8369        {
 8370          ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
 8371          ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
 8372          ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
 8373          fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
 8374            (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
 8375        }
 8376      }
 8377      /* copy station id to NLC */
 8378      for(i=0; i<20; i++)
 8379      {
 8380        if(i<b3_config_parms[2].length)
 8381        {
 8382          ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
 8383        }
 8384        else
 8385        {
 8386          ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
 8387        }
 8388      }
 8389      ((T30_INFO *)&nlc[1])->station_id_len = 20;
 8390      /* copy head line to NLC */
 8391      if(b3_config_parms[3].length)
 8392      {
 8393
 8394        pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
 8395        if (pos != 0)
 8396        {
 8397          if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
 8398            pos = 0;
 8399          else
 8400          {
 8401            ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
 8402            ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
 8403            len = (byte)b3_config_parms[2].length;
 8404            if (len > 20)
 8405              len = 20;
 8406            if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
 8407            {
 8408              for (i = 0; i < len; i++)
 8409                ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
 8410              ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
 8411              ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
 8412            }
 8413          }
 8414        }
 8415
 8416        len = (byte)b3_config_parms[3].length;
 8417        if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
 8418          len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
 8419        ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
 8420        nlc[0] += (byte)(pos + len);
 8421        for (i = 0; i < len; i++)
 8422          ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
 8423        }
 8424      else
 8425        ((T30_INFO *)&nlc[1])->head_line_len = 0;
 8426
 8427      plci->nsf_control_bits = 0;
 8428      if(plci->B3_prot == 5)
 8429      {
 8430        if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
 8431         && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
 8432        {
 8433          plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
 8434        }
 8435        if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
 8436         && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
 8437        {
 8438          plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
 8439        }
 8440        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
 8441          & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
 8442        {
 8443        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
 8444          & (1L << PRIVATE_FAX_SUB_SEP_PWD))
 8445        {
 8446          fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
 8447          if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
 8448            fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
 8449          }
 8450            len = nlc[0];
 8451          pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
 8452   if (pos < plci->fax_connect_info_length)
 8453   {
 8454     for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
 8455              nlc[++len] = plci->fax_connect_info_buffer[pos++];
 8456          }
 8457   else
 8458     nlc[++len] = 0;
 8459   if (pos < plci->fax_connect_info_length)
 8460   {
 8461     for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
 8462              nlc[++len] = plci->fax_connect_info_buffer[pos++];
 8463          }
 8464   else
 8465     nlc[++len] = 0;
 8466          if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
 8467            & (1L << PRIVATE_FAX_NONSTANDARD))
 8468          {
 8469     if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
 8470     {
 8471              if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
 8472                plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
 8473       for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
 8474                nlc[++len] = plci->fax_connect_info_buffer[pos++];
 8475            }
 8476     else
 8477     {
 8478              if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
 8479              {
 8480                dbug(1,dprintf("non-standard facilities info missing or wrong format"));
 8481                nlc[++len] = 0;
 8482              }
 8483       else
 8484       {
 8485                if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
 8486                  plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
 8487         nlc[++len] = (byte)(b3_config_parms[4].length);
 8488         for (i = 0; i < b3_config_parms[4].length; i++)
 8489    nlc[++len] = b3_config_parms[4].info[1+i];
 8490       }
 8491            }
 8492          }
 8493            nlc[0] = len;
 8494   if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
 8495    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
 8496   {
 8497            ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
 8498          }
 8499        }
 8500      }
 8501
 8502      PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
 8503      len = ((byte)(((T30_INFO *) 0)->station_id + 20));
 8504      for (i = 0; i < len; i++)
 8505        plci->fax_connect_info_buffer[i] = nlc[1+i];
 8506      ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
 8507      i += ((T30_INFO *)&nlc[1])->head_line_len;
 8508      while (i < nlc[0])
 8509        plci->fax_connect_info_buffer[len++] = nlc[++i];
 8510      plci->fax_connect_info_length = len;
 8511    }
 8512    else
 8513    {
 8514      nlc[0] = 14;
 8515      if(b3_config->length!=16)
 8516        return _B3_PARM_NOT_SUPPORTED;
 8517      for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
 8518      if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
 8519        return _B3_PARM_NOT_SUPPORTED;
 8520      nlc[13] = b3_config->info[13];
 8521      if(GET_WORD(&b3_config->info[15])>=nlc[13])
 8522        return _B3_PARM_NOT_SUPPORTED;
 8523      nlc[14] = b3_config->info[15];
 8524    }
 8525  }
 8526  else
 8527  {
 8528    if (plci->B3_prot == 4 
 8529     || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
 8530  }
 8531  add_p(plci, NLC, nlc);
 8532  return 0;
 8533}
 8534
 8535/*----------------------------------------------------------------*/
 8536/*      make the same as add_b23, but only for the modem related  */
 8537/*      L2 and L3 B-Chan protocol.                                */
 8538/*                                                                */
 8539/*      Enabled L2 and L3 Configurations:                         */
 8540/*        If L1 == Modem all negotiation                          */
 8541/*          only L2 == Modem with full negotiation is allowed     */
 8542/*        If L1 == Modem async or sync                            */
 8543/*          only L2 == Transparent is allowed                     */
 8544/*        L3 == Modem or L3 == Transparent are allowed            */
 8545/*      B2 Configuration for modem:                               */
 8546/*          word : enable/disable compression, bitoptions         */
 8547/*      B3 Configuration for modem:                               */
 8548/*          empty                                                 */
 8549/*----------------------------------------------------------------*/
 8550static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
 8551{
 8552  static byte lli[12] = {1,1};
 8553  static byte llc[3] = {2,0,0};
 8554  static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 8555    API_PARSE mdm_config[2];
 8556  word i;
 8557  word b2_config = 0;
 8558
 8559  for(i=0;i<2;i++) mdm_config[i].length = 0;
 8560  for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
 8561
 8562  if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
 8563    && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
 8564   || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
 8565    && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
 8566  {
 8567    return (_B_STACK_NOT_SUPPORTED);
 8568  }
 8569  if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
 8570   && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
 8571  {
 8572    return (_B_STACK_NOT_SUPPORTED);
 8573  }
 8574
 8575  plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
 8576  plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
 8577
 8578  if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
 8579  {
 8580    if (api_parse (&bp_parms[4].info[1],
 8581                  (word)bp_parms[4].length, "w",
 8582                  mdm_config))
 8583    {
 8584      return (_WRONG_MESSAGE_FORMAT);
 8585    }
 8586    b2_config = GET_WORD(mdm_config[0].info);
 8587  }
 8588
 8589  /* OK, L2 is modem */
 8590
 8591  lli[0] = 1;
 8592  lli[1] = 1;
 8593  if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
 8594    lli[1] |= 2;
 8595  if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
 8596    lli[1] |= 4;
 8597
 8598  if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
 8599    lli[1] |= 0x10;
 8600    if (plci->rx_dma_descriptor <= 0) {
 8601      plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
 8602      if (plci->rx_dma_descriptor >= 0)
 8603        plci->rx_dma_descriptor++;
 8604    }
 8605    if (plci->rx_dma_descriptor > 0) {
 8606      lli[1] |= 0x40;
 8607      lli[0] = 6;
 8608      lli[2] = (byte)(plci->rx_dma_descriptor - 1);
 8609      lli[3] = (byte)plci->rx_dma_magic;
 8610      lli[4] = (byte)(plci->rx_dma_magic >>  8);
 8611      lli[5] = (byte)(plci->rx_dma_magic >> 16);
 8612      lli[6] = (byte)(plci->rx_dma_magic >> 24);
 8613    }
 8614  }
 8615
 8616  if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
 8617    lli[1] |= 0x20;
 8618  }
 8619
 8620  llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
 8621    /*V42*/ 10 : /*V42_IN*/ 9;
 8622  llc[2] = 4;                      /* pass L3 always transparent */
 8623  add_p(plci, LLI, lli);
 8624  add_p(plci, LLC, llc);
 8625  i =  1;
 8626  PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
 8627  i += 2;
 8628  if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
 8629  {
 8630    if (bp_parms[4].length)
 8631  {
 8632    dbug(1, dprintf("MDM b2_config=%02x", b2_config));
 8633    dlc[i++] = 3; /* Addr A */
 8634    dlc[i++] = 1; /* Addr B */
 8635    dlc[i++] = 7; /* modulo mode */
 8636    dlc[i++] = 7; /* window size */
 8637    dlc[i++] = 0; /* XID len Lo  */
 8638    dlc[i++] = 0; /* XID len Hi  */
 8639
 8640    if (b2_config & MDM_B2_DISABLE_V42bis)
 8641    {
 8642      dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
 8643    }
 8644    if (b2_config & MDM_B2_DISABLE_MNP)
 8645    {
 8646      dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
 8647    }
 8648    if (b2_config & MDM_B2_DISABLE_TRANS)
 8649    {
 8650      dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
 8651    }
 8652    if (b2_config & MDM_B2_DISABLE_V42)
 8653    {
 8654      dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
 8655    }
 8656    if (b2_config & MDM_B2_DISABLE_COMP)
 8657    {
 8658      dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
 8659    }
 8660    i++;
 8661  }
 8662  }
 8663  else
 8664  {
 8665    dlc[i++] = 3; /* Addr A */
 8666    dlc[i++] = 1; /* Addr B */
 8667    dlc[i++] = 7; /* modulo mode */
 8668    dlc[i++] = 7; /* window size */
 8669    dlc[i++] = 0; /* XID len Lo  */
 8670    dlc[i++] = 0; /* XID len Hi  */
 8671    dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
 8672               DLC_MODEMPROT_DISABLE_MNP_MNP5 |
 8673               DLC_MODEMPROT_DISABLE_V42_DETECT |
 8674               DLC_MODEMPROT_DISABLE_COMPRESSION;
 8675  }
 8676  dlc[0] = (byte)(i - 1);
 8677/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
 8678  add_p(plci, DLC, dlc);
 8679  return (0);
 8680}
 8681
 8682
 8683/*------------------------------------------------------------------*/
 8684/* send a request for the signaling entity                          */
 8685/*------------------------------------------------------------------*/
 8686
 8687void sig_req(PLCI   * plci, byte req, byte Id)
 8688{
 8689  if(!plci) return;
 8690  if(plci->adapter->adapter_disabled) return;
 8691  dbug(1,dprintf("sig_req(%x)",req));
 8692  if (req == REMOVE)
 8693    plci->sig_remove_id = plci->Sig.Id;
 8694  if(plci->req_in==plci->req_in_start) {
 8695    plci->req_in +=2;
 8696    plci->RBuffer[plci->req_in++] = 0;
 8697  }
 8698  PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
 8699  plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
 8700  plci->RBuffer[plci->req_in++] = req;  /* request */
 8701  plci->RBuffer[plci->req_in++] = 0;    /* channel */
 8702  plci->req_in_start = plci->req_in;
 8703}
 8704
 8705/*------------------------------------------------------------------*/
 8706/* send a request for the network layer entity                      */
 8707/*------------------------------------------------------------------*/
 8708
 8709void nl_req_ncci(PLCI   * plci, byte req, byte ncci)
 8710{
 8711  if(!plci) return;
 8712  if(plci->adapter->adapter_disabled) return;
 8713  dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
 8714  if (req == REMOVE)
 8715  {
 8716    plci->nl_remove_id = plci->NL.Id;
 8717    ncci_remove (plci, 0, (byte)(ncci != 0));
 8718    ncci = 0;
 8719  }
 8720  if(plci->req_in==plci->req_in_start) {
 8721    plci->req_in +=2;
 8722    plci->RBuffer[plci->req_in++] = 0;
 8723  }
 8724  PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
 8725  plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
 8726  plci->RBuffer[plci->req_in++] = req;  /* request */
 8727  plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
 8728  plci->req_in_start = plci->req_in;
 8729}
 8730
 8731void send_req(PLCI   * plci)
 8732{
 8733  ENTITY   * e;
 8734  word l;
 8735/*  word i; */
 8736
 8737  if(!plci) return;
 8738  if(plci->adapter->adapter_disabled) return;
 8739  channel_xmit_xon (plci);
 8740
 8741        /* if nothing to do, return */
 8742  if(plci->req_in==plci->req_out) return;
 8743  dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
 8744
 8745  if(plci->nl_req || plci->sig_req) return;
 8746
 8747  l = GET_WORD(&plci->RBuffer[plci->req_out]);
 8748  plci->req_out += 2;
 8749  plci->XData[0].P = &plci->RBuffer[plci->req_out];
 8750  plci->req_out += l;
 8751  if(plci->RBuffer[plci->req_out]==1)
 8752  {
 8753    e = &plci->NL;
 8754    plci->req_out++;
 8755    e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
 8756    e->ReqCh = plci->RBuffer[plci->req_out++];
 8757    if(!(e->Id & 0x1f))
 8758    {
 8759      e->Id = NL_ID;
 8760      plci->RBuffer[plci->req_out-4] = CAI;
 8761      plci->RBuffer[plci->req_out-3] = 1;
 8762      plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
 8763      plci->RBuffer[plci->req_out-1] = 0;
 8764      l+=3;
 8765      plci->nl_global_req = plci->nl_req;
 8766    }
 8767    dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
 8768  }
 8769  else
 8770  {
 8771    e = &plci->Sig;
 8772    if(plci->RBuffer[plci->req_out])
 8773      e->Id = plci->RBuffer[plci->req_out];
 8774    plci->req_out++;
 8775    e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
 8776    e->ReqCh = plci->RBuffer[plci->req_out++];
 8777    if(!(e->Id & 0x1f))
 8778      plci->sig_global_req = plci->sig_req;
 8779    dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
 8780  }
 8781  plci->XData[0].PLength = l;
 8782  e->X = plci->XData;
 8783  plci->adapter->request(e);
 8784  dbug(1,dprintf("send_ok"));
 8785}
 8786
 8787void send_data(PLCI   * plci)
 8788{
 8789  DIVA_CAPI_ADAPTER   * a;
 8790  DATA_B3_DESC   * data;
 8791  NCCI   *ncci_ptr;
 8792  word ncci;
 8793
 8794  if (!plci->nl_req && plci->ncci_ring_list)
 8795  {
 8796    a = plci->adapter;
 8797    ncci = plci->ncci_ring_list;
 8798    do
 8799    {
 8800      ncci = a->ncci_next[ncci];
 8801      ncci_ptr = &(a->ncci[ncci]);
 8802      if (!(a->ncci_ch[ncci]
 8803         && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
 8804      {
 8805        if (ncci_ptr->data_pending)
 8806        {
 8807          if ((a->ncci_state[ncci] == CONNECTED)
 8808           || (a->ncci_state[ncci] == INC_ACT_PENDING)
 8809           || (plci->send_disc == ncci))
 8810          {
 8811            data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
 8812            if ((plci->B2_prot == B2_V120_ASYNC)
 8813             || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
 8814             || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
 8815            {
 8816              plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
 8817              plci->NData[1].PLength = data->Length;
 8818              if (data->Flags & 0x10)
 8819                plci->NData[0].P = v120_break_header;
 8820              else
 8821                plci->NData[0].P = v120_default_header;
 8822              plci->NData[0].PLength = 1 ;
 8823              plci->NL.XNum = 2;
 8824              plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
 8825            }
 8826            else
 8827            {
 8828              plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
 8829              plci->NData[0].PLength = data->Length;
 8830              if (data->Flags & 0x10)
 8831                plci->NL.Req = plci->nl_req = (byte)N_UDATA;
 8832
 8833              else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
 8834                plci->NL.Req = plci->nl_req = (byte)N_BDATA;
 8835
 8836              else
 8837                plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
 8838            }
 8839            plci->NL.X = plci->NData;
 8840            plci->NL.ReqCh = a->ncci_ch[ncci];
 8841            dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
 8842            plci->data_sent = true;
 8843            plci->data_sent_ptr = data->P;
 8844            a->request(&plci->NL);
 8845          }
 8846          else {
 8847            cleanup_ncci_data (plci, ncci);
 8848          }
 8849        }
 8850        else if (plci->send_disc == ncci)
 8851        {
 8852          /* dprintf("N_DISC"); */
 8853          plci->NData[0].PLength = 0;
 8854          plci->NL.ReqCh = a->ncci_ch[ncci];
 8855          plci->NL.Req = plci->nl_req = N_DISC;
 8856          a->request(&plci->NL);
 8857          plci->command = _DISCONNECT_B3_R;
 8858          plci->send_disc = 0;
 8859        }
 8860      }
 8861    } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
 8862    plci->ncci_ring_list = ncci;
 8863  }
 8864}
 8865
 8866void listen_check(DIVA_CAPI_ADAPTER   * a)
 8867{
 8868  word i,j;
 8869  PLCI   * plci;
 8870  byte activnotifiedcalls = 0;
 8871
 8872  dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
 8873  if (!remove_started && !a->adapter_disabled)
 8874  {
 8875    for(i=0;i<a->max_plci;i++)
 8876    {
 8877      plci = &(a->plci[i]);
 8878      if(plci->notifiedcall) activnotifiedcalls++;
 8879    }
 8880    dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
 8881
 8882    for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
 8883      if((j=get_plci(a))) {
 8884        a->listen_active++;
 8885        plci = &a->plci[j-1];
 8886        plci->State = LISTENING;
 8887
 8888        add_p(plci,OAD,"\x01\xfd");
 8889
 8890        add_p(plci,KEY,"\x04\x43\x41\x32\x30");
 8891
 8892        add_p(plci,CAI,"\x01\xc0");
 8893        add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 8894        add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
 8895        add_p(plci,SHIFT|6,NULL);
 8896        add_p(plci,SIN,"\x02\x00\x00");
 8897        plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
 8898        sig_req(plci,ASSIGN,DSIG_ID);
 8899        send_req(plci);
 8900      }
 8901    }
 8902  }
 8903}
 8904
 8905/*------------------------------------------------------------------*/
 8906/* functions for all parameters sent in INDs                        */
 8907/*------------------------------------------------------------------*/
 8908
 8909void IndParse(PLCI   * plci, word * parms_id, byte   ** parms, byte multiIEsize)
 8910{
 8911  word ploc;            /* points to current location within packet */
 8912  byte w;
 8913  byte wlen;
 8914  byte codeset,lock;
 8915  byte   * in;
 8916  word i;
 8917  word code;
 8918  word mIEindex = 0;
 8919  ploc = 0;
 8920  codeset = 0;
 8921  lock = 0;
 8922
 8923  in = plci->Sig.RBuffer->P;
 8924  for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
 8925  {                            /* element but parms array is larger      */
 8926    parms[i] = (byte   *)"";
 8927  }
 8928  for(i=0; i<multiIEsize; i++)
 8929  {
 8930    parms[i] = (byte   *)"";
 8931  }
 8932
 8933  while(ploc<plci->Sig.RBuffer->length-1) {
 8934
 8935        /* read information element id and length                   */
 8936    w = in[ploc];
 8937
 8938    if(w & 0x80) {
 8939/*    w &=0xf0; removed, cannot detect congestion levels */
 8940/*    upper 4 bit masked with w==SHIFT now               */
 8941      wlen = 0;
 8942    }
 8943    else {
 8944      wlen = (byte)(in[ploc+1]+1);
 8945    }
 8946        /* check if length valid (not exceeding end of packet)      */
 8947    if((ploc+wlen) > 270) return ;
 8948    if(lock & 0x80) lock &=0x7f;
 8949    else codeset = lock;
 8950
 8951    if((w&0xf0)==SHIFT) {
 8952      codeset = in[ploc];
 8953      if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
 8954      codeset &=7;
 8955      lock |=0x80;
 8956    }
 8957    else {
 8958      if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
 8959      else code = w;
 8960      code |= (codeset<<8);
 8961
 8962      for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
 8963
 8964      if(i<parms_id[0]+1) {
 8965        if(!multiIEsize) { /* with multiIEs use next field index,          */
 8966          mIEindex = i-1;    /* with normal IEs use same index like parms_id */
 8967        }
 8968
 8969        parms[mIEindex] = &in[ploc+1];
 8970        dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
 8971        if(parms_id[i]==OAD
 8972        || parms_id[i]==CONN_NR
 8973        || parms_id[i]==CAD) {
 8974          if(in[ploc+2] &0x80) {
 8975            in[ploc+0] = (byte)(in[ploc+1]+1);
 8976            in[ploc+1] = (byte)(in[ploc+2] &0x7f);
 8977            in[ploc+2] = 0x80;
 8978            parms[mIEindex] = &in[ploc];
 8979          }
 8980        }
 8981        mIEindex++;       /* effects multiIEs only */
 8982      }
 8983    }
 8984
 8985    ploc +=(wlen+1);
 8986  }
 8987  return ;
 8988}
 8989
 8990/*------------------------------------------------------------------*/
 8991/* try to match a cip from received BC and HLC                      */
 8992/*------------------------------------------------------------------*/
 8993
 8994byte ie_compare(byte   * ie1, byte * ie2)
 8995{
 8996  word i;
 8997  if(!ie1 || ! ie2) return false;
 8998  if(!ie1[0]) return false;
 8999  for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
 9000  return true;
 9001}
 9002
 9003word find_cip(DIVA_CAPI_ADAPTER   * a, byte   * bc, byte   * hlc)
 9004{
 9005  word i;
 9006  word j;
 9007
 9008  for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
 9009
 9010  for(j=16;j<29 &&
 9011           (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
 9012  if(j==29) return i;
 9013  return j;
 9014}
 9015
 9016
 9017static byte AddInfo(byte   **add_i,
 9018                    byte   **fty_i,
 9019                    byte   *esc_chi,
 9020                    byte *facility)
 9021{
 9022  byte i;
 9023  byte j;
 9024  byte k;
 9025  byte flen;
 9026  byte len=0;
 9027   /* facility is a nested structure */
 9028   /* FTY can be more than once      */
 9029
 9030        if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
 9031  {
 9032    add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
 9033  }
 9034
 9035  else
 9036  {
 9037    add_i[0] = (byte   *)"";
 9038  }
 9039  if(!fty_i[0][0])
 9040  {
 9041    add_i[3] = (byte   *)"";
 9042  }
 9043  else
 9044  {    /* facility array found  */
 9045    for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
 9046    {
 9047      dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
 9048      len += fty_i[i][0];
 9049      len += 2;
 9050      flen=fty_i[i][0];
 9051      facility[j++]=0x1c; /* copy fac IE */
 9052      for(k=0;k<=flen;k++,j++)
 9053      {
 9054        facility[j]=fty_i[i][k];
 9055/*      dbug(1,dprintf("%x ",facility[j])); */
 9056      }
 9057    }
 9058    facility[0] = len;
 9059    add_i[3] = facility;
 9060  }
 9061/*  dbug(1,dprintf("FacArrLen=%d ",len)); */
 9062  len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
 9063  len += 4;                          /* calculate length of all */
 9064  return(len);
 9065}
 9066
 9067/*------------------------------------------------------------------*/
 9068/* voice and codec features                                         */
 9069/*------------------------------------------------------------------*/
 9070
 9071void SetVoiceChannel(PLCI   *plci, byte   *chi, DIVA_CAPI_ADAPTER   * a)
 9072{
 9073  byte voice_chi[] = "\x02\x18\x01";
 9074  byte channel;
 9075
 9076  channel = chi[chi[0]]&0x3;
 9077  dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
 9078  voice_chi[2] = (channel) ? channel : 1;
 9079  add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
 9080  add_p(plci,ESC,voice_chi);                  /* Channel */
 9081  sig_req(plci,TEL_CTRL,0);
 9082  send_req(plci);
 9083  if(a->AdvSignalPLCI)
 9084  {
 9085    adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
 9086  }
 9087}
 9088
 9089void VoiceChannelOff(PLCI   *plci)
 9090{
 9091  dbug(1,dprintf("ExtDevOFF"));
 9092  add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
 9093  sig_req(plci,TEL_CTRL,0);
 9094  send_req(plci);
 9095  if(plci->adapter->AdvSignalPLCI)
 9096  {
 9097    adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
 9098  }
 9099}
 9100
 9101
 9102word AdvCodecSupport(DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, byte hook_listen)
 9103{
 9104  word j;
 9105  PLCI   *splci;
 9106
 9107  /* check if hardware supports handset with hook states (adv.codec) */
 9108  /* or if just a on board codec is supported                        */
 9109  /* the advanced codec plci is just for internal use                */
 9110
 9111  /* diva Pro with on-board codec:                                   */
 9112  if(a->profile.Global_Options & HANDSET)
 9113  {
 9114    /* new call, but hook states are already signalled */
 9115    if(a->AdvCodecFLAG)
 9116    {
 9117      if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
 9118      {
 9119        dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
 9120        return 0x2001; /* codec in use by another application */
 9121      }
 9122      if(plci!=NULL)
 9123      {
 9124        a->AdvSignalPLCI = plci;
 9125        plci->tel=ADV_VOICE;
 9126      }
 9127      return 0;                      /* adv codec still used */
 9128    }
 9129    if((j=get_plci(a)))
 9130    {
 9131      splci = &a->plci[j-1];
 9132      splci->tel = CODEC_PERMANENT;
 9133      /* hook_listen indicates if a facility_req with handset/hook support */
 9134      /* was sent. Otherwise if just a call on an external device was made */
 9135      /* the codec will be used but the hook info will be discarded (just  */
 9136      /* the external controller is in use                                 */
 9137      if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
 9138      else
 9139      {
 9140        splci->State = ADVANCED_VOICE_NOSIG;
 9141        if(plci)
 9142        {
 9143          plci->spoofed_msg = SPOOFING_REQUIRED;
 9144        }
 9145                                               /* indicate D-ch connect if  */
 9146      }                                        /* codec is connected OK     */
 9147      if(plci!=NULL)
 9148      {
 9149        a->AdvSignalPLCI = plci;
 9150        plci->tel=ADV_VOICE;
 9151      }
 9152      a->AdvSignalAppl = appl;
 9153      a->AdvCodecFLAG = true;
 9154      a->AdvCodecPLCI = splci;
 9155      add_p(splci,CAI,"\x01\x15");
 9156      add_p(splci,LLI,"\x01\x00");
 9157      add_p(splci,ESC,"\x02\x18\x00");
 9158      add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 9159      splci->internal_command = PERM_COD_ASSIGN;
 9160      dbug(1,dprintf("Codec Assign"));
 9161      sig_req(splci,ASSIGN,DSIG_ID);
 9162      send_req(splci);
 9163    }
 9164    else
 9165    {
 9166      return 0x2001; /* wrong state, no more plcis */
 9167    }
 9168  }
 9169  else if(a->profile.Global_Options & ON_BOARD_CODEC)
 9170  {
 9171    if(hook_listen) return 0x300B;               /* Facility not supported */
 9172                                                 /* no hook with SCOM      */
 9173    if(plci!=NULL) plci->tel = CODEC;
 9174    dbug(1,dprintf("S/SCOM codec"));
 9175    /* first time we use the scom-s codec we must shut down the internal   */
 9176    /* handset application of the card. This can be done by an assign with */
 9177    /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
 9178    if(!a->scom_appl_disable){
 9179      if((j=get_plci(a))) {
 9180        splci = &a->plci[j-1];
 9181        add_p(splci,CAI,"\x01\x80");
 9182        add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 9183        sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
 9184        send_req(splci);
 9185        a->scom_appl_disable = true;
 9186      }
 9187      else{
 9188        return 0x2001; /* wrong state, no more plcis */
 9189      }
 9190    }
 9191  }
 9192  else return 0x300B;               /* Facility not supported */
 9193
 9194  return 0;
 9195}
 9196
 9197
 9198void CodecIdCheck(DIVA_CAPI_ADAPTER   *a, PLCI   *plci)
 9199{
 9200
 9201  dbug(1,dprintf("CodecIdCheck"));
 9202
 9203  if(a->AdvSignalPLCI == plci)
 9204  {
 9205    dbug(1,dprintf("PLCI owns codec"));
 9206    VoiceChannelOff(a->AdvCodecPLCI);
 9207    if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
 9208    {
 9209      dbug(1,dprintf("remove temp codec PLCI"));
 9210      plci_remove(a->AdvCodecPLCI);
 9211      a->AdvCodecFLAG  = 0;
 9212      a->AdvCodecPLCI  = NULL;
 9213      a->AdvSignalAppl = NULL;
 9214    }
 9215    a->AdvSignalPLCI = NULL;
 9216  }
 9217}
 9218
 9219/* -------------------------------------------------------------------
 9220    Ask for physical address of card on PCI bus
 9221   ------------------------------------------------------------------- */
 9222static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
 9223                                        IDI_SYNC_REQ  * preq) {
 9224  a->sdram_bar = 0;
 9225  if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
 9226    ENTITY   * e = (ENTITY   *)preq;
 9227
 9228    e->user[0] = a->Id - 1;
 9229    preq->xdi_sdram_bar.info.bar    = 0;
 9230    preq->xdi_sdram_bar.Req         = 0;
 9231    preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
 9232
 9233    (*(a->request))(e);
 9234
 9235    a->sdram_bar = preq->xdi_sdram_bar.info.bar;
 9236    dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
 9237  }
 9238}
 9239
 9240/* -------------------------------------------------------------------
 9241     Ask XDI about extended features
 9242   ------------------------------------------------------------------- */
 9243static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
 9244  IDI_SYNC_REQ   * preq;
 9245    char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
 9246
 9247    char features[4];
 9248  preq = (IDI_SYNC_REQ   *)&buffer[0];
 9249
 9250  if (!diva_xdi_extended_features) {
 9251    ENTITY   * e = (ENTITY   *)preq;
 9252    diva_xdi_extended_features |= 0x80000000;
 9253
 9254    e->user[0] = a->Id - 1;
 9255    preq->xdi_extended_features.Req = 0;
 9256    preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
 9257    preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
 9258    preq->xdi_extended_features.info.features = &features[0];
 9259
 9260    (*(a->request))(e);
 9261
 9262    if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
 9263      /*
 9264         Check features located in the byte '0'
 9265         */
 9266      if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
 9267        diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
 9268      }
 9269      if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
 9270        diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
 9271        dbug(1,dprintf("XDI provides RxDMA"));
 9272      }
 9273      if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
 9274        diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
 9275      }
 9276      if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
 9277        diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
 9278        dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
 9279      }
 9280
 9281    }
 9282  }
 9283
 9284  diva_ask_for_xdi_sdram_bar (a, preq);
 9285}
 9286
 9287/*------------------------------------------------------------------*/
 9288/* automatic law                                                    */
 9289/*------------------------------------------------------------------*/
 9290/* called from OS specific part after init time to get the Law              */
 9291/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
 9292void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
 9293{
 9294  word j;
 9295  PLCI   *splci;
 9296
 9297  if(a->automatic_law) {
 9298    return;
 9299  }
 9300  if((j=get_plci(a))) {
 9301    diva_get_extended_adapter_features (a);
 9302    splci = &a->plci[j-1];
 9303    a->automatic_lawPLCI = splci;
 9304    a->automatic_law = 1;
 9305    add_p(splci,CAI,"\x01\x80");
 9306    add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 9307    splci->internal_command = USELAW_REQ;
 9308    splci->command = 0;
 9309    splci->number = 0;
 9310    sig_req(splci,ASSIGN,DSIG_ID);
 9311    send_req(splci);
 9312  }
 9313}
 9314
 9315/* called from OS specific part if an application sends an Capi20Release */
 9316word CapiRelease(word Id)
 9317{
 9318  word i, j, appls_found;
 9319  PLCI   *plci;
 9320  APPL   *this;
 9321  DIVA_CAPI_ADAPTER   *a;
 9322
 9323  if (!Id)
 9324  {
 9325    dbug(0,dprintf("A: CapiRelease(Id==0)"));
 9326    return (_WRONG_APPL_ID);
 9327  }
 9328
 9329  this = &application[Id-1];               /* get application pointer */
 9330
 9331  for(i=0,appls_found=0; i<max_appl; i++)
 9332  {
 9333    if(application[i].Id)       /* an application has been found        */
 9334    {
 9335      appls_found++;
 9336    }
 9337  }
 9338
 9339  for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
 9340  {
 9341    a = &adapter[i];
 9342    if (a->request)
 9343    {
 9344      a->Info_Mask[Id-1] = 0;
 9345      a->CIP_Mask[Id-1] = 0;
 9346      a->Notification_Mask[Id-1] = 0;
 9347      a->codec_listen[Id-1] = NULL;
 9348      a->requested_options_table[Id-1] = 0;
 9349      for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
 9350      {                                      /* with this application   */
 9351        plci = &a->plci[j];
 9352        if(plci->Id)                         /* if plci owns no application */
 9353        {                                    /* it may be not jet connected */
 9354          if(plci->State==INC_CON_PENDING
 9355          || plci->State==INC_CON_ALERT)
 9356          {
 9357            if(test_c_ind_mask_bit (plci, (word)(Id-1)))
 9358            {
 9359              clear_c_ind_mask_bit (plci, (word)(Id-1));
 9360              if(c_ind_mask_empty (plci))
 9361              {
 9362                sig_req(plci,HANGUP,0);
 9363                send_req(plci);
 9364                plci->State = OUTG_DIS_PENDING;
 9365              }
 9366            }
 9367          }
 9368          if(test_c_ind_mask_bit (plci, (word)(Id-1)))
 9369          {
 9370            clear_c_ind_mask_bit (plci, (word)(Id-1));
 9371            if(c_ind_mask_empty (plci))
 9372            {
 9373              if(!plci->appl)
 9374              {
 9375                plci_remove(plci);
 9376                plci->State = IDLE;
 9377              }
 9378            }
 9379          }
 9380          if(plci->appl==this)
 9381          {
 9382            plci->appl = NULL;
 9383            plci_remove(plci);
 9384            plci->State = IDLE;
 9385          }
 9386        }
 9387      }
 9388      listen_check(a);
 9389
 9390      if(a->flag_dynamic_l1_down)
 9391      {
 9392        if(appls_found==1)            /* last application does a capi release */
 9393        {
 9394          if((j=get_plci(a)))
 9395          {
 9396            plci = &a->plci[j-1];
 9397            plci->command = 0;
 9398            add_p(plci,OAD,"\x01\xfd");
 9399            add_p(plci,CAI,"\x01\x80");
 9400            add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
 9401            add_p(plci,SHIFT|6,NULL);
 9402            add_p(plci,SIN,"\x02\x00\x00");
 9403            plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
 9404            sig_req(plci,ASSIGN,DSIG_ID);
 9405            add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
 9406            sig_req(plci,SIG_CTRL,0);
 9407            send_req(plci);
 9408          }
 9409        }
 9410      }
 9411      if(a->AdvSignalAppl==this)
 9412      {
 9413        this->NullCREnable = false;
 9414        if (a->AdvCodecPLCI)
 9415        {
 9416          plci_remove(a->AdvCodecPLCI);
 9417          a->AdvCodecPLCI->tel = 0;
 9418          a->AdvCodecPLCI->adv_nl = 0;
 9419        }
 9420        a->AdvSignalAppl = NULL;
 9421        a->AdvSignalPLCI = NULL;
 9422        a->AdvCodecFLAG = 0;
 9423        a->AdvCodecPLCI = NULL;
 9424      }
 9425    }
 9426  }
 9427
 9428  this->Id = 0;
 9429
 9430  return GOOD;
 9431}
 9432
 9433static word plci_remove_check(PLCI   *plci)
 9434{
 9435  if(!plci) return true;
 9436  if(!plci->NL.Id && c_ind_mask_empty (plci))
 9437  {
 9438    if(plci->Sig.Id == 0xff)
 9439      plci->Sig.Id = 0;
 9440    if(!plci->Sig.Id)
 9441    {
 9442      dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
 9443      dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
 9444      if (plci->Id)
 9445      {
 9446        CodecIdCheck(plci->adapter, plci);
 9447        clear_b1_config (plci);
 9448        ncci_remove (plci, 0, false);
 9449        plci_free_msg_in_queue (plci);
 9450        channel_flow_control_remove (plci);
 9451        plci->Id = 0;
 9452        plci->State = IDLE;
 9453        plci->channels = 0;
 9454        plci->appl = NULL;
 9455        plci->notifiedcall = 0;
 9456      }
 9457      listen_check(plci->adapter);
 9458      return true;
 9459    }
 9460  }
 9461  return false;
 9462}
 9463
 9464
 9465/*------------------------------------------------------------------*/
 9466
 9467static byte plci_nl_busy (PLCI   *plci)
 9468{
 9469  /* only applicable for non-multiplexed protocols */
 9470  return (plci->nl_req
 9471    || (plci->ncci_ring_list
 9472     && plci->adapter->ncci_ch[plci->ncci_ring_list]
 9473     && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
 9474}
 9475
 9476
 9477/*------------------------------------------------------------------*/
 9478/* DTMF facilities                                                  */
 9479/*------------------------------------------------------------------*/
 9480
 9481
 9482static struct
 9483{
 9484  byte send_mask;
 9485  byte listen_mask;
 9486  byte character;
 9487  byte code;
 9488} dtmf_digit_map[] =
 9489{
 9490  { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
 9491  { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
 9492  { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
 9493  { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
 9494  { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
 9495  { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
 9496  { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
 9497  { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
 9498  { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
 9499  { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
 9500  { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
 9501  { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
 9502  { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
 9503  { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
 9504  { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
 9505  { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
 9506  { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
 9507  { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
 9508  { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
 9509  { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
 9510
 9511  { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
 9512  { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
 9513  { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
 9514  { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
 9515  { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
 9516  { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
 9517  { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
 9518  { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
 9519  { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
 9520  { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
 9521  { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
 9522  { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
 9523  { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
 9524  { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
 9525  { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
 9526  { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
 9527  { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
 9528  { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
 9529  { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
 9530  { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
 9531  { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
 9532  { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
 9533  { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
 9534  { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
 9535  { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
 9536  { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
 9537  { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
 9538  { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
 9539  { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
 9540  { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
 9541  { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
 9542  { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
 9543  { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
 9544  { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
 9545  { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
 9546  { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
 9547  { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
 9548  { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
 9549  { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
 9550  { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
 9551  { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
 9552  { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
 9553  { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
 9554  { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
 9555  { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
 9556  { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
 9557  { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
 9558  { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
 9559  { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
 9560  { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
 9561  { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
 9562  { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
 9563
 9564};
 9565
 9566#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
 9567
 9568
 9569static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
 9570{
 9571  word min_digit_duration, min_gap_duration;
 9572
 9573  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
 9574    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
 9575    (char   *)(FILE_), __LINE__, enable_mask));
 9576
 9577  if (enable_mask != 0)
 9578  {
 9579    min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
 9580    min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
 9581    plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
 9582    PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
 9583    PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
 9584    plci->NData[0].PLength = 5;
 9585
 9586    PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
 9587    plci->NData[0].PLength += 2;
 9588    capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
 9589
 9590  }
 9591  else
 9592  {
 9593    plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
 9594    plci->NData[0].PLength = 1;
 9595
 9596    capidtmf_recv_disable (&(plci->capidtmf_state));
 9597
 9598  }
 9599  plci->NData[0].P = plci->internal_req_buffer;
 9600  plci->NL.X = plci->NData;
 9601  plci->NL.ReqCh = 0;
 9602  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
 9603  plci->adapter->request (&plci->NL);
 9604}
 9605
 9606
 9607static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
 9608{
 9609  word w, i;
 9610
 9611  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
 9612    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
 9613    (char   *)(FILE_), __LINE__, digit_count));
 9614
 9615  plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
 9616  w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
 9617  PUT_WORD (&plci->internal_req_buffer[1], w);
 9618  w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
 9619  PUT_WORD (&plci->internal_req_buffer[3], w);
 9620  for (i = 0; i < digit_count; i++)
 9621  {
 9622    w = 0;
 9623    while ((w < DTMF_DIGIT_MAP_ENTRIES)
 9624      && (digit_buffer[i] != dtmf_digit_map[w].character))
 9625    {
 9626      w++;
 9627    }
 9628    plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
 9629      dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
 9630  }
 9631  plci->NData[0].PLength = 5 + digit_count;
 9632  plci->NData[0].P = plci->internal_req_buffer;
 9633  plci->NL.X = plci->NData;
 9634  plci->NL.ReqCh = 0;
 9635  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
 9636  plci->adapter->request (&plci->NL);
 9637}
 9638
 9639
 9640static void dtmf_rec_clear_config (PLCI   *plci)
 9641{
 9642
 9643  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
 9644    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
 9645    (char   *)(FILE_), __LINE__));
 9646
 9647  plci->dtmf_rec_active = 0;
 9648  plci->dtmf_rec_pulse_ms = 0;
 9649  plci->dtmf_rec_pause_ms = 0;
 9650
 9651  capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
 9652
 9653}
 9654
 9655
 9656static void dtmf_send_clear_config (PLCI   *plci)
 9657{
 9658
 9659  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
 9660    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
 9661    (char   *)(FILE_), __LINE__));
 9662
 9663  plci->dtmf_send_requests = 0;
 9664  plci->dtmf_send_pulse_ms = 0;
 9665  plci->dtmf_send_pause_ms = 0;
 9666}
 9667
 9668
 9669static void dtmf_prepare_switch (dword Id, PLCI   *plci)
 9670{
 9671
 9672  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
 9673    UnMapId (Id), (char   *)(FILE_), __LINE__));
 9674
 9675  while (plci->dtmf_send_requests != 0)
 9676    dtmf_confirmation (Id, plci);
 9677}
 9678
 9679
 9680static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
 9681{
 9682
 9683  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
 9684    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
 9685
 9686  return (GOOD);
 9687}
 9688
 9689
 9690static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
 9691{
 9692  word Info;
 9693
 9694  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
 9695    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
 9696
 9697  Info = GOOD;
 9698  if (plci->B1_facilities & B1_FACILITY_DTMFR)
 9699  {
 9700    switch (plci->adjust_b_state)
 9701    {
 9702    case ADJUST_B_RESTORE_DTMF_1:
 9703      plci->internal_command = plci->adjust_b_command;
 9704      if (plci_nl_busy (plci))
 9705      {
 9706        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
 9707        break;
 9708      }
 9709      dtmf_enable_receiver (plci, plci->dtmf_rec_active);
 9710      plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
 9711      break;
 9712    case ADJUST_B_RESTORE_DTMF_2:
 9713      if ((Rc != OK) && (Rc != OK_FC))
 9714      {
 9715        dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
 9716          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
 9717        Info = _WRONG_STATE;
 9718        break;
 9719      }
 9720      break;
 9721    }
 9722  }
 9723  return (Info);
 9724}
 9725
 9726
 9727static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
 9728{
 9729  word internal_command, Info;
 9730  byte mask;
 9731    byte result[4];
 9732
 9733  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
 9734    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
 9735    plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
 9736    plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
 9737
 9738  Info = GOOD;
 9739  result[0] = 2;
 9740  PUT_WORD (&result[1], DTMF_SUCCESS);
 9741  internal_command = plci->internal_command;
 9742  plci->internal_command = 0;
 9743  mask = 0x01;
 9744  switch (plci->dtmf_cmd)
 9745  {
 9746
 9747  case DTMF_LISTEN_TONE_START:
 9748    mask <<= 1;
 9749  case DTMF_LISTEN_MF_START:
 9750    mask <<= 1;
 9751
 9752  case DTMF_LISTEN_START:
 9753    switch (internal_command)
 9754    {
 9755    default:
 9756      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
 9757        B1_FACILITY_DTMFR), DTMF_COMMAND_1);
 9758    case DTMF_COMMAND_1:
 9759      if (adjust_b_process (Id, plci, Rc) != GOOD)
 9760      {
 9761        dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
 9762          UnMapId (Id), (char   *)(FILE_), __LINE__));
 9763        Info = _FACILITY_NOT_SUPPORTED;
 9764        break;
 9765      }
 9766      if (plci->internal_command)
 9767        return;
 9768    case DTMF_COMMAND_2:
 9769      if (plci_nl_busy (plci))
 9770      {
 9771        plci->internal_command = DTMF_COMMAND_2;
 9772        return;
 9773      }
 9774      plci->internal_command = DTMF_COMMAND_3;
 9775      dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
 9776      return;
 9777    case DTMF_COMMAND_3:
 9778      if ((Rc != OK) && (Rc != OK_FC))
 9779      {
 9780        dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
 9781          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
 9782        Info = _FACILITY_NOT_SUPPORTED;
 9783        break;
 9784      }
 9785
 9786      plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
 9787
 9788      plci->dtmf_rec_active |= mask;
 9789      break;
 9790    }
 9791    break;
 9792
 9793
 9794  case DTMF_LISTEN_TONE_STOP:
 9795    mask <<= 1;
 9796  case DTMF_LISTEN_MF_STOP:
 9797    mask <<= 1;
 9798
 9799  case DTMF_LISTEN_STOP:
 9800    switch (internal_command)
 9801    {
 9802    default:
 9803      plci->dtmf_rec_active &= ~mask;
 9804      if (plci->dtmf_rec_active)
 9805        break;
 9806/*
 9807    case DTMF_COMMAND_1:
 9808      if (plci->dtmf_rec_active)
 9809      {
 9810        if (plci_nl_busy (plci))
 9811        {
 9812          plci->internal_command = DTMF_COMMAND_1;
 9813          return;
 9814        }
 9815        plci->dtmf_rec_active &= ~mask;
 9816        plci->internal_command = DTMF_COMMAND_2;
 9817        dtmf_enable_receiver (plci, false);
 9818        return;
 9819      }
 9820      Rc = OK;
 9821    case DTMF_COMMAND_2:
 9822      if ((Rc != OK) && (Rc != OK_FC))
 9823      {
 9824        dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
 9825          UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
 9826        Info = _FACILITY_NOT_SUPPORTED;
 9827        break;
 9828      }
 9829*/
 9830      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
 9831        ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
 9832    case DTMF_COMMAND_3:
 9833      if (adjust_b_process (Id, plci, Rc) != GOOD)
 9834      {
 9835        dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
 9836          UnMapId (Id), (char   *)(FILE_), __LINE__));
 9837        Info = _FACILITY_NOT_SUPPORTED;
 9838        break;
 9839      }
 9840      if (plci->internal_command)
 9841        return;
 9842      break;
 9843    }
 9844    break;
 9845
 9846
 9847  case DTMF_SEND_TONE:
 9848    mask <<= 1;
 9849  case DTMF_SEND_MF:
 9850    mask <<= 1;
 9851
 9852  case DTMF_DIGITS_SEND:
 9853    switch (internal_command)
 9854    {
 9855    default:
 9856      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
 9857        ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
 9858        DTMF_COMMAND_1);
 9859    case DTMF_COMMAND_1:
 9860      if (adjust_b_process (Id, plci, Rc) != GOOD)
 9861      {
 9862        dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
 9863          UnMapId (Id), (char   *)(FILE_), __LINE__));
 9864        Info = _FACILITY_NOT_SUPPORTED;
 9865        break;
 9866      }
 9867      if (plci->internal_command)
 9868        return;
 9869    case DTMF_COMMAND_2:
 9870      if (plci_nl_busy (plci))
 9871      {
 9872        plci->internal_command = DTMF_COMMAND_2;
 9873        return;
 9874      }
 9875      plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
 9876      plci->internal_command = DTMF_COMMAND_3;
 9877      dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
 9878      return;
 9879    case DTMF_COMMAND_3:
 9880      if ((Rc != OK) && (Rc != OK_FC))
 9881      {
 9882        dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
 9883          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
 9884        if (plci->dtmf_send_requests != 0)
 9885          (plci->dtmf_send_requests)--;
 9886        Info = _FACILITY_NOT_SUPPORTED;
 9887        break;
 9888      }
 9889      return;
 9890    }
 9891    break;
 9892  }
 9893  sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
 9894    "wws", Info, SELECTOR_DTMF, result);
 9895}
 9896
 9897
 9898static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
 9899{
 9900  word Info;
 9901  word i, j;
 9902  byte mask;
 9903    API_PARSE dtmf_parms[5];
 9904    byte result[40];
 9905
 9906  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
 9907    UnMapId (Id), (char   *)(FILE_), __LINE__));
 9908
 9909  Info = GOOD;
 9910  result[0] = 2;
 9911  PUT_WORD (&result[1], DTMF_SUCCESS);
 9912  if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
 9913  {
 9914    dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
 9915      UnMapId (Id), (char   *)(FILE_), __LINE__));
 9916    Info = _FACILITY_NOT_SUPPORTED;
 9917  }
 9918  else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
 9919  {
 9920    dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
 9921      UnMapId (Id), (char   *)(FILE_), __LINE__));
 9922    Info = _WRONG_MESSAGE_FORMAT;
 9923  }
 9924
 9925  else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
 9926    || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
 9927  {
 9928    if (!((a->requested_options_table[appl->Id-1])
 9929        & (1L << PRIVATE_DTMF_TONE)))
 9930    {
 9931      dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
 9932        UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
 9933      PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
 9934    }
 9935    else
 9936    {
 9937      for (i = 0; i < 32; i++)
 9938        result[4 + i] = 0;
 9939      if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
 9940      {
 9941        for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
 9942        {
 9943          if (dtmf_digit_map[i].listen_mask != 0)
 9944            result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
 9945        }
 9946      }
 9947      else
 9948      {
 9949        for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
 9950        {
 9951          if (dtmf_digit_map[i].send_mask != 0)
 9952            result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
 9953        }
 9954      }
 9955      result[0] = 3 + 32;
 9956      result[3] = 32;
 9957    }
 9958  }
 9959
 9960  else if (plci == NULL)
 9961  {
 9962    dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
 9963      UnMapId (Id), (char   *)(FILE_), __LINE__));
 9964    Info = _WRONG_IDENTIFIER;
 9965  }
 9966  else
 9967  {
 9968    if (!plci->State
 9969     || !plci->NL.Id || plci->nl_remove_id)
 9970    {
 9971      dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
 9972        UnMapId (Id), (char   *)(FILE_), __LINE__));
 9973      Info = _WRONG_STATE;
 9974    }
 9975    else
 9976    {
 9977      plci->command = 0;
 9978      plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
 9979      mask = 0x01;
 9980      switch (plci->dtmf_cmd)
 9981      {
 9982
 9983      case DTMF_LISTEN_TONE_START:
 9984      case DTMF_LISTEN_TONE_STOP:
 9985        mask <<= 1;
 9986      case DTMF_LISTEN_MF_START:
 9987      case DTMF_LISTEN_MF_STOP:
 9988        mask <<= 1;
 9989        if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
 9990          & (1L << PRIVATE_DTMF_TONE)))
 9991        {
 9992          dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
 9993            UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
 9994          PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
 9995          break;
 9996        }
 9997
 9998      case DTMF_LISTEN_START:
 9999      case DTMF_LISTEN_STOP:
10000        if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10001         && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10002        {
10003          dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10004            UnMapId (Id), (char   *)(FILE_), __LINE__));
10005          Info = _FACILITY_NOT_SUPPORTED;
10006          break;
10007        }
10008        if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10009        {
10010          if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10011          {
10012            plci->dtmf_rec_pulse_ms = 0;
10013            plci->dtmf_rec_pause_ms = 0;
10014          }
10015          else
10016          {
10017            plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10018            plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10019          }
10020        }
10021        start_internal_command (Id, plci, dtmf_command);
10022        return (false);
10023
10024
10025      case DTMF_SEND_TONE:
10026        mask <<= 1;
10027      case DTMF_SEND_MF:
10028        mask <<= 1;
10029        if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10030          & (1L << PRIVATE_DTMF_TONE)))
10031        {
10032          dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10033            UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10034          PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10035          break;
10036        }
10037
10038      case DTMF_DIGITS_SEND:
10039        if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10040        {
10041          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10042            UnMapId (Id), (char   *)(FILE_), __LINE__));
10043          Info = _WRONG_MESSAGE_FORMAT;
10044          break;
10045        }
10046        if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10047        {
10048          plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10049          plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10050        }
10051        i = 0;
10052        j = 0;
10053        while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10054        {
10055          j = 0;
10056          while ((j < DTMF_DIGIT_MAP_ENTRIES)
10057            && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10058             || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10059          {
10060            j++;
10061          }
10062          i++;
10063        }
10064        if (j == DTMF_DIGIT_MAP_ENTRIES)
10065        {
10066          dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10067            UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10068          PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10069          break;
10070        }
10071        if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10072        {
10073          dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10074            UnMapId (Id), (char   *)(FILE_), __LINE__));
10075          Info = _WRONG_STATE;
10076          break;
10077        }
10078        api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10079        start_internal_command (Id, plci, dtmf_command);
10080        return (false);
10081
10082      default:
10083        dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10084          UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10085        PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10086      }
10087    }
10088  }
10089  sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10090    "wws", Info, SELECTOR_DTMF, result);
10091  return (false);
10092}
10093
10094
10095static void dtmf_confirmation (dword Id, PLCI   *plci)
10096{
10097  word Info;
10098  word i;
10099    byte result[4];
10100
10101  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10102    UnMapId (Id), (char   *)(FILE_), __LINE__));
10103
10104  Info = GOOD;
10105  result[0] = 2;
10106  PUT_WORD (&result[1], DTMF_SUCCESS);
10107  if (plci->dtmf_send_requests != 0)
10108  {
10109    sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10110      "wws", GOOD, SELECTOR_DTMF, result);
10111    (plci->dtmf_send_requests)--;
10112    for (i = 0; i < plci->dtmf_send_requests; i++)
10113      plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10114  }
10115}
10116
10117
10118static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10119{
10120  word i, j, n;
10121
10122  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10123    UnMapId (Id), (char   *)(FILE_), __LINE__));
10124
10125  n = 0;
10126  for (i = 1; i < length; i++)
10127  {
10128    j = 0;
10129    while ((j < DTMF_DIGIT_MAP_ENTRIES)
10130      && ((msg[i] != dtmf_digit_map[j].code)
10131       || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10132    {
10133      j++;
10134    }
10135    if (j < DTMF_DIGIT_MAP_ENTRIES)
10136    {
10137
10138      if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10139       && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10140       && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10141      {
10142        if (n + 1 == i)
10143        {
10144          for (i = length; i > n + 1; i--)
10145            msg[i] = msg[i - 1];
10146          length++;
10147          i++;
10148        }
10149        msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10150      }
10151      plci->tone_last_indication_code = dtmf_digit_map[j].character;
10152
10153      msg[++n] = dtmf_digit_map[j].character;
10154    }
10155  }
10156  if (n != 0)
10157  {
10158    msg[0] = (byte) n;
10159    sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10160  }
10161}
10162
10163
10164/*------------------------------------------------------------------*/
10165/* DTMF parameters                                                  */
10166/*------------------------------------------------------------------*/
10167
10168static void dtmf_parameter_write (PLCI   *plci)
10169{
10170  word i;
10171    byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10172
10173  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10174    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10175    (char   *)(FILE_), __LINE__));
10176
10177  parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10178  parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10179  for (i = 0; i < plci->dtmf_parameter_length; i++)
10180    parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10181  add_p (plci, FTY, parameter_buffer);
10182  sig_req (plci, TEL_CTRL, 0);
10183  send_req (plci);
10184}
10185
10186
10187static void dtmf_parameter_clear_config (PLCI   *plci)
10188{
10189
10190  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10191    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10192    (char   *)(FILE_), __LINE__));
10193
10194  plci->dtmf_parameter_length = 0;
10195}
10196
10197
10198static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10199{
10200
10201  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10202    UnMapId (Id), (char   *)(FILE_), __LINE__));
10203
10204}
10205
10206
10207static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10208{
10209
10210  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10211    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10212
10213  return (GOOD);
10214}
10215
10216
10217static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10218{
10219  word Info;
10220
10221  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10222    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10223
10224  Info = GOOD;
10225  if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10226   && (plci->dtmf_parameter_length != 0))
10227  {
10228    switch (plci->adjust_b_state)
10229    {
10230    case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10231      plci->internal_command = plci->adjust_b_command;
10232      if (plci->sig_req)
10233      {
10234        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10235        break;
10236      }
10237      dtmf_parameter_write (plci);
10238      plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10239      break;
10240    case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10241      if ((Rc != OK) && (Rc != OK_FC))
10242      {
10243        dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10244          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10245        Info = _WRONG_STATE;
10246        break;
10247      }
10248      break;
10249    }
10250  }
10251  return (Info);
10252}
10253
10254
10255/*------------------------------------------------------------------*/
10256/* Line interconnect facilities                                     */
10257/*------------------------------------------------------------------*/
10258
10259
10260LI_CONFIG   *li_config_table;
10261word li_total_channels;
10262
10263
10264/*------------------------------------------------------------------*/
10265/* translate a CHI information element to a channel number          */
10266/* returns 0xff - any channel                                       */
10267/*         0xfe - chi wrong coding                                  */
10268/*         0xfd - D-channel                                         */
10269/*         0x00 - no channel                                        */
10270/*         else channel number / PRI: timeslot                      */
10271/* if channels is provided we accept more than one channel.         */
10272/*------------------------------------------------------------------*/
10273
10274static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10275{
10276  int p;
10277  int i;
10278  dword map;
10279  byte excl;
10280  byte ofs;
10281  byte ch;
10282
10283  if (pchannelmap) *pchannelmap = 0;
10284  if(!chi[0]) return 0xff;
10285  excl = 0;
10286
10287  if(chi[1] & 0x20) {
10288    if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10289    for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10290    if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10291    if((chi[1] |0xc8)!=0xe9) return 0xfe;
10292    if(chi[1] &0x08) excl = 0x40;
10293
10294        /* int. id present */
10295    if(chi[1] &0x40) {
10296      p=i+1;
10297      for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10298      if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10299    }
10300
10301        /* coding standard, Number/Map, Channel Type */
10302    p=i+1;
10303    for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10304    if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10305    if((chi[p]|0xd0)!=0xd3) return 0xfe;
10306
10307        /* Number/Map */
10308    if(chi[p] &0x10) {
10309
10310        /* map */
10311      if((chi[0]-p)==4) ofs = 0;
10312      else if((chi[0]-p)==3) ofs = 1;
10313      else return 0xfe;
10314      ch = 0;
10315      map = 0;
10316      for(i=0; i<4 && p<chi[0]; i++) {
10317        p++;
10318        ch += 8;
10319        map <<= 8;
10320        if(chi[p]) {
10321          for (ch=0; !(chi[p] & (1 << ch)); ch++);
10322          map |= chi[p];
10323        }
10324      }
10325      ch += ofs;
10326      map <<= ofs;
10327    }
10328    else {
10329
10330        /* number */
10331      p=i+1;
10332      ch = chi[p] &0x3f;
10333      if(pchannelmap) {
10334        if((byte)(chi[0]-p)>30) return 0xfe;
10335        map = 0;
10336        for(i=p; i<=chi[0]; i++) {
10337          if ((chi[i] &0x7f) > 31) return 0xfe;
10338          map |= (1L << (chi[i] &0x7f));
10339        }
10340      }
10341      else {
10342        if(p!=chi[0]) return 0xfe;
10343        if (ch > 31) return 0xfe;
10344        map = (1L << ch);
10345      }
10346      if(chi[p] &0x40) return 0xfe;
10347    }
10348    if (pchannelmap) *pchannelmap = map;
10349    else if (map != ((dword)(1L << ch))) return 0xfe;
10350    return (byte)(excl | ch);
10351  }
10352  else {  /* not PRI */
10353    for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10354    if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10355    if(chi[1] &0x08) excl = 0x40;
10356
10357    switch(chi[1] |0x98) {
10358    case 0x98: return 0;
10359    case 0x99:
10360      if (pchannelmap) *pchannelmap = 2;
10361      return excl |1;
10362    case 0x9a:
10363      if (pchannelmap) *pchannelmap = 4;
10364      return excl |2;
10365    case 0x9b: return 0xff;
10366    case 0x9c: return 0xfd; /* d-ch */
10367    default: return 0xfe;
10368    }
10369  }
10370}
10371
10372
10373static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10374{
10375  DIVA_CAPI_ADAPTER   *a;
10376  PLCI   *splci;
10377  byte old_id;
10378
10379  a = plci->adapter;
10380  old_id = plci->li_bchannel_id;
10381  if (a->li_pri)
10382  {
10383    if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10384      li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10385    plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10386    if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10387      li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10388  }
10389  else
10390  {
10391    if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10392    {
10393      if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10394        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10395      plci->li_bchannel_id = bchannel_id & 0x03;
10396      if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10397      {
10398        splci = a->AdvSignalPLCI;
10399        if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10400        {
10401          if ((splci->li_bchannel_id != 0)
10402           && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10403          {
10404            li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10405          }
10406          splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10407          li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10408          dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10409            (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10410            (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10411        }
10412      }
10413      if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10414        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10415    }
10416  }
10417  if ((old_id == 0) && (plci->li_bchannel_id != 0)
10418   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10419  {
10420    mixer_clear_config (plci);
10421  }
10422  dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10423    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10424    (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10425}
10426
10427
10428static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10429{
10430  DIVA_CAPI_ADAPTER   *a;
10431  PLCI   *splci;
10432  byte ch, old_id;
10433
10434  a = plci->adapter;
10435  old_id = plci->li_bchannel_id;
10436  ch = chi_to_channel (chi, NULL);
10437  if (!(ch & 0x80))
10438  {
10439    if (a->li_pri)
10440    {
10441      if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10442        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10443      plci->li_bchannel_id = (ch & 0x1f) + 1;
10444      if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10445        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10446    }
10447    else
10448    {
10449      if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10450      {
10451        if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10452          li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10453        plci->li_bchannel_id = ch & 0x1f;
10454        if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10455        {
10456          splci = a->AdvSignalPLCI;
10457          if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10458          {
10459            if ((splci->li_bchannel_id != 0)
10460             && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10461            {
10462              li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10463            }
10464            splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10465            li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10466            dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10467              (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10468              (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10469          }
10470        }
10471        if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10472          li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10473      }
10474    }
10475  }
10476  if ((old_id == 0) && (plci->li_bchannel_id != 0)
10477   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10478  {
10479    mixer_clear_config (plci);
10480  }
10481  dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10482    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10483    (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10484}
10485
10486
10487#define MIXER_MAX_DUMP_CHANNELS 34
10488
10489static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10490{
10491static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10492  word n, i, j;
10493  char *p;
10494    char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10495
10496  dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10497    (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10498
10499  for (i = 0; i < li_total_channels; i++)
10500  {
10501    li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10502    if (li_config_table[i].chflags != 0)
10503      li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10504    else
10505    {
10506      for (j = 0; j < li_total_channels; j++)
10507      {
10508        if (((li_config_table[i].flag_table[j]) != 0)
10509         || ((li_config_table[j].flag_table[i]) != 0))
10510        {
10511          li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10512        }
10513        if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10514         || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10515        {
10516          li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10517        }
10518      }
10519    }
10520  }
10521  for (i = 0; i < li_total_channels; i++)
10522  {
10523    for (j = 0; j < li_total_channels; j++)
10524    {
10525      li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10526      if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10527        li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10528    }
10529  }
10530  for (n = 0; n < li_total_channels; n++)
10531  {
10532    if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10533    {
10534      for (i = 0; i < li_total_channels; i++)
10535      {
10536        if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10537        {
10538          for (j = 0; j < li_total_channels; j++)
10539          {
10540            li_config_table[i].coef_table[j] |=
10541              li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10542          }
10543        }
10544      }
10545    }
10546  }
10547  for (i = 0; i < li_total_channels; i++)
10548  {
10549    if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10550    {
10551      li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10552      for (j = 0; j < li_total_channels; j++)
10553      {
10554        if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10555          li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10556      }
10557      if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10558        li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10559    }
10560  }
10561  for (i = 0; i < li_total_channels; i++)
10562  {
10563    if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10564    {
10565      for (j = 0; j < li_total_channels; j++)
10566      {
10567        if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10568          li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10569        if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10570          li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10571        if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10572          li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10573        if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10574          li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10575      }
10576      if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10577      {
10578        for (j = 0; j < li_total_channels; j++)
10579        {
10580          if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10581          {
10582            li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10583            if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10584              li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10585          }
10586        }
10587      }
10588      if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10589      {
10590        for (j = 0; j < li_total_channels; j++)
10591        {
10592          if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10593            li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10594        }
10595      }
10596      if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10597      {
10598        for (j = 0; j < li_total_channels; j++)
10599        {
10600          if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10601          {
10602            for (n = 0; n < li_total_channels; n++)
10603            {
10604              if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10605              {
10606                li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10607                if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10608                {
10609                  li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10610                  if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10611                    li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10612                }
10613                else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10614                  li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10615              }
10616            }
10617          }
10618        }
10619      }
10620    }
10621  }
10622  for (i = 0; i < li_total_channels; i++)
10623  {
10624    if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10625    {
10626      if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10627        li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10628      if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10629        li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10630      if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10631        li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10632      for (j = 0; j < li_total_channels; j++)
10633      {
10634        if ((li_config_table[i].flag_table[j] &
10635          (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10636         || (li_config_table[j].flag_table[i] &
10637          (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10638        {
10639          li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10640        }
10641        if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10642          li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10643        if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10644          li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10645      }
10646      if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10647      {
10648        li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10649        li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10650      }
10651    }
10652  }
10653  for (i = 0; i < li_total_channels; i++)
10654  {
10655    if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10656    {
10657      j = 0;
10658      while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10659        j++;
10660      if (j < li_total_channels)
10661      {
10662        for (j = 0; j < li_total_channels; j++)
10663        {
10664          li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10665          if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10666            li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10667        }
10668      }
10669    }
10670  }
10671  n = li_total_channels;
10672  if (n > MIXER_MAX_DUMP_CHANNELS)
10673    n = MIXER_MAX_DUMP_CHANNELS;
10674  p = hex_line;
10675  for (j = 0; j < n; j++)
10676  {
10677    if ((j & 0x7) == 0)
10678      *(p++) = ' ';
10679    *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10680    *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10681  }
10682  *p = '\0';
10683  dbug (1, dprintf ("[%06lx] CURRENT %s",
10684    (dword)(UnMapController (a->Id)), (char   *) hex_line));
10685  p = hex_line;
10686  for (j = 0; j < n; j++)
10687  {
10688    if ((j & 0x7) == 0)
10689      *(p++) = ' ';
10690    *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10691    *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10692  }
10693  *p = '\0';
10694  dbug (1, dprintf ("[%06lx] CHANNEL %s",
10695    (dword)(UnMapController (a->Id)), (char   *) hex_line));
10696  p = hex_line;
10697  for (j = 0; j < n; j++)
10698  {
10699    if ((j & 0x7) == 0)
10700      *(p++) = ' ';
10701    *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10702    *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10703  }
10704  *p = '\0';
10705  dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10706    (dword)(UnMapController (a->Id)), (char   *) hex_line));
10707  for (i = 0; i < n; i++)
10708  {
10709    p = hex_line;
10710    for (j = 0; j < n; j++)
10711    {
10712      if ((j & 0x7) == 0)
10713        *(p++) = ' ';
10714      *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10715      *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10716    }
10717    *p = '\0';
10718    dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10719      (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10720  }
10721  for (i = 0; i < n; i++)
10722  {
10723    p = hex_line;
10724    for (j = 0; j < n; j++)
10725    {
10726      if ((j & 0x7) == 0)
10727        *(p++) = ' ';
10728      *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10729      *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10730    }
10731    *p = '\0';
10732    dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10733      (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10734  }
10735}
10736
10737
10738static struct
10739{
10740  byte mask;
10741  byte line_flags;
10742} mixer_write_prog_pri[] =
10743{
10744  { LI_COEF_CH_CH, 0 },
10745  { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10746  { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10747  { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10748};
10749
10750static struct
10751{
10752  byte from_ch;
10753  byte to_ch;
10754  byte mask;
10755  byte xconnect_override;
10756} mixer_write_prog_bri[] =
10757{
10758  { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10759  { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10760  { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10761  { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10762  { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10763  { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10764  { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10765  { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10766  { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10767  { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10768  { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10769  { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10770  { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10771  { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10772  { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10773  { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10774  { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10775  { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10776  { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10777  { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10778  { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10779  { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10780  { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10781  { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10782  { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10783  { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10784  { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10785  { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10786  { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10787  { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10788  { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10789  { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10790  { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10791  { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10792  { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10793  { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10794};
10795
10796static byte mixer_swapped_index_bri[] =
10797{
10798  18,  /* B      to B      */
10799  19,  /* Alt B  to B      */
10800  20,  /* PC     to B      */
10801  21,  /* Alt PC to B      */
10802  22,  /* IC     to B      */
10803  23,  /* Alt IC to B      */
10804  24,  /* B      to PC     */
10805  25,  /* Alt B  to PC     */
10806  26,  /* PC     to PC     */
10807  27,  /* Alt PC to PC     */
10808  28,  /* IC     to PC     */
10809  29,  /* Alt IC to PC     */
10810  30,  /* B      to IC     */
10811  31,  /* Alt B  to IC     */
10812  32,  /* PC     to IC     */
10813  33,  /* Alt PC to IC     */
10814  34,  /* IC     to IC     */
10815  35,  /* Alt IC to IC     */
10816  0,   /* Alt B  to Alt B  */
10817  1,   /* B      to Alt B  */
10818  2,   /* Alt PC to Alt B  */
10819  3,   /* PC     to Alt B  */
10820  4,   /* Alt IC to Alt B  */
10821  5,   /* IC     to Alt B  */
10822  6,   /* Alt B  to Alt PC */
10823  7,   /* B      to Alt PC */
10824  8,   /* Alt PC to Alt PC */
10825  9,   /* PC     to Alt PC */
10826  10,  /* Alt IC to Alt PC */
10827  11,  /* IC     to Alt PC */
10828  12,  /* Alt B  to Alt IC */
10829  13,  /* B      to Alt IC */
10830  14,  /* Alt PC to Alt IC */
10831  15,  /* PC     to Alt IC */
10832  16,  /* Alt IC to Alt IC */
10833  17   /* IC     to Alt IC */
10834};
10835
10836static struct
10837{
10838  byte mask;
10839  byte from_pc;
10840  byte to_pc;
10841} xconnect_write_prog[] =
10842{
10843  { LI_COEF_CH_CH, false, false },
10844  { LI_COEF_CH_PC, false, true },
10845  { LI_COEF_PC_CH, true, false },
10846  { LI_COEF_PC_PC, true, true }
10847};
10848
10849
10850static void xconnect_query_addresses (PLCI   *plci)
10851{
10852  DIVA_CAPI_ADAPTER   *a;
10853  word w, ch;
10854  byte   *p;
10855
10856  dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10857    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10858    (char   *)(FILE_), __LINE__));
10859
10860  a = plci->adapter;
10861  if (a->li_pri && ((plci->li_bchannel_id == 0)
10862   || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10863  {
10864    dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10865      (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10866      (char   *)(FILE_), __LINE__));
10867    return;
10868  }
10869  p = plci->internal_req_buffer;
10870  ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10871  *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10872  w = ch;
10873  *(p++) = (byte) w;
10874  *(p++) = (byte)(w >> 8);
10875  w = ch | XCONNECT_CHANNEL_PORT_PC;
10876  *(p++) = (byte) w;
10877  *(p++) = (byte)(w >> 8);
10878  plci->NData[0].P = plci->internal_req_buffer;
10879  plci->NData[0].PLength = p - plci->internal_req_buffer;
10880  plci->NL.X = plci->NData;
10881  plci->NL.ReqCh = 0;
10882  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10883  plci->adapter->request (&plci->NL);
10884}
10885
10886
10887static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10888{
10889
10890  dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10891    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10892    (char   *)(FILE_), __LINE__, internal_command));
10893
10894  plci->li_write_command = internal_command;
10895  plci->li_write_channel = 0;
10896}
10897
10898
10899static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10900{
10901  DIVA_CAPI_ADAPTER   *a;
10902  word w, n, i, j, r, s, to_ch;
10903  dword d;
10904  byte   *p;
10905  struct xconnect_transfer_address_s   *transfer_address;
10906  byte ch_map[MIXER_CHANNELS_BRI];
10907
10908  dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10909    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10910
10911  a = plci->adapter;
10912  if ((plci->li_bchannel_id == 0)
10913   || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10914  {
10915    dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10916      UnMapId (Id), (char   *)(FILE_), __LINE__));
10917    return (true);
10918  }
10919  i = a->li_base + (plci->li_bchannel_id - 1);
10920  j = plci->li_write_channel;
10921  p = plci->internal_req_buffer;
10922  if (j != 0)
10923  {
10924    if ((Rc != OK) && (Rc != OK_FC))
10925    {
10926      dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10927        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10928      return (false);
10929    }
10930  }
10931  if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10932  {
10933    r = 0;
10934    s = 0;
10935    if (j < li_total_channels)
10936    {
10937      if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10938      {
10939        s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10940            (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10941          ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10942            (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10943      }
10944      r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10945      while ((j < li_total_channels)
10946        && ((r == 0)
10947         || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10948         || (!li_config_table[j].adapter->li_pri
10949          && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10950         || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10951           || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10952          && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10953           || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10954         || ((li_config_table[j].adapter->li_base != a->li_base)
10955          && !(r & s &
10956            ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10957              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10958            ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10959              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10960      {
10961        j++;
10962        if (j < li_total_channels)
10963          r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964      }
10965    }
10966    if (j < li_total_channels)
10967    {
10968      plci->internal_command = plci->li_write_command;
10969      if (plci_nl_busy (plci))
10970        return (true);
10971      to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10972      *(p++) = UDATA_REQUEST_XCONNECT_TO;
10973      do
10974      {
10975        if (li_config_table[j].adapter->li_base != a->li_base)
10976        {
10977          r &= s &
10978            ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10979              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10980            ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10981              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10982        }
10983        n = 0;
10984        do
10985        {
10986          if (r & xconnect_write_prog[n].mask)
10987          {
10988            if (xconnect_write_prog[n].from_pc)
10989              transfer_address = &(li_config_table[j].send_pc);
10990            else
10991              transfer_address = &(li_config_table[j].send_b);
10992            d = transfer_address->card_address.low;
10993            *(p++) = (byte) d;
10994            *(p++) = (byte)(d >> 8);
10995            *(p++) = (byte)(d >> 16);
10996            *(p++) = (byte)(d >> 24);
10997            d = transfer_address->card_address.high;
10998            *(p++) = (byte) d;
10999            *(p++) = (byte)(d >> 8);
11000            *(p++) = (byte)(d >> 16);
11001            *(p++) = (byte)(d >> 24);
11002            d = transfer_address->offset;
11003            *(p++) = (byte) d;
11004            *(p++) = (byte)(d >> 8);
11005            *(p++) = (byte)(d >> 16);
11006            *(p++) = (byte)(d >> 24);
11007            w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11008            *(p++) = (byte) w;
11009            *(p++) = (byte)(w >> 8);
11010            w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11011              (li_config_table[i].adapter->u_law ?
11012                 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11013                 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11014            *(p++) = (byte) w;
11015            *(p++) = (byte) 0;
11016            li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11017          }
11018          n++;
11019        } while ((n < ARRAY_SIZE(xconnect_write_prog))
11020          && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11021        if (n == ARRAY_SIZE(xconnect_write_prog))
11022        {
11023          do
11024          {
11025            j++;
11026            if (j < li_total_channels)
11027              r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11028          } while ((j < li_total_channels)
11029            && ((r == 0)
11030             || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11031             || (!li_config_table[j].adapter->li_pri
11032              && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11033             || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11034               || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11035              && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11036               || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11037             || ((li_config_table[j].adapter->li_base != a->li_base)
11038              && !(r & s &
11039                ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11040                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11041                ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11042                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11043        }
11044      } while ((j < li_total_channels)
11045        && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11046    }
11047    else if (j == li_total_channels)
11048    {
11049      plci->internal_command = plci->li_write_command;
11050      if (plci_nl_busy (plci))
11051        return (true);
11052      if (a->li_pri)
11053      {
11054        *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11055        w = 0;
11056        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11057          w |= MIXER_FEATURE_ENABLE_TX_DATA;
11058        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11059          w |= MIXER_FEATURE_ENABLE_RX_DATA;
11060        *(p++) = (byte) w;
11061        *(p++) = (byte)(w >> 8);
11062      }
11063      else
11064      {
11065        *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11066        w = 0;
11067        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11068         && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11069        {
11070          w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11071        }
11072        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11073          w |= MIXER_FEATURE_ENABLE_TX_DATA;
11074        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11075          w |= MIXER_FEATURE_ENABLE_RX_DATA;
11076        *(p++) = (byte) w;
11077        *(p++) = (byte)(w >> 8);
11078        for (j = 0; j < sizeof(ch_map); j += 2)
11079        {
11080          if (plci->li_bchannel_id == 2)
11081          {
11082            ch_map[j] = (byte)(j+1);
11083            ch_map[j+1] = (byte) j;
11084          }
11085          else
11086          {
11087            ch_map[j] = (byte) j;
11088            ch_map[j+1] = (byte)(j+1);
11089          }
11090        }
11091        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11092        {
11093          i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11094          j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11095          if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11096          {
11097            *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11098              mixer_write_prog_bri[n].xconnect_override :
11099              ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11100            if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11101            {
11102              w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11103              li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11104            }
11105          }
11106          else
11107          {
11108            *p = 0x00;
11109            if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11110            {
11111              w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11112              if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11113                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11114            }
11115          }
11116          p++;
11117        }
11118      }
11119      j = li_total_channels + 1;
11120    }
11121  }
11122  else
11123  {
11124    if (j <= li_total_channels)
11125    {
11126      plci->internal_command = plci->li_write_command;
11127      if (plci_nl_busy (plci))
11128        return (true);
11129      if (j < a->li_base)
11130        j = a->li_base;
11131      if (a->li_pri)
11132      {
11133        *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11134        w = 0;
11135        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11136          w |= MIXER_FEATURE_ENABLE_TX_DATA;
11137        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11138          w |= MIXER_FEATURE_ENABLE_RX_DATA;
11139        *(p++) = (byte) w;
11140        *(p++) = (byte)(w >> 8);
11141        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11142        {
11143          *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11144          for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11145          {
11146            w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11147            if (w & mixer_write_prog_pri[n].mask)
11148            {
11149              *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11150              li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11151            }
11152            else
11153              *(p++) = 0x00;
11154          }
11155          *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11156          for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11157          {
11158            w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11159            if (w & mixer_write_prog_pri[n].mask)
11160            {
11161              *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11162              li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11163            }
11164            else
11165              *(p++) = 0x00;
11166          }
11167        }
11168      }
11169      else
11170      {
11171        *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11172        w = 0;
11173        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11174         && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11175        {
11176          w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11177        }
11178        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11179          w |= MIXER_FEATURE_ENABLE_TX_DATA;
11180        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11181          w |= MIXER_FEATURE_ENABLE_RX_DATA;
11182        *(p++) = (byte) w;
11183        *(p++) = (byte)(w >> 8);
11184        for (j = 0; j < sizeof(ch_map); j += 2)
11185        {
11186          if (plci->li_bchannel_id == 2)
11187          {
11188            ch_map[j] = (byte)(j+1);
11189            ch_map[j+1] = (byte) j;
11190          }
11191          else
11192          {
11193            ch_map[j] = (byte) j;
11194            ch_map[j+1] = (byte)(j+1);
11195          }
11196        }
11197        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11198        {
11199          i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11200          j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11201          if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11202          {
11203            *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11204            w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11205            li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11206          }
11207          else
11208          {
11209            *p = 0x00;
11210            if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11211            {
11212              w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11213              if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11214                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11215            }
11216          }
11217          p++;
11218        }
11219      }
11220      j = li_total_channels + 1;
11221    }
11222  }
11223  plci->li_write_channel = j;
11224  if (p != plci->internal_req_buffer)
11225  {
11226    plci->NData[0].P = plci->internal_req_buffer;
11227    plci->NData[0].PLength = p - plci->internal_req_buffer;
11228    plci->NL.X = plci->NData;
11229    plci->NL.ReqCh = 0;
11230    plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11231    plci->adapter->request (&plci->NL);
11232  }
11233  return (true);
11234}
11235
11236
11237static void mixer_notify_update (PLCI   *plci, byte others)
11238{
11239  DIVA_CAPI_ADAPTER   *a;
11240  word i, w;
11241  PLCI   *notify_plci;
11242    byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11243
11244  dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11245    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11246    (char   *)(FILE_), __LINE__, others));
11247
11248  a = plci->adapter;
11249  if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11250  {
11251    if (others)
11252      plci->li_notify_update = true;
11253    i = 0;
11254    do
11255    {
11256      notify_plci = NULL;
11257      if (others)
11258      {
11259        while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11260          i++;
11261        if (i < li_total_channels)
11262          notify_plci = li_config_table[i++].plci;
11263      }
11264      else
11265      {
11266        if ((plci->li_bchannel_id != 0)
11267         && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11268        {
11269          notify_plci = plci;
11270        }
11271      }
11272      if ((notify_plci != NULL)
11273       && !notify_plci->li_notify_update
11274       && (notify_plci->appl != NULL)
11275       && (notify_plci->State)
11276       && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11277      {
11278        notify_plci->li_notify_update = true;
11279        ((CAPI_MSG *) msg)->header.length = 18;
11280        ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11281        ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11282        ((CAPI_MSG *) msg)->header.number = 0;
11283        ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11284        ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11285        ((CAPI_MSG *) msg)->header.ncci = 0;
11286        ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11287        ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11288        PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11289        ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11290        w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11291        if (w != _QUEUE_FULL)
11292        {
11293          if (w != 0)
11294          {
11295            dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11296              (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11297              (char   *)(FILE_), __LINE__,
11298              (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11299          }
11300          notify_plci->li_notify_update = false;
11301        }
11302      }
11303    } while (others && (notify_plci != NULL));
11304    if (others)
11305      plci->li_notify_update = false;
11306  }
11307}
11308
11309
11310static void mixer_clear_config (PLCI   *plci)
11311{
11312  DIVA_CAPI_ADAPTER   *a;
11313  word i, j;
11314
11315  dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11316    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11317    (char   *)(FILE_), __LINE__));
11318
11319  plci->li_notify_update = false;
11320  plci->li_plci_b_write_pos = 0;
11321  plci->li_plci_b_read_pos = 0;
11322  plci->li_plci_b_req_pos = 0;
11323  a = plci->adapter;
11324  if ((plci->li_bchannel_id != 0)
11325   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11326  {
11327    i = a->li_base + (plci->li_bchannel_id - 1);
11328    li_config_table[i].curchnl = 0;
11329    li_config_table[i].channel = 0;
11330    li_config_table[i].chflags = 0;
11331    for (j = 0; j < li_total_channels; j++)
11332    {
11333      li_config_table[j].flag_table[i] = 0;
11334      li_config_table[i].flag_table[j] = 0;
11335      li_config_table[i].coef_table[j] = 0;
11336      li_config_table[j].coef_table[i] = 0;
11337    }
11338    if (!a->li_pri)
11339    {
11340      li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11341      if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11342      {
11343        i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11344        li_config_table[i].curchnl = 0;
11345        li_config_table[i].channel = 0;
11346        li_config_table[i].chflags = 0;
11347        for (j = 0; j < li_total_channels; j++)
11348        {
11349          li_config_table[i].flag_table[j] = 0;
11350          li_config_table[j].flag_table[i] = 0;
11351          li_config_table[i].coef_table[j] = 0;
11352          li_config_table[j].coef_table[i] = 0;
11353        }
11354        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11355        {
11356          i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11357          li_config_table[i].curchnl = 0;
11358          li_config_table[i].channel = 0;
11359          li_config_table[i].chflags = 0;
11360          for (j = 0; j < li_total_channels; j++)
11361          {
11362            li_config_table[i].flag_table[j] = 0;
11363            li_config_table[j].flag_table[i] = 0;
11364            li_config_table[i].coef_table[j] = 0;
11365            li_config_table[j].coef_table[i] = 0;
11366          }
11367        }
11368      }
11369    }
11370  }
11371}
11372
11373
11374static void mixer_prepare_switch (dword Id, PLCI   *plci)
11375{
11376
11377  dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11378    UnMapId (Id), (char   *)(FILE_), __LINE__));
11379
11380  do
11381  {
11382    mixer_indication_coefs_set (Id, plci);
11383  } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11384}
11385
11386
11387static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11388{
11389  DIVA_CAPI_ADAPTER   *a;
11390  word i, j;
11391
11392  dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11393    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11394
11395  a = plci->adapter;
11396  if ((plci->li_bchannel_id != 0)
11397   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11398  {
11399    i = a->li_base + (plci->li_bchannel_id - 1);
11400    for (j = 0; j < li_total_channels; j++)
11401    {
11402      li_config_table[i].coef_table[j] &= 0xf;
11403      li_config_table[j].coef_table[i] &= 0xf;
11404    }
11405    if (!a->li_pri)
11406      li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11407  }
11408  return (GOOD);
11409}
11410
11411
11412static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11413{
11414  DIVA_CAPI_ADAPTER   *a;
11415  word Info;
11416
11417  dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11418    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11419
11420  Info = GOOD;
11421  a = plci->adapter;
11422  if ((plci->B1_facilities & B1_FACILITY_MIXER)
11423   && (plci->li_bchannel_id != 0)
11424   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11425  {
11426    switch (plci->adjust_b_state)
11427    {
11428    case ADJUST_B_RESTORE_MIXER_1:
11429      if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11430      {
11431        plci->internal_command = plci->adjust_b_command;
11432        if (plci_nl_busy (plci))
11433        {
11434          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11435          break;
11436        }
11437        xconnect_query_addresses (plci);
11438        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11439        break;
11440      }
11441      plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11442      Rc = OK;
11443    case ADJUST_B_RESTORE_MIXER_2:
11444    case ADJUST_B_RESTORE_MIXER_3:
11445    case ADJUST_B_RESTORE_MIXER_4:
11446      if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11447      {
11448        dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11449          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11450        Info = _WRONG_STATE;
11451        break;
11452      }
11453      if (Rc == OK)
11454      {
11455        if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11456          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11457        else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11458          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11459      }
11460      else if (Rc == 0)
11461      {
11462        if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11463          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11464        else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11465          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11466      }
11467      if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11468      {
11469        plci->internal_command = plci->adjust_b_command;
11470        break;
11471      }
11472    case ADJUST_B_RESTORE_MIXER_5:
11473      xconnect_write_coefs (plci, plci->adjust_b_command);
11474      plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11475      Rc = OK;
11476    case ADJUST_B_RESTORE_MIXER_6:
11477      if (!xconnect_write_coefs_process (Id, plci, Rc))
11478      {
11479        dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11480          UnMapId (Id), (char   *)(FILE_), __LINE__));
11481        Info = _FACILITY_NOT_SUPPORTED;
11482        break;
11483      }
11484      if (plci->internal_command)
11485        break;
11486      plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11487    case ADJUST_B_RESTORE_MIXER_7:
11488      break;
11489    }
11490  }
11491  return (Info);
11492}
11493
11494
11495static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11496{
11497  DIVA_CAPI_ADAPTER   *a;
11498  word i, internal_command, Info;
11499
11500  dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11501    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11502    plci->li_cmd));
11503
11504  Info = GOOD;
11505  a = plci->adapter;
11506  internal_command = plci->internal_command;
11507  plci->internal_command = 0;
11508  switch (plci->li_cmd)
11509  {
11510  case LI_REQ_CONNECT:
11511  case LI_REQ_DISCONNECT:
11512  case LI_REQ_SILENT_UPDATE:
11513    switch (internal_command)
11514    {
11515    default:
11516      if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11517      {
11518        adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11519          B1_FACILITY_MIXER), MIXER_COMMAND_1);
11520      }
11521    case MIXER_COMMAND_1:
11522      if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11523      {
11524        if (adjust_b_process (Id, plci, Rc) != GOOD)
11525        {
11526          dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11527            UnMapId (Id), (char   *)(FILE_), __LINE__));
11528          Info = _FACILITY_NOT_SUPPORTED;
11529          break;
11530        }
11531        if (plci->internal_command)
11532          return;
11533      }
11534      plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11535      if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11536       || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11537        && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11538         ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11539      {
11540        xconnect_write_coefs (plci, MIXER_COMMAND_2);
11541      }
11542      else
11543      {
11544        do
11545        {
11546          mixer_indication_coefs_set (Id, plci);
11547        } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11548      }
11549    case MIXER_COMMAND_2:
11550      if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11551       || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11552        && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11553         ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11554      {
11555        if (!xconnect_write_coefs_process (Id, plci, Rc))
11556        {
11557          dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11558            UnMapId (Id), (char   *)(FILE_), __LINE__));
11559          if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11560          {
11561            do
11562            {
11563              plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11564                LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11565              i = (plci->li_plci_b_write_pos == 0) ?
11566                LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11567            } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11568              && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11569          }
11570          Info = _FACILITY_NOT_SUPPORTED;
11571          break;
11572        }
11573        if (plci->internal_command)
11574          return;
11575      }
11576      if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11577      {
11578        adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11579          ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11580      }
11581    case MIXER_COMMAND_3:
11582      if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11583      {
11584        if (adjust_b_process (Id, plci, Rc) != GOOD)
11585        {
11586          dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11587            UnMapId (Id), (char   *)(FILE_), __LINE__));
11588          Info = _FACILITY_NOT_SUPPORTED;
11589          break;
11590        }
11591        if (plci->internal_command)
11592          return;
11593      }
11594      break;
11595    }
11596    break;
11597  }
11598  if ((plci->li_bchannel_id == 0)
11599   || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11600  {
11601    dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11602      UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11603  }
11604  else
11605  {
11606    i = a->li_base + (plci->li_bchannel_id - 1);
11607    li_config_table[i].curchnl = plci->li_channel_bits;
11608    if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11609    {
11610      i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11611      li_config_table[i].curchnl = plci->li_channel_bits;
11612      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11613      {
11614        i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11615        li_config_table[i].curchnl = plci->li_channel_bits;
11616      }
11617    }
11618  }
11619}
11620
11621
11622static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11623  dword plci_b_id, byte connect, dword li_flags)
11624{
11625  word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11626  PLCI   *plci_b;
11627  DIVA_CAPI_ADAPTER   *a_b;
11628
11629  a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11630  plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11631  ch_a = a->li_base + (plci->li_bchannel_id - 1);
11632  if (!a->li_pri && (plci->tel == ADV_VOICE)
11633   && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11634  {
11635    ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11636    ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11637      a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11638  }
11639  else
11640  {
11641    ch_a_v = ch_a;
11642    ch_a_s = ch_a;
11643  }
11644  ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11645  if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11646   && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11647  {
11648    ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11649    ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11650      a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11651  }
11652  else
11653  {
11654    ch_b_v = ch_b;
11655    ch_b_s = ch_b;
11656  }
11657  if (connect)
11658  {
11659    li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11660    li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11661    li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11662    li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11663  }
11664  li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11665  li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11666  li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11667  li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11668  if (ch_a_v == ch_b_v)
11669  {
11670    li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11671    li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11672  }
11673  else
11674  {
11675    if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11676    {
11677      for (i = 0; i < li_total_channels; i++)
11678      {
11679        if (i != ch_a_v)
11680          li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11681      }
11682    }
11683    if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11684    {
11685      for (i = 0; i < li_total_channels; i++)
11686      {
11687        if (i != ch_a_s)
11688          li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11689      }
11690    }
11691    if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11692    {
11693      for (i = 0; i < li_total_channels; i++)
11694      {
11695        if (i != ch_a_v)
11696          li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11697      }
11698    }
11699    if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11700    {
11701      for (i = 0; i < li_total_channels; i++)
11702      {
11703        if (i != ch_a_s)
11704          li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11705      }
11706    }
11707  }
11708  if (li_flags & LI_FLAG_CONFERENCE_A_B)
11709  {
11710    li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11711    li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11712    li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11713    li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11714  }
11715  if (li_flags & LI_FLAG_CONFERENCE_B_A)
11716  {
11717    li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11718    li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11719    li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11720    li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11721  }
11722  if (li_flags & LI_FLAG_MONITOR_A)
11723  {
11724    li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11725    li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11726  }
11727  if (li_flags & LI_FLAG_MONITOR_B)
11728  {
11729    li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11730    li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11731  }
11732  if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11733  {
11734    li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11735    li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11736  }
11737  if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11738  {
11739    li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11740    li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11741  }
11742  if (li_flags & LI_FLAG_MIX_A)
11743  {
11744    li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11745    li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11746  }
11747  if (li_flags & LI_FLAG_MIX_B)
11748  {
11749    li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11750    li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11751  }
11752  if (ch_a_v != ch_a_s)
11753  {
11754    li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11755    li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11756  }
11757  if (ch_b_v != ch_b_s)
11758  {
11759    li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11760    li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11761  }
11762}
11763
11764
11765static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11766  dword plci_b_id, byte connect, dword li_flags)
11767{
11768  word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11769  PLCI   *plci_b;
11770  DIVA_CAPI_ADAPTER   *a_b;
11771
11772  a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11773  plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11774  ch_a = a->li_base + (plci->li_bchannel_id - 1);
11775  if (!a->li_pri && (plci->tel == ADV_VOICE)
11776   && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11777  {
11778    ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11779    ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11780      a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11781  }
11782  else
11783  {
11784    ch_a_v = ch_a;
11785    ch_a_s = ch_a;
11786  }
11787  ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11788  if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11789   && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11790  {
11791    ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11792    ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11793      a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11794  }
11795  else
11796  {
11797    ch_b_v = ch_b;
11798    ch_b_s = ch_b;
11799  }
11800  if (connect)
11801  {
11802    li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11803    li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11804    li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11805    li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11806    li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11807    li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11808  }
11809  li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11810  li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11811  li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11812  li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11813  li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11814  li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11815  li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816  li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817  if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11818  {
11819    li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11820    li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11821    li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11822    li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11823  }
11824  if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11825  {
11826    li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11827    li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11828    li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11829    li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11830  }
11831  if (li_flags & LI2_FLAG_MONITOR_B)
11832  {
11833    li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11834    li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11835  }
11836  if (li_flags & LI2_FLAG_MIX_B)
11837  {
11838    li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11839    li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11840  }
11841  if (li_flags & LI2_FLAG_MONITOR_X)
11842    li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11843  if (li_flags & LI2_FLAG_MIX_X)
11844    li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11845  if (li_flags & LI2_FLAG_LOOP_B)
11846  {
11847    li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11848    li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11849    li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11850    li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11851  }
11852  if (li_flags & LI2_FLAG_LOOP_PC)
11853    li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11854  if (li_flags & LI2_FLAG_LOOP_X)
11855    li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11856  if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11857    li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11858  if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11859    li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11860  if (ch_a_v != ch_a_s)
11861  {
11862    li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11863    li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11864  }
11865  if (ch_b_v != ch_b_s)
11866  {
11867    li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11868    li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11869  }
11870}
11871
11872
11873static word li_check_main_plci (dword Id, PLCI   *plci)
11874{
11875  if (plci == NULL)
11876  {
11877    dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11878      UnMapId (Id), (char   *)(FILE_), __LINE__));
11879    return (_WRONG_IDENTIFIER);
11880  }
11881  if (!plci->State
11882   || !plci->NL.Id || plci->nl_remove_id
11883   || (plci->li_bchannel_id == 0))
11884  {
11885    dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11886      UnMapId (Id), (char   *)(FILE_), __LINE__));
11887    return (_WRONG_STATE);
11888  }
11889  li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11890  return (GOOD);
11891}
11892
11893
11894static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11895  dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11896{
11897  byte ctlr_b;
11898  PLCI   *plci_b;
11899
11900  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11901    LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11902  {
11903    dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11904      UnMapId (Id), (char   *)(FILE_), __LINE__));
11905    PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11906    return (NULL);
11907  }
11908  ctlr_b = 0;
11909  if ((plci_b_id & 0x7f) != 0)
11910  {
11911    ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11912    if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11913      ctlr_b = 0;
11914  }
11915  if ((ctlr_b == 0)
11916   || (((plci_b_id >> 8) & 0xff) == 0)
11917   || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11918  {
11919    dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11920      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11921    PUT_WORD (p_result, _WRONG_IDENTIFIER);
11922    return (NULL);
11923  }
11924  plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11925  if (!plci_b->State
11926   || !plci_b->NL.Id || plci_b->nl_remove_id
11927   || (plci_b->li_bchannel_id == 0))
11928  {
11929    dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11930      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11931    PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11932    return (NULL);
11933  }
11934  li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11935  if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11936    ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11937   && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11938    || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11939  {
11940    dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11941      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11942    PUT_WORD (p_result, _WRONG_IDENTIFIER);
11943    return (NULL);
11944  }
11945  if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11946    (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11947  {
11948    dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11949      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11950    PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11951    return (NULL);
11952  }
11953  return (plci_b);
11954}
11955
11956
11957static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11958  dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11959{
11960  byte ctlr_b;
11961  PLCI   *plci_b;
11962
11963  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11964    LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11965  {
11966    dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11967      UnMapId (Id), (char   *)(FILE_), __LINE__));
11968    PUT_WORD (p_result, _WRONG_STATE);
11969    return (NULL);
11970  }
11971  ctlr_b = 0;
11972  if ((plci_b_id & 0x7f) != 0)
11973  {
11974    ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11975    if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11976      ctlr_b = 0;
11977  }
11978  if ((ctlr_b == 0)
11979   || (((plci_b_id >> 8) & 0xff) == 0)
11980   || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11981  {
11982    dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11983      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11984    PUT_WORD (p_result, _WRONG_IDENTIFIER);
11985    return (NULL);
11986  }
11987  plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11988  if (!plci_b->State
11989   || !plci_b->NL.Id || plci_b->nl_remove_id
11990   || (plci_b->li_bchannel_id == 0)
11991   || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11992  {
11993    dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11994      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11995    PUT_WORD (p_result, _WRONG_STATE);
11996    return (NULL);
11997  }
11998  if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11999    ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12000   && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12001    || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12002  {
12003    dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12004      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12005    PUT_WORD (p_result, _WRONG_IDENTIFIER);
12006    return (NULL);
12007  }
12008  if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12009    (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12010  {
12011    dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12012      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12013    PUT_WORD (p_result, _WRONG_STATE);
12014    return (NULL);
12015  }
12016  return (plci_b);
12017}
12018
12019
12020static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12021{
12022  word Info;
12023  word i;
12024  dword d, li_flags, plci_b_id;
12025  PLCI   *plci_b;
12026    API_PARSE li_parms[3];
12027    API_PARSE li_req_parms[3];
12028    API_PARSE li_participant_struct[2];
12029    API_PARSE li_participant_parms[3];
12030  word participant_parms_pos;
12031  byte result_buffer[32];
12032  byte   *result;
12033  word result_pos;
12034  word plci_b_write_pos;
12035
12036  dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12037    UnMapId (Id), (char   *)(FILE_), __LINE__));
12038
12039  Info = GOOD;
12040  result = result_buffer;
12041  result_buffer[0] = 0;
12042  if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12043  {
12044    dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12045      UnMapId (Id), (char   *)(FILE_), __LINE__));
12046    Info = _FACILITY_NOT_SUPPORTED;
12047  }
12048  else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12049  {
12050    dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12051      UnMapId (Id), (char   *)(FILE_), __LINE__));
12052    Info = _WRONG_MESSAGE_FORMAT;
12053  }
12054  else
12055  {
12056    result_buffer[0] = 3;
12057    PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12058    result_buffer[3] = 0;
12059    switch (GET_WORD (li_parms[0].info))
12060    {
12061    case LI_GET_SUPPORTED_SERVICES:
12062      if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12063      {
12064        result_buffer[0] = 17;
12065        result_buffer[3] = 14;
12066        PUT_WORD (&result_buffer[4], GOOD);
12067        d = 0;
12068        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12069          d |= LI_CONFERENCING_SUPPORTED;
12070        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12071          d |= LI_MONITORING_SUPPORTED;
12072        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12073          d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12074        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12075          d |= LI_CROSS_CONTROLLER_SUPPORTED;
12076        PUT_DWORD (&result_buffer[6], d);
12077        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12078        {
12079          d = 0;
12080          for (i = 0; i < li_total_channels; i++)
12081          {
12082            if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12083             && (li_config_table[i].adapter->li_pri
12084              || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12085            {
12086              d++;
12087            }
12088          }
12089        }
12090        else
12091        {
12092          d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12093        }
12094        PUT_DWORD (&result_buffer[10], d / 2);
12095        PUT_DWORD (&result_buffer[14], d);
12096      }
12097      else
12098      {
12099        result_buffer[0] = 25;
12100        result_buffer[3] = 22;
12101        PUT_WORD (&result_buffer[4], GOOD);
12102        d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12103        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12104          d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12105        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12106          d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12107        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12108          d |= LI2_PC_LOOPING_SUPPORTED;
12109        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12110          d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12111        PUT_DWORD (&result_buffer[6], d);
12112        d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12113        PUT_DWORD (&result_buffer[10], d / 2);
12114        PUT_DWORD (&result_buffer[14], d - 1);
12115        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12116        {
12117          d = 0;
12118          for (i = 0; i < li_total_channels; i++)
12119          {
12120            if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12121             && (li_config_table[i].adapter->li_pri
12122              || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12123            {
12124              d++;
12125            }
12126          }
12127        }
12128        PUT_DWORD (&result_buffer[18], d / 2);
12129        PUT_DWORD (&result_buffer[22], d - 1);
12130      }
12131      break;
12132
12133    case LI_REQ_CONNECT:
12134      if (li_parms[1].length == 8)
12135      {
12136        appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12137        if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12138        {
12139          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12140            UnMapId (Id), (char   *)(FILE_), __LINE__));
12141          Info = _WRONG_MESSAGE_FORMAT;
12142          break;
12143        }
12144        plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12145        li_flags = GET_DWORD (li_req_parms[1].info);
12146        Info = li_check_main_plci (Id, plci);
12147        result_buffer[0] = 9;
12148        result_buffer[3] = 6;
12149        PUT_DWORD (&result_buffer[4], plci_b_id);
12150        PUT_WORD (&result_buffer[8], GOOD);
12151        if (Info != GOOD)
12152          break;
12153        result = plci->saved_msg.info;
12154        for (i = 0; i <= result_buffer[0]; i++)
12155          result[i] = result_buffer[i];
12156        plci_b_write_pos = plci->li_plci_b_write_pos;
12157        plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12158        if (plci_b == NULL)
12159          break;
12160        li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12161        plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12162        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12163        plci->li_plci_b_write_pos = plci_b_write_pos;
12164      }
12165      else
12166      {
12167        appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12168        if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12169        {
12170          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12171            UnMapId (Id), (char   *)(FILE_), __LINE__));
12172          Info = _WRONG_MESSAGE_FORMAT;
12173          break;
12174        }
12175        li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12176        Info = li_check_main_plci (Id, plci);
12177        result_buffer[0] = 7;
12178        result_buffer[3] = 4;
12179        PUT_WORD (&result_buffer[4], Info);
12180        result_buffer[6] = 0;
12181        if (Info != GOOD)
12182          break;
12183        result = plci->saved_msg.info;
12184        for (i = 0; i <= result_buffer[0]; i++)
12185          result[i] = result_buffer[i];
12186        plci_b_write_pos = plci->li_plci_b_write_pos;
12187        participant_parms_pos = 0;
12188        result_pos = 7;
12189        li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12190        while (participant_parms_pos < li_req_parms[1].length)
12191        {
12192          result[result_pos] = 6;
12193          result_pos += 7;
12194          PUT_DWORD (&result[result_pos - 6], 0);
12195          PUT_WORD (&result[result_pos - 2], GOOD);
12196          if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12197            (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12198          {
12199            dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12200              UnMapId (Id), (char   *)(FILE_), __LINE__));
12201            PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12202            break;
12203          }
12204          if (api_parse (&li_participant_struct[0].info[1],
12205            li_participant_struct[0].length, "dd", li_participant_parms))
12206          {
12207            dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12208              UnMapId (Id), (char   *)(FILE_), __LINE__));
12209            PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210            break;
12211          }
12212          plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12213          li_flags = GET_DWORD (li_participant_parms[1].info);
12214          PUT_DWORD (&result[result_pos - 6], plci_b_id);
12215          if (sizeof(result) - result_pos < 7)
12216          {
12217            dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12218              UnMapId (Id), (char   *)(FILE_), __LINE__));
12219            PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12220            break;
12221          }
12222          plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12223          if (plci_b != NULL)
12224          {
12225            li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12226            plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12227              ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12228              LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12229            plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12230          }
12231          participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12232            (&li_req_parms[1].info[1]));
12233        }
12234        result[0] = (byte)(result_pos - 1);
12235        result[3] = (byte)(result_pos - 4);
12236        result[6] = (byte)(result_pos - 7);
12237        i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12238        if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12239         || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12240        {
12241          plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12242          plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12243        }
12244        else
12245          plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12246        plci->li_plci_b_write_pos = plci_b_write_pos;
12247      }
12248      mixer_calculate_coefs (a);
12249      plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12250      mixer_notify_update (plci, true);
12251      sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12252        "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12253      plci->command = 0;
12254      plci->li_cmd = GET_WORD (li_parms[0].info);
12255      start_internal_command (Id, plci, mixer_command);
12256      return (false);
12257
12258    case LI_REQ_DISCONNECT:
12259      if (li_parms[1].length == 4)
12260      {
12261        appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12262        if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12263        {
12264          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12265            UnMapId (Id), (char   *)(FILE_), __LINE__));
12266          Info = _WRONG_MESSAGE_FORMAT;
12267          break;
12268        }
12269        plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12270        Info = li_check_main_plci (Id, plci);
12271        result_buffer[0] = 9;
12272        result_buffer[3] = 6;
12273        PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12274        PUT_WORD (&result_buffer[8], GOOD);
12275        if (Info != GOOD)
12276          break;
12277        result = plci->saved_msg.info;
12278        for (i = 0; i <= result_buffer[0]; i++)
12279          result[i] = result_buffer[i];
12280        plci_b_write_pos = plci->li_plci_b_write_pos;
12281        plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12282        if (plci_b == NULL)
12283          break;
12284        li_update_connect (Id, a, plci, plci_b_id, false, 0);
12285        plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12286        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12287        plci->li_plci_b_write_pos = plci_b_write_pos;
12288      }
12289      else
12290      {
12291        appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12292        if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12293        {
12294          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12295            UnMapId (Id), (char   *)(FILE_), __LINE__));
12296          Info = _WRONG_MESSAGE_FORMAT;
12297          break;
12298        }
12299        Info = li_check_main_plci (Id, plci);
12300        result_buffer[0] = 7;
12301        result_buffer[3] = 4;
12302        PUT_WORD (&result_buffer[4], Info);
12303        result_buffer[6] = 0;
12304        if (Info != GOOD)
12305          break;
12306        result = plci->saved_msg.info;
12307        for (i = 0; i <= result_buffer[0]; i++)
12308          result[i] = result_buffer[i];
12309        plci_b_write_pos = plci->li_plci_b_write_pos;
12310        participant_parms_pos = 0;
12311        result_pos = 7;
12312        while (participant_parms_pos < li_req_parms[0].length)
12313        {
12314          result[result_pos] = 6;
12315          result_pos += 7;
12316          PUT_DWORD (&result[result_pos - 6], 0);
12317          PUT_WORD (&result[result_pos - 2], GOOD);
12318          if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12319            (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12320          {
12321            dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12322              UnMapId (Id), (char   *)(FILE_), __LINE__));
12323            PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12324            break;
12325          }
12326          if (api_parse (&li_participant_struct[0].info[1],
12327            li_participant_struct[0].length, "d", li_participant_parms))
12328          {
12329            dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12330              UnMapId (Id), (char   *)(FILE_), __LINE__));
12331            PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12332            break;
12333          }
12334          plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12335          PUT_DWORD (&result[result_pos - 6], plci_b_id);
12336          if (sizeof(result) - result_pos < 7)
12337          {
12338            dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12339              UnMapId (Id), (char   *)(FILE_), __LINE__));
12340            PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12341            break;
12342          }
12343          plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12344          if (plci_b != NULL)
12345          {
12346            li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12347            plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12348            plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12349          }
12350          participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12351            (&li_req_parms[0].info[1]));
12352        }
12353        result[0] = (byte)(result_pos - 1);
12354        result[3] = (byte)(result_pos - 4);
12355        result[6] = (byte)(result_pos - 7);
12356        i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12357        if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12358         || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12359        {
12360          plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12361          plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12362        }
12363        else
12364          plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12365        plci->li_plci_b_write_pos = plci_b_write_pos;
12366      }
12367      mixer_calculate_coefs (a);
12368      plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12369      mixer_notify_update (plci, true);
12370      sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12371        "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12372      plci->command = 0;
12373      plci->li_cmd = GET_WORD (li_parms[0].info);
12374      start_internal_command (Id, plci, mixer_command);
12375      return (false);
12376
12377    case LI_REQ_SILENT_UPDATE:
12378      if (!plci || !plci->State
12379       || !plci->NL.Id || plci->nl_remove_id
12380       || (plci->li_bchannel_id == 0)
12381       || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12382      {
12383        dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12384          UnMapId (Id), (char   *)(FILE_), __LINE__));
12385        return (false);
12386      }
12387      plci_b_write_pos = plci->li_plci_b_write_pos;
12388      if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12389        LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12390      {
12391        dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12392          UnMapId (Id), (char   *)(FILE_), __LINE__));
12393        return (false);
12394      }
12395      i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12396      if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12397       || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12398      {
12399        plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12400        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12401      }
12402      else
12403        plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12404      plci->li_plci_b_write_pos = plci_b_write_pos;
12405      plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12406      plci->command = 0;
12407      plci->li_cmd = GET_WORD (li_parms[0].info);
12408      start_internal_command (Id, plci, mixer_command);
12409      return (false);
12410
12411    default:
12412      dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12413        UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12414      Info = _FACILITY_NOT_SUPPORTED;
12415    }
12416  }
12417  sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12418    "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12419  return (false);
12420}
12421
12422
12423static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12424{
12425  dword d;
12426  DIVA_CAPI_ADAPTER   *a;
12427    byte result[12];
12428
12429  dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12430    UnMapId (Id), (char   *)(FILE_), __LINE__));
12431
12432  a = plci->adapter;
12433  if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12434  {
12435    do
12436    {
12437      d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12438      if (!(d & LI_PLCI_B_SKIP_FLAG))
12439      {
12440        if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12441        {
12442          if (d & LI_PLCI_B_DISC_FLAG)
12443          {
12444            result[0] = 5;
12445            PUT_WORD (&result[1], LI_IND_DISCONNECT);
12446            result[3] = 2;
12447            PUT_WORD (&result[4], _LI_USER_INITIATED);
12448          }
12449          else
12450          {
12451            result[0] = 7;
12452            PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12453            result[3] = 4;
12454            PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12455          }
12456        }
12457        else
12458        {
12459          if (d & LI_PLCI_B_DISC_FLAG)
12460          {
12461            result[0] = 9;
12462            PUT_WORD (&result[1], LI_IND_DISCONNECT);
12463            result[3] = 6;
12464            PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12465            PUT_WORD (&result[8], _LI_USER_INITIATED);
12466          }
12467          else
12468          {
12469            result[0] = 7;
12470            PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12471            result[3] = 4;
12472            PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12473          }
12474        }
12475        sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12476          "ws", SELECTOR_LINE_INTERCONNECT, result);
12477      }
12478      plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12479        0 : plci->li_plci_b_read_pos + 1;
12480    } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12481  }
12482}
12483
12484
12485static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12486{
12487  word i, j, ch;
12488  struct xconnect_transfer_address_s s,   *p;
12489  DIVA_CAPI_ADAPTER   *a;
12490
12491  dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12492    UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12493
12494  a = plci->adapter;
12495  i = 1;
12496  for (i = 1; i < length; i += 16)
12497  {
12498    s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12499    s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12500    s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12501    ch = msg[i+12] | (msg[i+13] << 8);
12502    j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12503    if (!a->li_pri && (plci->li_bchannel_id == 2))
12504      j = 1 - j;
12505    j += a->li_base;
12506    if (ch & XCONNECT_CHANNEL_PORT_PC)
12507      p = &(li_config_table[j].send_pc);
12508    else
12509      p = &(li_config_table[j].send_b);
12510    p->card_address.low = s.card_address.low;
12511    p->card_address.high = s.card_address.high;
12512    p->offset = s.offset;
12513    li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12514  }
12515  if (plci->internal_command_queue[0]
12516   && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12517    || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12518    || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12519  {
12520    (*(plci->internal_command_queue[0]))(Id, plci, 0);
12521    if (!plci->internal_command)
12522      next_internal_command (Id, plci);
12523  }
12524  mixer_notify_update (plci, true);
12525}
12526
12527
12528static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12529{
12530
12531  dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12532    UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12533
12534}
12535
12536
12537static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12538{
12539  word plci_b_write_pos;
12540
12541  plci_b_write_pos = plci->li_plci_b_write_pos;
12542  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12543    LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12544  {
12545    dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12546      (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12547      (char   *)(FILE_), __LINE__));
12548    return (false);
12549  }
12550  plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12551  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12552  plci->li_plci_b_write_pos = plci_b_write_pos;
12553  return (true);
12554}
12555
12556
12557static void mixer_remove (PLCI   *plci)
12558{
12559  DIVA_CAPI_ADAPTER   *a;
12560  PLCI   *notify_plci;
12561  dword plci_b_id;
12562  word i, j;
12563
12564  dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12565    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12566    (char   *)(FILE_), __LINE__));
12567
12568  a = plci->adapter;
12569  plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12570  if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12571  {
12572    if ((plci->li_bchannel_id != 0)
12573     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12574    {
12575      i = a->li_base + (plci->li_bchannel_id - 1);
12576      if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12577      {
12578        for (j = 0; j < li_total_channels; j++)
12579        {
12580          if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12581           || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12582          {
12583            notify_plci = li_config_table[j].plci;
12584            if ((notify_plci != NULL)
12585             && (notify_plci != plci)
12586             && (notify_plci->appl != NULL)
12587             && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12588             && (notify_plci->State)
12589             && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12590            {
12591              mixer_notify_source_removed (notify_plci, plci_b_id);
12592            }
12593          }
12594        }
12595        mixer_clear_config (plci);
12596        mixer_calculate_coefs (a);
12597        mixer_notify_update (plci, true);
12598      }
12599      li_config_table[i].plci = NULL;
12600      plci->li_bchannel_id = 0;
12601    }
12602  }
12603}
12604
12605
12606/*------------------------------------------------------------------*/
12607/* Echo canceller facilities                                        */
12608/*------------------------------------------------------------------*/
12609
12610
12611static void ec_write_parameters (PLCI   *plci)
12612{
12613  word w;
12614    byte parameter_buffer[6];
12615
12616  dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12617    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12618    (char   *)(FILE_), __LINE__));
12619
12620  parameter_buffer[0] = 5;
12621  parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12622  PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12623  plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12624  w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12625  PUT_WORD (&parameter_buffer[4], w);
12626  add_p (plci, FTY, parameter_buffer);
12627  sig_req (plci, TEL_CTRL, 0);
12628  send_req (plci);
12629}
12630
12631
12632static void ec_clear_config (PLCI   *plci)
12633{
12634
12635  dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12636    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12637    (char   *)(FILE_), __LINE__));
12638
12639  plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12640    LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12641  plci->ec_tail_length = 0;
12642}
12643
12644
12645static void ec_prepare_switch (dword Id, PLCI   *plci)
12646{
12647
12648  dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12649    UnMapId (Id), (char   *)(FILE_), __LINE__));
12650
12651}
12652
12653
12654static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12655{
12656
12657  dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12658    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12659
12660  return (GOOD);
12661}
12662
12663
12664static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12665{
12666  word Info;
12667
12668  dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12669    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12670
12671  Info = GOOD;
12672  if (plci->B1_facilities & B1_FACILITY_EC)
12673  {
12674    switch (plci->adjust_b_state)
12675    {
12676    case ADJUST_B_RESTORE_EC_1:
12677      plci->internal_command = plci->adjust_b_command;
12678      if (plci->sig_req)
12679      {
12680        plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12681        break;
12682      }
12683      ec_write_parameters (plci);
12684      plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12685      break;
12686    case ADJUST_B_RESTORE_EC_2:
12687      if ((Rc != OK) && (Rc != OK_FC))
12688      {
12689        dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12690          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12691        Info = _WRONG_STATE;
12692        break;
12693      }
12694      break;
12695    }
12696  }
12697  return (Info);
12698}
12699
12700
12701static void ec_command (dword Id, PLCI   *plci, byte Rc)
12702{
12703  word internal_command, Info;
12704    byte result[8];
12705
12706  dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12707    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12708    plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12709
12710  Info = GOOD;
12711  if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12712  {
12713    result[0] = 2;
12714    PUT_WORD (&result[1], EC_SUCCESS);
12715  }
12716  else
12717  {
12718    result[0] = 5;
12719    PUT_WORD (&result[1], plci->ec_cmd);
12720    result[3] = 2;
12721    PUT_WORD (&result[4], GOOD);
12722  }
12723  internal_command = plci->internal_command;
12724  plci->internal_command = 0;
12725  switch (plci->ec_cmd)
12726  {
12727  case EC_ENABLE_OPERATION:
12728  case EC_FREEZE_COEFFICIENTS:
12729  case EC_RESUME_COEFFICIENT_UPDATE:
12730  case EC_RESET_COEFFICIENTS:
12731    switch (internal_command)
12732    {
12733    default:
12734      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12735        B1_FACILITY_EC), EC_COMMAND_1);
12736    case EC_COMMAND_1:
12737      if (adjust_b_process (Id, plci, Rc) != GOOD)
12738      {
12739        dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12740          UnMapId (Id), (char   *)(FILE_), __LINE__));
12741        Info = _FACILITY_NOT_SUPPORTED;
12742        break;
12743      }
12744      if (plci->internal_command)
12745        return;
12746    case EC_COMMAND_2:
12747      if (plci->sig_req)
12748      {
12749        plci->internal_command = EC_COMMAND_2;
12750        return;
12751      }
12752      plci->internal_command = EC_COMMAND_3;
12753      ec_write_parameters (plci);
12754      return;
12755    case EC_COMMAND_3:
12756      if ((Rc != OK) && (Rc != OK_FC))
12757      {
12758        dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12759          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12760        Info = _FACILITY_NOT_SUPPORTED;
12761        break;
12762      }
12763      break;
12764    }
12765    break;
12766
12767  case EC_DISABLE_OPERATION:
12768    switch (internal_command)
12769    {
12770    default:
12771    case EC_COMMAND_1:
12772      if (plci->B1_facilities & B1_FACILITY_EC)
12773      {
12774        if (plci->sig_req)
12775        {
12776          plci->internal_command = EC_COMMAND_1;
12777          return;
12778        }
12779        plci->internal_command = EC_COMMAND_2;
12780        ec_write_parameters (plci);
12781        return;
12782      }
12783      Rc = OK;
12784    case EC_COMMAND_2:
12785      if ((Rc != OK) && (Rc != OK_FC))
12786      {
12787        dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12788          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12789        Info = _FACILITY_NOT_SUPPORTED;
12790        break;
12791      }
12792      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12793        ~B1_FACILITY_EC), EC_COMMAND_3);
12794    case EC_COMMAND_3:
12795      if (adjust_b_process (Id, plci, Rc) != GOOD)
12796      {
12797        dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12798          UnMapId (Id), (char   *)(FILE_), __LINE__));
12799        Info = _FACILITY_NOT_SUPPORTED;
12800        break;
12801      }
12802      if (plci->internal_command)
12803        return;
12804      break;
12805    }
12806    break;
12807  }
12808  sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12809    "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12810    PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12811}
12812
12813
12814static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12815{
12816  word Info;
12817  word opt;
12818    API_PARSE ec_parms[3];
12819    byte result[16];
12820
12821  dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12822    UnMapId (Id), (char   *)(FILE_), __LINE__));
12823
12824  Info = GOOD;
12825  result[0] = 0;
12826  if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12827  {
12828    dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12829      UnMapId (Id), (char   *)(FILE_), __LINE__));
12830    Info = _FACILITY_NOT_SUPPORTED;
12831  }
12832  else
12833  {
12834    if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12835    {
12836      if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12837      {
12838        dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12839          UnMapId (Id), (char   *)(FILE_), __LINE__));
12840        Info = _WRONG_MESSAGE_FORMAT;
12841      }
12842      else
12843      {
12844        if (plci == NULL)
12845        {
12846          dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12847            UnMapId (Id), (char   *)(FILE_), __LINE__));
12848          Info = _WRONG_IDENTIFIER;
12849        }
12850        else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12851        {
12852          dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12853            UnMapId (Id), (char   *)(FILE_), __LINE__));
12854          Info = _WRONG_STATE;
12855        }
12856        else
12857        {
12858          plci->command = 0;
12859          plci->ec_cmd = GET_WORD (ec_parms[0].info);
12860          plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12861          result[0] = 2;
12862          PUT_WORD (&result[1], EC_SUCCESS);
12863          if (msg[1].length >= 4)
12864          {
12865            opt = GET_WORD (&ec_parms[0].info[2]);
12866            plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12867              LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12868            if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12869              plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12870            if (opt & EC_DETECT_DISABLE_TONE)
12871              plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12872            if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12873              plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12874            if (msg[1].length >= 6)
12875            {
12876              plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12877            }
12878          }
12879          switch (plci->ec_cmd)
12880          {
12881          case EC_ENABLE_OPERATION:
12882            plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12883            start_internal_command (Id, plci, ec_command);
12884            return (false);
12885
12886          case EC_DISABLE_OPERATION:
12887            plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12888              LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12889              LEC_RESET_COEFFICIENTS;
12890            start_internal_command (Id, plci, ec_command);
12891            return (false);
12892
12893          case EC_FREEZE_COEFFICIENTS:
12894            plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12895            start_internal_command (Id, plci, ec_command);
12896            return (false);
12897
12898          case EC_RESUME_COEFFICIENT_UPDATE:
12899            plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12900            start_internal_command (Id, plci, ec_command);
12901            return (false);
12902
12903          case EC_RESET_COEFFICIENTS:
12904            plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12905            start_internal_command (Id, plci, ec_command);
12906            return (false);
12907
12908          default:
12909            dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12910              UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12911            PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12912          }
12913        }
12914      }
12915    }
12916    else
12917    {
12918      if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12919      {
12920        dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12921          UnMapId (Id), (char   *)(FILE_), __LINE__));
12922        Info = _WRONG_MESSAGE_FORMAT;
12923      }
12924      else
12925      {
12926        if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12927        {
12928          result[0] = 11;
12929          PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12930          result[3] = 8;
12931          PUT_WORD (&result[4], GOOD);
12932          PUT_WORD (&result[6], 0x0007);
12933          PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12934          PUT_WORD (&result[10], 0);
12935        }
12936        else if (plci == NULL)
12937        {
12938          dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12939            UnMapId (Id), (char   *)(FILE_), __LINE__));
12940          Info = _WRONG_IDENTIFIER;
12941        }
12942        else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12943        {
12944          dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12945            UnMapId (Id), (char   *)(FILE_), __LINE__));
12946          Info = _WRONG_STATE;
12947        }
12948        else
12949        {
12950          plci->command = 0;
12951          plci->ec_cmd = GET_WORD (ec_parms[0].info);
12952          plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12953          result[0] = 5;
12954          PUT_WORD (&result[1], plci->ec_cmd);
12955          result[3] = 2;
12956          PUT_WORD (&result[4], GOOD);
12957          plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12958            LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12959          plci->ec_tail_length = 0;
12960          if (ec_parms[1].length >= 2)
12961          {
12962            opt = GET_WORD (&ec_parms[1].info[1]);
12963            if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12964              plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12965            if (opt & EC_DETECT_DISABLE_TONE)
12966              plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12967            if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12968              plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12969            if (ec_parms[1].length >= 4)
12970            {
12971              plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12972            }
12973          }
12974          switch (plci->ec_cmd)
12975          {
12976          case EC_ENABLE_OPERATION:
12977            plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12978            start_internal_command (Id, plci, ec_command);
12979            return (false);
12980
12981          case EC_DISABLE_OPERATION:
12982            plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12983              LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12984              LEC_RESET_COEFFICIENTS;
12985            start_internal_command (Id, plci, ec_command);
12986            return (false);
12987
12988          default:
12989            dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12990              UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12991            PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12992          }
12993        }
12994      }
12995    }
12996  }
12997  sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12998    "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12999    PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13000  return (false);
13001}
13002
13003
13004static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13005{
13006    byte result[8];
13007
13008  dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13009    UnMapId (Id), (char   *)(FILE_), __LINE__));
13010
13011  if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13012  {
13013    if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13014    {
13015      result[0] = 2;
13016      PUT_WORD (&result[1], 0);
13017      switch (msg[1])
13018      {
13019      case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13020        PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13021        break;
13022      case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13023        PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13024        break;
13025      case LEC_DISABLE_RELEASED:
13026        PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13027        break;
13028      }
13029    }
13030    else
13031    {
13032      result[0] = 5;
13033      PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13034      result[3] = 2;
13035      PUT_WORD (&result[4], 0);
13036      switch (msg[1])
13037      {
13038      case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13039        PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13040        break;
13041      case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13042        PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13043        break;
13044      case LEC_DISABLE_RELEASED:
13045        PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13046        break;
13047      }
13048    }
13049    sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13050      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13051  }
13052}
13053
13054
13055
13056/*------------------------------------------------------------------*/
13057/* Advanced voice                                                   */
13058/*------------------------------------------------------------------*/
13059
13060static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13061{
13062  DIVA_CAPI_ADAPTER   *a;
13063  word i;
13064  byte *p;
13065
13066  word w, n, j, k;
13067  byte ch_map[MIXER_CHANNELS_BRI];
13068
13069    byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13070
13071  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13072    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13073    (char   *)(FILE_), __LINE__, write_command));
13074
13075  a = plci->adapter;
13076  p = coef_buffer + 1;
13077  *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13078  i = 0;
13079  while (i + sizeof(word) <= a->adv_voice_coef_length)
13080  {
13081    PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13082    p += 2;
13083    i += 2;
13084  }
13085  while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13086  {
13087    PUT_WORD (p, 0x8000);
13088    p += 2;
13089    i += 2;
13090  }
13091
13092  if (!a->li_pri && (plci->li_bchannel_id == 0))
13093  {
13094    if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13095    {
13096      plci->li_bchannel_id = 1;
13097      li_config_table[a->li_base].plci = plci;
13098      dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13099        (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13100        (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13101    }
13102    else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13103    {
13104      plci->li_bchannel_id = 2;
13105      li_config_table[a->li_base + 1].plci = plci;
13106      dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13107        (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13108        (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13109    }
13110  }
13111  if (!a->li_pri && (plci->li_bchannel_id != 0)
13112   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13113  {
13114    i = a->li_base + (plci->li_bchannel_id - 1);
13115    switch (write_command)
13116    {
13117    case ADV_VOICE_WRITE_ACTIVATION:
13118      j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13119      k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13120      if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13121      {
13122        li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13123        li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13124      }
13125      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13126      {
13127        li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13128        li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13129        li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13130        li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13131      }
13132      mixer_calculate_coefs (a);
13133      li_config_table[i].curchnl = li_config_table[i].channel;
13134      li_config_table[j].curchnl = li_config_table[j].channel;
13135      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13136        li_config_table[k].curchnl = li_config_table[k].channel;
13137      break;
13138
13139    case ADV_VOICE_WRITE_DEACTIVATION:
13140      for (j = 0; j < li_total_channels; j++)
13141      {
13142        li_config_table[i].flag_table[j] = 0;
13143        li_config_table[j].flag_table[i] = 0;
13144      }
13145      k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13146      for (j = 0; j < li_total_channels; j++)
13147      {
13148        li_config_table[k].flag_table[j] = 0;
13149        li_config_table[j].flag_table[k] = 0;
13150      }
13151      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13152      {
13153        k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13154        for (j = 0; j < li_total_channels; j++)
13155        {
13156          li_config_table[k].flag_table[j] = 0;
13157          li_config_table[j].flag_table[k] = 0;
13158        }
13159      }
13160      mixer_calculate_coefs (a);
13161      break;
13162    }
13163    if (plci->B1_facilities & B1_FACILITY_MIXER)
13164    {
13165      w = 0;
13166      if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13167        w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13168      if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13169        w |= MIXER_FEATURE_ENABLE_TX_DATA;
13170      if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13171        w |= MIXER_FEATURE_ENABLE_RX_DATA;
13172      *(p++) = (byte) w;
13173      *(p++) = (byte)(w >> 8);
13174      for (j = 0; j < sizeof(ch_map); j += 2)
13175      {
13176        ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13177        ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13178      }
13179      for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13180      {
13181        i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13182        j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13183        if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13184        {
13185          *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13186          w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13187          li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13188        }
13189        else
13190        {
13191          *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13192            a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13193        }
13194      }
13195    }
13196    else
13197    {
13198      for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13199        *(p++) = a->adv_voice_coef_buffer[i];
13200    }
13201  }
13202  else
13203
13204  {
13205    for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13206      *(p++) = a->adv_voice_coef_buffer[i];
13207  }
13208  coef_buffer[0] = (p - coef_buffer) - 1;
13209  add_p (plci, FTY, coef_buffer);
13210  sig_req (plci, TEL_CTRL, 0);
13211  send_req (plci);
13212}
13213
13214
13215static void adv_voice_clear_config (PLCI   *plci)
13216{
13217  DIVA_CAPI_ADAPTER   *a;
13218
13219  word i, j;
13220
13221
13222  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13223    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13224    (char   *)(FILE_), __LINE__));
13225
13226  a = plci->adapter;
13227  if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13228  {
13229    a->adv_voice_coef_length = 0;
13230
13231    if (!a->li_pri && (plci->li_bchannel_id != 0)
13232     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13233    {
13234      i = a->li_base + (plci->li_bchannel_id - 1);
13235      li_config_table[i].curchnl = 0;
13236      li_config_table[i].channel = 0;
13237      li_config_table[i].chflags = 0;
13238      for (j = 0; j < li_total_channels; j++)
13239      {
13240        li_config_table[i].flag_table[j] = 0;
13241        li_config_table[j].flag_table[i] = 0;
13242        li_config_table[i].coef_table[j] = 0;
13243        li_config_table[j].coef_table[i] = 0;
13244      }
13245      li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13246      i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13247      li_config_table[i].curchnl = 0;
13248      li_config_table[i].channel = 0;
13249      li_config_table[i].chflags = 0;
13250      for (j = 0; j < li_total_channels; j++)
13251      {
13252        li_config_table[i].flag_table[j] = 0;
13253        li_config_table[j].flag_table[i] = 0;
13254        li_config_table[i].coef_table[j] = 0;
13255        li_config_table[j].coef_table[i] = 0;
13256      }
13257      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13258      {
13259        i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13260        li_config_table[i].curchnl = 0;
13261        li_config_table[i].channel = 0;
13262        li_config_table[i].chflags = 0;
13263        for (j = 0; j < li_total_channels; j++)
13264        {
13265          li_config_table[i].flag_table[j] = 0;
13266          li_config_table[j].flag_table[i] = 0;
13267          li_config_table[i].coef_table[j] = 0;
13268          li_config_table[j].coef_table[i] = 0;
13269        }
13270      }
13271    }
13272
13273  }
13274}
13275
13276
13277static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13278{
13279
13280  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13281    UnMapId (Id), (char   *)(FILE_), __LINE__));
13282
13283}
13284
13285
13286static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13287{
13288
13289  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13290    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13291
13292  return (GOOD);
13293}
13294
13295
13296static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13297{
13298  DIVA_CAPI_ADAPTER   *a;
13299  word Info;
13300
13301  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13302    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13303
13304  Info = GOOD;
13305  a = plci->adapter;
13306  if ((plci->B1_facilities & B1_FACILITY_VOICE)
13307   && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13308  {
13309    switch (plci->adjust_b_state)
13310    {
13311    case ADJUST_B_RESTORE_VOICE_1:
13312      plci->internal_command = plci->adjust_b_command;
13313      if (plci->sig_req)
13314      {
13315        plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13316        break;
13317      }
13318      adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13319      plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13320      break;
13321    case ADJUST_B_RESTORE_VOICE_2:
13322      if ((Rc != OK) && (Rc != OK_FC))
13323      {
13324        dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13325          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13326        Info = _WRONG_STATE;
13327        break;
13328      }
13329      break;
13330    }
13331  }
13332  return (Info);
13333}
13334
13335
13336
13337
13338/*------------------------------------------------------------------*/
13339/* B1 resource switching                                            */
13340/*------------------------------------------------------------------*/
13341
13342static byte b1_facilities_table[] =
13343{
13344  0x00,  /* 0  No bchannel resources      */
13345  0x00,  /* 1  Codec (automatic law)      */
13346  0x00,  /* 2  Codec (A-law)              */
13347  0x00,  /* 3  Codec (y-law)              */
13348  0x00,  /* 4  HDLC for X.21              */
13349  0x00,  /* 5  HDLC                       */
13350  0x00,  /* 6  External Device 0          */
13351  0x00,  /* 7  External Device 1          */
13352  0x00,  /* 8  HDLC 56k                   */
13353  0x00,  /* 9  Transparent                */
13354  0x00,  /* 10 Loopback to network        */
13355  0x00,  /* 11 Test pattern to net        */
13356  0x00,  /* 12 Rate adaptation sync       */
13357  0x00,  /* 13 Rate adaptation async      */
13358  0x00,  /* 14 R-Interface                */
13359  0x00,  /* 15 HDLC 128k leased line      */
13360  0x00,  /* 16 FAX                        */
13361  0x00,  /* 17 Modem async                */
13362  0x00,  /* 18 Modem sync HDLC            */
13363  0x00,  /* 19 V.110 async HDLC           */
13364  0x12,  /* 20 Adv voice (Trans,mixer)    */
13365  0x00,  /* 21 Codec connected to IC      */
13366  0x0c,  /* 22 Trans,DTMF                 */
13367  0x1e,  /* 23 Trans,DTMF+mixer           */
13368  0x1f,  /* 24 Trans,DTMF+mixer+local     */
13369  0x13,  /* 25 Trans,mixer+local          */
13370  0x12,  /* 26 HDLC,mixer                 */
13371  0x12,  /* 27 HDLC 56k,mixer             */
13372  0x2c,  /* 28 Trans,LEC+DTMF             */
13373  0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13374  0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13375  0x2c,  /* 31 RTP,LEC+DTMF               */
13376  0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13377  0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13378  0x00,  /* 34 Signaling task             */
13379  0x00,  /* 35 PIAFS                      */
13380  0x0c,  /* 36 Trans,DTMF+TONE            */
13381  0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13382  0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13383};
13384
13385
13386static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13387{
13388  word b1_facilities;
13389
13390  b1_facilities = b1_facilities_table[b1_resource];
13391  if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13392  {
13393
13394    if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13395       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13396
13397    {
13398      if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13399        b1_facilities |= B1_FACILITY_DTMFX;
13400      if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13401        b1_facilities |= B1_FACILITY_DTMFR;
13402    }
13403  }
13404  if ((b1_resource == 17) || (b1_resource == 18))
13405  {
13406    if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13407      b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13408  }
13409/*
13410  dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13411    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13412    (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13413*/
13414  return (b1_facilities);
13415}
13416
13417
13418static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13419{
13420  byte b;
13421
13422  switch (b1_resource)
13423  {
13424  case 5:
13425  case 26:
13426    if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13427      b = 26;
13428    else
13429      b = 5;
13430    break;
13431
13432  case 8:
13433  case 27:
13434    if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13435      b = 27;
13436    else
13437      b = 8;
13438    break;
13439
13440  case 9:
13441  case 20:
13442  case 22:
13443  case 23:
13444  case 24:
13445  case 25:
13446  case 28:
13447  case 29:
13448  case 30:
13449  case 36:
13450  case 37:
13451  case 38:
13452    if (b1_facilities & B1_FACILITY_EC)
13453    {
13454      if (b1_facilities & B1_FACILITY_LOCAL)
13455        b = 30;
13456      else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13457        b = 29;
13458      else
13459        b = 28;
13460    }
13461
13462    else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13463      && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13464       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13465    {
13466      if (b1_facilities & B1_FACILITY_LOCAL)
13467        b = 38;
13468      else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13469        b = 37;
13470      else
13471        b = 36;
13472    }
13473
13474    else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13475      && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13476     || ((b1_facilities & B1_FACILITY_DTMFR)
13477      && ((b1_facilities & B1_FACILITY_MIXER)
13478       || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13479     || ((b1_facilities & B1_FACILITY_DTMFX)
13480      && ((b1_facilities & B1_FACILITY_MIXER)
13481       || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13482    {
13483      if (b1_facilities & B1_FACILITY_LOCAL)
13484        b = 24;
13485      else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13486        b = 23;
13487      else
13488        b = 22;
13489    }
13490    else
13491    {
13492      if (b1_facilities & B1_FACILITY_LOCAL)
13493        b = 25;
13494      else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13495        b = 20;
13496      else
13497        b = 9;
13498    }
13499    break;
13500
13501  case 31:
13502  case 32:
13503  case 33:
13504    if (b1_facilities & B1_FACILITY_LOCAL)
13505      b = 33;
13506    else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13507      b = 32;
13508    else
13509      b = 31;
13510    break;
13511
13512  default:
13513    b = b1_resource;
13514  }
13515  dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13516    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13517    (char   *)(FILE_), __LINE__,
13518    b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13519  return (b);
13520}
13521
13522
13523static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13524{
13525  word removed_facilities;
13526
13527  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13528    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13529    (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13530    new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13531
13532  new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13533  removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13534
13535  if (removed_facilities & B1_FACILITY_EC)
13536    ec_clear_config (plci);
13537
13538
13539  if (removed_facilities & B1_FACILITY_DTMFR)
13540  {
13541    dtmf_rec_clear_config (plci);
13542    dtmf_parameter_clear_config (plci);
13543  }
13544  if (removed_facilities & B1_FACILITY_DTMFX)
13545    dtmf_send_clear_config (plci);
13546
13547
13548  if (removed_facilities & B1_FACILITY_MIXER)
13549    mixer_clear_config (plci);
13550
13551  if (removed_facilities & B1_FACILITY_VOICE)
13552    adv_voice_clear_config (plci);
13553  plci->B1_facilities = new_b1_facilities;
13554}
13555
13556
13557static void adjust_b_clear (PLCI   *plci)
13558{
13559
13560  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13561    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13562    (char   *)(FILE_), __LINE__));
13563
13564  plci->adjust_b_restore = false;
13565}
13566
13567
13568static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13569{
13570  word Info;
13571  byte b1_resource;
13572  NCCI   * ncci_ptr;
13573    API_PARSE bp[2];
13574
13575  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13576    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13577
13578  Info = GOOD;
13579  switch (plci->adjust_b_state)
13580  {
13581  case ADJUST_B_START:
13582    if ((plci->adjust_b_parms_msg == NULL)
13583     && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13584     && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13585      ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13586    {
13587      b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13588        0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13589      if (b1_resource == plci->B1_resource)
13590      {
13591        adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13592        break;
13593      }
13594      if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13595      {
13596        dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13597          UnMapId (Id), (char   *)(FILE_), __LINE__,
13598          plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13599        Info = _WRONG_STATE;
13600        break;
13601      }
13602    }
13603    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13604    {
13605
13606      mixer_prepare_switch (Id, plci);
13607
13608
13609      dtmf_prepare_switch (Id, plci);
13610      dtmf_parameter_prepare_switch (Id, plci);
13611
13612
13613      ec_prepare_switch (Id, plci);
13614
13615      adv_voice_prepare_switch (Id, plci);
13616    }
13617    plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13618    Rc = OK;
13619  case ADJUST_B_SAVE_MIXER_1:
13620    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13621    {
13622
13623      Info = mixer_save_config (Id, plci, Rc);
13624      if ((Info != GOOD) || plci->internal_command)
13625        break;
13626
13627    }
13628    plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13629    Rc = OK;
13630  case ADJUST_B_SAVE_DTMF_1:
13631    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13632    {
13633
13634      Info = dtmf_save_config (Id, plci, Rc);
13635      if ((Info != GOOD) || plci->internal_command)
13636        break;
13637
13638    }
13639    plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13640  case ADJUST_B_REMOVE_L23_1:
13641    if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13642     && plci->NL.Id && !plci->nl_remove_id)
13643    {
13644      plci->internal_command = plci->adjust_b_command;
13645      if (plci->adjust_b_ncci != 0)
13646      {
13647        ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13648        while (ncci_ptr->data_pending)
13649        {
13650          plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13651          data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13652        }
13653        while (ncci_ptr->data_ack_pending)
13654          data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13655      }
13656      nl_req_ncci (plci, REMOVE,
13657        (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13658      send_req (plci);
13659      plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13660      break;
13661    }
13662    plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13663    Rc = OK;
13664  case ADJUST_B_REMOVE_L23_2:
13665    if ((Rc != OK) && (Rc != OK_FC))
13666    {
13667      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13668        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13669      Info = _WRONG_STATE;
13670      break;
13671    }
13672    if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13673    {
13674      if (plci_nl_busy (plci))
13675      {
13676        plci->internal_command = plci->adjust_b_command;
13677        break;
13678      }
13679    }
13680    plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13681    Rc = OK;
13682  case ADJUST_B_SAVE_EC_1:
13683    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13684    {
13685
13686      Info = ec_save_config (Id, plci, Rc);
13687      if ((Info != GOOD) || plci->internal_command)
13688        break;
13689
13690    }
13691    plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13692    Rc = OK;
13693  case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13694    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13695    {
13696
13697      Info = dtmf_parameter_save_config (Id, plci, Rc);
13698      if ((Info != GOOD) || plci->internal_command)
13699        break;
13700
13701    }
13702    plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13703    Rc = OK;
13704  case ADJUST_B_SAVE_VOICE_1:
13705    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13706    {
13707      Info = adv_voice_save_config (Id, plci, Rc);
13708      if ((Info != GOOD) || plci->internal_command)
13709        break;
13710    }
13711    plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13712  case ADJUST_B_SWITCH_L1_1:
13713    if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13714    {
13715      if (plci->sig_req)
13716      {
13717        plci->internal_command = plci->adjust_b_command;
13718        break;
13719      }
13720      if (plci->adjust_b_parms_msg != NULL)
13721        api_load_msg (plci->adjust_b_parms_msg, bp);
13722      else
13723        api_load_msg (&plci->B_protocol, bp);
13724      Info = add_b1 (plci, bp,
13725        (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13726        plci->adjust_b_facilities);
13727      if (Info != GOOD)
13728      {
13729        dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13730          UnMapId (Id), (char   *)(FILE_), __LINE__,
13731          plci->B1_resource, plci->adjust_b_facilities));
13732        break;
13733      }
13734      plci->internal_command = plci->adjust_b_command;
13735      sig_req (plci, RESOURCES, 0);
13736      send_req (plci);
13737      plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13738      break;
13739    }
13740    plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13741    Rc = OK;
13742  case ADJUST_B_SWITCH_L1_2:
13743    if ((Rc != OK) && (Rc != OK_FC))
13744    {
13745      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13746        UnMapId (Id), (char   *)(FILE_), __LINE__,
13747        Rc, plci->B1_resource, plci->adjust_b_facilities));
13748      Info = _WRONG_STATE;
13749      break;
13750    }
13751    plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13752    Rc = OK;
13753  case ADJUST_B_RESTORE_VOICE_1:
13754  case ADJUST_B_RESTORE_VOICE_2:
13755    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13756    {
13757      Info = adv_voice_restore_config (Id, plci, Rc);
13758      if ((Info != GOOD) || plci->internal_command)
13759        break;
13760    }
13761    plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13762    Rc = OK;
13763  case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13764  case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13765    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13766    {
13767
13768      Info = dtmf_parameter_restore_config (Id, plci, Rc);
13769      if ((Info != GOOD) || plci->internal_command)
13770        break;
13771
13772    }
13773    plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13774    Rc = OK;
13775  case ADJUST_B_RESTORE_EC_1:
13776  case ADJUST_B_RESTORE_EC_2:
13777    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13778    {
13779
13780      Info = ec_restore_config (Id, plci, Rc);
13781      if ((Info != GOOD) || plci->internal_command)
13782        break;
13783
13784    }
13785    plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13786  case ADJUST_B_ASSIGN_L23_1:
13787    if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13788    {
13789      if (plci_nl_busy (plci))
13790      {
13791        plci->internal_command = plci->adjust_b_command;
13792        break;
13793      }
13794      if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13795        plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13796      if (plci->adjust_b_parms_msg != NULL)
13797        api_load_msg (plci->adjust_b_parms_msg, bp);
13798      else
13799        api_load_msg (&plci->B_protocol, bp);
13800      Info = add_b23 (plci, bp);
13801      if (Info != GOOD)
13802      {
13803        dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13804          UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13805        break;
13806      }
13807      plci->internal_command = plci->adjust_b_command;
13808      nl_req_ncci (plci, ASSIGN, 0);
13809      send_req (plci);
13810      plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13811      break;
13812    }
13813    plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13814    Rc = ASSIGN_OK;
13815  case ADJUST_B_ASSIGN_L23_2:
13816    if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13817    {
13818      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13819        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13820      Info = _WRONG_STATE;
13821      break;
13822    }
13823    if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13824    {
13825      if (Rc != ASSIGN_OK)
13826      {
13827        plci->internal_command = plci->adjust_b_command;
13828        break;
13829      }
13830    }
13831    if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13832    {
13833      plci->adjust_b_restore = true;
13834      break;
13835    }
13836    plci->adjust_b_state = ADJUST_B_CONNECT_1;
13837  case ADJUST_B_CONNECT_1:
13838    if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13839    {
13840      plci->internal_command = plci->adjust_b_command;
13841      if (plci_nl_busy (plci))
13842        break;
13843      nl_req_ncci (plci, N_CONNECT, 0);
13844      send_req (plci);
13845      plci->adjust_b_state = ADJUST_B_CONNECT_2;
13846      break;
13847    }
13848    plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13849    Rc = OK;
13850  case ADJUST_B_CONNECT_2:
13851  case ADJUST_B_CONNECT_3:
13852  case ADJUST_B_CONNECT_4:
13853    if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13854    {
13855      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13856        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13857      Info = _WRONG_STATE;
13858      break;
13859    }
13860    if (Rc == OK)
13861    {
13862      if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13863      {
13864        get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13865        Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13866      }
13867      if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13868        plci->adjust_b_state = ADJUST_B_CONNECT_3;
13869      else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13870        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13871    }
13872    else if (Rc == 0)
13873    {
13874      if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13875        plci->adjust_b_state = ADJUST_B_CONNECT_4;
13876      else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13877        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13878    }
13879    if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13880    {
13881      plci->internal_command = plci->adjust_b_command;
13882      break;
13883    }
13884    Rc = OK;
13885  case ADJUST_B_RESTORE_DTMF_1:
13886  case ADJUST_B_RESTORE_DTMF_2:
13887    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13888    {
13889
13890      Info = dtmf_restore_config (Id, plci, Rc);
13891      if ((Info != GOOD) || plci->internal_command)
13892        break;
13893
13894    }
13895    plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13896    Rc = OK;
13897  case ADJUST_B_RESTORE_MIXER_1:
13898  case ADJUST_B_RESTORE_MIXER_2:
13899  case ADJUST_B_RESTORE_MIXER_3:
13900  case ADJUST_B_RESTORE_MIXER_4:
13901  case ADJUST_B_RESTORE_MIXER_5:
13902  case ADJUST_B_RESTORE_MIXER_6:
13903  case ADJUST_B_RESTORE_MIXER_7:
13904    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13905    {
13906
13907      Info = mixer_restore_config (Id, plci, Rc);
13908      if ((Info != GOOD) || plci->internal_command)
13909        break;
13910
13911    }
13912    plci->adjust_b_state = ADJUST_B_END;
13913  case ADJUST_B_END:
13914    break;
13915  }
13916  return (Info);
13917}
13918
13919
13920static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13921{
13922
13923  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13924    UnMapId (Id), (char   *)(FILE_), __LINE__,
13925    plci->B1_resource, b1_facilities));
13926
13927  plci->adjust_b_parms_msg = bp_msg;
13928  plci->adjust_b_facilities = b1_facilities;
13929  plci->adjust_b_command = internal_command;
13930  plci->adjust_b_ncci = (word)(Id >> 16);
13931  if ((bp_msg == NULL) && (plci->B1_resource == 0))
13932    plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13933  else
13934    plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13935  plci->adjust_b_state = ADJUST_B_START;
13936  dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13937    UnMapId (Id), (char   *)(FILE_), __LINE__,
13938    plci->B1_resource, b1_facilities));
13939}
13940
13941
13942static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13943{
13944  word internal_command;
13945
13946  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13947    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13948
13949  internal_command = plci->internal_command;
13950  plci->internal_command = 0;
13951  switch (internal_command)
13952  {
13953  default:
13954    plci->command = 0;
13955    if (plci->req_in != 0)
13956    {
13957      plci->internal_command = ADJUST_B_RESTORE_1;
13958      break;
13959    }
13960    Rc = OK;
13961  case ADJUST_B_RESTORE_1:
13962    if ((Rc != OK) && (Rc != OK_FC))
13963    {
13964      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13965        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13966    }
13967    plci->adjust_b_parms_msg = NULL;
13968    plci->adjust_b_facilities = plci->B1_facilities;
13969    plci->adjust_b_command = ADJUST_B_RESTORE_2;
13970    plci->adjust_b_ncci = (word)(Id >> 16);
13971    plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13972    plci->adjust_b_state = ADJUST_B_START;
13973    dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13974      UnMapId (Id), (char   *)(FILE_), __LINE__));
13975  case ADJUST_B_RESTORE_2:
13976    if (adjust_b_process (Id, plci, Rc) != GOOD)
13977    {
13978      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13979        UnMapId (Id), (char   *)(FILE_), __LINE__));
13980    }
13981    if (plci->internal_command)
13982      break;
13983    break;
13984  }
13985}
13986
13987
13988static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
13989{
13990  word Info;
13991  word internal_command;
13992
13993  dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
13994    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13995
13996  Info = GOOD;
13997  internal_command = plci->internal_command;
13998  plci->internal_command = 0;
13999  switch (internal_command)
14000  {
14001  default:
14002    plci->command = 0;
14003    plci->adjust_b_parms_msg = NULL;
14004    plci->adjust_b_facilities = plci->B1_facilities;
14005    plci->adjust_b_command = RESET_B3_COMMAND_1;
14006    plci->adjust_b_ncci = (word)(Id >> 16);
14007    plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14008    plci->adjust_b_state = ADJUST_B_START;
14009    dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14010      UnMapId (Id), (char   *)(FILE_), __LINE__));
14011  case RESET_B3_COMMAND_1:
14012    Info = adjust_b_process (Id, plci, Rc);
14013    if (Info != GOOD)
14014    {
14015      dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14016        UnMapId (Id), (char   *)(FILE_), __LINE__));
14017      break;
14018    }
14019    if (plci->internal_command)
14020      return;
14021    break;
14022  }
14023/*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14024  sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14025}
14026
14027
14028static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14029{
14030  word Info;
14031  word internal_command;
14032  byte esc_chi[3];
14033
14034  dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14035    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14036
14037  Info = GOOD;
14038  internal_command = plci->internal_command;
14039  plci->internal_command = 0;
14040  switch (internal_command)
14041  {
14042  default:
14043    plci->command = 0;
14044    plci->adjust_b_parms_msg = &plci->saved_msg;
14045    if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14046      plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14047    else
14048      plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14049    plci->adjust_b_command = SELECT_B_COMMAND_1;
14050    plci->adjust_b_ncci = (word)(Id >> 16);
14051    if (plci->saved_msg.parms[0].length == 0)
14052    {
14053      plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14054        ADJUST_B_MODE_NO_RESOURCE;
14055    }
14056    else
14057    {
14058      plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14059        ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14060    }
14061    plci->adjust_b_state = ADJUST_B_START;
14062    dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14063      UnMapId (Id), (char   *)(FILE_), __LINE__));
14064  case SELECT_B_COMMAND_1:
14065    Info = adjust_b_process (Id, plci, Rc);
14066    if (Info != GOOD)
14067    {
14068      dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14069        UnMapId (Id), (char   *)(FILE_), __LINE__));
14070      break;
14071    }
14072    if (plci->internal_command)
14073      return;
14074    if (plci->tel == ADV_VOICE)
14075    {
14076      esc_chi[0] = 0x02;
14077      esc_chi[1] = 0x18;
14078      esc_chi[2] = plci->b_channel;
14079      SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14080    }
14081    break;
14082  }
14083  sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14084}
14085
14086
14087static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14088{
14089  word Info;
14090  word internal_command;
14091
14092  dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14093    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14094
14095  Info = GOOD;
14096  internal_command = plci->internal_command;
14097  plci->internal_command = 0;
14098  switch (internal_command)
14099  {
14100  default:
14101    plci->command = 0;
14102  case FAX_CONNECT_ACK_COMMAND_1:
14103    if (plci_nl_busy (plci))
14104    {
14105      plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14106      return;
14107    }
14108    plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14109    plci->NData[0].P = plci->fax_connect_info_buffer;
14110    plci->NData[0].PLength = plci->fax_connect_info_length;
14111    plci->NL.X = plci->NData;
14112    plci->NL.ReqCh = 0;
14113    plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14114    plci->adapter->request (&plci->NL);
14115    return;
14116  case FAX_CONNECT_ACK_COMMAND_2:
14117    if ((Rc != OK) && (Rc != OK_FC))
14118    {
14119      dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14120        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14121      break;
14122    }
14123  }
14124  if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14125   && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14126  {
14127    if (plci->B3_prot == 4)
14128      sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14129    else
14130      sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14131    plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14132  }
14133}
14134
14135
14136static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14137{
14138  word Info;
14139  word internal_command;
14140
14141  dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14142    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14143
14144  Info = GOOD;
14145  internal_command = plci->internal_command;
14146  plci->internal_command = 0;
14147  switch (internal_command)
14148  {
14149  default:
14150    plci->command = 0;
14151  case FAX_EDATA_ACK_COMMAND_1:
14152    if (plci_nl_busy (plci))
14153    {
14154      plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14155      return;
14156    }
14157    plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14158    plci->NData[0].P = plci->fax_connect_info_buffer;
14159    plci->NData[0].PLength = plci->fax_edata_ack_length;
14160    plci->NL.X = plci->NData;
14161    plci->NL.ReqCh = 0;
14162    plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14163    plci->adapter->request (&plci->NL);
14164    return;
14165  case FAX_EDATA_ACK_COMMAND_2:
14166    if ((Rc != OK) && (Rc != OK_FC))
14167    {
14168      dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14169        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14170      break;
14171    }
14172  }
14173}
14174
14175
14176static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14177{
14178  word Info;
14179  word internal_command;
14180
14181  dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14182    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14183
14184  Info = GOOD;
14185  internal_command = plci->internal_command;
14186  plci->internal_command = 0;
14187  switch (internal_command)
14188  {
14189  default:
14190    plci->command = 0;
14191  case FAX_CONNECT_INFO_COMMAND_1:
14192    if (plci_nl_busy (plci))
14193    {
14194      plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14195      return;
14196    }
14197    plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14198    plci->NData[0].P = plci->fax_connect_info_buffer;
14199    plci->NData[0].PLength = plci->fax_connect_info_length;
14200    plci->NL.X = plci->NData;
14201    plci->NL.ReqCh = 0;
14202    plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14203    plci->adapter->request (&plci->NL);
14204    return;
14205  case FAX_CONNECT_INFO_COMMAND_2:
14206    if ((Rc != OK) && (Rc != OK_FC))
14207    {
14208      dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14209        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14210      Info = _WRONG_STATE;
14211      break;
14212    }
14213    if (plci_nl_busy (plci))
14214    {
14215      plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14216      return;
14217    }
14218    plci->command = _CONNECT_B3_R;
14219    nl_req_ncci (plci, N_CONNECT, 0);
14220    send_req (plci);
14221    return;
14222  }
14223  sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14224}
14225
14226
14227static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14228{
14229  word Info;
14230  word internal_command;
14231
14232  dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14233    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14234
14235  Info = GOOD;
14236  internal_command = plci->internal_command;
14237  plci->internal_command = 0;
14238  switch (internal_command)
14239  {
14240  default:
14241    plci->command = 0;
14242    plci->adjust_b_parms_msg = NULL;
14243    plci->adjust_b_facilities = plci->B1_facilities;
14244    plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14245    plci->adjust_b_ncci = (word)(Id >> 16);
14246    plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14247    plci->adjust_b_state = ADJUST_B_START;
14248    dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14249      UnMapId (Id), (char   *)(FILE_), __LINE__));
14250  case FAX_ADJUST_B23_COMMAND_1:
14251    Info = adjust_b_process (Id, plci, Rc);
14252    if (Info != GOOD)
14253    {
14254      dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14255        UnMapId (Id), (char   *)(FILE_), __LINE__));
14256      break;
14257    }
14258    if (plci->internal_command)
14259      return;
14260  case FAX_ADJUST_B23_COMMAND_2:
14261    if (plci_nl_busy (plci))
14262    {
14263      plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14264      return;
14265    }
14266    plci->command = _CONNECT_B3_R;
14267    nl_req_ncci (plci, N_CONNECT, 0);
14268    send_req (plci);
14269    return;
14270  }
14271  sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14272}
14273
14274
14275static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14276{
14277  word internal_command;
14278
14279  dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14280    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14281
14282  internal_command = plci->internal_command;
14283  plci->internal_command = 0;
14284  switch (internal_command)
14285  {
14286  default:
14287    plci->command = 0;
14288    plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14289    return;
14290  case FAX_DISCONNECT_COMMAND_1:
14291  case FAX_DISCONNECT_COMMAND_2:
14292  case FAX_DISCONNECT_COMMAND_3:
14293    if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14294    {
14295      dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14296        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14297      break;
14298    }
14299    if (Rc == OK)
14300    {
14301      if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14302       || (internal_command == FAX_DISCONNECT_COMMAND_2))
14303      {
14304        plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14305      }
14306    }
14307    else if (Rc == 0)
14308    {
14309      if (internal_command == FAX_DISCONNECT_COMMAND_1)
14310        plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14311    }
14312    return;
14313  }
14314}
14315
14316
14317
14318static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14319{
14320  word Info;
14321  word internal_command;
14322
14323  dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14324    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14325
14326  Info = GOOD;
14327  internal_command = plci->internal_command;
14328  plci->internal_command = 0;
14329  switch (internal_command)
14330  {
14331  default:
14332    plci->command = 0;
14333  case RTP_CONNECT_B3_REQ_COMMAND_1:
14334    if (plci_nl_busy (plci))
14335    {
14336      plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14337      return;
14338    }
14339    plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14340    nl_req_ncci (plci, N_CONNECT, 0);
14341    send_req (plci);
14342    return;
14343  case RTP_CONNECT_B3_REQ_COMMAND_2:
14344    if ((Rc != OK) && (Rc != OK_FC))
14345    {
14346      dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14347        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14348      Info = _WRONG_STATE;
14349      break;
14350    }
14351    if (plci_nl_busy (plci))
14352    {
14353      plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14354      return;
14355    }
14356    plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14357    plci->NData[0].PLength = plci->internal_req_buffer[0];
14358    plci->NData[0].P = plci->internal_req_buffer + 1;
14359    plci->NL.X = plci->NData;
14360    plci->NL.ReqCh = 0;
14361    plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14362    plci->adapter->request (&plci->NL);
14363    break;
14364  case RTP_CONNECT_B3_REQ_COMMAND_3:
14365    return;
14366  }
14367  sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14368}
14369
14370
14371static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14372{
14373  word Info;
14374  word internal_command;
14375
14376  dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14377    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14378
14379  Info = GOOD;
14380  internal_command = plci->internal_command;
14381  plci->internal_command = 0;
14382  switch (internal_command)
14383  {
14384  default:
14385    plci->command = 0;
14386  case RTP_CONNECT_B3_RES_COMMAND_1:
14387    if (plci_nl_busy (plci))
14388    {
14389      plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14390      return;
14391    }
14392    plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14393    nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14394    send_req (plci);
14395    return;
14396  case RTP_CONNECT_B3_RES_COMMAND_2:
14397    if ((Rc != OK) && (Rc != OK_FC))
14398    {
14399      dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14400        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14401      Info = _WRONG_STATE;
14402      break;
14403    }
14404    if (plci_nl_busy (plci))
14405    {
14406      plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14407      return;
14408    }
14409    sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14410    plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14411    plci->NData[0].PLength = plci->internal_req_buffer[0];
14412    plci->NData[0].P = plci->internal_req_buffer + 1;
14413    plci->NL.X = plci->NData;
14414    plci->NL.ReqCh = 0;
14415    plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14416    plci->adapter->request (&plci->NL);
14417    return;
14418  case RTP_CONNECT_B3_RES_COMMAND_3:
14419    return;
14420  }
14421}
14422
14423
14424
14425static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14426{
14427    byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14428  word Info;
14429  word internal_command;
14430
14431  dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14432    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14433
14434  Info = GOOD;
14435  internal_command = plci->internal_command;
14436  plci->internal_command = 0;
14437  switch (internal_command)
14438  {
14439  default:
14440    if (!plci->NL.Id)
14441      break;
14442    plci->command = 0;
14443    plci->adjust_b_parms_msg = NULL;
14444    plci->adjust_b_facilities = plci->B1_facilities;
14445    plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14446    plci->adjust_b_ncci = (word)(Id >> 16);
14447    plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14448    plci->adjust_b_state = ADJUST_B_START;
14449    dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14450      UnMapId (Id), (char   *)(FILE_), __LINE__));
14451  case HOLD_SAVE_COMMAND_1:
14452    Info = adjust_b_process (Id, plci, Rc);
14453    if (Info != GOOD)
14454    {
14455      dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14456        UnMapId (Id), (char   *)(FILE_), __LINE__));
14457      break;
14458    }
14459    if (plci->internal_command)
14460      return;
14461  }
14462  sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14463}
14464
14465
14466static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14467{
14468    byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14469  word Info;
14470  word internal_command;
14471
14472  dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14473    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14474
14475  Info = GOOD;
14476  internal_command = plci->internal_command;
14477  plci->internal_command = 0;
14478  switch (internal_command)
14479  {
14480  default:
14481    plci->command = 0;
14482    plci->adjust_b_parms_msg = NULL;
14483    plci->adjust_b_facilities = plci->B1_facilities;
14484    plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14485    plci->adjust_b_ncci = (word)(Id >> 16);
14486    plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14487    plci->adjust_b_state = ADJUST_B_START;
14488    dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14489      UnMapId (Id), (char   *)(FILE_), __LINE__));
14490  case RETRIEVE_RESTORE_COMMAND_1:
14491    Info = adjust_b_process (Id, plci, Rc);
14492    if (Info != GOOD)
14493    {
14494      dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14495        UnMapId (Id), (char   *)(FILE_), __LINE__));
14496      break;
14497    }
14498    if (plci->internal_command)
14499      return;
14500  }
14501  sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14502}
14503
14504
14505static void init_b1_config (PLCI   *plci)
14506{
14507
14508  dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14509    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14510    (char   *)(FILE_), __LINE__));
14511
14512  plci->B1_resource = 0;
14513  plci->B1_facilities = 0;
14514
14515  plci->li_bchannel_id = 0;
14516  mixer_clear_config (plci);
14517
14518
14519  ec_clear_config (plci);
14520
14521
14522  dtmf_rec_clear_config (plci);
14523  dtmf_send_clear_config (plci);
14524  dtmf_parameter_clear_config (plci);
14525
14526  adv_voice_clear_config (plci);
14527  adjust_b_clear (plci);
14528}
14529
14530
14531static void clear_b1_config (PLCI   *plci)
14532{
14533
14534  dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14535    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14536    (char   *)(FILE_), __LINE__));
14537
14538  adv_voice_clear_config (plci);
14539  adjust_b_clear (plci);
14540
14541  ec_clear_config (plci);
14542
14543
14544  dtmf_rec_clear_config (plci);
14545  dtmf_send_clear_config (plci);
14546  dtmf_parameter_clear_config (plci);
14547
14548
14549  if ((plci->li_bchannel_id != 0)
14550   && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14551  {
14552    mixer_clear_config (plci);
14553    li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14554    plci->li_bchannel_id = 0;
14555  }
14556
14557  plci->B1_resource = 0;
14558  plci->B1_facilities = 0;
14559}
14560
14561
14562/* -----------------------------------------------------------------
14563                XON protocol local helpers
14564   ----------------------------------------------------------------- */
14565static void channel_flow_control_remove (PLCI   * plci) {
14566  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14567  word i;
14568  for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14569    if (a->ch_flow_plci[i] == plci->Id) {
14570      a->ch_flow_plci[i] = 0;
14571      a->ch_flow_control[i] = 0;
14572    }
14573  }
14574}
14575
14576static void channel_x_on (PLCI   * plci, byte ch) {
14577  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14578  if (a->ch_flow_control[ch] & N_XON_SENT) {
14579    a->ch_flow_control[ch] &= ~N_XON_SENT;
14580  }
14581}
14582
14583static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14584  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14585  if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14586    a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14587    a->ch_flow_plci[ch] = plci->Id;
14588    a->ch_flow_control_pending++;
14589  }
14590}
14591
14592static void channel_request_xon (PLCI   * plci, byte ch) {
14593  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14594
14595  if (a->ch_flow_control[ch] & N_CH_XOFF) {
14596    a->ch_flow_control[ch] |= N_XON_REQ;
14597    a->ch_flow_control[ch] &= ~N_CH_XOFF;
14598    a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14599  }
14600}
14601
14602static void channel_xmit_extended_xon (PLCI   * plci) {
14603  DIVA_CAPI_ADAPTER   * a;
14604  int max_ch = ARRAY_SIZE(a->ch_flow_control);
14605  int i, one_requested = 0;
14606
14607  if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14608    return;
14609  }
14610
14611  for (i = 0; i < max_ch; i++) {
14612    if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14613        (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14614        (plci->Id == a->ch_flow_plci[i])) {
14615      channel_request_xon (plci, (byte)i);
14616      one_requested = 1;
14617    }
14618  }
14619
14620  if (one_requested) {
14621    channel_xmit_xon (plci);
14622  }
14623}
14624
14625/*
14626  Try to xmit next X_ON
14627  */
14628static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14629  int max_ch = ARRAY_SIZE(a->ch_flow_control);
14630  int i;
14631
14632  if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14633    return (0);
14634  }
14635
14636  if (a->last_flow_control_ch >= max_ch) {
14637    a->last_flow_control_ch = 1;
14638  }
14639  for (i=a->last_flow_control_ch; i < max_ch; i++) {
14640    if ((a->ch_flow_control[i] & N_XON_REQ) &&
14641        (plci->Id == a->ch_flow_plci[i])) {
14642      a->last_flow_control_ch = i+1;
14643      return (i);
14644    }
14645  }
14646
14647  for (i = 1; i < a->last_flow_control_ch; i++) {
14648    if ((a->ch_flow_control[i] & N_XON_REQ) &&
14649        (plci->Id == a->ch_flow_plci[i])) {
14650      a->last_flow_control_ch = i+1;
14651      return (i);
14652    }
14653  }
14654
14655  return (0);
14656}
14657
14658static void channel_xmit_xon (PLCI   * plci) {
14659  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14660  byte ch;
14661
14662  if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14663    return;
14664  }
14665  if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14666    return;
14667  }
14668  a->ch_flow_control[ch] &= ~N_XON_REQ;
14669  a->ch_flow_control[ch] |= N_XON_SENT;
14670
14671  plci->NL.Req = plci->nl_req = (byte)N_XON;
14672  plci->NL.ReqCh         = ch;
14673  plci->NL.X             = plci->NData;
14674  plci->NL.XNum          = 1;
14675  plci->NData[0].P       = &plci->RBuffer[0];
14676  plci->NData[0].PLength = 0;
14677
14678  plci->adapter->request(&plci->NL);
14679}
14680
14681static int channel_can_xon (PLCI   * plci, byte ch) {
14682  APPL   * APPLptr;
14683  DIVA_CAPI_ADAPTER   * a;
14684  word NCCIcode;
14685  dword count;
14686  word Num;
14687  word i;
14688
14689  APPLptr = plci->appl;
14690  a = plci->adapter;
14691
14692  if (!APPLptr)
14693    return (0);
14694
14695  NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14696
14697                /* count all buffers within the Application pool    */
14698                /* belonging to the same NCCI. XON if a first is    */
14699                /* used.                                            */
14700  count = 0;
14701  Num = 0xffff;
14702  for(i=0; i<APPLptr->MaxBuffer; i++) {
14703    if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14704    if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14705  }
14706  if ((count > 2) || (Num == 0xffff)) {
14707    return (0);
14708  }
14709  return (1);
14710}
14711
14712
14713/*------------------------------------------------------------------*/
14714
14715static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14716{
14717  return 1;
14718}
14719
14720
14721
14722/**********************************************************************************/
14723/* function groups the listening applications according to the CIP mask and the   */
14724/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14725/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14726/* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14727/* function must be enabled by setting "a->group_optimization_enabled" from the   */
14728/* OS specific part (per adapter).                                                */
14729/**********************************************************************************/
14730static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14731{
14732  word i,j,k,busy,group_found;
14733  dword info_mask_group[MAX_CIP_TYPES];
14734  dword cip_mask_group[MAX_CIP_TYPES];
14735  word appl_number_group_type[MAX_APPL];
14736  PLCI   *auxplci;
14737
14738  set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14739
14740  if(!a->group_optimization_enabled)
14741  {
14742    dbug(1,dprintf("No group optimization"));
14743    return;
14744  }
14745
14746  dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14747
14748  for(i=0;i<MAX_CIP_TYPES;i++)
14749  {
14750    info_mask_group[i] = 0;
14751    cip_mask_group [i] = 0;
14752  }
14753  for(i=0;i<MAX_APPL;i++)
14754  {
14755    appl_number_group_type[i] = 0;
14756  }
14757  for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14758  {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14759    if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14760    {
14761      dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14762      return; /* allow good application unfiltered access */
14763    }
14764  }
14765  for(i=0; i<max_appl; i++) /* Build CIP Groups */
14766  {
14767    if(application[i].Id && a->CIP_Mask[i] )
14768    {
14769      for(k=0,busy=false; k<a->max_plci; k++)
14770      {
14771        if(a->plci[k].Id) 
14772        {
14773          auxplci = &a->plci[k];
14774          if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14775          {
14776            busy = true;
14777            dbug(1,dprintf("Appl 0x%x is busy",i+1));
14778          }
14779          else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14780          {
14781            busy = true;
14782            dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14783          }
14784        }
14785      }
14786
14787      for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14788      {
14789        if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14790        {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14791          appl_number_group_type[i] = MAX_CIP_TYPES;
14792          group_found=true;
14793          dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14794        }
14795        else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14796        {                                      /* is group already present ?                  */
14797          appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14798          group_found=true;
14799          dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14800        }
14801        else if(!info_mask_group[j])
14802        {                                      /* establish a new group                       */
14803          appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14804          info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14805          cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14806          group_found=true;
14807          dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14808        }
14809      }
14810    }
14811  }
14812        
14813  for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14814  {
14815    if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14816    {
14817      if(appl_number_group_type[i] == MAX_CIP_TYPES)
14818      {
14819        dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14820      }
14821      else
14822      {
14823        dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14824        for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14825        {
14826          if(appl_number_group_type[i] == appl_number_group_type[j]) 
14827          {
14828            dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14829            clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14830            appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14831          }
14832        }
14833      }
14834    }
14835    else                                                 /* application should not get a call */
14836    {
14837      clear_group_ind_mask_bit (plci, i);
14838    }
14839  }
14840
14841}
14842
14843
14844
14845/* OS notifies the driver about a application Capi_Register */
14846word CapiRegister(word id)
14847{
14848  word i,j,appls_found;
14849
14850  PLCI   *plci;
14851  DIVA_CAPI_ADAPTER   *a;
14852
14853  for(i=0,appls_found=0; i<max_appl; i++)
14854  {
14855    if( application[i].Id && (application[i].Id!=id) )
14856    {
14857      appls_found++;                       /* an application has been found */
14858    }
14859  }
14860
14861  if(appls_found) return true;
14862  for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14863  {
14864    a = &adapter[i];
14865    if(a->request)
14866    {
14867      if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14868      {
14869        if(!appls_found)           /* first application does a capi register   */
14870        {
14871          if((j=get_plci(a)))                    /* activate L1 of all adapters */
14872          {
14873            plci = &a->plci[j-1];
14874            plci->command = 0;
14875            add_p(plci,OAD,"\x01\xfd");
14876            add_p(plci,CAI,"\x01\x80");
14877            add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14878            add_p(plci,SHIFT|6,NULL);
14879            add_p(plci,SIN,"\x02\x00\x00");
14880            plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14881            sig_req(plci,ASSIGN,DSIG_ID);
14882            add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14883            sig_req(plci,SIG_CTRL,0);
14884            send_req(plci);
14885          }
14886        }
14887      }
14888    }
14889  }
14890  return false;
14891}
14892
14893/*------------------------------------------------------------------*/
14894
14895/* Functions for virtual Switching e.g. Transfer by join, Conference */
14896
14897static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14898{
14899 word i;
14900 /* Format of vswitch_t:
14901 0 byte length
14902 1 byte VSWITCHIE
14903 2 byte VSWITCH_REQ/VSWITCH_IND
14904 3 byte reserved
14905 4 word VSwitchcommand
14906 6 word returnerror
14907 8... Params
14908 */
14909 if(!plci ||
14910  !plci->appl ||
14911  !plci->State ||
14912  plci->Sig.Ind==NCR_FACILITY
14913  )
14914  return;
14915 
14916 for(i=0;i<MAX_MULTI_IE;i++)
14917 {
14918        if(!parms[i][0]) continue;
14919  if(parms[i][0]<7)
14920  {
14921   parms[i][0]=0; /* kill it */
14922   continue;
14923  }
14924  dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14925  switch(parms[i][4])
14926  {
14927  case VSJOIN:
14928   if(!plci->relatedPTYPLCI ||
14929    (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14930   { /* Error */
14931    break;
14932   }
14933   /* remember all necessary informations */
14934   if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14935   {
14936    break;
14937   }
14938   if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14939   {   /* first indication after ECT-Request on Consultation Call */
14940    plci->vswitchstate=parms[i][9];
14941    parms[i][9]=2; /* State */
14942    /* now ask first Call to join */
14943   }
14944   else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14945   { /* Answer of VSWITCH_REQ from first Call */
14946    plci->vswitchstate=parms[i][9];
14947    /* tell consultation call to join
14948    and the protocol capabilities of the first call */
14949   }
14950   else
14951   { /* Error */
14952    break;
14953   }    
14954   plci->vsprot=parms[i][10]; /* protocol */
14955   plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14956   /* send join request to related PLCI */
14957   parms[i][1]=VSWITCHIE;
14958   parms[i][2]=VSWITCH_REQ;
14959   
14960   plci->relatedPTYPLCI->command = 0;
14961   plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14962   add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14963   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14964   send_req(plci->relatedPTYPLCI);
14965   break;
14966  case VSTRANSPORT:
14967  default:
14968   if(plci->relatedPTYPLCI &&
14969    plci->vswitchstate==3 &&
14970    plci->relatedPTYPLCI->vswitchstate==3)
14971   {
14972    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14973    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14974    send_req(plci->relatedPTYPLCI);
14975   }
14976   break;
14977  }  
14978  parms[i][0]=0; /* kill it */
14979 }
14980}
14981
14982
14983/*------------------------------------------------------------------*/
14984
14985static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
14986  ENTITY e;
14987  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14988
14989  if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14990    return (-1);
14991  }
14992
14993  pReq->xdi_dma_descriptor_operation.Req = 0;
14994  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14995
14996  pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14997  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14998  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14999  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15000
15001  e.user[0] = plci->adapter->Id - 1;
15002  plci->adapter->request((ENTITY*)pReq);
15003
15004  if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15005      (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15006      pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15007    *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15008    dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15009         plci->adapter->Id,
15010         pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15011         *dma_magic));
15012    return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15013  } else {
15014    dbug(1,dprintf("dma_alloc failed"));
15015    return (-1);
15016  }
15017}
15018
15019static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15020  ENTITY e;
15021  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15022
15023  if (nr < 0) {
15024    return;
15025  }
15026
15027  pReq->xdi_dma_descriptor_operation.Req = 0;
15028  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15029
15030  pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15031  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15032  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15033  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15034
15035  e.user[0] = plci->adapter->Id - 1;
15036  plci->adapter->request((ENTITY*)pReq);
15037
15038  if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15039    dbug(1,dprintf("dma_free(%d)", nr));
15040  } else {
15041    dbug(1,dprintf("dma_free failed (%d)", nr));
15042  }
15043}
15044
15045/*------------------------------------------------------------------*/