linux/drivers/isdn/hardware/eicon/message.c
<<
>>
Prefs
   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; i < ARRAY_SIZE(ftable); i++) {
 555
 556    if(ftable[i].command==msg->header.command) {
 557      /* break loop if the message is correct, otherwise continue scan  */
 558      /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
 559      if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
 560        ret = 0;
 561        break;
 562      }
 563      for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
 564    }
 565  }
 566  if(ret) {
 567    dbug(1,dprintf("BAD_MSG"));
 568    if(plci) plci->command = 0;
 569    return ret;
 570  }
 571
 572
 573  c = ftable[i].function(GET_DWORD(&msg->header.controller),
 574                         msg->header.number,
 575                         a,
 576                         plci,
 577                         appl,
 578                         msg_parms);
 579
 580  channel_xmit_extended_xon (plci);
 581
 582  if(c==1) send_req(plci);
 583  if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
 584  if(plci && !plci->req_in) plci->command = 0;
 585  return 0;
 586}
 587
 588
 589/*------------------------------------------------------------------*/
 590/* api_parse function, check the format of api messages             */
 591/*------------------------------------------------------------------*/
 592
 593static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
 594{
 595  word i;
 596  word p;
 597
 598  for(i=0,p=0; format[i]; i++) {
 599    if(parms)
 600    {
 601      parms[i].info = &msg[p];
 602    }
 603    switch(format[i]) {
 604    case 'b':
 605      p +=1;
 606      break;
 607    case 'w':
 608      p +=2;
 609      break;
 610    case 'd':
 611      p +=4;
 612      break;
 613    case 's':
 614      if(msg[p]==0xff) {
 615        parms[i].info +=2;
 616        parms[i].length = msg[p+1] + (msg[p+2]<<8);
 617        p +=(parms[i].length +3);
 618      }
 619      else {
 620        parms[i].length = msg[p];
 621        p +=(parms[i].length +1);
 622      }
 623      break;
 624    }
 625
 626    if(p>length) return true;
 627  }
 628  if(parms) parms[i].info = NULL;
 629  return false;
 630}
 631
 632static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
 633{
 634  word i, j, n = 0;
 635  byte   *p;
 636
 637  p = out->info;
 638  for (i = 0; format[i] != '\0'; i++)
 639  {
 640    out->parms[i].info = p;
 641    out->parms[i].length = in[i].length;
 642    switch (format[i])
 643    {
 644    case 'b':
 645      n = 1;
 646      break;
 647    case 'w':
 648      n = 2;
 649      break;
 650    case 'd':
 651      n = 4;
 652      break;
 653    case 's':
 654      n = in[i].length + 1;
 655      break;
 656    }
 657    for (j = 0; j < n; j++)
 658      *(p++) = in[i].info[j];
 659  }
 660  out->parms[i].info = NULL;
 661  out->parms[i].length = 0;
 662}
 663
 664static void api_load_msg(API_SAVE *in, API_PARSE *out)
 665{
 666  word i;
 667
 668  i = 0;
 669  do
 670  {
 671    out[i].info = in->parms[i].info;
 672    out[i].length = in->parms[i].length;
 673  } while (in->parms[i++].info);
 674}
 675
 676
 677/*------------------------------------------------------------------*/
 678/* CAPI remove function                                             */
 679/*------------------------------------------------------------------*/
 680
 681word api_remove_start(void)
 682{
 683  word i;
 684  word j;
 685
 686  if(!remove_started) {
 687    remove_started = true;
 688    for(i=0;i<max_adapter;i++) {
 689      if(adapter[i].request) {
 690        for(j=0;j<adapter[i].max_plci;j++) {
 691          if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
 692        }
 693      }
 694    }
 695    return 1;
 696  }
 697  else {
 698    for(i=0;i<max_adapter;i++) {
 699      if(adapter[i].request) {
 700        for(j=0;j<adapter[i].max_plci;j++) {
 701          if(adapter[i].plci[j].Sig.Id) return 1;
 702        }
 703      }
 704    }
 705  }
 706  api_remove_complete();
 707  return 0;
 708}
 709
 710
 711/*------------------------------------------------------------------*/
 712/* internal command queue                                           */
 713/*------------------------------------------------------------------*/
 714
 715static void init_internal_command_queue (PLCI   *plci)
 716{
 717  word i;
 718
 719  dbug (1, dprintf ("%s,%d: init_internal_command_queue",
 720    (char   *)(FILE_), __LINE__));
 721
 722  plci->internal_command = 0;
 723  for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
 724    plci->internal_command_queue[i] = NULL;
 725}
 726
 727
 728static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
 729{
 730  word i;
 731
 732  dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
 733    UnMapId (Id), (char   *)(FILE_), __LINE__));
 734
 735  if (plci->internal_command == 0)
 736  {
 737    plci->internal_command_queue[0] = command_function;
 738    (* command_function)(Id, plci, OK);
 739  }
 740  else
 741  {
 742    i = 1;
 743    while (plci->internal_command_queue[i] != NULL)
 744      i++;
 745    plci->internal_command_queue[i] = command_function;
 746  }
 747}
 748
 749
 750static void next_internal_command (dword Id, PLCI   *plci)
 751{
 752  word i;
 753
 754  dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
 755    UnMapId (Id), (char   *)(FILE_), __LINE__));
 756
 757  plci->internal_command = 0;
 758  plci->internal_command_queue[0] = NULL;
 759  while (plci->internal_command_queue[1] != NULL)
 760  {
 761    for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
 762      plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
 763    plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
 764    (*(plci->internal_command_queue[0]))(Id, plci, OK);
 765    if (plci->internal_command != 0)
 766      return;
 767    plci->internal_command_queue[0] = NULL;
 768  }
 769}
 770
 771
 772/*------------------------------------------------------------------*/
 773/* NCCI allocate/remove function                                    */
 774/*------------------------------------------------------------------*/
 775
 776static dword ncci_mapping_bug = 0;
 777
 778static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
 779{
 780  DIVA_CAPI_ADAPTER   *a;
 781  word ncci, i, j, k;
 782
 783  a = plci->adapter;
 784  if (!ch || a->ch_ncci[ch])
 785  {
 786    ncci_mapping_bug++;
 787    dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
 788      ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
 789    ncci = ch;
 790  }
 791  else
 792  {
 793    if (force_ncci)
 794      ncci = force_ncci;
 795    else
 796    {
 797      if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
 798        ncci = ch;
 799      else
 800      {
 801        ncci = 1;
 802        while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
 803          ncci++;
 804        if (ncci == MAX_NCCI+1)
 805        {
 806          ncci_mapping_bug++;
 807          i = 1;
 808          do
 809          {
 810            j = 1;
 811            while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
 812              j++;
 813            k = j;
 814            if (j < MAX_NCCI+1)
 815            {
 816              do
 817              {
 818                j++;
 819              } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
 820            }
 821          } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
 822          if (i < MAX_NL_CHANNEL+1)
 823          {
 824            dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
 825              ncci_mapping_bug, ch, force_ncci, i, k, j));
 826          }
 827          else
 828          {
 829            dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
 830              ncci_mapping_bug, ch, force_ncci));
 831          }
 832          ncci = ch;
 833        }
 834      }
 835      a->ncci_plci[ncci] = plci->Id;
 836      a->ncci_state[ncci] = IDLE;
 837      if (!plci->ncci_ring_list)
 838        plci->ncci_ring_list = ncci;
 839      else
 840        a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
 841      a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
 842    }
 843    a->ncci_ch[ncci] = ch;
 844    a->ch_ncci[ch] = (byte) ncci;
 845    dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
 846      ncci_mapping_bug, ch, force_ncci, ch, ncci));
 847  }
 848  return (ncci);
 849}
 850
 851
 852static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
 853{
 854  DIVA_CAPI_ADAPTER   *a;
 855  APPL   *appl;
 856  word i, ncci_code;
 857  dword Id;
 858
 859  a = plci->adapter;
 860  Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
 861  if (ncci)
 862  {
 863    if (a->ncci_plci[ncci] == plci->Id)
 864    {
 865      if (!plci->appl)
 866      {
 867        ncci_mapping_bug++;
 868        dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
 869          ncci_mapping_bug, Id));
 870      }
 871      else
 872      {
 873        appl = plci->appl;
 874        ncci_code = ncci | (((word) a->Id) << 8);
 875        for (i = 0; i < appl->MaxBuffer; i++)
 876        {
 877          if ((appl->DataNCCI[i] == ncci_code)
 878           && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
 879          {
 880            appl->DataNCCI[i] = 0;
 881          }
 882        }
 883      }
 884    }
 885  }
 886  else
 887  {
 888    for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
 889    {
 890      if (a->ncci_plci[ncci] == plci->Id)
 891      {
 892        if (!plci->appl)
 893        {
 894          ncci_mapping_bug++;
 895          dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
 896            ncci_mapping_bug, Id));
 897        }
 898        else
 899        {
 900          appl = plci->appl;
 901          ncci_code = ncci | (((word) a->Id) << 8);
 902          for (i = 0; i < appl->MaxBuffer; i++)
 903          {
 904            if ((appl->DataNCCI[i] == ncci_code)
 905             && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
 906            {
 907              appl->DataNCCI[i] = 0;
 908            }
 909          }
 910        }
 911      }
 912    }
 913  }
 914}
 915
 916
 917static void cleanup_ncci_data (PLCI   *plci, word ncci)
 918{
 919  NCCI   *ncci_ptr;
 920
 921  if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
 922  {
 923    ncci_ptr = &(plci->adapter->ncci[ncci]);
 924    if (plci->appl)
 925    {
 926      while (ncci_ptr->data_pending != 0)
 927      {
 928        if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
 929          TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
 930        (ncci_ptr->data_out)++;
 931        if (ncci_ptr->data_out == MAX_DATA_B3)
 932          ncci_ptr->data_out = 0;
 933        (ncci_ptr->data_pending)--;
 934      }
 935    }
 936    ncci_ptr->data_out = 0;
 937    ncci_ptr->data_pending = 0;
 938    ncci_ptr->data_ack_out = 0;
 939    ncci_ptr->data_ack_pending = 0;
 940  }
 941}
 942
 943
 944static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
 945{
 946  DIVA_CAPI_ADAPTER   *a;
 947  dword Id;
 948  word i;
 949
 950  a = plci->adapter;
 951  Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
 952  if (!preserve_ncci)
 953    ncci_free_receive_buffers (plci, ncci);
 954  if (ncci)
 955  {
 956    if (a->ncci_plci[ncci] != plci->Id)
 957    {
 958      ncci_mapping_bug++;
 959      dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
 960        ncci_mapping_bug, Id, preserve_ncci));
 961    }
 962    else
 963    {
 964      cleanup_ncci_data (plci, ncci);
 965      dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
 966        ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
 967      a->ch_ncci[a->ncci_ch[ncci]] = 0;
 968      if (!preserve_ncci)
 969      {
 970        a->ncci_ch[ncci] = 0;
 971        a->ncci_plci[ncci] = 0;
 972        a->ncci_state[ncci] = IDLE;
 973        i = plci->ncci_ring_list;
 974        while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
 975          i = a->ncci_next[i];
 976        if ((i != 0) && (a->ncci_next[i] == ncci))
 977        {
 978          if (i == ncci)
 979            plci->ncci_ring_list = 0;
 980          else if (plci->ncci_ring_list == ncci)
 981            plci->ncci_ring_list = i;
 982          a->ncci_next[i] = a->ncci_next[ncci];
 983        }
 984        a->ncci_next[ncci] = 0;
 985      }
 986    }
 987  }
 988  else
 989  {
 990    for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
 991    {
 992      if (a->ncci_plci[ncci] == plci->Id)
 993      {
 994        cleanup_ncci_data (plci, ncci);
 995        dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
 996          ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
 997        a->ch_ncci[a->ncci_ch[ncci]] = 0;
 998        if (!preserve_ncci)
 999        {
1000          a->ncci_ch[ncci] = 0;
1001          a->ncci_plci[ncci] = 0;
1002          a->ncci_state[ncci] = IDLE;
1003          a->ncci_next[ncci] = 0;
1004        }
1005      }
1006    }
1007    if (!preserve_ncci)
1008      plci->ncci_ring_list = 0;
1009  }
1010}
1011
1012
1013/*------------------------------------------------------------------*/
1014/* PLCI remove function                                             */
1015/*------------------------------------------------------------------*/
1016
1017static void plci_free_msg_in_queue (PLCI   *plci)
1018{
1019  word i;
1020
1021  if (plci->appl)
1022  {
1023    i = plci->msg_in_read_pos;
1024    while (i != plci->msg_in_write_pos)
1025    {
1026      if (i == plci->msg_in_wrap_pos)
1027        i = 0;
1028      if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029      {
1030
1031        TransmitBufferFree (plci->appl,
1032          (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033
1034      }
1035
1036      i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1037        MSG_IN_OVERHEAD + 3) & 0xfffc;
1038
1039    }
1040  }
1041  plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042  plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043  plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044}
1045
1046
1047static void plci_remove(PLCI   * plci)
1048{
1049
1050  if(!plci) {
1051    dbug(1,dprintf("plci_remove(no plci)"));
1052    return;
1053  }
1054  init_internal_command_queue (plci);
1055  dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1056  if(plci_remove_check(plci))
1057  {
1058    return;
1059  }
1060  if (plci->Sig.Id == 0xff)
1061  {
1062    dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063    if (plci->NL.Id && !plci->nl_remove_id)
1064    {
1065      nl_req_ncci(plci,REMOVE,0);
1066      send_req(plci);
1067    }
1068  }
1069  else
1070  {
1071    if (!plci->sig_remove_id
1072     && (plci->Sig.Id
1073      || (plci->req_in!=plci->req_out)
1074      || (plci->nl_req || plci->sig_req)))
1075    {
1076      sig_req(plci,HANGUP,0);
1077      send_req(plci);
1078    }
1079  }
1080  ncci_remove (plci, 0, false);
1081  plci_free_msg_in_queue (plci);
1082
1083  plci->channels = 0;
1084  plci->appl = NULL;
1085  if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086    plci->State = OUTG_DIS_PENDING;
1087}
1088
1089/*------------------------------------------------------------------*/
1090/* Application Group function helpers                               */
1091/*------------------------------------------------------------------*/
1092
1093static void set_group_ind_mask (PLCI   *plci)
1094{
1095  word i;
1096
1097  for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098    plci->group_optimization_mask_table[i] = 0xffffffffL;
1099}
1100
1101static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1102{
1103  plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104}
1105
1106static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1107{
1108  return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109}
1110
1111/*------------------------------------------------------------------*/
1112/* c_ind_mask operations for arbitrary MAX_APPL                     */
1113/*------------------------------------------------------------------*/
1114
1115static void clear_c_ind_mask (PLCI   *plci)
1116{
1117  word i;
1118
1119  for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120    plci->c_ind_mask_table[i] = 0;
1121}
1122
1123static byte c_ind_mask_empty (PLCI   *plci)
1124{
1125  word i;
1126
1127  i = 0;
1128  while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129    i++;
1130  return (i == C_IND_MASK_DWORDS);
1131}
1132
1133static void set_c_ind_mask_bit (PLCI   *plci, word b)
1134{
1135  plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136}
1137
1138static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1139{
1140  plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141}
1142
1143static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1144{
1145  return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146}
1147
1148static void dump_c_ind_mask (PLCI   *plci)
1149{
1150static char hex_digit_table[0x10] =
1151  {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1152  word i, j, k;
1153  dword d;
1154    char *p;
1155    char buf[40];
1156
1157  for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158  {
1159    p = buf + 36;
1160    *p = '\0';
1161    for (j = 0; j < 4; j++)
1162    {
1163      if (i+j < C_IND_MASK_DWORDS)
1164      {
1165        d = plci->c_ind_mask_table[i+j];
1166        for (k = 0; k < 8; k++)
1167        {
1168          *(--p) = hex_digit_table[d & 0xf];
1169          d >>= 4;
1170        }
1171      }
1172      else if (i != 0)
1173      {
1174        for (k = 0; k < 8; k++)
1175          *(--p) = ' ';
1176      }
1177      *(--p) = ' ';
1178    }
1179    dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1180  }
1181}
1182
1183
1184
1185
1186
1187#define dump_plcis(a)
1188
1189
1190
1191/*------------------------------------------------------------------*/
1192/* translation function for each message                            */
1193/*------------------------------------------------------------------*/
1194
1195static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196                        PLCI *plci, APPL *appl, API_PARSE *parms)
1197{
1198  word ch;
1199  word i;
1200  word Info;
1201  word CIP;
1202  byte LinkLayer;
1203  API_PARSE * ai;
1204  API_PARSE * bp;
1205    API_PARSE ai_parms[5];
1206  word channel = 0;
1207  dword ch_mask;
1208  byte m;
1209  static byte esc_chi[35] = {0x02,0x18,0x01};
1210  static byte lli[2] = {0x01,0x00};
1211  byte noCh = 0;
1212  word dir = 0;
1213  byte   *p_chi = "";
1214
1215  for(i=0;i<5;i++) ai_parms[i].length = 0;
1216
1217  dbug(1,dprintf("connect_req(%d)",parms->length));
1218  Info = _WRONG_IDENTIFIER;
1219  if(a)
1220  {
1221    if(a->adapter_disabled)
1222    {
1223      dbug(1,dprintf("adapter disabled"));
1224      Id = ((word)1<<8)|a->Id;
1225      sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1226      sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1227      return false;
1228    }
1229    Info = _OUT_OF_PLCI;
1230    if((i=get_plci(a)))
1231    {
1232      Info = 0;
1233      plci = &a->plci[i-1];
1234      plci->appl = appl;
1235      plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1236      /* check 'external controller' bit for codec support */
1237      if(Id & EXT_CONTROLLER)
1238      {
1239        if(AdvCodecSupport(a, plci, appl, 0) )
1240        {
1241          plci->Id = 0;
1242          sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1243          return 2;
1244        }
1245      }
1246      ai = &parms[9];
1247      bp = &parms[5];
1248      ch = 0;
1249      if(bp->length)LinkLayer = bp->info[3];
1250      else LinkLayer = 0;
1251      if(ai->length)
1252      {
1253        ch=0xffff;
1254        if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1255        {
1256          ch = 0;
1257          if(ai_parms[0].length)
1258          {
1259            ch = GET_WORD(ai_parms[0].info+1);
1260            if(ch>4) ch=0; /* safety -> ignore ChannelID */
1261            if(ch==4) /* explizit CHI in message */
1262            {
1263              /* check length of B-CH struct */
1264              if((ai_parms[0].info)[3]>=1)
1265              {
1266                if((ai_parms[0].info)[4]==CHI)
1267                {
1268                  p_chi = &((ai_parms[0].info)[5]);
1269                }
1270                else
1271                {
1272                  p_chi = &((ai_parms[0].info)[3]);
1273                }
1274                if(p_chi[0]>35) /* check length of channel ID */
1275                {
1276                  Info = _WRONG_MESSAGE_FORMAT;    
1277                }
1278              }
1279              else Info = _WRONG_MESSAGE_FORMAT;    
1280            }
1281
1282            if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1283            {
1284              dir = GET_WORD(ai_parms[0].info+3);
1285              ch_mask = 0;
1286              m = 0x3f;
1287              for(i=0; i+5<=ai_parms[0].length; i++)
1288              {
1289                if(ai_parms[0].info[i+5]!=0)
1290                {
1291                  if((ai_parms[0].info[i+5] | m) != 0xff)
1292                    Info = _WRONG_MESSAGE_FORMAT;
1293                  else
1294                  {
1295                    if (ch_mask == 0)
1296                      channel = i;
1297                    ch_mask |= 1L << i;
1298                  }
1299                }
1300                m = 0;
1301              }
1302              if (ch_mask == 0)
1303                Info = _WRONG_MESSAGE_FORMAT;
1304              if (!Info)
1305              {
1306                if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1307                {
1308                  esc_chi[0] = (byte)(ai_parms[0].length - 2);
1309                  for(i=0; i+5<=ai_parms[0].length; i++)
1310                    esc_chi[i+3] = ai_parms[0].info[i+5];
1311                }
1312                else
1313                  esc_chi[0] = 2;
1314                esc_chi[2] = (byte)channel;
1315                plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1316                add_p(plci,LLI,lli);
1317                add_p(plci,ESC,esc_chi);
1318                plci->State = LOCAL_CONNECT;
1319                if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1320              }
1321            }
1322          }
1323        }
1324        else  Info = _WRONG_MESSAGE_FORMAT;
1325      }
1326
1327      dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1328      plci->command = _CONNECT_R;
1329      plci->number = Number;
1330      /* x.31 or D-ch free SAPI in LinkLayer? */
1331      if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1332      if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1333      {
1334        /* B-channel used for B3 connections (ch==0), or no B channel    */
1335        /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1336        if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1337        else     Info = add_b1(plci,&parms[5],ch,0); 
1338        add_s(plci,OAD,&parms[2]);
1339        add_s(plci,OSA,&parms[4]);
1340        add_s(plci,BC,&parms[6]);
1341        add_s(plci,LLC,&parms[7]);
1342        add_s(plci,HLC,&parms[8]);
1343        CIP = GET_WORD(parms[0].info);
1344        if (a->Info_Mask[appl->Id-1] & 0x200)
1345        {
1346          /* early B3 connect (CIP mask bit 9) no release after a disc */
1347          add_p(plci,LLI,"\x01\x01");
1348        }
1349        if(GET_WORD(parms[0].info)<29) {
1350          add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1351          add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1352        }
1353        add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1354        sig_req(plci,ASSIGN,DSIG_ID);
1355      }
1356      else if(ch==1) {
1357
1358        /* D-Channel used for B3 connections */
1359        plci->Sig.Id = 0xff;
1360        Info = 0;
1361      }
1362
1363      if(!Info && ch!=2 && !noCh ) {
1364        Info = add_b23(plci,&parms[5]);
1365        if(!Info) {
1366          if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1367        }
1368      }
1369
1370      if(!Info)
1371      {
1372        if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1373        {
1374          if(plci->spoofed_msg==SPOOFING_REQUIRED)
1375          {
1376            api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1377            plci->spoofed_msg = CALL_REQ;
1378            plci->internal_command = BLOCK_PLCI;
1379            plci->command = 0;
1380            dbug(1,dprintf("Spoof"));
1381            send_req(plci);
1382            return false;
1383          }
1384          if(ch==4)add_p(plci,CHI,p_chi);
1385          add_s(plci,CPN,&parms[1]);
1386          add_s(plci,DSA,&parms[3]);
1387          if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1388          add_ai(plci,&parms[9]);
1389          if(!dir)sig_req(plci,CALL_REQ,0);
1390          else
1391          {
1392            plci->command = PERM_LIST_REQ;
1393            plci->appl = appl;
1394            sig_req(plci,LISTEN_REQ,0);
1395            send_req(plci);
1396            return false;
1397          }
1398        }
1399        send_req(plci);
1400        return false;
1401      }
1402      plci->Id = 0;
1403    }
1404  }
1405  sendf(appl,
1406        _CONNECT_R|CONFIRM,
1407        Id,
1408        Number,
1409        "w",Info);
1410  return 2;
1411}
1412
1413static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1414                        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
1570static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1571                          PLCI *plci, APPL *appl, API_PARSE *msg)
1572{
1573  dbug(1,dprintf("connect_a_res"));
1574  return false;
1575}
1576
1577static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1578                           PLCI *plci, APPL *appl, API_PARSE *msg)
1579{
1580  word Info;
1581  word i;
1582
1583  dbug(1,dprintf("disconnect_req"));
1584
1585  Info = _WRONG_IDENTIFIER;
1586
1587  if(plci)
1588  {
1589    if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1590    {
1591      clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1592      plci->appl = appl;
1593      for(i=0; i<max_appl; i++)
1594      {
1595        if(test_c_ind_mask_bit (plci, i))
1596          sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1597      }
1598      plci->State = OUTG_DIS_PENDING;
1599    }
1600    if(plci->Sig.Id && plci->appl)
1601    {
1602      Info = 0;
1603        if(plci->Sig.Id!=0xff)
1604        {
1605          if(plci->State!=INC_DIS_PENDING)
1606          {
1607            add_ai(plci, &msg[0]);
1608            sig_req(plci,HANGUP,0);
1609            plci->State = OUTG_DIS_PENDING;
1610            return 1;
1611          }
1612        }
1613        else
1614        {
1615          if (plci->NL.Id && !plci->nl_remove_id)
1616          {
1617            mixer_remove (plci);
1618            nl_req_ncci(plci,REMOVE,0);
1619          sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1620          sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1621          plci->State = INC_DIS_PENDING;
1622          }
1623          return 1;
1624        }
1625      }
1626    }
1627
1628  if(!appl)  return false;
1629  sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1630  return false;
1631}
1632
1633static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1634                           PLCI *plci, APPL *appl, API_PARSE *msg)
1635{
1636  dbug(1,dprintf("disconnect_res"));
1637  if(plci)
1638  {
1639        /* clear ind mask bit, just in case of collsion of          */
1640        /* DISCONNECT_IND and CONNECT_RES                           */
1641    clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1642    ncci_free_receive_buffers (plci, 0);
1643    if(plci_remove_check(plci))
1644    {
1645      return 0;
1646    }
1647    if(plci->State==INC_DIS_PENDING
1648    || plci->State==SUSPENDING) {
1649      if(c_ind_mask_empty (plci)) {
1650        if(plci->State!=SUSPENDING)plci->State = IDLE;
1651        dbug(1,dprintf("chs=%d",plci->channels));
1652        if(!plci->channels) {
1653          plci_remove(plci);
1654        }
1655      }
1656    }
1657  }
1658  return 0;
1659}
1660
1661static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1662                       PLCI *plci, APPL *appl, API_PARSE *parms)
1663{
1664  word Info;
1665  byte i;
1666
1667  dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1668
1669  Info = _WRONG_IDENTIFIER;
1670  if(a) {
1671    Info = 0;
1672    a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1673    a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1674    dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1675    if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1676      a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1677    }
1678
1679    /* check if external controller listen and switch listen on or off*/
1680    if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1681      if(a->profile.Global_Options & ON_BOARD_CODEC) {
1682        dummy_plci.State = IDLE;
1683        a->codec_listen[appl->Id-1] = &dummy_plci;
1684        a->TelOAD[0] = (byte)(parms[3].length);
1685        for(i=1;parms[3].length>=i && i<22;i++) {
1686          a->TelOAD[i] = parms[3].info[i];
1687        }
1688        a->TelOAD[i] = 0;
1689        a->TelOSA[0] = (byte)(parms[4].length);
1690        for(i=1;parms[4].length>=i && i<22;i++) {
1691          a->TelOSA[i] = parms[4].info[i];
1692        }
1693        a->TelOSA[i] = 0;
1694      }
1695      else Info = 0x2002; /* wrong controller, codec not supported */
1696    }
1697    else{               /* clear listen */
1698      a->codec_listen[appl->Id-1] = (PLCI   *)0;
1699    }
1700  }
1701  sendf(appl,
1702        _LISTEN_R|CONFIRM,
1703        Id,
1704        Number,
1705        "w",Info);
1706
1707  if (a) listen_check(a);
1708  return false;
1709}
1710
1711static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1712                     PLCI *plci, APPL *appl, API_PARSE *msg)
1713{
1714  word i;
1715  API_PARSE * ai;
1716  PLCI   * rc_plci = NULL;
1717    API_PARSE ai_parms[5];
1718  word Info = 0;
1719
1720  dbug(1,dprintf("info_req"));
1721  for(i=0;i<5;i++) ai_parms[i].length = 0;
1722
1723  ai = &msg[1];
1724
1725  if(ai->length)
1726  {
1727    if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1728    {
1729      dbug(1,dprintf("AddInfo wrong"));
1730      Info = _WRONG_MESSAGE_FORMAT;
1731    }
1732  }
1733  if(!a) Info = _WRONG_STATE;
1734
1735  if(!Info && plci)
1736  {                /* no fac, with CPN, or KEY */
1737    rc_plci = plci;
1738    if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1739    {
1740      /* overlap sending option */
1741      dbug(1,dprintf("OvlSnd"));
1742      add_s(plci,CPN,&msg[0]);
1743      add_s(plci,KEY,&ai_parms[1]);
1744      sig_req(plci,INFO_REQ,0);
1745      send_req(plci);
1746      return false;
1747    }
1748
1749    if(plci->State && ai_parms[2].length)
1750    {
1751      /* User_Info option */
1752      dbug(1,dprintf("UUI"));
1753      add_s(plci,UUI,&ai_parms[2]);
1754      sig_req(plci,USER_DATA,0);
1755    }
1756    else if(plci->State && ai_parms[3].length)
1757    {
1758      /* Facility option */
1759      dbug(1,dprintf("FAC"));
1760      add_s(plci,CPN,&msg[0]);
1761      add_ai(plci, &msg[1]);
1762      sig_req(plci,FACILITY_REQ,0);
1763    }
1764    else
1765    {
1766      Info = _WRONG_STATE;
1767    }
1768  }
1769  else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1770  {
1771    /* NCR_Facility option -> send UUI and Keypad too */
1772    dbug(1,dprintf("NCR_FAC"));
1773    if((i=get_plci(a)))
1774    {
1775      rc_plci = &a->plci[i-1];
1776      appl->NullCREnable  = true;
1777      rc_plci->internal_command = C_NCR_FAC_REQ;
1778      rc_plci->appl = appl;
1779      add_p(rc_plci,CAI,"\x01\x80");
1780      add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1781      sig_req(rc_plci,ASSIGN,DSIG_ID);
1782      send_req(rc_plci);
1783    }
1784    else
1785    {
1786      Info = _OUT_OF_PLCI;
1787    }
1788
1789    if(!Info)
1790    {
1791      add_s(rc_plci,CPN,&msg[0]);
1792      add_ai(rc_plci, &msg[1]);
1793      sig_req(rc_plci,NCR_FACILITY,0);
1794      send_req(rc_plci);
1795      return false;
1796     /* for application controlled supplementary services    */
1797    }
1798  }
1799
1800  if (!rc_plci)
1801  {
1802    Info = _WRONG_MESSAGE_FORMAT;
1803  }
1804
1805  if(!Info)
1806  {
1807    send_req(rc_plci);
1808  }
1809  else
1810  {  /* appl is not assigned to a PLCI or error condition */
1811    dbug(1,dprintf("localInfoCon"));
1812    sendf(appl,
1813          _INFO_R|CONFIRM,
1814          Id,
1815          Number,
1816          "w",Info);
1817  }
1818  return false;
1819}
1820
1821static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1822                     PLCI *plci, APPL *appl, API_PARSE *msg)
1823{
1824  dbug(1,dprintf("info_res"));
1825  return false;
1826}
1827
1828static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1829                      PLCI *plci, APPL *appl, API_PARSE *msg)
1830{
1831  word Info;
1832  byte ret;
1833
1834  dbug(1,dprintf("alert_req"));
1835
1836  Info = _WRONG_IDENTIFIER;
1837  ret = false;
1838  if(plci) {
1839    Info = _ALERT_IGNORED;
1840    if(plci->State!=INC_CON_ALERT) {
1841      Info = _WRONG_STATE;
1842      if(plci->State==INC_CON_PENDING) {
1843        Info = 0;
1844        plci->State=INC_CON_ALERT;
1845        add_ai(plci, &msg[0]);
1846        sig_req(plci,CALL_ALERT,0);
1847        ret = 1;
1848      }
1849    }
1850  }
1851  sendf(appl,
1852        _ALERT_R|CONFIRM,
1853        Id,
1854        Number,
1855        "w",Info);
1856  return ret;
1857}
1858
1859static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1860                         PLCI *plci, APPL *appl, API_PARSE *msg)
1861{
1862  word Info = 0;
1863  word i    = 0;
1864
1865  word selector;
1866  word SSreq;
1867  long relatedPLCIvalue;
1868  DIVA_CAPI_ADAPTER   * relatedadapter;
1869  byte * SSparms  = "";
1870    byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1871    byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1872  API_PARSE * parms;
1873    API_PARSE ss_parms[11];
1874  PLCI   *rplci;
1875    byte cai[15];
1876  dword d;
1877    API_PARSE dummy;
1878
1879  dbug(1,dprintf("facility_req"));
1880  for(i=0;i<9;i++) ss_parms[i].length = 0;
1881
1882  parms = &msg[1];
1883
1884  if(!a)
1885  {
1886    dbug(1,dprintf("wrong Ctrl"));
1887    Info = _WRONG_IDENTIFIER;
1888  }
1889
1890  selector = GET_WORD(msg[0].info);
1891
1892  if(!Info)
1893  {
1894    switch(selector)
1895    {
1896      case SELECTOR_HANDSET:
1897        Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1898        break;
1899
1900      case SELECTOR_SU_SERV:
1901        if(!msg[1].length)
1902        {
1903          Info = _WRONG_MESSAGE_FORMAT;
1904          break;
1905        }
1906        SSreq = GET_WORD(&(msg[1].info[1]));
1907        PUT_WORD(&RCparms[1],SSreq);
1908        SSparms = RCparms;
1909        switch(SSreq)
1910        {
1911          case S_GET_SUPPORTED_SERVICES:
1912            if((i=get_plci(a)))
1913            {
1914              rplci = &a->plci[i-1];
1915              rplci->appl = appl;
1916              add_p(rplci,CAI,"\x01\x80");
1917              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1918              sig_req(rplci,ASSIGN,DSIG_ID);
1919              send_req(rplci);
1920            }
1921            else
1922            {
1923              PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1924              SSparms = (byte *)SSstruct;
1925              break;
1926            }
1927            rplci->internal_command = GETSERV_REQ_PEND;
1928            rplci->number = Number;
1929            rplci->appl = appl;
1930            sig_req(rplci,S_SUPPORTED,0);
1931            send_req(rplci);
1932            return false;
1933            break;
1934
1935          case S_LISTEN:
1936            if(parms->length==7)
1937            {
1938              if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1939              {
1940                dbug(1,dprintf("format wrong"));
1941                Info = _WRONG_MESSAGE_FORMAT;
1942                break;
1943              }
1944            }
1945            else
1946            {
1947              Info = _WRONG_MESSAGE_FORMAT;
1948              break;
1949            }
1950            a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1951            if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1952            {
1953              if((i=get_plci(a)))
1954              {
1955                rplci = &a->plci[i-1];
1956                rplci->appl = appl;
1957                add_p(rplci,CAI,"\x01\x80");
1958                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1959                sig_req(rplci,ASSIGN,DSIG_ID);
1960                send_req(rplci);
1961              }
1962              else
1963              {
1964                break;
1965              }
1966              rplci->internal_command = GET_MWI_STATE;
1967              rplci->number = Number;
1968              sig_req(rplci,MWI_POLL,0);
1969              send_req(rplci);
1970            }
1971            break;
1972
1973          case S_HOLD:
1974            api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1975            if(plci && plci->State && plci->SuppState==IDLE)
1976            {
1977              plci->SuppState = HOLD_REQUEST;
1978              plci->command = C_HOLD_REQ;
1979              add_s(plci,CAI,&ss_parms[1]);
1980              sig_req(plci,CALL_HOLD,0);
1981              send_req(plci);
1982              return false;
1983            }
1984            else Info = 0x3010;                    /* wrong state           */
1985            break;
1986          case S_RETRIEVE:
1987            if(plci && plci->State && plci->SuppState==CALL_HELD)
1988            {
1989              if(Id & EXT_CONTROLLER)
1990              {
1991                if(AdvCodecSupport(a, plci, appl, 0))
1992                {
1993                  Info = 0x3010;                    /* wrong state           */
1994                  break;
1995                }
1996              }
1997              else plci->tel = 0;
1998
1999              plci->SuppState = RETRIEVE_REQUEST;
2000              plci->command = C_RETRIEVE_REQ;
2001              if(plci->spoofed_msg==SPOOFING_REQUIRED)
2002              {
2003                plci->spoofed_msg = CALL_RETRIEVE;
2004                plci->internal_command = BLOCK_PLCI;
2005                plci->command = 0;
2006                dbug(1,dprintf("Spoof"));
2007                return false;
2008              }
2009              else
2010              {
2011                sig_req(plci,CALL_RETRIEVE,0);
2012                send_req(plci);
2013                return false;
2014              }
2015            }
2016            else Info = 0x3010;                    /* wrong state           */
2017            break;
2018          case S_SUSPEND:
2019            if(parms->length)
2020            {
2021              if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2022              {
2023                dbug(1,dprintf("format wrong"));
2024                Info = _WRONG_MESSAGE_FORMAT;
2025                break;
2026              }
2027            }
2028            if(plci && plci->State)
2029            {
2030              add_s(plci,CAI,&ss_parms[2]);
2031              plci->command = SUSPEND_REQ;
2032              sig_req(plci,SUSPEND,0);
2033              plci->State = SUSPENDING;
2034              send_req(plci);
2035            }
2036            else Info = 0x3010;                    /* wrong state           */
2037            break;
2038
2039          case S_RESUME:
2040            if(!(i=get_plci(a)) )
2041            {
2042              Info = _OUT_OF_PLCI;
2043              break;
2044            }
2045            rplci = &a->plci[i-1];
2046            rplci->appl = appl;
2047            rplci->number = Number;
2048            rplci->tel = 0;
2049            rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2050            /* check 'external controller' bit for codec support */
2051            if(Id & EXT_CONTROLLER)
2052            {
2053              if(AdvCodecSupport(a, rplci, appl, 0) )
2054              {
2055                rplci->Id = 0;
2056                Info = 0x300A;
2057                break;
2058              }
2059            }
2060            if(parms->length)
2061            {
2062              if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2063              {
2064                dbug(1,dprintf("format wrong"));
2065                rplci->Id = 0;
2066                Info = _WRONG_MESSAGE_FORMAT;
2067                break;
2068              }
2069            }
2070            dummy.length = 0;
2071            dummy.info = "\x00";
2072            add_b1(rplci, &dummy, 0, 0);
2073            if (a->Info_Mask[appl->Id-1] & 0x200)
2074            {
2075              /* early B3 connect (CIP mask bit 9) no release after a disc */
2076              add_p(rplci,LLI,"\x01\x01");
2077            }
2078            add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2079            sig_req(rplci,ASSIGN,DSIG_ID);
2080            send_req(rplci);
2081            add_s(rplci,CAI,&ss_parms[2]);
2082            rplci->command = RESUME_REQ;
2083            sig_req(rplci,RESUME,0);
2084            rplci->State = RESUMING;
2085            send_req(rplci);
2086            break;
2087
2088          case S_CONF_BEGIN: /* Request */
2089          case S_CONF_DROP:
2090          case S_CONF_ISOLATE:
2091          case S_CONF_REATTACH:
2092            if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2093            {
2094              dbug(1,dprintf("format wrong"));
2095              Info = _WRONG_MESSAGE_FORMAT;
2096              break;
2097            }
2098            if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2099            {
2100              d = GET_DWORD(ss_parms[2].info);     
2101              if(d>=0x80)
2102              {
2103                dbug(1,dprintf("format wrong"));
2104                Info = _WRONG_MESSAGE_FORMAT;
2105                break;
2106              }
2107              plci->ptyState = (byte)SSreq;
2108              plci->command = 0;
2109              cai[0] = 2;
2110              switch(SSreq)
2111              {
2112              case S_CONF_BEGIN:
2113                  cai[1] = CONF_BEGIN;
2114                  plci->internal_command = CONF_BEGIN_REQ_PEND;
2115                  break;
2116              case S_CONF_DROP:
2117                  cai[1] = CONF_DROP;
2118                  plci->internal_command = CONF_DROP_REQ_PEND;
2119                  break;
2120              case S_CONF_ISOLATE:
2121                  cai[1] = CONF_ISOLATE;
2122                  plci->internal_command = CONF_ISOLATE_REQ_PEND;
2123                  break;
2124              case S_CONF_REATTACH:
2125                  cai[1] = CONF_REATTACH;
2126                  plci->internal_command = CONF_REATTACH_REQ_PEND;
2127                  break;
2128              }
2129              cai[2] = (byte)d; /* Conference Size resp. PartyId */
2130              add_p(plci,CAI,cai);
2131              sig_req(plci,S_SERVICE,0);
2132              send_req(plci);
2133              return false;
2134            }
2135            else Info = 0x3010;                    /* wrong state           */
2136            break;
2137
2138          case S_ECT:
2139          case S_3PTY_BEGIN:
2140          case S_3PTY_END:
2141          case S_CONF_ADD:
2142            if(parms->length==7)
2143            {
2144              if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2145              {
2146                dbug(1,dprintf("format wrong"));
2147                Info = _WRONG_MESSAGE_FORMAT;
2148                break;
2149              }
2150            }
2151            else if(parms->length==8) /* workaround for the T-View-S */
2152            {
2153              if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2154              {
2155                dbug(1,dprintf("format wrong"));
2156                Info = _WRONG_MESSAGE_FORMAT;
2157                break;
2158              }
2159            }
2160            else
2161            {
2162              Info = _WRONG_MESSAGE_FORMAT;
2163              break;
2164            }
2165            if(!msg[1].length)
2166            {
2167              Info = _WRONG_MESSAGE_FORMAT;
2168              break;
2169            }
2170            if (!plci)
2171            {
2172              Info = _WRONG_IDENTIFIER;
2173              break;
2174            }
2175            relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2176            relatedPLCIvalue &= 0x0000FFFF;
2177            dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2178            /* controller starts with 0 up to (max_adapter - 1) */
2179            if (((relatedPLCIvalue & 0x7f) == 0)
2180             || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2181             || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2182            {
2183              if(SSreq==S_3PTY_END)
2184              {
2185                dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2186                rplci = plci;
2187              }
2188              else
2189              {
2190                Info = 0x3010;                    /* wrong state           */
2191                break;
2192              }
2193            }
2194            else
2195            {  
2196              relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2197              relatedPLCIvalue >>=8;
2198              /* find PLCI PTR*/
2199              for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2200              {
2201                if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2202                {
2203                  rplci = &relatedadapter->plci[i];
2204                }
2205              }
2206              if(!rplci || !relatedPLCIvalue)
2207              {
2208                if(SSreq==S_3PTY_END)
2209                {
2210                  dbug(1, dprintf("use 2nd PLCI=PLCI"));
2211                  rplci = plci;
2212                }
2213                else
2214                {
2215                  Info = 0x3010;                    /* wrong state           */
2216                  break;
2217                }
2218              }
2219            }
2220/*
2221            dbug(1,dprintf("rplci:%x",rplci));
2222            dbug(1,dprintf("plci:%x",plci));
2223            dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2224            dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2225            dbug(1,dprintf("SSreq:%x",SSreq));
2226            dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2227            dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2228            dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2229*/
2230            /* send PTY/ECT req, cannot check all states because of US stuff */
2231            if( !rplci->internal_command && rplci->appl )
2232            {
2233              plci->command = 0;
2234              rplci->relatedPTYPLCI = plci;
2235              plci->relatedPTYPLCI = rplci;
2236              rplci->ptyState = (byte)SSreq;
2237              if(SSreq==S_ECT)
2238              {
2239                rplci->internal_command = ECT_REQ_PEND;
2240                cai[1] = ECT_EXECUTE;
2241
2242                rplci->vswitchstate=0;
2243                rplci->vsprot=0;
2244                rplci->vsprotdialect=0;
2245                plci->vswitchstate=0;
2246                plci->vsprot=0;
2247                plci->vsprotdialect=0;
2248
2249              }
2250              else if(SSreq==S_CONF_ADD)
2251              {
2252                rplci->internal_command = CONF_ADD_REQ_PEND;
2253                cai[1] = CONF_ADD;
2254              }
2255              else
2256              {
2257                rplci->internal_command = PTY_REQ_PEND;
2258                cai[1] = (byte)(SSreq-3);
2259              }
2260              rplci->number = Number;
2261              if(plci!=rplci) /* explicit invocation */
2262              {
2263                cai[0] = 2;
2264                cai[2] = plci->Sig.Id;
2265                dbug(1,dprintf("explicit invocation"));
2266              }
2267              else
2268              {
2269                dbug(1,dprintf("implicit invocation"));
2270                cai[0] = 1;
2271              }
2272              add_p(rplci,CAI,cai);
2273              sig_req(rplci,S_SERVICE,0);
2274              send_req(rplci);
2275              return false;
2276            }
2277            else
2278            {
2279              dbug(0,dprintf("Wrong line"));
2280              Info = 0x3010;                    /* wrong state           */
2281              break;
2282            }
2283            break;
2284
2285          case S_CALL_DEFLECTION:
2286            if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2287            {
2288              dbug(1,dprintf("format wrong"));
2289              Info = _WRONG_MESSAGE_FORMAT;
2290              break;
2291            }
2292            if (!plci)
2293            {
2294              Info = _WRONG_IDENTIFIER;
2295              break;
2296            }
2297            /* reuse unused screening indicator */
2298            ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2299            plci->command = 0;
2300            plci->internal_command = CD_REQ_PEND;
2301            appl->CDEnable = true;
2302            cai[0] = 1;
2303            cai[1] = CALL_DEFLECTION;
2304            add_p(plci,CAI,cai);
2305            add_p(plci,CPN,ss_parms[3].info);
2306            sig_req(plci,S_SERVICE,0);
2307            send_req(plci);
2308            return false;
2309            break;
2310
2311          case S_CALL_FORWARDING_START:
2312            if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2313            {
2314              dbug(1,dprintf("format wrong"));
2315              Info = _WRONG_MESSAGE_FORMAT;
2316              break;
2317            }
2318
2319            if((i=get_plci(a)))
2320            {
2321              rplci = &a->plci[i-1];
2322              rplci->appl = appl;
2323              add_p(rplci,CAI,"\x01\x80");
2324              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2325              sig_req(rplci,ASSIGN,DSIG_ID);
2326              send_req(rplci);
2327            }
2328            else
2329            {
2330              Info = _OUT_OF_PLCI;
2331              break;
2332            }
2333
2334            /* reuse unused screening indicator */
2335            rplci->internal_command = CF_START_PEND;
2336            rplci->appl = appl;
2337            rplci->number = Number;
2338            appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2339            cai[0] = 2;
2340            cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2341            cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2342            add_p(rplci,CAI,cai);
2343            add_p(rplci,OAD,ss_parms[5].info);
2344            add_p(rplci,CPN,ss_parms[6].info);
2345            sig_req(rplci,S_SERVICE,0);
2346            send_req(rplci);
2347            return false;
2348            break;
2349
2350          case S_INTERROGATE_DIVERSION:
2351          case S_INTERROGATE_NUMBERS:
2352          case S_CALL_FORWARDING_STOP:
2353          case S_CCBS_REQUEST:
2354          case S_CCBS_DEACTIVATE:
2355          case S_CCBS_INTERROGATE:
2356            switch(SSreq)
2357            {
2358            case S_INTERROGATE_NUMBERS:
2359                if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2360                {
2361                  dbug(0,dprintf("format wrong"));
2362                  Info = _WRONG_MESSAGE_FORMAT;
2363                }
2364                break;
2365            case S_CCBS_REQUEST:
2366            case S_CCBS_DEACTIVATE:
2367                if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2368                {
2369                  dbug(0,dprintf("format wrong"));
2370                  Info = _WRONG_MESSAGE_FORMAT;
2371                }
2372                break;
2373            case S_CCBS_INTERROGATE:
2374                if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2375                {
2376                  dbug(0,dprintf("format wrong"));
2377                  Info = _WRONG_MESSAGE_FORMAT;
2378                }
2379                break;
2380            default:
2381            if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2382            {
2383              dbug(0,dprintf("format wrong"));
2384              Info = _WRONG_MESSAGE_FORMAT;
2385              break;
2386            }
2387                break;
2388            }
2389
2390            if(Info) break;
2391            if((i=get_plci(a)))
2392            {
2393              rplci = &a->plci[i-1];
2394              switch(SSreq)
2395              {
2396                case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2397                  cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2398                  rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2399                  break;
2400                case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2401                  cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2402                  rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2403                  break;
2404                case S_CALL_FORWARDING_STOP:
2405                  rplci->internal_command = CF_STOP_PEND;
2406                  cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2407                  break;
2408                case S_CCBS_REQUEST:
2409                  cai[1] = CCBS_REQUEST;
2410                  rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2411                  break;
2412                case S_CCBS_DEACTIVATE:
2413                  cai[1] = CCBS_DEACTIVATE;
2414                  rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2415                  break;
2416                case S_CCBS_INTERROGATE:
2417                  cai[1] = CCBS_INTERROGATE;
2418                  rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2419                  break;
2420                default:
2421                  cai[1] = 0;
2422                break;
2423              }
2424              rplci->appl = appl;
2425              rplci->number = Number;
2426              add_p(rplci,CAI,"\x01\x80");
2427              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2428              sig_req(rplci,ASSIGN,DSIG_ID);
2429              send_req(rplci);
2430            }
2431            else
2432            {
2433              Info = _OUT_OF_PLCI;
2434              break;
2435            }
2436
2437            appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2438            switch(SSreq)
2439            {
2440            case S_INTERROGATE_NUMBERS:
2441                cai[0] = 1;
2442                add_p(rplci,CAI,cai);
2443                break;
2444            case S_CCBS_REQUEST:
2445            case S_CCBS_DEACTIVATE:
2446                cai[0] = 3;
2447                PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2448                add_p(rplci,CAI,cai);
2449                break;
2450            case S_CCBS_INTERROGATE:
2451                cai[0] = 3;
2452                PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2453                add_p(rplci,CAI,cai);
2454                add_p(rplci,OAD,ss_parms[4].info);
2455                break;
2456            default:
2457            cai[0] = 2;
2458            cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2459            add_p(rplci,CAI,cai);
2460            add_p(rplci,OAD,ss_parms[5].info);
2461                break;
2462            }
2463                        
2464            sig_req(rplci,S_SERVICE,0);
2465            send_req(rplci);
2466            return false;
2467            break;
2468
2469          case S_MWI_ACTIVATE:
2470            if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2471            {
2472              dbug(1,dprintf("format wrong"));
2473              Info = _WRONG_MESSAGE_FORMAT;
2474              break;
2475            }
2476            if(!plci)
2477            {                               
2478              if((i=get_plci(a)))
2479              {
2480                rplci = &a->plci[i-1];
2481                rplci->appl = appl;
2482                rplci->cr_enquiry=true;
2483                add_p(rplci,CAI,"\x01\x80");
2484                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2485                sig_req(rplci,ASSIGN,DSIG_ID);
2486                send_req(rplci);
2487              }
2488              else
2489              {
2490                Info = _OUT_OF_PLCI;
2491                break;
2492              }
2493            }
2494            else
2495            {
2496              rplci = plci;
2497              rplci->cr_enquiry=false;
2498            }
2499
2500            rplci->command = 0;
2501            rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2502            rplci->appl = appl;
2503            rplci->number = Number;
2504
2505            cai[0] = 13;
2506            cai[1] = ACTIVATION_MWI; /* Function */
2507            PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2508            PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2509            PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2510            PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2511            PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2512            add_p(rplci,CAI,cai);
2513            add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2514            add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2515            add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2516            add_p(rplci,UID,ss_parms[10].info); /* Time */
2517            sig_req(rplci,S_SERVICE,0);
2518            send_req(rplci);
2519            return false;
2520
2521          case S_MWI_DEACTIVATE:
2522            if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2523            {
2524              dbug(1,dprintf("format wrong"));
2525              Info = _WRONG_MESSAGE_FORMAT;
2526              break;
2527            }
2528            if(!plci)
2529            {                               
2530              if((i=get_plci(a)))
2531              {
2532                rplci = &a->plci[i-1];
2533                rplci->appl = appl;
2534                rplci->cr_enquiry=true;
2535                add_p(rplci,CAI,"\x01\x80");
2536                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2537                sig_req(rplci,ASSIGN,DSIG_ID);
2538                send_req(rplci);
2539              }
2540              else
2541              {
2542                Info = _OUT_OF_PLCI;
2543                break;
2544              }
2545            }
2546            else
2547            {
2548              rplci = plci;
2549              rplci->cr_enquiry=false;
2550            }
2551
2552            rplci->command = 0;
2553            rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2554            rplci->appl = appl;
2555            rplci->number = Number;
2556
2557            cai[0] = 5;
2558            cai[1] = DEACTIVATION_MWI; /* Function */
2559            PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2560            PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2561            add_p(rplci,CAI,cai);
2562            add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2563            add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2564            sig_req(rplci,S_SERVICE,0);
2565            send_req(rplci);
2566            return false;
2567
2568          default:
2569            Info = 0x300E;  /* not supported */
2570            break;
2571        }
2572        break; /* case SELECTOR_SU_SERV: end */
2573
2574
2575      case SELECTOR_DTMF:
2576        return (dtmf_request (Id, Number, a, plci, appl, msg));
2577
2578
2579
2580      case SELECTOR_LINE_INTERCONNECT:
2581        return (mixer_request (Id, Number, a, plci, appl, msg));
2582
2583
2584
2585      case PRIV_SELECTOR_ECHO_CANCELLER:
2586        appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2587        return (ec_request (Id, Number, a, plci, appl, msg));
2588
2589      case SELECTOR_ECHO_CANCELLER:
2590        appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2591        return (ec_request (Id, Number, a, plci, appl, msg));
2592
2593
2594      case SELECTOR_V42BIS:
2595      default:
2596        Info = _FACILITY_NOT_SUPPORTED;
2597        break;
2598    } /* end of switch(selector) */
2599  }
2600
2601  dbug(1,dprintf("SendFacRc"));
2602  sendf(appl,
2603        _FACILITY_R|CONFIRM,
2604        Id,
2605        Number,
2606        "wws",Info,selector,SSparms);
2607  return false;
2608}
2609
2610static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2611                         PLCI *plci, APPL *appl, API_PARSE *msg)
2612{
2613  dbug(1,dprintf("facility_res"));
2614  return false;
2615}
2616
2617static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2618                           PLCI *plci, APPL *appl, API_PARSE *parms)
2619{
2620  word Info = 0;
2621  byte req;
2622  byte len;
2623  word w;
2624  word fax_control_bits, fax_feature_bits, fax_info_change;
2625  API_PARSE * ncpi;
2626    byte pvc[2];
2627
2628    API_PARSE fax_parms[9];
2629  word i;
2630
2631
2632  dbug(1,dprintf("connect_b3_req"));
2633  if(plci)
2634  {
2635    if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2636     || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2637    {
2638      Info = _WRONG_STATE;
2639    }
2640    else
2641    {
2642      /* local reply if assign unsuccessfull
2643         or B3 protocol allows only one layer 3 connection
2644           and already connected
2645             or B2 protocol not any LAPD
2646               and connect_b3_req contradicts originate/answer direction */
2647      if (!plci->NL.Id
2648       || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2649        && ((plci->channels != 0)
2650         || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2651          && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2652      {
2653        dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2654                       plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2655        Info = _WRONG_STATE;
2656        sendf(appl,                                                        
2657              _CONNECT_B3_R|CONFIRM,
2658              Id,
2659              Number,
2660              "w",Info);
2661        return false;
2662      }
2663      plci->requested_options_conn = 0;
2664
2665      req = N_CONNECT;
2666      ncpi = &parms[0];
2667      if(plci->B3_prot==2 || plci->B3_prot==3)
2668      {
2669        if(ncpi->length>2)
2670        {
2671          /* check for PVC */
2672          if(ncpi->info[2] || ncpi->info[3])
2673          {
2674            pvc[0] = ncpi->info[3];
2675            pvc[1] = ncpi->info[2];
2676            add_d(plci,2,pvc);
2677            req = N_RESET;
2678          }
2679          else
2680          {
2681            if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2682            add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2683          }
2684        }
2685      }
2686      else if(plci->B3_prot==5)
2687      {
2688        if (plci->NL.Id && !plci->nl_remove_id)
2689        {
2690          fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2691          fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2692          if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2693           || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2694          {
2695            len = offsetof(T30_INFO, universal_6);
2696            fax_info_change = false;
2697            if (ncpi->length >= 4)
2698            {
2699              w = GET_WORD(&ncpi->info[3]);
2700              if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2701              {
2702                ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2703                  (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2704                  ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2705                fax_info_change = true;
2706              }
2707              fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2708              if (w & 0x0002)  /* Fax-polling request */
2709                fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2710              if ((w & 0x0004) /* Request to send / poll another document */
2711               && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2712              {
2713                fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2714              }
2715              if (ncpi->length >= 6)
2716              {
2717                w = GET_WORD(&ncpi->info[5]);
2718                if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2719                {
2720                  ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2721                  fax_info_change = true;
2722                }
2723
2724                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2725                 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2726                {
2727                  plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2728                }
2729                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2730                 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2731                {
2732                  plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2733                }
2734                fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2735                  T30_CONTROL_BIT_ACCEPT_PASSWORD);
2736                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2737                  & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2738                {
2739                  if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2740                    Info = _WRONG_MESSAGE_FORMAT;
2741                  else
2742                  {
2743                    if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2744                      & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2745      {
2746                    fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2747                    if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2748                      fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2749      }
2750                    w = fax_parms[4].length;
2751                    if (w > 20)
2752                      w = 20;
2753                    ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2754                    for (i = 0; i < w; i++)
2755                      ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2756                    ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2757                    len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2758                    w = fax_parms[5].length;
2759                    if (w > 20)
2760                      w = 20;
2761                    plci->fax_connect_info_buffer[len++] = (byte) w;
2762                    for (i = 0; i < w; i++)
2763                      plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2764                    w = fax_parms[6].length;
2765                    if (w > 20)
2766                      w = 20;
2767                    plci->fax_connect_info_buffer[len++] = (byte) w;
2768                    for (i = 0; i < w; i++)
2769                      plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2770                    if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2771                      & (1L << PRIVATE_FAX_NONSTANDARD))
2772      {
2773                      if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2774        {
2775                        dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2776                        plci->fax_connect_info_buffer[len++] = 0;
2777        }
2778                      else
2779                      {
2780          if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2781            plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2782   plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2783          for (i = 0; i < fax_parms[7].length; i++)
2784     plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2785                      }
2786                    }
2787                  }
2788                }
2789                else
2790                {
2791                  len = offsetof(T30_INFO, universal_6);
2792                }
2793                fax_info_change = true;
2794
2795              }
2796              if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2797              {
2798                PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2799                fax_info_change = true;
2800              }
2801            }
2802            if (Info == GOOD)
2803            {
2804              plci->fax_connect_info_length = len;
2805              if (fax_info_change)
2806              {
2807                if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2808                {
2809                  start_internal_command (Id, plci, fax_connect_info_command);
2810                  return false;
2811                }
2812                else
2813                {
2814                  start_internal_command (Id, plci, fax_adjust_b23_command);
2815                  return false;
2816                }
2817              }
2818            }
2819          }
2820          else  Info = _WRONG_STATE;
2821        }
2822        else  Info = _WRONG_STATE;
2823      }
2824
2825      else if (plci->B3_prot == B3_RTP)
2826      {
2827        plci->internal_req_buffer[0] = ncpi->length + 1;
2828        plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2829        for (w = 0; w < ncpi->length; w++)
2830          plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2831        start_internal_command (Id, plci, rtp_connect_b3_req_command);
2832        return false;
2833      }
2834
2835      if(!Info)
2836      {
2837        nl_req_ncci(plci,req,0);
2838        return 1;
2839      }
2840    }
2841  }
2842  else Info = _WRONG_IDENTIFIER;
2843
2844  sendf(appl,
2845        _CONNECT_B3_R|CONFIRM,
2846        Id,
2847        Number,
2848        "w",Info);
2849  return false;
2850}
2851
2852static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2853                           PLCI *plci, APPL *appl, API_PARSE *parms)
2854{
2855  word ncci;
2856  API_PARSE * ncpi;
2857  byte req;
2858
2859  word w;
2860
2861
2862    API_PARSE fax_parms[9];
2863  word i;
2864  byte len;
2865
2866
2867  dbug(1,dprintf("connect_b3_res"));
2868
2869  ncci = (word)(Id>>16);
2870  if(plci && ncci) {
2871    if(a->ncci_state[ncci]==INC_CON_PENDING) {
2872      if (GET_WORD (&parms[0].info[0]) != 0)
2873      {
2874        a->ncci_state[ncci] = OUTG_REJ_PENDING;
2875        channel_request_xon (plci, a->ncci_ch[ncci]);
2876        channel_xmit_xon (plci);
2877        cleanup_ncci_data (plci, ncci);
2878        nl_req_ncci(plci,N_DISC,(byte)ncci);
2879        return 1;
2880      }
2881      a->ncci_state[ncci] = INC_ACT_PENDING;
2882
2883      req = N_CONNECT_ACK;
2884      ncpi = &parms[1];
2885      if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2886      {
2887
2888        if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2889          & (1L << PRIVATE_FAX_NONSTANDARD))
2890 {
2891   if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2892    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2893    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2894   {
2895            len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2896            if (plci->fax_connect_info_length < len)
2897            {
2898              ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2899              ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2900            }
2901            if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2902            {
2903              dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2904            }
2905            else
2906            {
2907              if (plci->fax_connect_info_length <= len)
2908                plci->fax_connect_info_buffer[len] = 0;
2909              len += 1 + plci->fax_connect_info_buffer[len];
2910              if (plci->fax_connect_info_length <= len)
2911                plci->fax_connect_info_buffer[len] = 0;
2912              len += 1 + plci->fax_connect_info_buffer[len];
2913              if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2914                plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2915              plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2916              for (i = 0; i < fax_parms[7].length; i++)
2917                plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2918            }
2919            plci->fax_connect_info_length = len;
2920            ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2921            start_internal_command (Id, plci, fax_connect_ack_command);
2922     return false;
2923          }
2924        }
2925
2926        nl_req_ncci(plci,req,(byte)ncci);
2927        if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2928         && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2929        {
2930          if (plci->B3_prot == 4)
2931            sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2932          else
2933            sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2934          plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2935        }
2936      }
2937
2938      else if (plci->B3_prot == B3_RTP)
2939      {
2940        plci->internal_req_buffer[0] = ncpi->length + 1;
2941        plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2942        for (w = 0; w < ncpi->length; w++)
2943          plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2944        start_internal_command (Id, plci, rtp_connect_b3_res_command);
2945        return false;
2946      }
2947
2948      else
2949      {
2950        if(ncpi->length>2) {
2951          if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2952          add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2953        }
2954        nl_req_ncci(plci,req,(byte)ncci);
2955        sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2956        if (plci->adjust_b_restore)
2957        {
2958          plci->adjust_b_restore = false;
2959          start_internal_command (Id, plci, adjust_b_restore);
2960        }
2961      }
2962      return 1;
2963    }
2964  }
2965  return false;
2966}
2967
2968static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2969                             PLCI *plci, APPL *appl, API_PARSE *parms)
2970{
2971  word ncci;
2972
2973  ncci = (word)(Id>>16);
2974  dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2975
2976  if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2977   && (plci->State != OUTG_DIS_PENDING))
2978  {
2979    if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2980      a->ncci_state[ncci] = CONNECTED;
2981      if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2982      channel_request_xon (plci, a->ncci_ch[ncci]);
2983      channel_xmit_xon (plci);
2984    }
2985  }
2986  return false;
2987}
2988
2989static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2990                              PLCI *plci, APPL *appl, API_PARSE *parms)
2991{
2992  word Info;
2993  word ncci;
2994  API_PARSE * ncpi;
2995
2996  dbug(1,dprintf("disconnect_b3_req"));
2997
2998  Info = _WRONG_IDENTIFIER;
2999  ncci = (word)(Id>>16);
3000  if (plci && ncci)
3001  {
3002    Info = _WRONG_STATE;
3003    if ((a->ncci_state[ncci] == CONNECTED)
3004     || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3005     || (a->ncci_state[ncci] == INC_CON_PENDING)
3006     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3007    {
3008      a->ncci_state[ncci] = OUTG_DIS_PENDING;
3009      channel_request_xon (plci, a->ncci_ch[ncci]);
3010      channel_xmit_xon (plci);
3011
3012      if (a->ncci[ncci].data_pending
3013       && ((plci->B3_prot == B3_TRANSPARENT)
3014        || (plci->B3_prot == B3_T30)
3015        || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3016      {
3017        plci->send_disc = (byte)ncci;
3018        plci->command = 0;
3019        return false;
3020      }
3021      else
3022      {
3023        cleanup_ncci_data (plci, ncci);
3024
3025        if(plci->B3_prot==2 || plci->B3_prot==3)
3026        {
3027          ncpi = &parms[0];
3028          if(ncpi->length>3)
3029          {
3030            add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3031          }
3032        }
3033        nl_req_ncci(plci,N_DISC,(byte)ncci);
3034      }
3035      return 1;
3036    }
3037  }
3038  sendf(appl,
3039        _DISCONNECT_B3_R|CONFIRM,
3040        Id,
3041        Number,
3042        "w",Info);
3043  return false;
3044}
3045
3046static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3047                              PLCI *plci, APPL *appl, API_PARSE *parms)
3048{
3049  word ncci;
3050  word i;
3051
3052  ncci = (word)(Id>>16);
3053  dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3054  if(plci && ncci) {
3055    plci->requested_options_conn = 0;
3056    plci->fax_connect_info_length = 0;
3057    plci->ncpi_state = 0x00;
3058    if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3059      && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3060    {
3061      plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3062    }
3063    for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3064    if(i<MAX_CHANNELS_PER_PLCI) {
3065      if(plci->channels)plci->channels--;
3066      for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3067      plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3068
3069      ncci_free_receive_buffers (plci, ncci);
3070
3071      if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3072        if(plci->State == SUSPENDING){
3073          sendf(plci->appl,
3074                _FACILITY_I,
3075                Id & 0xffffL,
3076                0,
3077                "ws", (word)3, "\x03\x04\x00\x00");
3078          sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3079        }
3080        plci_remove(plci);
3081        plci->State=IDLE;
3082      }
3083    }
3084    else
3085    {
3086      if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3087       && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3088       && (a->ncci_state[ncci] == INC_DIS_PENDING))
3089      {
3090        ncci_free_receive_buffers (plci, ncci);
3091
3092        nl_req_ncci(plci,N_EDATA,(byte)ncci);
3093
3094        plci->adapter->ncci_state[ncci] = IDLE;
3095        start_internal_command (Id, plci, fax_disconnect_command);
3096        return 1;
3097      }
3098    }
3099  }
3100  return false;
3101}
3102
3103static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3104                        PLCI *plci, APPL *appl, API_PARSE *parms)
3105{
3106  NCCI   *ncci_ptr;
3107  DATA_B3_DESC   *data;
3108  word Info;
3109  word ncci;
3110  word i;
3111
3112  dbug(1,dprintf("data_b3_req"));
3113
3114  Info = _WRONG_IDENTIFIER;
3115  ncci = (word)(Id>>16);
3116  dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3117
3118  if (plci && ncci)
3119  {
3120    Info = _WRONG_STATE;
3121    if ((a->ncci_state[ncci] == CONNECTED)
3122     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3123    {
3124        /* queue data */
3125      ncci_ptr = &(a->ncci[ncci]);
3126      i = ncci_ptr->data_out + ncci_ptr->data_pending;
3127      if (i >= MAX_DATA_B3)
3128        i -= MAX_DATA_B3;
3129      data = &(ncci_ptr->DBuffer[i]);
3130      data->Number = Number;
3131      if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3132       && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3133      {
3134
3135        data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3136
3137      }
3138      else
3139        data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3140      data->Length = GET_WORD(parms[1].info);
3141      data->Handle = GET_WORD(parms[2].info);
3142      data->Flags = GET_WORD(parms[3].info);
3143      (ncci_ptr->data_pending)++;
3144
3145        /* check for delivery confirmation */
3146      if (data->Flags & 0x0004)
3147      {
3148        i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3149        if (i >= MAX_DATA_ACK)
3150          i -= MAX_DATA_ACK;
3151        ncci_ptr->DataAck[i].Number = data->Number;
3152        ncci_ptr->DataAck[i].Handle = data->Handle;
3153        (ncci_ptr->data_ack_pending)++;
3154      }
3155
3156      send_data(plci);
3157      return false;
3158    }
3159  }
3160  if (appl)
3161  {
3162    if (plci)
3163    {
3164      if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3165       && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3166      {
3167
3168        TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3169
3170      }
3171    }
3172    sendf(appl,
3173          _DATA_B3_R|CONFIRM,
3174          Id,
3175          Number,
3176          "ww",GET_WORD(parms[2].info),Info);
3177  }
3178  return false;
3179}
3180
3181static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3182                        PLCI *plci, APPL *appl, API_PARSE *parms)
3183{
3184  word n;
3185  word ncci;
3186  word NCCIcode;
3187
3188  dbug(1,dprintf("data_b3_res"));
3189
3190  ncci = (word)(Id>>16);
3191  if(plci && ncci) {
3192    n = GET_WORD(parms[0].info);
3193    dbug(1,dprintf("free(%d)",n));
3194    NCCIcode = ncci | (((word) a->Id) << 8);
3195    if(n<appl->MaxBuffer &&
3196       appl->DataNCCI[n]==NCCIcode &&
3197       (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3198      dbug(1,dprintf("found"));
3199      appl->DataNCCI[n] = 0;
3200
3201      if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3202        channel_request_xon (plci, a->ncci_ch[ncci]);
3203      }
3204      channel_xmit_xon (plci);
3205
3206      if(appl->DataFlags[n] &4) {
3207        nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3208        return 1;
3209      }
3210    }
3211  }
3212  return false;
3213}
3214
3215static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3216                         PLCI *plci, APPL *appl, API_PARSE *parms)
3217{
3218  word Info;
3219  word ncci;
3220
3221  dbug(1,dprintf("reset_b3_req"));
3222
3223  Info = _WRONG_IDENTIFIER;
3224  ncci = (word)(Id>>16);
3225  if(plci && ncci)
3226  {
3227    Info = _WRONG_STATE;
3228    switch (plci->B3_prot)
3229    {
3230    case B3_ISO8208:
3231    case B3_X25_DCE:
3232      if(a->ncci_state[ncci]==CONNECTED)
3233      {
3234        nl_req_ncci(plci,N_RESET,(byte)ncci);
3235        send_req(plci);
3236        Info = GOOD;
3237      }
3238      break;
3239    case B3_TRANSPARENT:
3240      if(a->ncci_state[ncci]==CONNECTED)
3241      {
3242        start_internal_command (Id, plci, reset_b3_command);
3243        Info = GOOD;
3244      }
3245      break;
3246    }
3247  }
3248  /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3249  sendf(appl,
3250        _RESET_B3_R|CONFIRM,
3251        Id,
3252        Number,
3253        "w",Info);
3254  return false;
3255}
3256
3257static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3258                         PLCI *plci, APPL *appl, API_PARSE *parms)
3259{
3260  word ncci;
3261
3262  dbug(1,dprintf("reset_b3_res"));
3263
3264  ncci = (word)(Id>>16);
3265  if(plci && ncci) {
3266    switch (plci->B3_prot)
3267    {
3268    case B3_ISO8208:
3269    case B3_X25_DCE:
3270      if(a->ncci_state[ncci]==INC_RES_PENDING)
3271      {
3272        a->ncci_state[ncci] = CONNECTED;
3273        nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3274        return true;
3275      }
3276    break;
3277    }
3278  }
3279  return false;
3280}
3281
3282static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3283                                 PLCI *plci, APPL *appl, API_PARSE *parms)
3284{
3285  word ncci;
3286  API_PARSE * ncpi;
3287  byte req;
3288
3289  dbug(1,dprintf("connect_b3_t90_a_res"));
3290
3291  ncci = (word)(Id>>16);
3292  if(plci && ncci) {
3293    if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3294      a->ncci_state[ncci] = CONNECTED;
3295    }
3296    else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3297      a->ncci_state[ncci] = CONNECTED;
3298
3299      req = N_CONNECT_ACK;
3300
3301        /* parms[0]==0 for CAPI original message definition! */
3302      if(parms[0].info) {
3303        ncpi = &parms[1];
3304        if(ncpi->length>2) {
3305          if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3306          add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3307        }
3308      }
3309      nl_req_ncci(plci,req,(byte)ncci);
3310      return 1;
3311    }
3312  }
3313  return false;
3314}
3315
3316
3317static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3318                         PLCI *plci, APPL *appl, API_PARSE *msg)
3319{
3320  word Info=0;
3321  word i;
3322  byte tel;
3323    API_PARSE bp_parms[7];
3324
3325  if(!plci || !msg)
3326  {
3327    Info = _WRONG_IDENTIFIER;
3328  }
3329  else
3330  {
3331    dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3332                   msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3333    dbug(1,dprintf("PlciState=0x%x",plci->State));
3334    for(i=0;i<7;i++) bp_parms[i].length = 0;
3335
3336    /* check if no channel is open, no B3 connected only */
3337    if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3338     || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3339    {
3340      Info = _WRONG_STATE;
3341    }
3342    /* check message format and fill bp_parms pointer */
3343    else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3344    {
3345      Info = _WRONG_MESSAGE_FORMAT;
3346    }
3347    else
3348    {
3349      if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3350      {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3351        if(Id & EXT_CONTROLLER)
3352        {
3353          sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3354          return 0;
3355        }
3356        plci->State=INC_CON_CONNECTED_ALERT;
3357        plci->appl = appl;
3358        clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3359        dump_c_ind_mask (plci);
3360        for(i=0; i<max_appl; i++) /* disconnect the other appls */
3361        {                         /* its quasi a connect        */
3362          if(test_c_ind_mask_bit (plci, i))
3363            sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3364        }
3365      }
3366
3367      api_save_msg(msg, "s", &plci->saved_msg);
3368      tel = plci->tel;
3369      if(Id & EXT_CONTROLLER)
3370      {
3371        if(tel) /* external controller in use by this PLCI */
3372        {
3373          if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3374          {
3375            dbug(1,dprintf("Ext_Ctrl in use 1"));
3376            Info = _WRONG_STATE;
3377          }
3378        }
3379        else  /* external controller NOT in use by this PLCI ? */
3380        {
3381          if(a->AdvSignalPLCI)
3382          {
3383            dbug(1,dprintf("Ext_Ctrl in use 2"));
3384            Info = _WRONG_STATE;
3385          }
3386          else /* activate the codec */
3387          {
3388            dbug(1,dprintf("Ext_Ctrl start"));
3389            if(AdvCodecSupport(a, plci, appl, 0) )
3390            {
3391              dbug(1,dprintf("Error in codec procedures"));
3392              Info = _WRONG_STATE;
3393            }
3394            else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3395            {
3396              plci->spoofed_msg = AWAITING_SELECT_B;
3397              plci->internal_command = BLOCK_PLCI; /* lock other commands */
3398              plci->command = 0;
3399              dbug(1,dprintf("continue if codec loaded"));
3400              return false;
3401            }
3402          }
3403        }
3404      }
3405      else /* external controller bit is OFF */
3406      {
3407        if(tel) /* external controller in use, need to switch off */
3408        {
3409          if(a->AdvSignalAppl==appl)
3410          {
3411            CodecIdCheck(a, plci);
3412            plci->tel = 0;
3413            plci->adv_nl = 0;
3414            dbug(1,dprintf("Ext_Ctrl disable"));
3415          }
3416          else
3417          {
3418            dbug(1,dprintf("Ext_Ctrl not requested"));
3419          }
3420        }
3421      }
3422      if (!Info)
3423      {
3424        if (plci->call_dir & CALL_DIR_OUT)
3425          plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3426        else if (plci->call_dir & CALL_DIR_IN)
3427          plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3428        start_internal_command (Id, plci, select_b_command);
3429        return false;
3430      }
3431    }
3432  }
3433  sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3434  return false;
3435}
3436
3437static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3438                             PLCI *plci, APPL *appl, API_PARSE *parms)
3439{
3440  word command;
3441  word i;
3442  word ncci;
3443  API_PARSE * m;
3444    API_PARSE m_parms[5];
3445  word codec;
3446  byte req;
3447  byte ch;
3448  byte dir;
3449  static byte chi[2] = {0x01,0x00};
3450  static byte lli[2] = {0x01,0x00};
3451  static byte codec_cai[2] = {0x01,0x01};
3452  static byte null_msg = {0};
3453  static API_PARSE null_parms = { 0, &null_msg };
3454  PLCI   * v_plci;
3455  word Info=0;
3456
3457  dbug(1,dprintf("manufacturer_req"));
3458  for(i=0;i<5;i++) m_parms[i].length = 0;
3459
3460  if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3461    Info = _WRONG_MESSAGE_FORMAT;
3462  }
3463  command = GET_WORD(parms[1].info);
3464  m = &parms[2];
3465  if (!Info)
3466  {
3467    switch(command) {
3468    case _DI_ASSIGN_PLCI:
3469      if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3470        Info = _WRONG_MESSAGE_FORMAT;
3471        break;
3472      }
3473      codec = GET_WORD(m_parms[0].info);
3474      ch = m_parms[1].info[0];
3475      dir = m_parms[2].info[0];
3476      if((i=get_plci(a))) {
3477        plci = &a->plci[i-1];
3478        plci->appl = appl;
3479        plci->command = _MANUFACTURER_R;
3480        plci->m_command = command;
3481        plci->number = Number;
3482        plci->State = LOCAL_CONNECT;
3483        Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3484        dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3485
3486        if((ch==1 || ch==2) && (dir<=2)) {
3487          chi[1] = (byte)(0x80|ch);
3488          lli[1] = 0;
3489          plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3490          switch(codec)
3491          {
3492          case 0:
3493            Info = add_b1(plci,&m_parms[3],0,0);
3494            break;
3495          case 1:
3496            add_p(plci,CAI,codec_cai);
3497            break;
3498          /* manual 'swich on' to the codec support without signalling */
3499          /* first 'assign plci' with this function, then use */
3500          case 2:
3501            if(AdvCodecSupport(a, plci, appl, 0) ) {
3502              Info = _RESOURCE_ERROR;
3503            }
3504            else {
3505              Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3506              lli[1] = 0x10; /* local call codec stream */
3507            }
3508            break;
3509          }
3510
3511          plci->State = LOCAL_CONNECT;
3512          plci->manufacturer = true;
3513          plci->command = _MANUFACTURER_R;
3514          plci->m_command = command;
3515          plci->number = Number;
3516
3517          if(!Info)
3518          {
3519            add_p(plci,LLI,lli);
3520            add_p(plci,CHI,chi);
3521            add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3522            sig_req(plci,ASSIGN,DSIG_ID);
3523
3524            if(!codec)
3525            {
3526              Info = add_b23(plci,&m_parms[3]);
3527              if(!Info)
3528              {
3529                nl_req_ncci(plci,ASSIGN,0);
3530                send_req(plci);
3531              }
3532            }
3533            if(!Info)
3534            {
3535              dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3536              if (plci->spoofed_msg==SPOOFING_REQUIRED)
3537              {
3538                api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3539                plci->spoofed_msg = AWAITING_MANUF_CON;
3540                plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3541                plci->command = 0;
3542                send_req(plci);
3543                return false;
3544              }
3545              if(dir==1) {
3546                sig_req(plci,CALL_REQ,0);
3547              }
3548              else if(!dir){
3549                sig_req(plci,LISTEN_REQ,0);
3550              }
3551              send_req(plci);
3552            }
3553            else
3554            {
3555              sendf(appl,
3556                    _MANUFACTURER_R|CONFIRM,
3557                    Id,
3558                    Number,
3559                    "dww",_DI_MANU_ID,command,Info);
3560              return 2;
3561            }
3562          }
3563        }
3564      }
3565      else  Info = _OUT_OF_PLCI;
3566      break;
3567
3568    case _DI_IDI_CTRL:
3569      if(!plci)
3570      {
3571        Info = _WRONG_IDENTIFIER;
3572        break;
3573      }
3574      if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3575        Info = _WRONG_MESSAGE_FORMAT;
3576        break;
3577      }
3578      req = m_parms[0].info[0];
3579      plci->command = _MANUFACTURER_R;
3580      plci->m_command = command;
3581      plci->number = Number;
3582      if(req==CALL_REQ)
3583      {
3584        plci->b_channel = getChannel(&m_parms[1]);
3585        mixer_set_bchannel_id_esc (plci, plci->b_channel);
3586        if(plci->spoofed_msg==SPOOFING_REQUIRED)
3587        {
3588          plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3589          plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3590          plci->command = 0;
3591          break;
3592        }
3593      }
3594      else if(req==LAW_REQ)
3595      {
3596        plci->cr_enquiry = true;
3597      }
3598      add_ss(plci,FTY,&m_parms[1]);
3599      sig_req(plci,req,0);
3600      send_req(plci);
3601      if(req==HANGUP)
3602      {      
3603        if (plci->NL.Id && !plci->nl_remove_id)
3604        {
3605          if (plci->channels)
3606          {
3607            for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3608            {
3609              if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3610              {
3611                a->ncci_state[ncci] = OUTG_DIS_PENDING;
3612                cleanup_ncci_data (plci, ncci);
3613                nl_req_ncci(plci,N_DISC,(byte)ncci);
3614              }
3615            }
3616          }
3617          mixer_remove (plci);
3618          nl_req_ncci(plci,REMOVE,0);
3619          send_req(plci);
3620        }  
3621      }
3622      break;
3623
3624    case _DI_SIG_CTRL:
3625    /* signalling control for loop activation B-channel */
3626      if(!plci)
3627      {
3628        Info = _WRONG_IDENTIFIER;
3629        break;
3630      }
3631      if(m->length){
3632        plci->command = _MANUFACTURER_R;
3633        plci->number = Number;
3634        add_ss(plci,FTY,m);
3635        sig_req(plci,SIG_CTRL,0);
3636        send_req(plci);
3637      }
3638      else Info = _WRONG_MESSAGE_FORMAT;
3639      break;
3640
3641    case _DI_RXT_CTRL:
3642    /* activation control for receiver/transmitter B-channel */
3643      if(!plci)
3644      {
3645        Info = _WRONG_IDENTIFIER;
3646        break;
3647      }
3648      if(m->length){
3649        plci->command = _MANUFACTURER_R;
3650        plci->number = Number;
3651        add_ss(plci,FTY,m);
3652        sig_req(plci,DSP_CTRL,0);
3653        send_req(plci);
3654      }
3655      else Info = _WRONG_MESSAGE_FORMAT;
3656      break;
3657
3658    case _DI_ADV_CODEC:
3659    case _DI_DSP_CTRL:
3660      /* TEL_CTRL commands to support non standard adjustments: */
3661      /* Ring on/off, Handset micro volume, external micro vol. */
3662      /* handset+external speaker volume, receiver+transm. gain,*/
3663      /* handsfree on (hookinfo off), set mixer command         */
3664
3665      if(command == _DI_ADV_CODEC)
3666      {
3667        if(!a->AdvCodecPLCI) {
3668          Info = _WRONG_STATE;
3669          break;
3670        }
3671        v_plci = a->AdvCodecPLCI;
3672      }
3673      else
3674      {
3675        if (plci
3676         && (m->length >= 3)
3677         && (m->info[1] == 0x1c)
3678         && (m->info[2] >= 1))
3679        {
3680          if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3681          {
3682            if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3683            {
3684              Info = _WRONG_STATE;
3685              break;
3686            }
3687            a->adv_voice_coef_length = m->info[2] - 1;
3688            if (a->adv_voice_coef_length > m->length - 3)
3689              a->adv_voice_coef_length = (byte)(m->length - 3);
3690            if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3691              a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3692            for (i = 0; i < a->adv_voice_coef_length; i++)
3693              a->adv_voice_coef_buffer[i] = m->info[4 + i];
3694            if (plci->B1_facilities & B1_FACILITY_VOICE)
3695              adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3696            break;
3697          }
3698          else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3699          {
3700            if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3701            {
3702              Info = _FACILITY_NOT_SUPPORTED;
3703              break;
3704            }
3705
3706            plci->dtmf_parameter_length = m->info[2] - 1;
3707            if (plci->dtmf_parameter_length > m->length - 3)
3708              plci->dtmf_parameter_length = (byte)(m->length - 3);
3709            if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3710              plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3711            for (i = 0; i < plci->dtmf_parameter_length; i++)
3712              plci->dtmf_parameter_buffer[i] = m->info[4+i];
3713            if (plci->B1_facilities & B1_FACILITY_DTMFR)
3714              dtmf_parameter_write (plci);
3715            break;
3716
3717          }
3718        }
3719        v_plci = plci;
3720      }
3721
3722      if(!v_plci)
3723      {
3724        Info = _WRONG_IDENTIFIER;
3725        break;
3726      }
3727      if(m->length){
3728        add_ss(v_plci,FTY,m);
3729        sig_req(v_plci,TEL_CTRL,0);
3730        send_req(v_plci);
3731      }
3732      else Info = _WRONG_MESSAGE_FORMAT;
3733
3734      break;
3735
3736    case _DI_OPTIONS_REQUEST:
3737      if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3738        Info = _WRONG_MESSAGE_FORMAT;
3739        break;
3740      }
3741      if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3742      {
3743        Info = _FACILITY_NOT_SUPPORTED;
3744        break;
3745      }
3746      a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3747      break;
3748
3749
3750
3751    default:
3752      Info = _WRONG_MESSAGE_FORMAT;
3753      break;
3754    }
3755  }
3756
3757  sendf(appl,
3758        _MANUFACTURER_R|CONFIRM,
3759        Id,
3760        Number,
3761        "dww",_DI_MANU_ID,command,Info);
3762  return false;
3763}
3764
3765
3766static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3767                             PLCI *plci, APPL *appl, API_PARSE *msg)
3768{
3769  word indication;
3770
3771    API_PARSE m_parms[3];
3772  API_PARSE *ncpi;
3773    API_PARSE fax_parms[9];
3774  word i;
3775  byte len;
3776
3777
3778  dbug(1,dprintf("manufacturer_res"));
3779
3780  if ((msg[0].length == 0)
3781   || (msg[1].length == 0)
3782   || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3783  {
3784    return false;
3785  }
3786  indication = GET_WORD(msg[1].info);
3787  switch (indication)
3788  {
3789
3790  case _DI_NEGOTIATE_B3:
3791    if(!plci)
3792      break;
3793    if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3794     || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3795    {
3796      dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3797      break;
3798    }
3799    if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3800    {
3801      dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3802      break;
3803    }
3804    ncpi = &m_parms[1];
3805    len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3806    if (plci->fax_connect_info_length < len)
3807    {
3808      ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3809      ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3810    }
3811    if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3812    {
3813      dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3814    }
3815    else
3816    {
3817      if (plci->fax_connect_info_length <= len)
3818        plci->fax_connect_info_buffer[len] = 0;
3819      len += 1 + plci->fax_connect_info_buffer[len];
3820      if (plci->fax_connect_info_length <= len)
3821        plci->fax_connect_info_buffer[len] = 0;
3822      len += 1 + plci->fax_connect_info_buffer[len];
3823      if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3824        plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3825      plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3826      for (i = 0; i < fax_parms[7].length; i++)
3827        plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3828    }
3829    plci->fax_connect_info_length = len;
3830    plci->fax_edata_ack_length = plci->fax_connect_info_length;
3831    start_internal_command (Id, plci, fax_edata_ack_command);
3832    break;
3833
3834  }
3835  return false;
3836}
3837
3838/*------------------------------------------------------------------*/
3839/* IDI callback function                                            */
3840/*------------------------------------------------------------------*/
3841
3842void   callback(ENTITY   * e)
3843{
3844  DIVA_CAPI_ADAPTER   * a;
3845  APPL   * appl;
3846  PLCI   * plci;
3847  CAPI_MSG   *m;
3848  word i, j;
3849  byte rc;
3850  byte ch;
3851  byte req;
3852  byte global_req;
3853  int no_cancel_rc;
3854
3855  dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3856                 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3857
3858  a = &(adapter[(byte)e->user[0]]);
3859  plci = &(a->plci[e->user[1]]);
3860  no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3861
3862  /*
3863     If new protocol code and new XDI is used then CAPI should work
3864     fully in accordance with IDI cpec an look on callback field instead
3865     of Rc field for return codes.
3866   */
3867  if (((e->complete == 0xff) && no_cancel_rc) ||
3868      (e->Rc && !no_cancel_rc)) {
3869    rc = e->Rc;
3870    ch = e->RcCh;
3871    req = e->Req;
3872    e->Rc = 0;
3873
3874    if (e->user[0] & 0x8000)
3875    {
3876      /*
3877         If REMOVE request was sent then we have to wait until
3878         return code with Id set to zero arrives.
3879         All other return codes should be ignored.
3880         */
3881      if (req == REMOVE)
3882      {
3883        if (e->Id)
3884        {
3885          dbug(1,dprintf("cancel RC in REMOVE state"));
3886          return;
3887        }
3888        channel_flow_control_remove (plci);
3889        for (i = 0; i < 256; i++)
3890        {
3891          if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3892            a->FlowControlIdTable[i] = 0;
3893        }
3894        plci->nl_remove_id = 0;
3895        if (plci->rx_dma_descriptor > 0) {
3896          diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3897          plci->rx_dma_descriptor = 0;
3898        }
3899      }
3900      if (rc == OK_FC)
3901      {
3902        a->FlowControlIdTable[ch] = e->Id;
3903        a->FlowControlSkipTable[ch] = 0;
3904
3905        a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3906        a->ch_flow_plci[ch] = plci->Id;
3907        plci->nl_req = 0;
3908      }
3909      else
3910      {
3911        /*
3912          Cancel return codes self, if feature was requested
3913          */
3914        if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3915          a->FlowControlIdTable[ch] = 0;
3916          if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3917            dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3918            return;
3919          }
3920        }
3921
3922        if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3923        {
3924          a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3925          if (ch == e->ReqCh)
3926            plci->nl_req = 0;
3927        }
3928        else
3929          plci->nl_req = 0;
3930      }
3931      if (plci->nl_req)
3932        control_rc (plci, 0, rc, ch, 0, true);
3933      else
3934      {
3935        if (req == N_XON)
3936        {
3937          channel_x_on (plci, ch);
3938          if (plci->internal_command)
3939            control_rc (plci, req, rc, ch, 0, true);
3940        }
3941        else
3942        {
3943          if (plci->nl_global_req)
3944          {
3945            global_req = plci->nl_global_req;
3946            plci->nl_global_req = 0;
3947            if (rc != ASSIGN_OK) {
3948              e->Id = 0;
3949              if (plci->rx_dma_descriptor > 0) {
3950                diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3951                plci->rx_dma_descriptor = 0;
3952              }
3953            }
3954            channel_xmit_xon (plci);
3955            control_rc (plci, 0, rc, ch, global_req, true);
3956          }
3957          else if (plci->data_sent)
3958          {
3959            channel_xmit_xon (plci);
3960            plci->data_sent = false;
3961            plci->NL.XNum = 1;
3962            data_rc (plci, ch);
3963            if (plci->internal_command)
3964              control_rc (plci, req, rc, ch, 0, true);
3965          }
3966          else
3967          {
3968            channel_xmit_xon (plci);
3969            control_rc (plci, req, rc, ch, 0, true);
3970          }
3971        }
3972      }
3973    }
3974    else
3975    {
3976      /*
3977         If REMOVE request was sent then we have to wait until
3978         return code with Id set to zero arrives.
3979         All other return codes should be ignored.
3980         */
3981      if (req == REMOVE)
3982      {
3983        if (e->Id)
3984        {
3985          dbug(1,dprintf("cancel RC in REMOVE state"));
3986          return;
3987        }
3988        plci->sig_remove_id = 0;
3989      }
3990      plci->sig_req = 0;
3991      if (plci->sig_global_req)
3992      {
3993        global_req = plci->sig_global_req;
3994        plci->sig_global_req = 0;
3995        if (rc != ASSIGN_OK)
3996          e->Id = 0;
3997        channel_xmit_xon (plci);
3998        control_rc (plci, 0, rc, ch, global_req, false);
3999      }
4000      else
4001      {
4002        channel_xmit_xon (plci);
4003        control_rc (plci, req, rc, ch, 0, false);
4004      }
4005    }
4006    /*
4007      Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4008      same callback. Also if new XDI and protocol code used then jump
4009      direct to finish.
4010      */
4011    if (no_cancel_rc) {
4012      channel_xmit_xon(plci);
4013      goto capi_callback_suffix;
4014    }
4015  }
4016
4017  channel_xmit_xon(plci);
4018
4019  if (e->Ind) {
4020    if (e->user[0] &0x8000) {
4021      byte Ind = e->Ind & 0x0f;
4022      byte Ch = e->IndCh;
4023      if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4024          (a->ch_flow_plci[Ch] == plci->Id)) {
4025        if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4026          dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4027        }
4028        a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4029      }
4030      nl_ind(plci);
4031      if ((e->RNR != 1) &&
4032          (a->ch_flow_plci[Ch] == plci->Id) &&
4033          (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4034        a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4035        dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4036      }
4037    } else {
4038      sig_ind(plci);
4039    }
4040    e->Ind = 0;
4041  }
4042
4043capi_callback_suffix:
4044
4045  while (!plci->req_in
4046   && !plci->internal_command
4047   && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4048  {
4049    j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4050
4051    i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4052
4053    m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4054    appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4055    dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4056      m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4057    if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4058    {
4059      plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4060      plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4061    }
4062    else
4063    {
4064      plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4065    }
4066    if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4067    {
4068      plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4069      plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4070    }
4071    else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4072    {
4073      plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4074      plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4075    }
4076    i = api_put (appl, m);
4077    if (i != 0)
4078    {
4079      if (m->header.command == _DATA_B3_R)
4080
4081        TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4082
4083      dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4084      break;
4085    }
4086
4087    if (plci->li_notify_update)
4088    {
4089      plci->li_notify_update = false;
4090      mixer_notify_update (plci, false);
4091    }
4092
4093  }
4094  send_data(plci);
4095  send_req(plci);
4096}
4097
4098
4099static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4100                       byte nl_rc)
4101{
4102  dword Id;
4103  dword rId;
4104  word Number;
4105  word Info=0;
4106  word i;
4107  word ncci;
4108  DIVA_CAPI_ADAPTER   * a;
4109  APPL   * appl;
4110  PLCI   * rplci;
4111    byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4112    byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4113
4114  if (!plci) {
4115    dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4116    return;
4117  }
4118  dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4119  if(plci->req_in!=plci->req_out)
4120  {
4121    if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4122    {
4123      dbug(1,dprintf("req_1return"));
4124      return;
4125    }
4126    /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4127  }
4128  plci->req_in = plci->req_in_start = plci->req_out = 0;
4129  dbug(1,dprintf("control_rc"));
4130
4131  appl = plci->appl;
4132  a = plci->adapter;
4133  ncci = a->ch_ncci[ch];
4134  if(appl)
4135  {
4136    Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4137    if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4138    Number = plci->number;
4139    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));
4140    dbug(1,dprintf("channels=0x%x",plci->channels));
4141    if (plci_remove_check(plci))
4142      return;
4143    if(req==REMOVE && rc==ASSIGN_OK)
4144    {
4145      sig_req(plci,HANGUP,0);
4146      sig_req(plci,REMOVE,0);
4147      send_req(plci);
4148    }
4149    if(plci->command)
4150    {
4151      switch(plci->command)
4152      {
4153      case C_HOLD_REQ:
4154        dbug(1,dprintf("HoldRC=0x%x",rc));
4155        SSparms[1] = (byte)S_HOLD;
4156        if(rc!=OK)
4157        {
4158          plci->SuppState = IDLE;
4159          Info = 0x2001;
4160        }
4161        sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4162        break;
4163
4164      case C_RETRIEVE_REQ:
4165        dbug(1,dprintf("RetrieveRC=0x%x",rc));
4166        SSparms[1] = (byte)S_RETRIEVE;
4167        if(rc!=OK)
4168        {
4169          plci->SuppState = CALL_HELD;
4170          Info = 0x2001;
4171        }
4172        sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4173        break;
4174
4175      case _INFO_R:
4176        dbug(1,dprintf("InfoRC=0x%x",rc));
4177        if(rc!=OK) Info=_WRONG_STATE;
4178        sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4179        break;
4180
4181      case _CONNECT_R:
4182        dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4183        if (plci->State == INC_DIS_PENDING)
4184          break;
4185        if(plci->Sig.Id!=0xff)
4186        {
4187          if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4188           || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4189          {
4190            dbug(1,dprintf("No more IDs/Call_Req failed"));
4191            sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4192            plci_remove(plci);
4193            plci->State = IDLE;
4194            break;
4195          }
4196          if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4197          sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4198        }
4199        else /* D-ch activation */
4200        {
4201          if (rc != ASSIGN_OK)
4202          {
4203            dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4204            sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4205            plci_remove(plci);
4206            plci->State = IDLE;
4207            break;
4208          }
4209          sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4210          sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4211          plci->State = INC_ACT_PENDING;
4212        }
4213        break;
4214
4215      case _CONNECT_I|RESPONSE:
4216        if (plci->State != INC_DIS_PENDING)
4217          plci->State = INC_CON_ACCEPT;
4218        break;
4219
4220      case _DISCONNECT_R:
4221        if (plci->State == INC_DIS_PENDING)
4222          break;
4223        if(plci->Sig.Id!=0xff)
4224        {
4225          plci->State = OUTG_DIS_PENDING;
4226          sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4227        }
4228        break;
4229
4230      case SUSPEND_REQ:
4231        break;
4232
4233      case RESUME_REQ:
4234        break;
4235
4236      case _CONNECT_B3_R:
4237        if(rc!=OK)
4238        {
4239          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4240          break;
4241        }
4242        ncci = get_ncci (plci, ch, 0);
4243        Id = (Id & 0xffff) | (((dword) ncci) << 16);
4244        plci->channels++;
4245        if(req==N_RESET)
4246        {
4247          a->ncci_state[ncci] = INC_ACT_PENDING;
4248          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4249          sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4250        }
4251        else
4252        {
4253          a->ncci_state[ncci] = OUTG_CON_PENDING;
4254          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4255        }
4256        break;
4257
4258      case _CONNECT_B3_I|RESPONSE:
4259        break;
4260
4261      case _RESET_B3_R:
4262/*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4263        break;
4264
4265      case _DISCONNECT_B3_R:
4266        sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4267        break;
4268
4269      case _MANUFACTURER_R:
4270        break;
4271
4272      case PERM_LIST_REQ:
4273        if(rc!=OK)
4274        {
4275          Info = _WRONG_IDENTIFIER;
4276          sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4277          plci_remove(plci);
4278        }
4279        else
4280          sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4281        break;
4282
4283      default:
4284        break;
4285      }
4286      plci->command = 0;
4287    }
4288    else if (plci->internal_command)
4289    {
4290      switch(plci->internal_command)
4291      {
4292      case BLOCK_PLCI:
4293        return;
4294
4295      case GET_MWI_STATE:
4296        if(rc==OK) /* command supported, wait for indication */
4297        {
4298          return;
4299        }
4300        plci_remove(plci);
4301        break;
4302
4303        /* Get Supported Services */
4304      case GETSERV_REQ_PEND:
4305        if(rc==OK) /* command supported, wait for indication */
4306        {
4307          break;
4308        }
4309        PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4310        sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4311        plci_remove(plci);
4312        break;
4313
4314      case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4315      case INTERR_NUMBERS_REQ_PEND:
4316      case CF_START_PEND:                  /* Call Forwarding Start pending */
4317      case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4318      case CCBS_REQUEST_REQ_PEND:
4319      case CCBS_DEACTIVATE_REQ_PEND:
4320      case CCBS_INTERROGATE_REQ_PEND:
4321        switch(plci->internal_command)
4322        {
4323          case INTERR_DIVERSION_REQ_PEND:
4324            SSparms[1] = S_INTERROGATE_DIVERSION;
4325            break;
4326          case INTERR_NUMBERS_REQ_PEND:
4327            SSparms[1] = S_INTERROGATE_NUMBERS;
4328            break;
4329          case CF_START_PEND:
4330            SSparms[1] = S_CALL_FORWARDING_START;
4331            break;
4332          case CF_STOP_PEND:
4333            SSparms[1] = S_CALL_FORWARDING_STOP;
4334            break;
4335          case CCBS_REQUEST_REQ_PEND:
4336            SSparms[1] = S_CCBS_REQUEST;
4337            break;
4338          case CCBS_DEACTIVATE_REQ_PEND:
4339            SSparms[1] = S_CCBS_DEACTIVATE;
4340            break;
4341          case CCBS_INTERROGATE_REQ_PEND:
4342            SSparms[1] = S_CCBS_INTERROGATE;
4343            break;
4344        }
4345        if(global_req==ASSIGN)
4346        {
4347          dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4348          return;
4349        }
4350        if(!plci->appl) break;
4351        if(rc==ISDN_GUARD_REJ)
4352        {
4353          Info = _CAPI_GUARD_ERROR;
4354        }
4355        else if(rc!=OK)
4356        {
4357          Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4358        }
4359        sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4360              plci->number,"wws",Info,(word)3,SSparms);
4361        if(Info) plci_remove(plci);
4362        break;
4363
4364        /* 3pty conference pending */
4365      case PTY_REQ_PEND:
4366        if(!plci->relatedPTYPLCI) break;
4367        rplci = plci->relatedPTYPLCI;
4368        SSparms[1] = plci->ptyState;
4369        rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4370        if(rplci->tel) rId|=EXT_CONTROLLER;
4371        if(rc!=OK)
4372        {
4373          Info = 0x300E; /* not supported */
4374          plci->relatedPTYPLCI = NULL;
4375          plci->ptyState = 0;
4376        }
4377        sendf(rplci->appl,
4378              _FACILITY_R|CONFIRM,
4379              rId,
4380              plci->number,
4381              "wws",Info,(word)3,SSparms);
4382        break;
4383
4384        /* Explicit Call Transfer pending */
4385      case ECT_REQ_PEND:
4386        dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4387        if(!plci->relatedPTYPLCI) break;
4388        rplci = plci->relatedPTYPLCI;
4389        SSparms[1] = S_ECT;
4390        rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4391        if(rplci->tel) rId|=EXT_CONTROLLER;
4392        if(rc!=OK)
4393        {
4394          Info = 0x300E; /* not supported */
4395          plci->relatedPTYPLCI = NULL;
4396          plci->ptyState = 0;
4397        }
4398        sendf(rplci->appl,
4399              _FACILITY_R|CONFIRM,
4400              rId,
4401              plci->number,
4402              "wws",Info,(word)3,SSparms);
4403        break;
4404
4405      case _MANUFACTURER_R:
4406        dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4407        if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4408        {
4409          dbug(1,dprintf("No more IDs"));
4410          sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4411          plci_remove(plci);  /* after codec init, internal codec commands pending */
4412        }
4413        break;
4414
4415      case _CONNECT_R:
4416        dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4417        if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4418        {
4419          dbug(1,dprintf("No more IDs"));
4420          sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4421          plci_remove(plci);  /* after codec init, internal codec commands pending */
4422        }
4423        break;
4424
4425      case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4426        return;
4427
4428      case PERM_COD_CALL:
4429        dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4430        plci->internal_command = PERM_COD_CONN_PEND;
4431        return;
4432
4433      case PERM_COD_ASSIGN:
4434        dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4435        if(rc!=ASSIGN_OK) break;
4436        sig_req(plci,CALL_REQ,0);
4437        send_req(plci);
4438        plci->internal_command = PERM_COD_CALL;
4439        return;
4440
4441        /* Null Call Reference Request pending */
4442      case C_NCR_FAC_REQ:
4443        dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4444        if(global_req==ASSIGN)
4445        {
4446          if(rc==ASSIGN_OK)
4447          {
4448            return;
4449          }
4450          else
4451          {
4452            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4453            appl->NullCREnable = false;
4454            plci_remove(plci);
4455          }
4456        }
4457        else if(req==NCR_FACILITY)
4458        {
4459          if(rc==OK)
4460          {
4461            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4462          }
4463          else
4464          {
4465            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4466            appl->NullCREnable = false;
4467          }
4468          plci_remove(plci);
4469        }
4470        break;
4471
4472      case HOOK_ON_REQ:
4473        if(plci->channels)
4474        {
4475          if(a->ncci_state[ncci]==CONNECTED)
4476          {
4477            a->ncci_state[ncci] = OUTG_DIS_PENDING;
4478            cleanup_ncci_data (plci, ncci);
4479            nl_req_ncci(plci,N_DISC,(byte)ncci);
4480          }
4481          break;
4482        }
4483        break;
4484
4485      case HOOK_OFF_REQ:
4486        if (plci->State == INC_DIS_PENDING)
4487          break;
4488        sig_req(plci,CALL_REQ,0);
4489        send_req(plci);
4490        plci->State=OUTG_CON_PENDING;
4491        break;
4492
4493
4494      case MWI_ACTIVATE_REQ_PEND:
4495      case MWI_DEACTIVATE_REQ_PEND:
4496        if(global_req == ASSIGN && rc==ASSIGN_OK)
4497        {
4498          dbug(1,dprintf("MWI_REQ assigned"));
4499          return;
4500        }
4501        else if(rc!=OK)
4502        {                 
4503          if(rc==WRONG_IE)
4504          {
4505            Info = 0x2007; /* Illegal message parameter coding */
4506            dbug(1,dprintf("MWI_REQ invalid parameter"));
4507          }
4508          else
4509          {
4510            Info = 0x300B; /* not supported */                      
4511            dbug(1,dprintf("MWI_REQ not supported"));
4512          }
4513          /* 0x3010: Request not allowed in this state */
4514          PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4515                    
4516        }
4517        if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4518        {
4519          PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4520        }
4521        else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4522
4523        if(plci->cr_enquiry)
4524        {
4525          sendf(plci->appl,
4526                _FACILITY_R|CONFIRM,
4527                Id&0xf,
4528                plci->number,
4529                "wws",Info,(word)3,SSparms);
4530          if(rc!=OK) plci_remove(plci);
4531        }
4532        else
4533        {
4534          sendf(plci->appl,
4535                _FACILITY_R|CONFIRM,
4536                Id,
4537                plci->number,
4538                "wws",Info,(word)3,SSparms);
4539        }
4540        break;
4541
4542      case CONF_BEGIN_REQ_PEND:
4543      case CONF_ADD_REQ_PEND:
4544      case CONF_SPLIT_REQ_PEND:
4545      case CONF_DROP_REQ_PEND:
4546      case CONF_ISOLATE_REQ_PEND:
4547      case CONF_REATTACH_REQ_PEND:
4548        dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4549        if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4550        rplci = plci;
4551        rId = Id;
4552        switch(plci->internal_command)
4553        {
4554          case CONF_BEGIN_REQ_PEND:
4555            SSparms[1] = S_CONF_BEGIN;
4556            break;
4557          case CONF_ADD_REQ_PEND:
4558            SSparms[1] = S_CONF_ADD;
4559            rplci = plci->relatedPTYPLCI;
4560            rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4561            break;
4562          case CONF_SPLIT_REQ_PEND:
4563            SSparms[1] = S_CONF_SPLIT;
4564            break;
4565          case CONF_DROP_REQ_PEND:
4566            SSparms[1] = S_CONF_DROP;
4567            break;
4568          case CONF_ISOLATE_REQ_PEND:
4569            SSparms[1] = S_CONF_ISOLATE;
4570            break;
4571          case CONF_REATTACH_REQ_PEND:
4572            SSparms[1] = S_CONF_REATTACH;
4573            break;
4574        }
4575        
4576        if(rc!=OK)
4577        {
4578          Info = 0x300E; /* not supported */
4579          plci->relatedPTYPLCI = NULL;
4580          plci->ptyState = 0;
4581        }
4582        sendf(rplci->appl,
4583              _FACILITY_R|CONFIRM,
4584              rId,
4585              plci->number,
4586              "wws",Info,(word)3,SSparms);
4587        break;
4588
4589      case VSWITCH_REQ_PEND:
4590        if(rc!=OK)
4591        {
4592          if(plci->relatedPTYPLCI)
4593          {
4594            plci->relatedPTYPLCI->vswitchstate=0;
4595            plci->relatedPTYPLCI->vsprot=0;
4596            plci->relatedPTYPLCI->vsprotdialect=0;    
4597          }
4598          plci->vswitchstate=0;
4599          plci->vsprot=0;
4600          plci->vsprotdialect=0;
4601        }
4602        else
4603        {
4604          if(plci->relatedPTYPLCI &&
4605             plci->vswitchstate==1 &&
4606             plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4607            plci->vswitchstate=3;
4608        }
4609        break;
4610
4611  /* Call Deflection Request pending (SSCT) */
4612      case CD_REQ_PEND:
4613        SSparms[1] = S_CALL_DEFLECTION;
4614        if(rc!=OK)
4615        {
4616          Info = 0x300E; /* not supported */
4617          plci->appl->CDEnable = 0;
4618        }  
4619        sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4620          plci->number,"wws",Info,(word)3,SSparms);
4621        break;
4622
4623      case RTP_CONNECT_B3_REQ_COMMAND_2:
4624        if (rc == OK)
4625        {
4626          ncci = get_ncci (plci, ch, 0);
4627          Id = (Id & 0xffff) | (((dword) ncci) << 16);
4628          plci->channels++;
4629          a->ncci_state[ncci] = OUTG_CON_PENDING;
4630        }
4631
4632      default:
4633        if (plci->internal_command_queue[0])
4634        {
4635          (*(plci->internal_command_queue[0]))(Id, plci, rc);
4636          if (plci->internal_command)
4637            return;
4638        }
4639        break;
4640      }
4641      next_internal_command (Id, plci);
4642    }
4643  }
4644  else /* appl==0 */
4645  {
4646    Id = ((word)plci->Id<<8)|plci->adapter->Id;
4647    if(plci->tel) Id|=EXT_CONTROLLER;
4648
4649    switch(plci->internal_command)
4650    {
4651    case BLOCK_PLCI:
4652      return;
4653
4654    case START_L1_SIG_ASSIGN_PEND:
4655    case REM_L1_SIG_ASSIGN_PEND:
4656      if(global_req == ASSIGN)
4657      {
4658        break;
4659      }
4660      else
4661      {
4662        dbug(1,dprintf("***L1 Req rem PLCI"));
4663        plci->internal_command = 0;
4664        sig_req(plci,REMOVE,0);
4665        send_req(plci);
4666      }
4667      break;
4668
4669      /* Call Deflection Request pending, just no appl ptr assigned */
4670    case CD_REQ_PEND:
4671      SSparms[1] = S_CALL_DEFLECTION;
4672      if(rc!=OK)
4673      {
4674        Info = 0x300E; /* not supported */
4675      }
4676      for(i=0; i<max_appl; i++)
4677      {
4678        if(application[i].CDEnable)
4679        {
4680          if(!application[i].Id) application[i].CDEnable = 0;
4681          else
4682          {
4683            sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4684                  plci->number,"wws",Info,(word)3,SSparms);
4685            if(Info) application[i].CDEnable = 0;
4686          }
4687        }
4688      }
4689      plci->internal_command = 0;
4690      break;
4691
4692    case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4693      return;
4694
4695    case PERM_COD_CALL:
4696      plci->internal_command = PERM_COD_CONN_PEND;
4697      dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4698      return;
4699
4700    case PERM_COD_ASSIGN:
4701      dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4702      plci->internal_command = 0;
4703      if(rc!=ASSIGN_OK) break;
4704      plci->internal_command = PERM_COD_CALL;
4705      sig_req(plci,CALL_REQ,0);
4706      send_req(plci);
4707      return;
4708
4709    case LISTEN_SIG_ASSIGN_PEND:
4710      if(rc == ASSIGN_OK)
4711      {
4712        plci->internal_command = 0;
4713        dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4714        add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4715        sig_req(plci,INDICATE_REQ,0);
4716        send_req(plci);
4717      }
4718      else
4719      {
4720        dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4721        a->listen_active--;
4722        plci_remove(plci);
4723        plci->State = IDLE;
4724      }
4725      break;
4726
4727    case USELAW_REQ:
4728      if(global_req == ASSIGN)
4729      {
4730        if (rc==ASSIGN_OK)
4731      {
4732        sig_req(plci,LAW_REQ,0);
4733        send_req(plci);
4734        dbug(1,dprintf("Auto-Law assigned"));
4735        }
4736        else
4737        {
4738          dbug(1,dprintf("Auto-Law assign failed"));
4739          a->automatic_law = 3;
4740          plci->internal_command = 0;
4741          a->automatic_lawPLCI = NULL;
4742        }
4743        break;
4744      }
4745      else if(req == LAW_REQ && rc==OK)
4746      {
4747        dbug(1,dprintf("Auto-Law initiated"));
4748        a->automatic_law = 2;
4749        plci->internal_command = 0;
4750      }
4751      else
4752      {
4753        dbug(1,dprintf("Auto-Law not supported"));
4754        a->automatic_law = 3;
4755        plci->internal_command = 0;
4756        sig_req(plci,REMOVE,0);
4757        send_req(plci);
4758        a->automatic_lawPLCI = NULL;
4759      }
4760      break;
4761    }
4762    plci_remove_check(plci);
4763  }
4764}
4765
4766static void data_rc(PLCI *plci, byte ch)
4767{
4768  dword Id;
4769  DIVA_CAPI_ADAPTER   * a;
4770  NCCI   *ncci_ptr;
4771  DATA_B3_DESC   *data;
4772  word ncci;
4773
4774  if (plci->appl)
4775  {
4776    TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4777    a = plci->adapter;
4778    ncci = a->ch_ncci[ch];
4779    if (ncci && (a->ncci_plci[ncci] == plci->Id))
4780    {
4781      ncci_ptr = &(a->ncci[ncci]);
4782      dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4783      if (ncci_ptr->data_pending)
4784      {
4785        data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4786        if (!(data->Flags &4) && a->ncci_state[ncci])
4787        {
4788          Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4789          if(plci->tel) Id|=EXT_CONTROLLER;
4790          sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4791                "ww",data->Handle,0);
4792        }
4793        (ncci_ptr->data_out)++;
4794        if (ncci_ptr->data_out == MAX_DATA_B3)
4795          ncci_ptr->data_out = 0;
4796        (ncci_ptr->data_pending)--;
4797      }
4798    }
4799  }
4800}
4801
4802static void data_ack(PLCI *plci, byte ch)
4803{
4804  dword Id;
4805  DIVA_CAPI_ADAPTER   * a;
4806  NCCI   *ncci_ptr;
4807  word ncci;
4808
4809  a = plci->adapter;
4810  ncci = a->ch_ncci[ch];
4811  ncci_ptr = &(a->ncci[ncci]);
4812  if (ncci_ptr->data_ack_pending)
4813  {
4814    if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4815    {
4816      Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4817      if(plci->tel) Id|=EXT_CONTROLLER;
4818      sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4819            "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4820    }
4821    (ncci_ptr->data_ack_out)++;
4822    if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4823      ncci_ptr->data_ack_out = 0;
4824    (ncci_ptr->data_ack_pending)--;
4825  }
4826}
4827
4828static void sig_ind(PLCI *plci)
4829{
4830  dword x_Id;
4831  dword Id;
4832  dword rId;
4833  word Number = 0;
4834  word i;
4835  word cip;
4836  dword cip_mask;
4837  byte   *ie;
4838  DIVA_CAPI_ADAPTER   * a;
4839    API_PARSE saved_parms[MAX_MSG_PARMS+1];
4840#define MAXPARMSIDS 31
4841    byte   * parms[MAXPARMSIDS];
4842    byte   * add_i[4];
4843    byte   * multi_fac_parms[MAX_MULTI_IE];
4844    byte   * multi_pi_parms [MAX_MULTI_IE];
4845    byte   * multi_ssext_parms [MAX_MULTI_IE];
4846    byte   * multi_CiPN_parms [MAX_MULTI_IE];
4847
4848    byte   * multi_vswitch_parms [MAX_MULTI_IE];
4849
4850  byte ai_len;
4851    byte   *esc_chi = "";
4852    byte   *esc_law = "";
4853    byte   *pty_cai = "";
4854    byte   *esc_cr  = "";
4855    byte   *esc_profile = "";
4856
4857    byte facility[256];
4858  PLCI   * tplci = NULL;
4859  byte chi[] = "\x02\x18\x01";
4860  byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4861    byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4862  /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4863  /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4864  /* SMSG is situated at the end because its 0 (for compatibility reasons */
4865  /* (see Info_Mask Bit 4, first IE. then the message type)           */
4866    word parms_id[] =
4867         {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4868          UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4869          RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4870          CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4871          /* 14 FTY repl by ESC_CHI */
4872          /* 18 PI  repl by ESC_LAW */
4873         /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4874     word multi_fac_id[] = {1, FTY};
4875     word multi_pi_id[]  = {1, PI};
4876     word multi_CiPN_id[]  = {1, OAD};
4877     word multi_ssext_id[]  = {1, ESC_SSEXT};
4878
4879     word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4880
4881  byte   * cau;
4882  word ncci;
4883    byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4884    byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4885    byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4886    byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4887  byte force_mt_info = false;
4888  byte dir;
4889  dword d;
4890  word w;
4891
4892  a = plci->adapter;
4893  Id = ((word)plci->Id<<8)|a->Id;
4894  PUT_WORD(&SS_Ind[4],0x0000);
4895
4896  if (plci->sig_remove_id)
4897  {
4898    plci->Sig.RNR = 2; /* discard */
4899    dbug(1,dprintf("SIG discard while remove pending"));
4900    return;
4901  }
4902  if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4903  dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4904    Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4905  if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4906  {
4907    plci->Sig.RNR = 1;
4908    return;
4909  }
4910  if(plci->Sig.Ind==HANGUP && plci->channels)
4911  {
4912    plci->Sig.RNR = 1;
4913    plci->hangup_flow_ctrl_timer++;
4914    /* recover the network layer after timeout */
4915    if(plci->hangup_flow_ctrl_timer==100)
4916    {
4917      dbug(1,dprintf("Exceptional disc"));
4918      plci->Sig.RNR = 0;
4919      plci->hangup_flow_ctrl_timer = 0;
4920      for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4921      {
4922        if (a->ncci_plci[ncci] == plci->Id)
4923        {
4924          cleanup_ncci_data (plci, ncci);
4925          if(plci->channels)plci->channels--;
4926          if (plci->appl)
4927            sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4928        }
4929      }
4930      if (plci->appl)
4931        sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4932      plci_remove(plci);
4933      plci->State=IDLE;
4934    }
4935    return;
4936  }
4937
4938  /* do first parse the info with no OAD in, because OAD will be converted */
4939  /* first the multiple facility IE, then mult. progress ind.              */
4940  /* then the parameters for the info_ind + conn_ind                       */
4941  IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4942  IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4943  IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4944
4945  IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4946
4947  IndParse(plci,parms_id,parms,0);
4948  IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4949  esc_chi  = parms[14];
4950  esc_law  = parms[18];
4951  pty_cai  = parms[24];
4952  esc_cr   = parms[25];
4953  esc_profile = parms[27];
4954  if(esc_cr[0] && plci)
4955  {
4956    if(plci->cr_enquiry && plci->appl)
4957    {
4958      plci->cr_enquiry = false;
4959      /* d = MANU_ID            */
4960      /* w = m_command          */
4961      /* b = total length       */
4962      /* b = indication type    */
4963      /* b = length of all IEs  */
4964      /* b = IE1                */
4965      /* S = IE1 length + cont. */
4966      /* b = IE2                */
4967      /* S = IE2 length + cont. */
4968      sendf(plci->appl,
4969        _MANUFACTURER_I,
4970        Id,
4971        0,
4972        "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4973        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);
4974    }
4975  }
4976  /* create the additional info structure                                  */
4977  add_i[1] = parms[15]; /* KEY of additional info */
4978  add_i[2] = parms[11]; /* UUI of additional info */
4979  ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4980
4981  /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4982  /* indication returns by the card if requested by the function           */
4983  /* AutomaticLaw() after driver init                                      */
4984  if (a->automatic_law<4)
4985  {
4986    if(esc_law[0]){
4987      if(esc_law[2]){
4988        dbug(0,dprintf("u-Law selected"));
4989        a->u_law = 1;
4990      }
4991      else {
4992        dbug(0,dprintf("a-Law selected"));
4993        a->u_law = 0;
4994      }
4995      a->automatic_law = 4;
4996      if(plci==a->automatic_lawPLCI) {
4997        plci->internal_command = 0;
4998        sig_req(plci,REMOVE,0);
4999        send_req(plci);
5000        a->automatic_lawPLCI = NULL;
5001      }
5002    }
5003    if (esc_profile[0])
5004    {
5005      dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5006        UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
5007        GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
5008        GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
5009
5010      a->profile.Global_Options &= 0x000000ffL;
5011      a->profile.B1_Protocols &= 0x000003ffL;
5012      a->profile.B2_Protocols &= 0x00001fdfL;
5013      a->profile.B3_Protocols &= 0x000000b7L;
5014
5015      a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
5016        GL_BCHANNEL_OPERATION_SUPPORTED;
5017      a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
5018      a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
5019      a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5020      a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5021      a->man_profile.private_options = 0;
5022
5023      if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5024      {
5025        a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5026        a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5027      }
5028
5029
5030      if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5031        a->man_profile.private_options |= 1L << PRIVATE_RTP;
5032      a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5033      a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5034
5035
5036      if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5037        a->man_profile.private_options |= 1L << PRIVATE_T38;
5038
5039
5040      if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5041        a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5042
5043
5044      if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5045        a->man_profile.private_options |= 1L << PRIVATE_V18;
5046
5047
5048      if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5049        a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5050
5051
5052      if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5053        a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5054
5055
5056      if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5057        a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5058
5059
5060      if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5061        a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5062
5063
5064      if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5065        a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5066
5067    }
5068    else
5069    {
5070      a->profile.Global_Options &= 0x0000007fL;
5071      a->profile.B1_Protocols &= 0x000003dfL;
5072      a->profile.B2_Protocols &= 0x00001adfL;
5073      a->profile.B3_Protocols &= 0x000000b7L;
5074      a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5075    }
5076    if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5077      MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5078    {
5079      a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5080    }
5081    a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5082    dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5083      UnMapController (a->Id), a->profile.Global_Options,
5084      a->profile.B1_Protocols, a->profile.B2_Protocols,
5085      a->profile.B3_Protocols, a->manufacturer_features));
5086  }
5087  /* codec plci for the handset/hook state support is just an internal id  */
5088  if(plci!=a->AdvCodecPLCI)
5089  {
5090    force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5091    force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5092    SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5093    SendInfo(plci,Id, parms, force_mt_info);
5094
5095    VSwitchReqInd(plci,Id,multi_vswitch_parms);
5096
5097  }
5098
5099  /* switch the codec to the b-channel                                     */
5100  if(esc_chi[0] && plci && !plci->SuppState){
5101    plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5102    mixer_set_bchannel_id_esc (plci, plci->b_channel);
5103    dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5104    if(plci->tel==ADV_VOICE && plci->appl) {
5105      SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5106    }
5107  }
5108
5109  if(plci->appl) Number = plci->appl->Number++;
5110
5111  switch(plci->Sig.Ind) {
5112  /* Response to Get_Supported_Services request */
5113  case S_SUPPORTED:
5114    dbug(1,dprintf("S_Supported"));
5115    if(!plci->appl) break;
5116    if(pty_cai[0]==4)
5117    {
5118      PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5119    }
5120    else
5121    {
5122      PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5123    }
5124    PUT_WORD (&CF_Ind[1], 0);
5125    PUT_WORD (&CF_Ind[4], 0);
5126    sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5127    plci_remove(plci);
5128    break;
5129                    
5130  /* Supplementary Service rejected */
5131  case S_SERVICE_REJ:
5132    dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5133    if(!pty_cai[0]) break;
5134    switch (pty_cai[5])
5135    {
5136    case ECT_EXECUTE:
5137    case THREE_PTY_END:
5138    case THREE_PTY_BEGIN:
5139      if(!plci->relatedPTYPLCI) break;
5140      tplci = plci->relatedPTYPLCI;
5141      rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5142      if(tplci->tel) rId|=EXT_CONTROLLER;
5143      if(pty_cai[5]==ECT_EXECUTE)
5144      {
5145        PUT_WORD(&SS_Ind[1],S_ECT);
5146
5147        plci->vswitchstate=0;
5148        plci->relatedPTYPLCI->vswitchstate=0;
5149
5150      }
5151      else
5152      {
5153        PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5154      }
5155      if(pty_cai[2]!=0xff)
5156      {
5157        PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5158      }
5159      else
5160      {
5161        PUT_WORD(&SS_Ind[4],0x300E);
5162      }
5163      plci->relatedPTYPLCI = NULL;
5164      plci->ptyState = 0;
5165      sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5166      break;
5167
5168    case CALL_DEFLECTION:
5169      if(pty_cai[2]!=0xff)
5170      {
5171        PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5172      }
5173      else
5174      {
5175        PUT_WORD(&SS_Ind[4],0x300E);
5176      }
5177      PUT_WORD(&SS_Ind[1],pty_cai[5]);
5178      for(i=0; i<max_appl; i++)
5179      {
5180        if(application[i].CDEnable)
5181        {
5182          if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5183          application[i].CDEnable = false;
5184        }
5185      }
5186      break;
5187
5188    case DEACTIVATION_DIVERSION:
5189    case ACTIVATION_DIVERSION:
5190    case DIVERSION_INTERROGATE_CFU:
5191    case DIVERSION_INTERROGATE_CFB:
5192    case DIVERSION_INTERROGATE_CFNR:
5193    case DIVERSION_INTERROGATE_NUM:
5194    case CCBS_REQUEST:
5195    case CCBS_DEACTIVATE:
5196    case CCBS_INTERROGATE:
5197      if(!plci->appl) break;
5198      if(pty_cai[2]!=0xff)
5199      {
5200        PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5201      }
5202      else
5203      {
5204        PUT_WORD(&Interr_Err_Ind[4],0x300E);
5205      }
5206      switch (pty_cai[5])
5207      {
5208        case DEACTIVATION_DIVERSION:
5209          dbug(1,dprintf("Deact_Div"));
5210          Interr_Err_Ind[0]=0x9;
5211          Interr_Err_Ind[3]=0x6;
5212          PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5213          break;
5214        case ACTIVATION_DIVERSION:
5215          dbug(1,dprintf("Act_Div"));
5216          Interr_Err_Ind[0]=0x9;
5217          Interr_Err_Ind[3]=0x6;
5218          PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5219          break;
5220        case DIVERSION_INTERROGATE_CFU:
5221        case DIVERSION_INTERROGATE_CFB:
5222        case DIVERSION_INTERROGATE_CFNR:
5223          dbug(1,dprintf("Interr_Div"));
5224          Interr_Err_Ind[0]=0xa;
5225          Interr_Err_Ind[3]=0x7;
5226          PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5227          break;
5228        case DIVERSION_INTERROGATE_NUM:
5229          dbug(1,dprintf("Interr_Num"));
5230          Interr_Err_Ind[0]=0xa;
5231          Interr_Err_Ind[3]=0x7;
5232          PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5233          break;
5234        case CCBS_REQUEST:
5235          dbug(1,dprintf("CCBS Request"));
5236          Interr_Err_Ind[0]=0xd;
5237          Interr_Err_Ind[3]=0xa;
5238          PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5239          break;
5240        case CCBS_DEACTIVATE:
5241          dbug(1,dprintf("CCBS Deactivate"));
5242          Interr_Err_Ind[0]=0x9;
5243          Interr_Err_Ind[3]=0x6;
5244          PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5245          break;
5246        case CCBS_INTERROGATE:
5247          dbug(1,dprintf("CCBS Interrogate"));
5248          Interr_Err_Ind[0]=0xb;
5249          Interr_Err_Ind[3]=0x8;
5250          PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5251          break;
5252      }
5253      PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5254      sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5255      plci_remove(plci);
5256      break;
5257    case ACTIVATION_MWI:      
5258    case DEACTIVATION_MWI:
5259      if(pty_cai[5]==ACTIVATION_MWI)
5260      {
5261        PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5262      }
5263      else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5264      
5265      if(pty_cai[2]!=0xff)
5266      {
5267        PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5268      }
5269      else
5270      {
5271        PUT_WORD(&SS_Ind[4],0x300E);
5272      }
5273
5274      if(plci->cr_enquiry)
5275      {
5276        sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5277        plci_remove(plci);
5278      }
5279      else
5280      {
5281        sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5282      }
5283      break;
5284    case CONF_ADD: /* ERROR */
5285    case CONF_BEGIN:
5286    case CONF_DROP:
5287    case CONF_ISOLATE:
5288    case CONF_REATTACH:
5289      CONF_Ind[0]=9;
5290      CONF_Ind[3]=6;   
5291      switch(pty_cai[5])
5292      {
5293      case CONF_BEGIN:
5294          PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5295          plci->ptyState = 0;
5296          break;
5297      case CONF_DROP:
5298          CONF_Ind[0]=5;
5299          CONF_Ind[3]=2;
5300          PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5301          plci->ptyState = CONNECTED;
5302          break;
5303      case CONF_ISOLATE:
5304          CONF_Ind[0]=5;
5305          CONF_Ind[3]=2;
5306          PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5307          plci->ptyState = CONNECTED;
5308          break;
5309      case CONF_REATTACH:
5310          CONF_Ind[0]=5;
5311          CONF_Ind[3]=2;
5312          PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5313          plci->ptyState = CONNECTED;
5314          break;
5315      case CONF_ADD:
5316          PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5317          plci->relatedPTYPLCI = NULL;
5318          tplci=plci->relatedPTYPLCI;
5319          if(tplci) tplci->ptyState = CONNECTED;
5320          plci->ptyState = CONNECTED;
5321          break;
5322      }
5323          
5324      if(pty_cai[2]!=0xff)
5325      {
5326        PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5327      }
5328      else
5329      {
5330        PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5331                                            within the required time */
5332      }
5333
5334      PUT_DWORD(&CONF_Ind[6],0x0);
5335      sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5336      break;
5337    }
5338    break;
5339
5340  /* Supplementary Service indicates success */
5341  case S_SERVICE:
5342    dbug(1,dprintf("Service_Ind"));
5343    PUT_WORD (&CF_Ind[4], 0);
5344    switch (pty_cai[5])
5345    {
5346    case THREE_PTY_END:
5347    case THREE_PTY_BEGIN:
5348    case ECT_EXECUTE:
5349      if(!plci->relatedPTYPLCI) break;
5350      tplci = plci->relatedPTYPLCI;
5351      rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5352      if(tplci->tel) rId|=EXT_CONTROLLER;
5353      if(pty_cai[5]==ECT_EXECUTE)
5354      {
5355        PUT_WORD(&SS_Ind[1],S_ECT);
5356
5357        if(plci->vswitchstate!=3)
5358        {
5359
5360        plci->ptyState = IDLE;
5361        plci->relatedPTYPLCI = NULL;
5362        plci->ptyState = 0;
5363
5364        }
5365
5366        dbug(1,dprintf("ECT OK"));
5367        sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5368
5369
5370
5371      }
5372      else
5373      {
5374        switch (plci->ptyState)
5375        {
5376        case S_3PTY_BEGIN:
5377          plci->ptyState = CONNECTED;
5378          dbug(1,dprintf("3PTY ON"));
5379          break;
5380
5381        case S_3PTY_END:
5382          plci->ptyState = IDLE;
5383          plci->relatedPTYPLCI = NULL;
5384          plci->ptyState = 0;
5385          dbug(1,dprintf("3PTY OFF"));
5386          break;
5387        }
5388        PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5389        sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5390      }
5391      break;
5392
5393    case CALL_DEFLECTION:
5394      PUT_WORD(&SS_Ind[1],pty_cai[5]);
5395      for(i=0; i<max_appl; i++)
5396      {
5397        if(application[i].CDEnable)
5398        {
5399          if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5400          application[i].CDEnable = false;
5401        }
5402      }
5403      break;
5404
5405    case DEACTIVATION_DIVERSION:
5406    case ACTIVATION_DIVERSION:
5407      if(!plci->appl) break;
5408      PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5409      PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5410      sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5411      plci_remove(plci);
5412      break;
5413
5414    case DIVERSION_INTERROGATE_CFU:
5415    case DIVERSION_INTERROGATE_CFB:
5416    case DIVERSION_INTERROGATE_CFNR:
5417    case DIVERSION_INTERROGATE_NUM:
5418    case CCBS_REQUEST:
5419    case CCBS_DEACTIVATE:
5420    case CCBS_INTERROGATE:
5421      if(!plci->appl) break;
5422      switch (pty_cai[5])
5423      {
5424        case DIVERSION_INTERROGATE_CFU:
5425        case DIVERSION_INTERROGATE_CFB:
5426        case DIVERSION_INTERROGATE_CFNR:
5427          dbug(1,dprintf("Interr_Div"));
5428          PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5429          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5430          break;
5431        case DIVERSION_INTERROGATE_NUM:
5432          dbug(1,dprintf("Interr_Num"));
5433          PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5434          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5435          break;
5436        case CCBS_REQUEST:
5437          dbug(1,dprintf("CCBS Request"));
5438          PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5439          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5440          break;
5441        case CCBS_DEACTIVATE:
5442          dbug(1,dprintf("CCBS Deactivate"));
5443          PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5444          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5445          break;
5446        case CCBS_INTERROGATE:
5447          dbug(1,dprintf("CCBS Interrogate"));
5448          PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5449          pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5450          break;
5451      }
5452      PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5453      PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5454      sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5455      plci_remove(plci);
5456      break;
5457
5458    case ACTIVATION_MWI:
5459    case DEACTIVATION_MWI:
5460      if(pty_cai[5]==ACTIVATION_MWI)
5461      {
5462        PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5463      }
5464      else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5465      if(plci->cr_enquiry)
5466      {
5467        sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5468        plci_remove(plci);
5469      }
5470      else
5471      {
5472        sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5473      }
5474      break;
5475    case MWI_INDICATION:
5476      if(pty_cai[0]>=0x12)
5477      {
5478        PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5479        pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5480        pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5481        if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5482        {
5483          if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5484          {
5485            sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5486            plci_remove(plci);
5487            return;
5488          }
5489          else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5490          pty_cai[0]=0;
5491        }
5492        else
5493        {
5494          for(i=0; i<max_appl; i++)
5495          {                     
5496            if(a->Notification_Mask[i]&SMASK_MWI)
5497            {
5498              sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5499              pty_cai[0]=0;
5500            }
5501          }
5502        }
5503
5504        if(!pty_cai[0])
5505        { /* acknowledge */
5506          facility[2]= 0; /* returncode */
5507        }
5508        else facility[2]= 0xff;
5509      }
5510      else
5511      {
5512        /* reject */
5513        facility[2]= 0xff; /* returncode */
5514      }
5515      facility[0]= 2;
5516      facility[1]= MWI_RESPONSE; /* Function */
5517      add_p(plci,CAI,facility);
5518      add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5519      sig_req(plci,S_SERVICE,0);
5520      send_req(plci);
5521      plci->command = 0;
5522      next_internal_command (Id, plci);
5523      break;
5524    case CONF_ADD: /* OK */
5525    case CONF_BEGIN:
5526    case CONF_DROP:
5527    case CONF_ISOLATE:
5528    case CONF_REATTACH:
5529    case CONF_PARTYDISC:
5530      CONF_Ind[0]=9;
5531      CONF_Ind[3]=6;
5532      switch(pty_cai[5])
5533      {
5534      case CONF_BEGIN:
5535          PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5536          if(pty_cai[0]==6)
5537          {
5538              d=pty_cai[6];
5539              PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5540          }
5541          else
5542          {
5543              PUT_DWORD(&CONF_Ind[6],0x0);
5544          }
5545          break;
5546      case CONF_ISOLATE:
5547          PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5548          CONF_Ind[0]=5;
5549          CONF_Ind[3]=2;
5550          break;
5551      case CONF_REATTACH:
5552          PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5553          CONF_Ind[0]=5;
5554          CONF_Ind[3]=2;
5555          break;
5556      case CONF_DROP:
5557          PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5558          CONF_Ind[0]=5;
5559          CONF_Ind[3]=2;
5560          break;
5561      case CONF_ADD:
5562          PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5563          d=pty_cai[6];
5564          PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5565          tplci=plci->relatedPTYPLCI;
5566          if(tplci) tplci->ptyState = CONNECTED;
5567          break;
5568      case CONF_PARTYDISC:
5569          CONF_Ind[0]=7;
5570          CONF_Ind[3]=4;          
5571          PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5572          d=pty_cai[6];
5573          PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5574          break;
5575      }
5576      plci->ptyState = CONNECTED;
5577      sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5578      break;
5579    case CCBS_INFO_RETAIN:
5580    case CCBS_ERASECALLLINKAGEID:
5581    case CCBS_STOP_ALERTING:
5582      CONF_Ind[0]=5;
5583      CONF_Ind[3]=2;
5584      switch(pty_cai[5])
5585      {
5586      case CCBS_INFO_RETAIN:
5587        PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5588        break;
5589      case CCBS_STOP_ALERTING:
5590        PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5591    break;
5592      case CCBS_ERASECALLLINKAGEID:
5593        PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5594        CONF_Ind[0]=7;
5595        CONF_Ind[3]=4;
5596        CONF_Ind[6]=0;
5597        CONF_Ind[7]=0;
5598        break;
5599      }      
5600      w=pty_cai[6];
5601      PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5602
5603      if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5604      {
5605        sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5606      }
5607      else
5608      {
5609        for(i=0; i<max_appl; i++)
5610            if(a->Notification_Mask[i]&SMASK_CCBS)
5611                sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5612      }
5613      break;
5614    }
5615    break;
5616  case CALL_HOLD_REJ:
5617    cau = parms[7];
5618    if(cau)
5619    {
5620      i = _L3_CAUSE | cau[2];
5621      if(cau[2]==0) i = 0x3603;
5622    }
5623    else
5624    {
5625      i = 0x3603;
5626    }
5627    PUT_WORD(&SS_Ind[1],S_HOLD);
5628    PUT_WORD(&SS_Ind[4],i);
5629    if(plci->SuppState == HOLD_REQUEST)
5630    {
5631      plci->SuppState = IDLE;
5632      sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5633    }
5634    break;
5635
5636  case CALL_HOLD_ACK:
5637    if(plci->SuppState == HOLD_REQUEST)
5638    {
5639      plci->SuppState = CALL_HELD;
5640      CodecIdCheck(a, plci);
5641      start_internal_command (Id, plci, hold_save_command);
5642    }
5643    break;
5644
5645  case CALL_RETRIEVE_REJ:
5646    cau = parms[7];
5647    if(cau)
5648    {
5649      i = _L3_CAUSE | cau[2];
5650      if(cau[2]==0) i = 0x3603;
5651    }
5652    else
5653    {
5654      i = 0x3603;
5655    }
5656    PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5657    PUT_WORD(&SS_Ind[4],i);
5658    if(plci->SuppState == RETRIEVE_REQUEST)
5659    {
5660      plci->SuppState = CALL_HELD;
5661      CodecIdCheck(a, plci);
5662      sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5663    }
5664    break;
5665
5666  case CALL_RETRIEVE_ACK:
5667    PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5668    if(plci->SuppState == RETRIEVE_REQUEST)
5669    {
5670      plci->SuppState = IDLE;
5671      plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5672      plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5673      if(plci->tel)
5674      {
5675        mixer_set_bchannel_id_esc (plci, plci->b_channel);
5676        dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5677        SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5678        if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5679        {
5680          dbug(1,dprintf("Get B-ch"));
5681          start_internal_command (Id, plci, retrieve_restore_command);
5682        }
5683        else
5684          sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5685      }
5686      else
5687        start_internal_command (Id, plci, retrieve_restore_command);
5688    }
5689    break;
5690
5691  case INDICATE_IND:
5692    if(plci->State != LISTENING) {
5693      sig_req(plci,HANGUP,0);
5694      send_req(plci);
5695      break;
5696    }
5697    cip = find_cip(a,parms[4],parms[6]);
5698    cip_mask = 1L<<cip;
5699    dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5700    clear_c_ind_mask (plci);
5701    if (!remove_started && !a->adapter_disabled)
5702    {
5703      set_c_ind_mask_bit (plci, MAX_APPL);
5704      group_optimization(a, plci);
5705      for(i=0; i<max_appl; i++) {
5706        if(application[i].Id
5707        && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5708        && CPN_filter_ok(parms[0],a,i)
5709        && test_group_ind_mask_bit (plci, i) ) {
5710          dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5711          set_c_ind_mask_bit (plci, i);
5712          dump_c_ind_mask (plci);
5713          plci->State = INC_CON_PENDING;
5714          plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5715            CALL_DIR_IN | CALL_DIR_ANSWER;
5716          if(esc_chi[0]) {
5717            plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5718            mixer_set_bchannel_id_esc (plci, plci->b_channel);
5719          }
5720          /* if a listen on the ext controller is done, check if hook states */
5721          /* are supported or if just a on board codec must be activated     */
5722          if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5723            if(a->profile.Global_Options & HANDSET)
5724              plci->tel = ADV_VOICE;
5725            else if(a->profile.Global_Options & ON_BOARD_CODEC)
5726              plci->tel = CODEC;
5727            if(plci->tel) Id|=EXT_CONTROLLER;
5728            a->codec_listen[i] = plci;
5729          }
5730
5731          sendf(&application[i],_CONNECT_I,Id,0,
5732                "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5733                             parms[0],    /* CalledPartyNumber   */
5734                             multi_CiPN_parms[0],    /* CallingPartyNumber  */
5735                             parms[2],    /* CalledPartySubad    */
5736                             parms[3],    /* CallingPartySubad   */
5737                             parms[4],    /* BearerCapability    */
5738                             parms[5],    /* LowLC               */
5739                             parms[6],    /* HighLC              */
5740                             ai_len,      /* nested struct add_i */
5741                             add_i[0],    /* B channel info    */
5742                             add_i[1],    /* keypad facility   */
5743                             add_i[2],    /* user user data    */
5744                             add_i[3],    /* nested facility   */
5745                             multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5746                             );
5747          SendSSExtInd(&application[i],
5748                        plci,
5749                        Id,
5750                        multi_ssext_parms);
5751          SendSetupInfo(&application[i],
5752                        plci,
5753                        Id,
5754                        parms,
5755                        SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5756        }
5757      }
5758      clear_c_ind_mask_bit (plci, MAX_APPL);
5759      dump_c_ind_mask (plci);
5760    }
5761    if(c_ind_mask_empty (plci)) {
5762      sig_req(plci,HANGUP,0);
5763      send_req(plci);
5764      plci->State = IDLE;
5765    }
5766    plci->notifiedcall = 0;
5767    a->listen_active--;
5768    listen_check(a);
5769    break;
5770
5771  case CALL_PEND_NOTIFY:
5772    plci->notifiedcall = 1;
5773    listen_check(a);
5774    break;
5775
5776  case CALL_IND:
5777  case CALL_CON:
5778    if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5779    {
5780      if(plci->internal_command==PERM_COD_CONN_PEND)
5781      {
5782        if(plci->State==ADVANCED_VOICE_NOSIG)
5783        {
5784          dbug(1,dprintf("***Codec OK"));
5785          if(a->AdvSignalPLCI)
5786          {
5787            tplci = a->AdvSignalPLCI;
5788            if(tplci->spoofed_msg)
5789            {
5790              dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5791              tplci->command = 0;
5792              tplci->internal_command = 0;
5793              x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5794              switch (tplci->spoofed_msg)
5795              {
5796              case CALL_RES:
5797                tplci->command = _CONNECT_I|RESPONSE;
5798                api_load_msg (&tplci->saved_msg, saved_parms);
5799                add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5800                if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5801                {
5802                  /* early B3 connect (CIP mask bit 9) no release after a disc */
5803                  add_p(tplci,LLI,"\x01\x01");
5804                }
5805                add_s(tplci, CONN_NR, &saved_parms[2]);
5806                add_s(tplci, LLC, &saved_parms[4]);
5807                add_ai(tplci, &saved_parms[5]);
5808                tplci->State = INC_CON_ACCEPT;
5809                sig_req(tplci, CALL_RES,0);
5810                send_req(tplci);
5811                break;
5812
5813              case AWAITING_SELECT_B:
5814                dbug(1,dprintf("Select_B continue"));
5815                start_internal_command (x_Id, tplci, select_b_command);
5816                break;
5817
5818              case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5819                if(!tplci->Sig.Id)
5820                {
5821                  dbug(1,dprintf("No SigID!"));
5822                  sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5823                  plci_remove(tplci);
5824                  break;
5825                }
5826                tplci->command = _MANUFACTURER_R;
5827                api_load_msg (&tplci->saved_msg, saved_parms);
5828                dir = saved_parms[2].info[0];
5829                if(dir==1) {
5830                  sig_req(tplci,CALL_REQ,0);
5831                }
5832                else if(!dir){
5833                  sig_req(tplci,LISTEN_REQ,0);
5834                }
5835                send_req(tplci);
5836                sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5837                break;
5838
5839              case (CALL_REQ|AWAITING_MANUF_CON):
5840                sig_req(tplci,CALL_REQ,0);
5841                send_req(tplci);
5842                break;
5843
5844              case CALL_REQ:
5845                if(!tplci->Sig.Id)
5846                {
5847                  dbug(1,dprintf("No SigID!"));
5848                  sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5849                  plci_remove(tplci);
5850                  break;
5851                }
5852                tplci->command = _CONNECT_R;
5853                api_load_msg (&tplci->saved_msg, saved_parms);
5854                add_s(tplci,CPN,&saved_parms[1]);
5855                add_s(tplci,DSA,&saved_parms[3]);
5856                add_ai(tplci,&saved_parms[9]);
5857                sig_req(tplci,CALL_REQ,0);
5858                send_req(tplci);
5859                break;
5860
5861              case CALL_RETRIEVE:
5862                tplci->command = C_RETRIEVE_REQ;
5863                sig_req(tplci,CALL_RETRIEVE,0);
5864                send_req(tplci);
5865                break;
5866              }
5867              tplci->spoofed_msg = 0;
5868              if (tplci->internal_command == 0)
5869                next_internal_command (x_Id, tplci);
5870            }
5871          }
5872          next_internal_command (Id, plci);
5873          break;
5874        }
5875        dbug(1,dprintf("***Codec Hook Init Req"));
5876        plci->internal_command = PERM_COD_HOOK;
5877        add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5878        sig_req(plci,TEL_CTRL,0);
5879        send_req(plci);
5880      }
5881    }
5882    else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5883    && plci->State!=INC_ACT_PENDING)
5884    {
5885      mixer_set_bchannel_id_esc (plci, plci->b_channel);
5886      if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5887      {
5888        chi[2] = plci->b_channel;
5889        SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5890      }
5891      sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5892      plci->State = INC_ACT_PENDING;
5893    }
5894    break;
5895
5896  case TEL_CTRL:
5897    Number = 0;
5898    ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5899    if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5900      switch (ie[1]&0x91) {
5901        case 0x80:   /* hook off */
5902        case 0x81:
5903          if(plci->internal_command==PERM_COD_HOOK)
5904          {
5905            dbug(1,dprintf("init:hook_off"));
5906            plci->hook_state = ie[1];
5907            next_internal_command (Id, plci);
5908            break;
5909          }
5910          else /* ignore doubled hook indications */
5911          {
5912            if( ((plci->hook_state)&0xf0)==0x80)
5913            {
5914              dbug(1,dprintf("ignore hook"));
5915              break;
5916            }
5917            plci->hook_state = ie[1]&0x91;
5918          }
5919          /* check for incoming call pending */
5920          /* and signal '+'.Appl must decide */
5921          /* with connect_res if call must   */
5922          /* accepted or not                 */
5923          for(i=0, tplci=NULL;i<max_appl;i++){
5924            if(a->codec_listen[i]
5925            && (a->codec_listen[i]->State==INC_CON_PENDING
5926              ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5927              tplci = a->codec_listen[i];
5928              tplci->appl = &application[i];
5929            }
5930          }
5931          /* no incoming call, do outgoing call */
5932          /* and signal '+' if outg. setup   */
5933          if(!a->AdvSignalPLCI && !tplci){
5934            if((i=get_plci(a))) {
5935              a->AdvSignalPLCI = &a->plci[i-1];
5936              tplci = a->AdvSignalPLCI;
5937              tplci->tel  = ADV_VOICE;
5938              PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5939              if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5940                /* early B3 connect (CIP mask bit 9) no release after a disc */
5941                add_p(tplci,LLI,"\x01\x01");
5942              }
5943              add_p(tplci, CAI, voice_cai);
5944              add_p(tplci, OAD, a->TelOAD);
5945              add_p(tplci, OSA, a->TelOSA);
5946              add_p(tplci,SHIFT|6,NULL);
5947              add_p(tplci,SIN,"\x02\x01\x00");
5948              add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5949              sig_req(tplci,ASSIGN,DSIG_ID);
5950              a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5951              a->AdvSignalPLCI->command = 0;
5952              tplci->appl = a->AdvSignalAppl;
5953              tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5954              send_req(tplci);
5955            }
5956
5957          }
5958
5959          if(!tplci) break;
5960          Id = ((word)tplci->Id<<8)|a->Id;
5961          Id|=EXT_CONTROLLER;
5962          sendf(tplci->appl,
5963                _FACILITY_I,
5964                Id,
5965                0,
5966                "ws", (word)0, "\x01+");
5967          break;
5968
5969        case 0x90:   /* hook on  */
5970        case 0x91:
5971          if(plci->internal_command==PERM_COD_HOOK)
5972          {
5973            dbug(1,dprintf("init:hook_on"));
5974            plci->hook_state = ie[1]&0x91;
5975            next_internal_command (Id, plci);
5976            break;
5977          }
5978          else /* ignore doubled hook indications */
5979          {
5980            if( ((plci->hook_state)&0xf0)==0x90) break;
5981            plci->hook_state = ie[1]&0x91;
5982          }
5983          /* hangup the adv. voice call and signal '-' to the appl */
5984          if(a->AdvSignalPLCI) {
5985            Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5986            if(plci->tel) Id|=EXT_CONTROLLER;
5987            sendf(a->AdvSignalAppl,
5988                  _FACILITY_I,
5989                  Id,
5990                  0,
5991                  "ws", (word)0, "\x01-");
5992            a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5993            a->AdvSignalPLCI->command = 0;
5994            sig_req(a->AdvSignalPLCI,HANGUP,0);
5995            send_req(a->AdvSignalPLCI);
5996          }
5997          break;
5998      }
5999    }
6000    break;
6001
6002  case RESUME:
6003    clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
6004    PUT_WORD(&resume_cau[4],GOOD);
6005    sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6006    break;
6007
6008  case SUSPEND:
6009    clear_c_ind_mask (plci);
6010
6011    if (plci->NL.Id && !plci->nl_remove_id) {
6012      mixer_remove (plci);
6013      nl_req_ncci(plci,REMOVE,0);
6014    }
6015    if (!plci->sig_remove_id) {
6016      plci->internal_command = 0;
6017      sig_req(plci,REMOVE,0);
6018    }
6019    send_req(plci);
6020    if(!plci->channels) {
6021      sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6022      sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6023    }
6024    break;
6025
6026  case SUSPEND_REJ:
6027    break;
6028
6029  case HANGUP:
6030    plci->hangup_flow_ctrl_timer=0;
6031    if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6032    cau = parms[7];
6033    if(cau) {
6034      i = _L3_CAUSE | cau[2];
6035      if(cau[2]==0) i = 0;
6036      else if(cau[2]==8) i = _L1_ERROR;
6037      else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6038      else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6039    }
6040    else {
6041      i = _L3_ERROR;
6042    }
6043
6044    if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6045    {
6046      for(i=0; i<max_appl; i++)
6047      {
6048        if(test_c_ind_mask_bit (plci, i))
6049          sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6050      }
6051    }
6052    else
6053    {
6054      clear_c_ind_mask (plci);
6055    }
6056    if(!plci->appl)
6057    {
6058      if (plci->State == LISTENING)
6059      {
6060        plci->notifiedcall=0;
6061        a->listen_active--;
6062      }
6063      plci->State = INC_DIS_PENDING;
6064      if(c_ind_mask_empty (plci))
6065      {
6066        plci->State = IDLE;
6067        if (plci->NL.Id && !plci->nl_remove_id)
6068        {
6069          mixer_remove (plci);
6070          nl_req_ncci(plci,REMOVE,0);
6071        }
6072        if (!plci->sig_remove_id)
6073        {
6074          plci->internal_command = 0;
6075          sig_req(plci,REMOVE,0);
6076        }
6077        send_req(plci);
6078      }
6079    }
6080    else
6081    {
6082        /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6083        /* result in a second HANGUP! Don't generate another        */
6084        /* DISCONNECT                                               */
6085      if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6086      {
6087        if(plci->State==RESUMING)
6088        {
6089          PUT_WORD(&resume_cau[4],i);
6090          sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6091        }
6092        plci->State = INC_DIS_PENDING;
6093        sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6094      }
6095    }
6096    break;
6097
6098  case SSEXT_IND:
6099    SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6100    break;
6101
6102  case VSWITCH_REQ:
6103    VSwitchReqInd(plci,Id,multi_vswitch_parms);
6104    break;
6105  case VSWITCH_IND:
6106 if(plci->relatedPTYPLCI &&
6107  plci->vswitchstate==3 &&
6108  plci->relatedPTYPLCI->vswitchstate==3 &&
6109  parms[MAXPARMSIDS-1][0])
6110 {
6111  add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6112  sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6113  send_req(plci->relatedPTYPLCI);
6114 }
6115    else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6116    break;
6117
6118  }
6119}
6120
6121
6122static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6123{
6124  word i;
6125  byte   * ie;
6126  word Info_Number;
6127  byte   * Info_Element;
6128  word Info_Mask = 0;
6129
6130  dbug(1,dprintf("SetupInfo"));
6131
6132  for(i=0; i<MAXPARMSIDS; i++) {
6133    ie = parms[i];
6134    Info_Number = 0;
6135    Info_Element = ie;
6136    if(ie[0]) {
6137      switch(i) {
6138      case 0:
6139        dbug(1,dprintf("CPN "));
6140        Info_Number = 0x0070;
6141        Info_Mask   = 0x80;
6142        Info_Sent_Flag = true;
6143        break;
6144      case 8:  /* display      */
6145        dbug(1,dprintf("display(%d)",i));
6146        Info_Number = 0x0028;
6147        Info_Mask = 0x04;
6148        Info_Sent_Flag = true;
6149        break;
6150      case 16: /* Channel Id */
6151        dbug(1,dprintf("CHI"));
6152        Info_Number = 0x0018;
6153        Info_Mask = 0x100;
6154        Info_Sent_Flag = true;
6155        mixer_set_bchannel_id (plci, Info_Element);
6156        break;
6157      case 19: /* Redirected Number */
6158        dbug(1,dprintf("RDN"));
6159        Info_Number = 0x0074;
6160        Info_Mask = 0x400;
6161        Info_Sent_Flag = true;
6162        break;
6163      case 20: /* Redirected Number extended */
6164        dbug(1,dprintf("RDX"));
6165        Info_Number = 0x0073;
6166        Info_Mask = 0x400;
6167        Info_Sent_Flag = true;
6168        break;
6169      case 22: /* Redirecing Number  */
6170        dbug(1,dprintf("RIN"));
6171        Info_Number = 0x0076;
6172        Info_Mask = 0x400;
6173        Info_Sent_Flag = true;
6174        break;
6175      default:
6176        Info_Number = 0;
6177        break;
6178      }
6179    }
6180
6181    if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6182      Info_Number = 0x8000 |5;
6183      Info_Mask = 0x10;
6184      Info_Element = "";
6185    }
6186
6187    if(Info_Sent_Flag && Info_Number){
6188      if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6189        sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6190      }
6191    }
6192  }
6193}
6194
6195
6196static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6197{
6198  word i;
6199  word j;
6200  word k;
6201  byte   * ie;
6202  word Info_Number;
6203  byte   * Info_Element;
6204  word Info_Mask = 0;
6205  static byte charges[5] = {4,0,0,0,0};
6206  static byte cause[] = {0x02,0x80,0x00};
6207  APPL   *appl;
6208
6209  dbug(1,dprintf("InfoParse "));
6210
6211  if(
6212        !plci->appl
6213        && !plci->State
6214        && plci->Sig.Ind!=NCR_FACILITY
6215      )
6216  {
6217    dbug(1,dprintf("NoParse "));
6218    return;
6219  }
6220  cause[2] = 0;
6221  for(i=0; i<MAXPARMSIDS; i++) {
6222    ie = parms[i];
6223    Info_Number = 0;
6224    Info_Element = ie;
6225    if(ie[0]) {
6226      switch(i) {
6227      case 0:
6228        dbug(1,dprintf("CPN "));
6229        Info_Number = 0x0070;
6230        Info_Mask   = 0x80;
6231        break;
6232      case 7: /* ESC_CAU */
6233        dbug(1,dprintf("cau(0x%x)",ie[2]));
6234        Info_Number = 0x0008;
6235        Info_Mask = 0x00;
6236        cause[2] = ie[2];
6237        Info_Element = NULL;
6238        break;
6239      case 8:  /* display      */
6240        dbug(1,dprintf("display(%d)",i));
6241        Info_Number = 0x0028;
6242        Info_Mask = 0x04;
6243        break;
6244      case 9:  /* Date display */
6245        dbug(1,dprintf("date(%d)",i));
6246        Info_Number = 0x0029;
6247        Info_Mask = 0x02;
6248        break;
6249      case 10: /* charges */
6250        for(j=0;j<4;j++) charges[1+j] = 0;
6251        for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6252        for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6253        Info_Number = 0x4000;
6254        Info_Mask = 0x40;
6255        Info_Element = charges;
6256        break;
6257      case 11: /* user user info */
6258        dbug(1,dprintf("uui"));
6259        Info_Number = 0x007E;
6260        Info_Mask = 0x08;
6261        break;
6262      case 12: /* congestion receiver ready */
6263        dbug(1,dprintf("clRDY"));
6264        Info_Number = 0x00B0;
6265        Info_Mask = 0x08;
6266        Info_Element = "";
6267        break;
6268      case 13: /* congestion receiver not ready */
6269        dbug(1,dprintf("clNRDY"));
6270        Info_Number = 0x00BF;
6271        Info_Mask = 0x08;
6272        Info_Element = "";
6273        break;
6274      case 15: /* Keypad Facility */
6275        dbug(1,dprintf("KEY"));
6276        Info_Number = 0x002C;
6277        Info_Mask = 0x20;
6278        break;
6279      case 16: /* Channel Id */
6280        dbug(1,dprintf("CHI"));
6281        Info_Number = 0x0018;
6282        Info_Mask = 0x100;
6283        mixer_set_bchannel_id (plci, Info_Element);
6284        break;
6285      case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6286        dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6287        if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6288        Info_Number = 0x0008;
6289        Info_Mask = 0x01;
6290        if(cause[2] != ie[2]) Info_Element = cause;
6291        break;
6292      case 19: /* Redirected Number */
6293        dbug(1,dprintf("RDN"));
6294        Info_Number = 0x0074;
6295        Info_Mask = 0x400;
6296        break;
6297      case 22: /* Redirecing Number  */
6298        dbug(1,dprintf("RIN"));
6299        Info_Number = 0x0076;
6300        Info_Mask = 0x400;
6301        break;
6302      case 23: /* Notification Indicator  */
6303        dbug(1,dprintf("NI"));
6304        Info_Number = (word)NI;
6305        Info_Mask = 0x210;
6306        break;
6307      case 26: /* Call State  */
6308        dbug(1,dprintf("CST"));
6309        Info_Number = (word)CST;
6310        Info_Mask = 0x01; /* do with cause i.e. for now */
6311        break;
6312      case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6313        dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6314        Info_Number = 0x8000 |ie[3];
6315        if(iesent) Info_Mask = 0xffff;
6316        else  Info_Mask = 0x10;
6317        Info_Element = "";
6318        break;
6319      default:
6320        Info_Number  = 0;
6321        Info_Mask    = 0;
6322        Info_Element = "";
6323        break;
6324      }
6325    }
6326
6327    if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6328    {
6329      for(j=0; j<max_appl; j++)
6330      {
6331        appl = &application[j];
6332        if(Info_Number
6333        && appl->Id
6334        && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6335        {
6336          dbug(1,dprintf("NCR_Ind"));
6337          iesent=true;
6338          sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6339        }
6340      }
6341    }
6342    else if(!plci->appl)
6343    { /* overlap receiving broadcast */
6344      if(Info_Number==CPN
6345      || Info_Number==KEY
6346      || Info_Number==NI
6347      || Info_Number==DSP
6348      || Info_Number==UUI )
6349      {
6350        for(j=0; j<max_appl; j++)
6351        {
6352          if(test_c_ind_mask_bit (plci, j))
6353          {
6354            dbug(1,dprintf("Ovl_Ind"));
6355            iesent=true;
6356            sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6357          }
6358        }
6359      }
6360    }               /* all other signalling states */
6361    else if(Info_Number
6362    && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6363    {
6364      dbug(1,dprintf("Std_Ind"));
6365      iesent=true;
6366      sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6367    }
6368  }
6369}
6370
6371
6372static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6373                        dword info_mask, byte setupParse)
6374{
6375  word i;
6376  word j;
6377  byte   * ie;
6378  word Info_Number;
6379  byte   * Info_Element;
6380  APPL   *appl;
6381  word Info_Mask = 0;
6382  byte iesent=0;
6383
6384  if(
6385      !plci->appl
6386      && !plci->State
6387      && plci->Sig.Ind!=NCR_FACILITY
6388      && !setupParse
6389      )
6390  {
6391    dbug(1,dprintf("NoM-IEParse "));
6392    return 0;
6393  }
6394  dbug(1,dprintf("M-IEParse "));
6395
6396  for(i=0; i<MAX_MULTI_IE; i++)
6397  {
6398    ie = parms[i];
6399    Info_Number = 0;
6400    Info_Element = ie;
6401    if(ie[0])
6402    {
6403      dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6404      Info_Number = (word)ie_type;
6405      Info_Mask = (word)info_mask;
6406    }
6407
6408    if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6409    {
6410      for(j=0; j<max_appl; j++)
6411      {
6412        appl = &application[j];
6413        if(Info_Number
6414        && appl->Id
6415        && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6416        {
6417          iesent = true;
6418          dbug(1,dprintf("Mlt_NCR_Ind"));
6419          sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6420        }
6421      }
6422    }
6423    else if(!plci->appl && Info_Number)
6424    {                                        /* overlap receiving broadcast */
6425      for(j=0; j<max_appl; j++)
6426      {
6427        if(test_c_ind_mask_bit (plci, j))
6428        {
6429          iesent = true;
6430          dbug(1,dprintf("Mlt_Ovl_Ind"));
6431          sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6432        }
6433      }
6434    }                                        /* all other signalling states */
6435    else if(Info_Number
6436    && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6437    {
6438      iesent = true;
6439      dbug(1,dprintf("Mlt_Std_Ind"));
6440      sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6441    }
6442  }
6443  return iesent;
6444}
6445
6446static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6447{
6448  word i;
6449   /* Format of multi_ssext_parms[i][]:
6450   0 byte length
6451   1 byte SSEXTIE
6452   2 byte SSEXT_REQ/SSEXT_IND
6453   3 byte length
6454   4 word SSExtCommand
6455   6... Params
6456   */
6457  if(
6458   plci
6459   && plci->State
6460   && plci->Sig.Ind!=NCR_FACILITY
6461    )
6462 for(i=0;i<MAX_MULTI_IE;i++)
6463    {
6464      if(parms[i][0]<6) continue;
6465   if(parms[i][2]==SSEXT_REQ) continue;
6466
6467   if(appl)
6468   {
6469    parms[i][0]=0; /* kill it */
6470    sendf(appl,_MANUFACTURER_I,
6471    Id,
6472    0,
6473    "dwS",
6474    _DI_MANU_ID,
6475    _DI_SSEXT_CTRL,
6476    &parms[i][3]);
6477   }
6478   else if(plci->appl)
6479   {
6480    parms[i][0]=0; /* kill it */
6481    sendf(plci->appl,_MANUFACTURER_I,
6482    Id,
6483    0,
6484    "dwS",
6485    _DI_MANU_ID,
6486    _DI_SSEXT_CTRL,
6487    &parms[i][3]);
6488   }
6489    }
6490};
6491
6492static void nl_ind(PLCI *plci)
6493{
6494  byte ch;
6495  word ncci;
6496  dword Id;
6497  DIVA_CAPI_ADAPTER   * a;
6498  word NCCIcode;
6499  APPL   * APPLptr;
6500  word count;
6501  word Num;
6502  word i, ncpi_state;
6503  byte len, ncci_state;
6504  word msg;
6505  word info = 0;
6506  word fax_feature_bits;
6507  byte fax_send_edata_ack;
6508  static byte v120_header_buffer[2 + 3];
6509  static word fax_info[] = {
6510    0,                     /* T30_SUCCESS                        */
6511    _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6512    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6513    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6514    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6515    _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6516    _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6517    _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6518    _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6519    _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6520    _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6521    _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6522    _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6523    _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6524    _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6525    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6526    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6527    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6528    _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6529    _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6530    _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6531    _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6532    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6533    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6534    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6535    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6536    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6537    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6538    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6539    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6540    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6541    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6542    _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6543    0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6544    0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6545    0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6546    _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6547    _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6548    _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6549    _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6550    _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6551    _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6552    _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6553    _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6554    _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6555    _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6556    _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6557  };
6558
6559    byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6560
6561
6562  static word rtp_info[] = {
6563    GOOD,                  /* RTP_SUCCESS                       */
6564    0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6565  };
6566
6567  static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6568  {
6569    0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6570    0x00000000, 0x00000000, 0x00000000, 0x00000000
6571  };
6572
6573  ch = plci->NL.IndCh;
6574  a = plci->adapter;
6575  ncci = a->ch_ncci[ch];
6576  Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6577  if(plci->tel) Id|=EXT_CONTROLLER;
6578  APPLptr = plci->appl;
6579  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",
6580    plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6581
6582  /* in the case if no connect_active_Ind was sent to the appl we wait for */
6583
6584  if (plci->nl_remove_id)
6585  {
6586    plci->NL.RNR = 2; /* discard */
6587    dbug(1,dprintf("NL discard while remove pending"));
6588    return;
6589  }
6590  if((plci->NL.Ind &0x0f)==N_CONNECT)
6591  {
6592    if(plci->State==INC_DIS_PENDING
6593    || plci->State==OUTG_DIS_PENDING
6594    || plci->State==IDLE)
6595    {
6596      plci->NL.RNR = 2; /* discard */
6597      dbug(1,dprintf("discard n_connect"));
6598      return;
6599    }
6600    if(plci->State < INC_ACT_PENDING)
6601    {
6602      plci->NL.RNR = 1; /* flow control */
6603      channel_x_off (plci, ch, N_XON_CONNECT_IND);
6604      return;
6605    }
6606  }
6607
6608  if(!APPLptr)                         /* no application or invalid data */
6609  {                                    /* while reloading the DSP        */
6610    dbug(1,dprintf("discard1"));
6611    plci->NL.RNR = 2;
6612    return;
6613  }
6614
6615  if (((plci->NL.Ind &0x0f) == N_UDATA)
6616     && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6617        || (plci->B2_prot == 7)
6618        || (plci->B3_prot == 7)) )
6619  {
6620    plci->ncpi_buffer[0] = 0;
6621
6622    ncpi_state = plci->ncpi_state;
6623    if (plci->NL.complete == 1)
6624    {
6625      byte  * data = &plci->NL.RBuffer->P[0];
6626
6627      if ((plci->NL.RBuffer->length >= 12)
6628        &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6629          ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6630      {
6631        word conn_opt, ncpi_opt = 0x00;
6632/*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6633
6634        if (*data == DSP_UDATA_INDICATION_DCD_ON)
6635          plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6636        if (*data == DSP_UDATA_INDICATION_CTS_ON)
6637          plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6638
6639        data++;    /* indication code */
6640        data += 2; /* timestamp */
6641        if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6642          ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6643        data++;    /* connected norm */
6644        conn_opt = GET_WORD(data);
6645        data += 2; /* connected options */
6646
6647        PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6648
6649        if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6650        {
6651          ncpi_opt |= MDM_NCPI_ECM_V42;
6652        }
6653        else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6654        {
6655          ncpi_opt |= MDM_NCPI_ECM_MNP;
6656        }
6657        else
6658        {
6659          ncpi_opt |= MDM_NCPI_TRANSPARENT;
6660        }
6661        if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6662        {
6663          ncpi_opt |= MDM_NCPI_COMPRESSED;
6664        }
6665        PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6666        plci->ncpi_buffer[0] = 4;
6667
6668        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6669      }
6670    }
6671    if (plci->B3_prot == 7)
6672    {
6673      if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6674       && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6675       && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6676      {
6677        a->ncci_state[ncci] = INC_ACT_PENDING;
6678        sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6679        plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6680      }
6681    }
6682
6683    if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6684        & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6685     || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6686     || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6687
6688    {
6689      plci->NL.RNR = 2;
6690      return;
6691    }
6692  }
6693
6694  if(plci->NL.complete == 2)
6695    {
6696    if (((plci->NL.Ind &0x0f) == N_UDATA)
6697     && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6698    {
6699      switch(plci->RData[0].P[0])
6700      {
6701
6702      case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6703        if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704          sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6705        break;
6706      case DTMF_UDATA_INDICATION_ANSWER_TONE:
6707        if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6708          sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6709        break;
6710      case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6711        dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6712        break;
6713      case DTMF_UDATA_INDICATION_DIGITS_SENT:
6714        dtmf_confirmation (Id, plci);
6715        break;
6716
6717
6718      case UDATA_INDICATION_MIXER_TAP_DATA:
6719        capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6720 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6721 if (i != 0)
6722 {
6723   dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6724          dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6725 }
6726        break;
6727
6728
6729      case UDATA_INDICATION_MIXER_COEFS_SET:
6730        mixer_indication_coefs_set (Id, plci);
6731        break;
6732      case UDATA_INDICATION_XCONNECT_FROM:
6733        mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6734        break;
6735      case UDATA_INDICATION_XCONNECT_TO:
6736        mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6737        break;
6738
6739
6740      case LEC_UDATA_INDICATION_DISABLE_DETECT:
6741        ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6742        break;
6743
6744
6745
6746      default:
6747        break;
6748      }
6749    }
6750    else
6751  {
6752      if ((plci->RData[0].PLength != 0)
6753     && ((plci->B2_prot == B2_V120_ASYNC)
6754      || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6755      || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6756    {
6757
6758      sendf(plci->appl,_DATA_B3_I,Id,0,
6759            "dwww",
6760            plci->RData[1].P,
6761              (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6762            plci->RNum,
6763            plci->RFlags);
6764
6765    }
6766    else
6767    {
6768
6769      sendf(plci->appl,_DATA_B3_I,Id,0,
6770            "dwww",
6771            plci->RData[0].P,
6772            plci->RData[0].PLength,
6773            plci->RNum,
6774            plci->RFlags);
6775
6776    }
6777    }
6778    return;
6779  }
6780
6781  fax_feature_bits = 0;
6782  if((plci->NL.Ind &0x0f)==N_CONNECT ||
6783     (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6784     (plci->NL.Ind &0x0f)==N_DISC ||
6785     (plci->NL.Ind &0x0f)==N_EDATA ||
6786     (plci->NL.Ind &0x0f)==N_DISC_ACK)
6787  {
6788    info = 0;
6789    plci->ncpi_buffer[0] = 0;
6790    switch (plci->B3_prot) {
6791    case  0: /*XPARENT*/
6792    case  1: /*T.90 NL*/
6793      break;    /* no network control protocol info - jfr */
6794    case  2: /*ISO8202*/
6795    case  3: /*X25 DCE*/
6796      for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6797      plci->ncpi_buffer[0] = (byte)(i+3);
6798      plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6799      plci->ncpi_buffer[2] = 0;
6800      plci->ncpi_buffer[3] = 0;
6801      break;
6802    case  4: /*T.30 - FAX*/
6803    case  5: /*T.30 - FAX*/
6804      if(plci->NL.RLength>=sizeof(T30_INFO))
6805      {
6806        dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6807        len = 9;
6808        PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6809        fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6810        i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6811        if (plci->B3_prot == 5)
6812        {
6813          if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6814            i |= 0x8000; /* This is not an ECM connection */
6815          if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6816            i |= 0x4000; /* This is a connection with MMR compression */
6817          if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6818            i |= 0x2000; /* This is a connection with MR compression */
6819          if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6820            i |= 0x0004; /* More documents */
6821          if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6822            i |= 0x0002; /* Fax-polling indication */
6823        }
6824        dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6825        PUT_WORD(&(plci->ncpi_buffer[3]),i);
6826        PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6827        plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6828        plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6829        plci->ncpi_buffer[len] = 0;
6830        if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6831        {
6832          plci->ncpi_buffer[len] = 20;
6833          for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6834            plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6835        }
6836        if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6837        {
6838          if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6839            info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6840          else
6841            info = _FAX_PROTOCOL_ERROR;
6842        }
6843
6844        if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6845          & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6846        {
6847          i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6848          while (i < plci->NL.RBuffer->length)
6849            plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6850        }
6851
6852        plci->ncpi_buffer[0] = len;
6853        fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6854        PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6855
6856        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6857 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6858         || (((plci->NL.Ind &0x0f) == N_CONNECT)
6859          && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6860         || (((plci->NL.Ind &0x0f) == N_EDATA)
6861          && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6862           || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6863           || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6864 {
6865          plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6866 }
6867 if (((plci->NL.Ind &0x0f) == N_DISC)
6868  || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6869  || (((plci->NL.Ind &0x0f) == N_EDATA)
6870   && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6871 {
6872          plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6873 }
6874      }
6875      break;
6876
6877    case B3_RTP:
6878      if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6879      {
6880        if (plci->NL.RLength != 0)
6881        {
6882          info = rtp_info[plci->NL.RBuffer->P[0]];
6883          plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6884          for (i = 1; i < plci->NL.RLength; i++)
6885            plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6886        }
6887      }
6888      break;
6889
6890    }
6891    plci->NL.RNR = 2;
6892  }
6893  switch(plci->NL.Ind &0x0f) {
6894  case N_EDATA:
6895    if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6896    {
6897      dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6898        ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6899      fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6900
6901      if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6902       && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6903       && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6904       && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6905       && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6906       && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6907      {
6908        ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6909        sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6910          (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6911        plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6912 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6913   fax_send_edata_ack = false;
6914      }
6915
6916      if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6917      {
6918        switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6919        {
6920        case EDATA_T30_DIS:
6921          if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6922           && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6923           && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6924           && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6925          {
6926            a->ncci_state[ncci] = INC_ACT_PENDING;
6927            if (plci->B3_prot == 4)
6928              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6929            else
6930              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6931            plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6932          }
6933          break;
6934
6935        case EDATA_T30_TRAIN_OK:
6936          if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6937           && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6938           && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6939          {
6940            if (plci->B3_prot == 4)
6941              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6942            else
6943              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6944            plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6945          }
6946          break;
6947
6948        case EDATA_T30_EOP_CAPI:
6949          if (a->ncci_state[ncci] == CONNECTED)
6950          {
6951            sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6952            a->ncci_state[ncci] = INC_DIS_PENDING;
6953            plci->ncpi_state = 0;
6954     fax_send_edata_ack = false;
6955          }
6956          break;
6957        }
6958      }
6959      else
6960      {
6961        switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6962        {
6963        case EDATA_T30_TRAIN_OK:
6964          if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6965           && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6966           && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6967          {
6968            if (plci->B3_prot == 4)
6969              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6970            else
6971              sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6972            plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6973          }
6974          break;
6975        }
6976      }
6977      if (fax_send_edata_ack)
6978      {
6979        ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6980 plci->fax_edata_ack_length = 1;
6981        start_internal_command (Id, plci, fax_edata_ack_command);
6982      }
6983    }
6984    else
6985    {
6986      dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6987    }
6988    break;
6989  case N_CONNECT:
6990    if (!a->ch_ncci[ch])
6991    {
6992      ncci = get_ncci (plci, ch, 0);
6993      Id = (Id & 0xffff) | (((dword) ncci) << 16);
6994    }
6995    dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6996      ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6997
6998    msg = _CONNECT_B3_I;
6999    if (a->ncci_state[ncci] == IDLE)
7000      plci->channels++;
7001    else if (plci->B3_prot == 1)
7002      msg = _CONNECT_B3_T90_ACTIVE_I;
7003
7004    a->ncci_state[ncci] = INC_CON_PENDING;
7005    if(plci->B3_prot == 4)
7006      sendf(plci->appl,msg,Id,0,"s","");
7007    else
7008      sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7009    break;
7010  case N_CONNECT_ACK:
7011    dbug(1,dprintf("N_connect_Ack"));
7012    if (plci->internal_command_queue[0]
7013     && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7014      || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7015      || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7016    {
7017      (*(plci->internal_command_queue[0]))(Id, plci, 0);
7018      if (!plci->internal_command)
7019        next_internal_command (Id, plci);
7020      break;
7021    }
7022    msg = _CONNECT_B3_ACTIVE_I;
7023    if (plci->B3_prot == 1)
7024    {
7025      if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7026        msg = _CONNECT_B3_T90_ACTIVE_I;
7027      a->ncci_state[ncci] = INC_ACT_PENDING;
7028      sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7029    }
7030    else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7031    {
7032      if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7033       && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7034       && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7035      {
7036        a->ncci_state[ncci] = INC_ACT_PENDING;
7037        if (plci->B3_prot == 4)
7038          sendf(plci->appl,msg,Id,0,"s","");
7039        else
7040          sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7041        plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7042      }
7043    }
7044    else
7045    {
7046      a->ncci_state[ncci] = INC_ACT_PENDING;
7047      sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7048    }
7049    if (plci->adjust_b_restore)
7050    {
7051      plci->adjust_b_restore = false;
7052      start_internal_command (Id, plci, adjust_b_restore);
7053    }
7054    break;
7055  case N_DISC:
7056  case N_DISC_ACK:
7057    if (plci->internal_command_queue[0]
7058     && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7059      || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7060      || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7061    {
7062      (*(plci->internal_command_queue[0]))(Id, plci, 0);
7063      if (!plci->internal_command)
7064        next_internal_command (Id, plci);
7065    }
7066    ncci_state = a->ncci_state[ncci];
7067    ncci_remove (plci, ncci, false);
7068
7069        /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7070        /* channel, so we cannot store the state in ncci_state! The */
7071        /* information which channel we received a N_DISC is thus   */
7072        /* stored in the inc_dis_ncci_table buffer.                 */
7073    for(i=0; plci->inc_dis_ncci_table[i]; i++);
7074    plci->inc_dis_ncci_table[i] = (byte) ncci;
7075
7076      /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7077    if (!plci->channels
7078     && (plci->B1_resource == 16)
7079     && (plci->State <= CONNECTED))
7080    {
7081      len = 9;
7082      i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7083      PUT_WORD (&plci->ncpi_buffer[1], i);
7084      PUT_WORD (&plci->ncpi_buffer[3], 0);
7085      i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
7086      PUT_WORD (&plci->ncpi_buffer[5], i);
7087      PUT_WORD (&plci->ncpi_buffer[7], 0);
7088      plci->ncpi_buffer[len] = 0;
7089      plci->ncpi_buffer[0] = len;
7090      if(plci->B3_prot == 4)
7091        sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7092      else
7093      {
7094
7095        if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7096          & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7097        {
7098          plci->ncpi_buffer[++len] = 0;
7099          plci->ncpi_buffer[++len] = 0;
7100          plci->ncpi_buffer[++len] = 0;
7101          plci->ncpi_buffer[0] = len;
7102        }
7103
7104        sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7105      }
7106      sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7107      plci->ncpi_state = 0;
7108      sig_req(plci,HANGUP,0);
7109      send_req(plci);
7110      plci->State = OUTG_DIS_PENDING;
7111      /* disc here */
7112    }
7113    else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7114     && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7115     && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7116    {
7117      if (ncci_state == IDLE)
7118      {
7119        if (plci->channels)
7120          plci->channels--;
7121        if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7122          if(plci->State == SUSPENDING){
7123            sendf(plci->appl,
7124                  _FACILITY_I,
7125                  Id & 0xffffL,
7126                  0,
7127                  "ws", (word)3, "\x03\x04\x00\x00");
7128            sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7129          }
7130          plci_remove(plci);
7131          plci->State=IDLE;
7132        }
7133      }
7134    }
7135    else if (plci->channels)
7136    {
7137      sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7138      plci->ncpi_state = 0;
7139      if ((ncci_state == OUTG_REJ_PENDING)
7140       && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7141      {
7142        sig_req(plci,HANGUP,0);
7143        send_req(plci);
7144        plci->State = OUTG_DIS_PENDING;
7145      }
7146    }
7147    break;
7148  case N_RESET:
7149    a->ncci_state[ncci] = INC_RES_PENDING;
7150    sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7151    break;
7152  case N_RESET_ACK:
7153    a->ncci_state[ncci] = CONNECTED;
7154    sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7155    break;
7156
7157  case N_UDATA:
7158    if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7159    {
7160      plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7161      plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7162      plci->NL.R = plci->RData;
7163      plci->NL.RNum = 1;
7164      return;
7165    }
7166  case N_BDATA:
7167  case N_DATA:
7168    if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7169     || (a->ncci_state[ncci] == IDLE)
7170     || (a->ncci_state[ncci] == INC_DIS_PENDING))
7171    {
7172      plci->NL.RNR = 2;
7173      break;
7174    }
7175    if ((a->ncci_state[ncci] != CONNECTED)
7176     && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7177     && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7178    {
7179      dbug(1,dprintf("flow control"));
7180      plci->NL.RNR = 1; /* flow control  */
7181      channel_x_off (plci, ch, 0);
7182      break;
7183    }
7184
7185    NCCIcode = ncci | (((word)a->Id) << 8);
7186
7187                /* count all buffers within the Application pool    */
7188                /* belonging to the same NCCI. If this is below the */
7189                /* number of buffers available per NCCI we accept   */
7190                /* this packet, otherwise we reject it              */
7191    count = 0;
7192    Num = 0xffff;
7193    for(i=0; i<APPLptr->MaxBuffer; i++) {
7194      if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7195      if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7196    }
7197
7198    if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7199    {
7200      dbug(3,dprintf("Flow-Control"));
7201      plci->NL.RNR = 1;
7202      if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7203       (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7204      {
7205        plci->NL.RNR = 2;
7206        dbug(3,dprintf("DiscardData"));
7207      } else {
7208        channel_x_off (plci, ch, 0);
7209      }
7210      break;
7211    }
7212    else
7213    {
7214      APPLptr->NCCIDataFlowCtrlTimer = 0;
7215    }
7216
7217    plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7218    if(!plci->RData[0].P) {
7219      plci->NL.RNR = 1;
7220      channel_x_off (plci, ch, 0);
7221      break;
7222    }
7223
7224    APPLptr->DataNCCI[Num] = NCCIcode;
7225    APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7226    dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7227
7228    plci->RNum = Num;
7229    plci->RFlags = plci->NL.Ind>>4;
7230    plci->RData[0].PLength = APPLptr->MaxDataLength;
7231    plci->NL.R = plci->RData;
7232    if ((plci->NL.RLength != 0)
7233     && ((plci->B2_prot == B2_V120_ASYNC)
7234      || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7235      || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7236    {
7237      plci->RData[1].P = plci->RData[0].P;
7238      plci->RData[1].PLength = plci->RData[0].PLength;
7239      plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7240      if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7241        plci->RData[0].PLength = 1;
7242      else
7243        plci->RData[0].PLength = 2;
7244      if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7245        plci->RFlags |= 0x0010;
7246      if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7247        plci->RFlags |= 0x8000;
7248      plci->NL.RNum = 2;
7249    }
7250    else
7251    {
7252      if((plci->NL.Ind &0x0f)==N_UDATA)
7253        plci->RFlags |= 0x0010;
7254
7255      else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7256        plci->RFlags |= 0x0001;
7257
7258      plci->NL.RNum = 1;
7259    }
7260    break;
7261  case N_DATA_ACK:
7262    data_ack (plci, ch);
7263    break;
7264  default:
7265    plci->NL.RNR = 2;
7266    break;
7267  }
7268}
7269
7270/*------------------------------------------------------------------*/
7271/* find a free PLCI                                                 */
7272/*------------------------------------------------------------------*/
7273
7274static word get_plci(DIVA_CAPI_ADAPTER *a)
7275{
7276  word i,j;
7277  PLCI   * plci;
7278
7279  dump_plcis (a);
7280  for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7281  if(i==a->max_plci) {
7282    dbug(1,dprintf("get_plci: out of PLCIs"));
7283    return 0;
7284  }
7285  plci = &a->plci[i];
7286  plci->Id = (byte)(i+1);
7287
7288  plci->Sig.Id = 0;
7289  plci->NL.Id = 0;
7290  plci->sig_req = 0;
7291  plci->nl_req = 0;
7292
7293  plci->appl = NULL;
7294  plci->relatedPTYPLCI = NULL;
7295  plci->State = IDLE;
7296  plci->SuppState = IDLE;
7297  plci->channels = 0;
7298  plci->tel = 0;
7299  plci->B1_resource = 0;
7300  plci->B2_prot = 0;
7301  plci->B3_prot = 0;
7302
7303  plci->command = 0;
7304  plci->m_command = 0;
7305  init_internal_command_queue (plci);
7306  plci->number = 0;
7307  plci->req_in_start = 0;
7308  plci->req_in = 0;
7309  plci->req_out = 0;
7310  plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7311  plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7312  plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7313
7314  plci->data_sent = false;
7315  plci->send_disc = 0;
7316  plci->sig_global_req = 0;
7317  plci->sig_remove_id = 0;
7318  plci->nl_global_req = 0;
7319  plci->nl_remove_id = 0;
7320  plci->adv_nl = 0;
7321  plci->manufacturer = false;
7322  plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7323  plci->spoofed_msg = 0;
7324  plci->ptyState = 0;
7325  plci->cr_enquiry = false;
7326  plci->hangup_flow_ctrl_timer = 0;
7327
7328  plci->ncci_ring_list = 0;
7329  for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7330  clear_c_ind_mask (plci);
7331  set_group_ind_mask (plci);
7332  plci->fax_connect_info_length = 0;
7333  plci->nsf_control_bits = 0;
7334  plci->ncpi_state = 0x00;
7335  plci->ncpi_buffer[0] = 0;
7336
7337  plci->requested_options_conn = 0;
7338  plci->requested_options = 0;
7339  plci->notifiedcall = 0;
7340  plci->vswitchstate = 0;
7341  plci->vsprot = 0;
7342  plci->vsprotdialect = 0;
7343  init_b1_config (plci);
7344  dbug(1,dprintf("get_plci(%x)",plci->Id));
7345  return i+1;
7346}
7347
7348/*------------------------------------------------------------------*/
7349/* put a parameter in the parameter buffer                          */
7350/*------------------------------------------------------------------*/
7351
7352static void add_p(PLCI   * plci, byte code, byte   * p)
7353{
7354  word p_length;
7355
7356  p_length = 0;
7357  if(p) p_length = p[0];
7358  add_ie(plci, code, p, p_length);
7359}
7360
7361/*------------------------------------------------------------------*/
7362/* put a structure in the parameter buffer                          */
7363/*------------------------------------------------------------------*/
7364static void add_s(PLCI   * plci, byte code, API_PARSE * p)
7365{
7366  if(p) add_ie(plci, code, p->info, (word)p->length);
7367}
7368
7369/*------------------------------------------------------------------*/
7370/* put multiple structures in the parameter buffer                  */
7371/*------------------------------------------------------------------*/
7372static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
7373{
7374  byte i;
7375
7376  if(p){
7377    dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7378    for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7379      dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7380      add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
7381    }
7382  }
7383}
7384
7385/*------------------------------------------------------------------*/
7386/* return the channel number sent by the application in a esc_chi   */
7387/*------------------------------------------------------------------*/
7388static byte getChannel(API_PARSE * p)
7389{
7390  byte i;
7391
7392  if(p){
7393    for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7394      if(p->info[i]==2){
7395        if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7396      }
7397    }
7398  }
7399  return 0;
7400}
7401
7402
7403/*------------------------------------------------------------------*/
7404/* put an information element in the parameter buffer               */
7405/*------------------------------------------------------------------*/
7406
7407static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
7408{
7409  word i;
7410
7411  if(!(code &0x80) && !p_length) return;
7412
7413  if(plci->req_in==plci->req_in_start) {
7414    plci->req_in +=2;
7415  }
7416  else {
7417    plci->req_in--;
7418  }
7419  plci->RBuffer[plci->req_in++] = code;
7420
7421  if(p) {
7422    plci->RBuffer[plci->req_in++] = (byte)p_length;
7423    for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7424  }
7425
7426  plci->RBuffer[plci->req_in++] = 0;
7427}
7428
7429/*------------------------------------------------------------------*/
7430/* put a unstructured data into the buffer                          */
7431/*------------------------------------------------------------------*/
7432
7433static void add_d(PLCI *plci, word length, byte *p)
7434{
7435  word i;
7436
7437  if(plci->req_in==plci->req_in_start) {
7438    plci->req_in +=2;
7439  }
7440  else {
7441    plci->req_in--;
7442  }
7443  for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7444}
7445
7446/*------------------------------------------------------------------*/
7447/* put parameters from the Additional Info parameter in the         */
7448/* parameter buffer                                                 */
7449/*------------------------------------------------------------------*/
7450
7451static void add_ai(PLCI *plci, API_PARSE *ai)
7452{
7453  word i;
7454    API_PARSE ai_parms[5];
7455
7456  for(i=0;i<5;i++) ai_parms[i].length = 0;
7457
7458  if(!ai->length)
7459    return;
7460  if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7461    return;
7462
7463  add_s (plci,KEY,&ai_parms[1]);
7464  add_s (plci,UUI,&ai_parms[2]);
7465  add_ss(plci,FTY,&ai_parms[3]);
7466}
7467
7468/*------------------------------------------------------------------*/
7469/* put parameter for b1 protocol in the parameter buffer            */
7470/*------------------------------------------------------------------*/
7471
7472static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7473                   word b1_facilities)
7474{
7475    API_PARSE bp_parms[8];
7476    API_PARSE mdm_cfg[9];
7477    API_PARSE global_config[2];
7478    byte cai[256];
7479  byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7480  byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7481  word i;
7482
7483    API_PARSE mdm_cfg_v18[4];
7484  word j, n, w;
7485  dword d;
7486
7487
7488  for(i=0;i<8;i++) bp_parms[i].length = 0;
7489  for(i=0;i<2;i++) global_config[i].length = 0;
7490
7491  dbug(1,dprintf("add_b1"));
7492  api_save_msg(bp, "s", &plci->B_protocol);
7493
7494  if(b_channel_info==2){
7495    plci->B1_resource = 0;
7496    adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7497    add_p(plci, CAI, "\x01\x00");
7498    dbug(1,dprintf("Cai=1,0 (no resource)"));
7499    return 0;
7500  }
7501
7502  if(plci->tel == CODEC_PERMANENT) return 0;
7503  else if(plci->tel == CODEC){
7504    plci->B1_resource = 1;
7505    adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7506    add_p(plci, CAI, "\x01\x01");
7507    dbug(1,dprintf("Cai=1,1 (Codec)"));
7508    return 0;
7509  }
7510  else if(plci->tel == ADV_VOICE){
7511    plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7512    adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7513    voice_cai[1] = plci->B1_resource;
7514    PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7515    add_p(plci, CAI, voice_cai);
7516    dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7517    return 0;
7518  }
7519  plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7520  if (plci->call_dir & CALL_DIR_OUT)
7521    plci->call_dir |= CALL_DIR_ORIGINATE;
7522  else if (plci->call_dir & CALL_DIR_IN)
7523    plci->call_dir |= CALL_DIR_ANSWER;
7524
7525  if(!bp->length){
7526    plci->B1_resource = 0x5;
7527    adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7528    add_p(plci, CAI, "\x01\x05");
7529    return 0;
7530  }
7531
7532  dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7533  if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7534  if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7535  {
7536    bp_parms[6].length = 0;
7537    if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7538    {
7539      dbug(1,dprintf("b-form.!"));
7540      return _WRONG_MESSAGE_FORMAT;
7541    }
7542  }
7543  else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7544  {
7545    dbug(1,dprintf("b-form.!"));
7546    return _WRONG_MESSAGE_FORMAT;
7547  }
7548
7549  if(bp_parms[6].length)
7550  {
7551    if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7552    {
7553      return _WRONG_MESSAGE_FORMAT;
7554    }
7555    switch(GET_WORD(global_config[0].info))
7556    {
7557    case 1:
7558      plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7559      break;
7560    case 2:
7561      plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7562      break;
7563    }
7564  }
7565  dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7566
7567
7568  if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7569   && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7570  {
7571    plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7572    adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7573    cai[1] = plci->B1_resource;
7574    cai[2] = 0;
7575    cai[3] = 0;
7576    cai[4] = 0;
7577    PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7578    for (i = 0; i < bp_parms[3].length; i++)
7579      cai[7+i] = bp_parms[3].info[1+i];
7580    cai[0] = 6 + bp_parms[3].length;
7581    add_p(plci, CAI, cai);
7582    return 0;
7583  }
7584
7585
7586  if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7587   && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7588  {
7589    plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7590    adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7591    cai[1] = plci->B1_resource;
7592    cai[2] = 0;
7593    cai[3] = 0;
7594    cai[4] = 0;
7595    PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7596    cai[0] = 6;
7597    add_p(plci, CAI, cai);
7598    return 0;
7599  }
7600
7601
7602  if ((GET_WORD(bp_parms[0].info) >= 32)
7603   || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7604    && ((GET_WORD(bp_parms[0].info) != 3)
7605     || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7606     || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7607  {
7608    return _B1_NOT_SUPPORTED;
7609  }
7610  plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7611    (word)(b1_facilities & ~B1_FACILITY_VOICE));
7612  adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7613  cai[0] = 6;
7614  cai[1] = plci->B1_resource;
7615  for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7616
7617  if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7618   || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7619   || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7620  { /* B1 - modem */
7621    for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7622
7623    if (bp_parms[3].length)
7624    {
7625      if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7626      {
7627        return (_WRONG_MESSAGE_FORMAT);
7628      }
7629        
7630      cai[2] = 0; /* Bit rate for adaptation */
7631
7632      dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7633
7634      PUT_WORD (&cai[13], 0);                          /* Min Tx speed */
7635      PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7636      PUT_WORD (&cai[17], 0);                          /* Min Rx speed */
7637      PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7638
7639      cai[3] = 0; /* Async framing parameters */
7640      switch (GET_WORD (mdm_cfg[2].info))
7641      {       /* Parity     */
7642      case 1: /* odd parity */
7643        cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7644        dbug(1,dprintf("MDM: odd parity"));
7645        break;
7646
7647      case 2: /* even parity */
7648        cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7649        dbug(1,dprintf("MDM: even parity"));
7650        break;
7651
7652      default:
7653        dbug(1,dprintf("MDM: no parity"));
7654        break;
7655      }
7656
7657      switch (GET_WORD (mdm_cfg[3].info))
7658      {       /* stop bits   */
7659      case 1: /* 2 stop bits */
7660        cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7661        dbug(1,dprintf("MDM: 2 stop bits"));
7662        break;
7663
7664      default:
7665        dbug(1,dprintf("MDM: 1 stop bit"));
7666        break;
7667      }
7668
7669      switch (GET_WORD (mdm_cfg[1].info))
7670      {     /* char length */
7671      case 5:
7672        cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7673        dbug(1,dprintf("MDM: 5 bits"));
7674        break;
7675
7676      case 6:
7677        cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7678        dbug(1,dprintf("MDM: 6 bits"));
7679        break;
7680
7681      case 7:
7682        cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7683        dbug(1,dprintf("MDM: 7 bits"));
7684        break;
7685
7686      default:
7687        dbug(1,dprintf("MDM: 8 bits"));
7688        break;
7689      }
7690
7691      cai[7] = 0; /* Line taking options */
7692      cai[8] = 0; /* Modulation negotiation options */
7693      cai[9] = 0; /* Modulation options */
7694
7695      if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7696      {
7697        cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7698        dbug(1, dprintf("MDM: Reverse direction"));
7699      }
7700
7701      if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7702      {
7703        cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7704        dbug(1, dprintf("MDM: Disable retrain"));
7705      }
7706
7707      if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7708      {
7709        cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7710        dbug(1, dprintf("MDM: Disable ring tone"));
7711      }
7712
7713      if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7714      {
7715        cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7716        dbug(1, dprintf("MDM: 1800 guard tone"));
7717      }
7718      else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7719      {
7720        cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7721        dbug(1, dprintf("MDM: 550 guard tone"));
7722      }
7723
7724      if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7725      {
7726        cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7727        dbug(1, dprintf("MDM: V100"));
7728      }
7729      else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7730      {
7731        cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7732        dbug(1, dprintf("MDM: IN CLASS"));
7733      }
7734      else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7735      {
7736        cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7737        dbug(1, dprintf("MDM: DISABLED"));
7738      }
7739      cai[0] = 20;
7740
7741      if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7742       && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7743      {
7744        plci->requested_options |= 1L << PRIVATE_V18;
7745      }
7746      if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7747        plci->requested_options |= 1L << PRIVATE_VOWN;
7748
7749      if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7750        & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7751      {
7752        if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7753        {
7754          i = 27;
7755          if (mdm_cfg[6].length >= 4)
7756          {
7757            d = GET_DWORD(&mdm_cfg[6].info[1]);
7758            cai[7] |= (byte) d;          /* line taking options */
7759            cai[9] |= (byte)(d >> 8);    /* modulation options */
7760            cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7761            cai[++i] = (byte)(d >> 24);
7762            if (mdm_cfg[6].length >= 8)
7763            {
7764              d = GET_DWORD(&mdm_cfg[6].info[5]);
7765              cai[10] |= (byte) d;        /* disabled modulations mask */
7766              cai[11] |= (byte)(d >> 8);
7767              if (mdm_cfg[6].length >= 12)
7768              {
7769                d = GET_DWORD(&mdm_cfg[6].info[9]);
7770                cai[12] = (byte) d;          /* enabled modulations mask */
7771                cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7772                cai[++i] = (byte)(d >> 16);
7773                cai[++i] = (byte)(d >> 24);
7774                cai[++i] = 0;
7775                if (mdm_cfg[6].length >= 14)
7776                {
7777                  w = GET_WORD(&mdm_cfg[6].info[13]);
7778                  if (w != 0)
7779                    PUT_WORD(&cai[13], w);  /* min tx speed */
7780                  if (mdm_cfg[6].length >= 16)
7781                  {
7782                    w = GET_WORD(&mdm_cfg[6].info[15]);
7783                    if (w != 0)
7784                      PUT_WORD(&cai[15], w);  /* max tx speed */
7785                    if (mdm_cfg[6].length >= 18)
7786                    {
7787                      w = GET_WORD(&mdm_cfg[6].info[17]);
7788                      if (w != 0)
7789                        PUT_WORD(&cai[17], w);  /* min rx speed */
7790                      if (mdm_cfg[6].length >= 20)
7791                      {
7792                        w = GET_WORD(&mdm_cfg[6].info[19]);
7793                        if (w != 0)
7794                          PUT_WORD(&cai[19], w);  /* max rx speed */
7795                        if (mdm_cfg[6].length >= 22)
7796                        {
7797                          w = GET_WORD(&mdm_cfg[6].info[21]);
7798                          cai[23] = (byte)(-((short) w));  /* transmit level */
7799                          if (mdm_cfg[6].length >= 24)
7800                          {
7801                            w = GET_WORD(&mdm_cfg[6].info[23]);
7802                            cai[22] |= (byte) w;        /* info options mask */
7803                            cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7804                          }
7805                        }
7806                      }
7807                    }
7808                  }
7809                }
7810              }
7811            }
7812          }
7813          cai[27] = i - 27;
7814          i++;
7815          if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7816          {
7817            if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7818            {
7819              for (n = 0; n < 3; n++)
7820              {
7821                cai[i] = (byte)(mdm_cfg_v18[n].length);
7822                for (j = 1; j < ((word)(cai[i] + 1)); j++)
7823                  cai[i+j] = mdm_cfg_v18[n].info[j];
7824                i += cai[i] + 1;
7825              }
7826            }
7827          }
7828          cai[0] = (byte)(i - 1);
7829        }
7830      }
7831
7832    }
7833  }
7834  if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */
7835     GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */
7836  {
7837    if(bp_parms[3].length){
7838      dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7839      switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */
7840        case 0:
7841        case 56000:
7842          if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */
7843            dbug(1,dprintf("56k sync HSCX"));
7844            cai[1] = 8;
7845            cai[2] = 0;
7846            cai[3] = 0;
7847          }
7848          else if(GET_WORD(bp_parms[0].info)==2){
7849            dbug(1,dprintf("56k async DSP"));
7850            cai[2] = 9;
7851          }
7852          break;
7853        case 50:     cai[2] = 1;  break;
7854        case 75:     cai[2] = 1;  break;
7855        case 110:    cai[2] = 1;  break;
7856        case 150:    cai[2] = 1;  break;
7857        case 200:    cai[2] = 1;  break;
7858        case 300:    cai[2] = 1;  break;
7859        case 600:    cai[2] = 1;  break;
7860        case 1200:   cai[2] = 2;  break;
7861        case 2400:   cai[2] = 3;  break;
7862        case 4800:   cai[2] = 4;  break;
7863        case 7200:   cai[2] = 10; break;
7864        case 9600:   cai[2] = 5;  break;
7865        case 12000:  cai[2] = 13; break;
7866        case 24000:  cai[2] = 0;  break;
7867        case 14400:  cai[2] = 11; break;
7868        case 19200:  cai[2] = 6;  break;
7869        case 28800:  cai[2] = 12; break;
7870        case 38400:  cai[2] = 7;  break;
7871        case 48000:  cai[2] = 8;  break;
7872        case 76:     cai[2] = 15; break;  /* 75/1200     */
7873        case 1201:   cai[2] = 14; break;  /* 1200/75     */
7874        case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7875
7876        default:
7877          return _B1_PARM_NOT_SUPPORTED;
7878      }
7879      cai[3] = 0;
7880      if (cai[1] == 13)                                        /* v.110 async */
7881      {
7882        if (bp_parms[3].length >= 8)
7883        {
7884          switch (GET_WORD (&bp_parms[3].info[3]))
7885          {       /* char length */
7886          case 5:
7887            cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7888            break;
7889          case 6:
7890            cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7891            break;
7892          case 7:
7893            cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7894            break;
7895          }
7896          switch (GET_WORD (&bp_parms[3].info[5]))
7897          {       /* Parity     */
7898          case 1: /* odd parity */
7899            cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7900            break;
7901          case 2: /* even parity */
7902            cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7903            break;
7904          }
7905          switch (GET_WORD (&bp_parms[3].info[7]))
7906          {       /* stop bits   */
7907          case 1: /* 2 stop bits */
7908            cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7909            break;
7910          }
7911        }
7912      }
7913    }
7914    else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7915      dbug(1,dprintf("V.110 default 56k sync"));
7916      cai[1] = 8;
7917      cai[2] = 0;
7918      cai[3] = 0;
7919    }
7920    else {
7921      dbug(1,dprintf("V.110 default 9600 async"));
7922      cai[2] = 5;
7923    }
7924  }
7925  PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7926  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]));
7927/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7928
7929  add_p(plci, CAI, cai);
7930  return 0;
7931}
7932
7933/*------------------------------------------------------------------*/
7934/* put parameter for b2 and B3  protocol in the parameter buffer    */
7935/*------------------------------------------------------------------*/
7936
7937static word add_b23(PLCI *plci, API_PARSE *bp)
7938{
7939  word i, fax_control_bits;
7940  byte pos, len;
7941  byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7942    API_PARSE bp_parms[8];
7943  API_PARSE * b1_config;
7944  API_PARSE * b2_config;
7945    API_PARSE b2_config_parms[8];
7946  API_PARSE * b3_config;
7947    API_PARSE b3_config_parms[6];
7948    API_PARSE global_config[2];
7949
7950  static byte llc[3] = {2,0,0};
7951  static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7952  static byte nlc[256];
7953  static byte lli[12] = {1,1};
7954
7955  const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7956  const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7957
7958  const byte llc3[] = {4,3,2,2,6,6,0};
7959  const byte header[] = {0,2,3,3,0,0,0};
7960
7961  for(i=0;i<8;i++) bp_parms[i].length = 0;
7962  for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7963  for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7964
7965  lli[0] = 1;
7966  lli[1] = 1;
7967  if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7968    lli[1] |= 2;
7969  if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7970    lli[1] |= 4;
7971
7972  if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7973    lli[1] |= 0x10;
7974    if (plci->rx_dma_descriptor <= 0) {
7975      plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7976      if (plci->rx_dma_descriptor >= 0)
7977        plci->rx_dma_descriptor++;
7978    }
7979    if (plci->rx_dma_descriptor > 0) {
7980      lli[0] = 6;
7981      lli[1] |= 0x40;
7982      lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7983      lli[3] = (byte)plci->rx_dma_magic;
7984      lli[4] = (byte)(plci->rx_dma_magic >>  8);
7985      lli[5] = (byte)(plci->rx_dma_magic >> 16);
7986      lli[6] = (byte)(plci->rx_dma_magic >> 24);
7987    }
7988  }
7989
7990  if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7991    lli[1] |= 0x20;
7992  }
7993
7994  dbug(1,dprintf("add_b23"));
7995  api_save_msg(bp, "s", &plci->B_protocol);
7996
7997  if(!bp->length && plci->tel)
7998  {
7999    plci->adv_nl = true;
8000    dbug(1,dprintf("Default adv.Nl"));
8001    add_p(plci,LLI,lli);
8002    plci->B2_prot = 1 /*XPARENT*/;
8003    plci->B3_prot = 0 /*XPARENT*/;
8004    llc[1] = 2;
8005    llc[2] = 4;
8006    add_p(plci, LLC, llc);
8007    dlc[0] = 2;
8008    PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8009    add_p(plci, DLC, dlc);
8010    return 0;
8011  }
8012
8013  if(!bp->length) /*default*/
8014  {   
8015    dbug(1,dprintf("ret default"));
8016    add_p(plci,LLI,lli);
8017    plci->B2_prot = 0 /*X.75   */;
8018    plci->B3_prot = 0 /*XPARENT*/;
8019    llc[1] = 1;
8020    llc[2] = 4;
8021    add_p(plci, LLC, llc);
8022    dlc[0] = 2;
8023    PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8024    add_p(plci, DLC, dlc);
8025    return 0;
8026  }
8027  dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8028  if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8029
8030  if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8031  {
8032    bp_parms[6].length = 0;
8033    if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8034    {
8035      dbug(1,dprintf("b-form.!"));
8036      return _WRONG_MESSAGE_FORMAT;
8037    }
8038  }
8039  else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8040  {
8041    dbug(1,dprintf("b-form.!"));
8042    return _WRONG_MESSAGE_FORMAT;
8043  }
8044
8045  if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8046  {  
8047    if(GET_WORD(bp_parms[1].info)!=1
8048    || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8049    plci->adv_nl = true;
8050  }
8051  else if(plci->tel) return _B2_NOT_SUPPORTED;
8052
8053
8054  if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8055   && (GET_WORD(bp_parms[2].info) == B3_RTP)
8056   && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8057  {
8058    add_p(plci,LLI,lli);
8059    plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8060    plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8061    llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8062    llc[2] = 4;
8063    add_p(plci, LLC, llc);
8064    dlc[0] = 2;
8065    PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8066    dlc[3] = 3; /* Addr A */
8067    dlc[4] = 1; /* Addr B */
8068    dlc[5] = 7; /* modulo mode */
8069    dlc[6] = 7; /* window size */
8070    dlc[7] = 0; /* XID len Lo  */
8071    dlc[8] = 0; /* XID len Hi  */
8072    for (i = 0; i < bp_parms[4].length; i++)
8073      dlc[9+i] = bp_parms[4].info[1+i];
8074    dlc[0] = (byte)(8 + bp_parms[4].length);
8075    add_p(plci, DLC, dlc);
8076    for (i = 0; i < bp_parms[5].length; i++)
8077      nlc[1+i] = bp_parms[5].info[1+i];
8078    nlc[0] = (byte)(bp_parms[5].length);
8079    add_p(plci, NLC, nlc);
8080    return 0;
8081  }
8082
8083
8084
8085  if ((GET_WORD(bp_parms[1].info) >= 32)
8086   || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8087    && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8088     || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8089
8090  {
8091    return _B2_NOT_SUPPORTED;
8092  }
8093  if ((GET_WORD(bp_parms[2].info) >= 32)
8094   || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8095  {
8096    return _B3_NOT_SUPPORTED;
8097  }
8098  if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8099   && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8100    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8101    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8102  {
8103    return (add_modem_b23 (plci, bp_parms));
8104  }
8105
8106  add_p(plci,LLI,lli);
8107
8108  plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8109  plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8110  if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8111
8112  if(bp_parms[6].length)
8113  {
8114    if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8115    {
8116      return _WRONG_MESSAGE_FORMAT;
8117    }
8118    switch(GET_WORD(global_config[0].info))
8119    {
8120    case 1:
8121      plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8122      break;
8123    case 2:
8124      plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8125      break;
8126    }
8127  }
8128  dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8129
8130
8131  if (plci->B2_prot == B2_PIAFS)
8132    llc[1] = PIAFS_CRC;
8133  else
8134/* IMPLEMENT_PIAFS */
8135  {
8136    llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8137             llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8138  }
8139  llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8140
8141  add_p(plci, LLC, llc);
8142
8143  dlc[0] = 2;
8144  PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8145                      header[GET_WORD(bp_parms[2].info)]);
8146
8147  b1_config = &bp_parms[3];
8148  nlc[0] = 0;
8149  if(plci->B3_prot == 4
8150  || plci->B3_prot == 5)
8151  {
8152    for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8153    nlc[0] = sizeof(T30_INFO);
8154    if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8155      ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8156    ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8157    if(b1_config->length>=2)
8158    {
8159      ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8160    }
8161  }
8162  b2_config = &bp_parms[4];
8163
8164
8165  if (llc[1] == PIAFS_CRC)
8166  {
8167    if (plci->B3_prot != B3_TRANSPARENT)
8168    {
8169      return _B_STACK_NOT_SUPPORTED;
8170    }
8171    if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8172      return _WRONG_MESSAGE_FORMAT;
8173    }
8174    PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8175    dlc[3] = 0; /* Addr A */
8176    dlc[4] = 0; /* Addr B */
8177    dlc[5] = 0; /* modulo mode */
8178    dlc[6] = 0; /* window size */
8179    if (b2_config->length >= 7){
8180      dlc[ 7] = 7; 
8181      dlc[ 8] = 0; 
8182      dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8183      dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8184      dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8185      dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8186      dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8187      dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8188      dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8189      dlc[ 0] = 15;
8190      if(b2_config->length >= 8) { /* PIAFS control abilities */
8191        dlc[ 7] = 10; 
8192        dlc[16] = 2; /* Length of PIAFS extention */
8193        dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8194        dlc[18] = b2_config_parms[4].info[0]; /* value */
8195        dlc[ 0] = 18;
8196      }
8197    }
8198    else /* default values, 64K, variable, no compression */
8199    {
8200      dlc[ 7] = 7; 
8201      dlc[ 8] = 0; 
8202      dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8203      dlc[10] = 0x03; /* V.42bis P0 */
8204      dlc[11] = 0;    /* V.42bis P0 */
8205      dlc[12] = 0;    /* V.42bis P1 */
8206      dlc[13] = 0;    /* V.42bis P1 */
8207      dlc[14] = 0;    /* V.42bis P2 */
8208      dlc[15] = 0;    /* V.42bis P2 */
8209    dlc[ 0] = 15;
8210    }
8211    add_p(plci, DLC, dlc);
8212  }
8213  else
8214
8215  if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8216  {
8217    if (plci->B3_prot != B3_TRANSPARENT)
8218      return _B_STACK_NOT_SUPPORTED;
8219
8220    dlc[0] = 6;
8221    PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8222    dlc[3] = 0x08;
8223    dlc[4] = 0x01;
8224    dlc[5] = 127;
8225    dlc[6] = 7;
8226    if (b2_config->length != 0)
8227    {
8228      if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8229        return _WRONG_MESSAGE_FORMAT;
8230      }
8231      dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8232      dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8233      if (b2_config->info[3] != 128)
8234      {
8235        dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8236        return _B2_PARM_NOT_SUPPORTED;
8237      }
8238      dlc[5] = (byte)(b2_config->info[3] - 1);
8239      dlc[6] = b2_config->info[4];
8240      if(llc[1]==V120_V42BIS){
8241        if (b2_config->length >= 10){
8242          dlc[ 7] = 6; 
8243          dlc[ 8] = 0; 
8244          dlc[ 9] = b2_config_parms[4].info[0];
8245          dlc[10] = b2_config_parms[4].info[1];
8246          dlc[11] = b2_config_parms[5].info[0];
8247          dlc[12] = b2_config_parms[5].info[1];
8248          dlc[13] = b2_config_parms[6].info[0];
8249          dlc[14] = b2_config_parms[6].info[1];
8250          dlc[ 0] = 14;
8251          dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8252          dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8253          dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8254        }
8255        else {
8256          dlc[ 6] = 14;
8257        }
8258      }
8259    }
8260  }
8261  else
8262  {
8263    if(b2_config->length)
8264    {
8265      dbug(1,dprintf("B2-Config"));
8266      if(llc[1]==X75_V42BIS){
8267        if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8268        {
8269          return _WRONG_MESSAGE_FORMAT;
8270        }
8271      }
8272      else {
8273        if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8274        {
8275          return _WRONG_MESSAGE_FORMAT;
8276        }
8277      }
8278          /* if B2 Protocol is LAPD, b2_config structure is different */
8279      if(llc[1]==6)
8280      {
8281        dlc[0] = 4;
8282        if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
8283        else dlc[2] = 0x01;
8284        if( (b2_config->length>=2) && (plci->B2_prot==12) )
8285        {
8286          SAPI = b2_config->info[2];    /* SAPI */
8287        }
8288        dlc[1] = SAPI;
8289        if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8290        {
8291          dlc[3] = 127;      /* Mode */
8292        }
8293        else
8294        {
8295          dlc[3] = 7;        /* Mode */
8296        }
8297   
8298        if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
8299        else dlc[4] = 1;
8300        dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8301        if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8302      }
8303      else
8304      {
8305        dlc[0] = (byte)(b2_config_parms[4].length+6);
8306        dlc[3] = b2_config->info[1];
8307        dlc[4] = b2_config->info[2];
8308        if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8309          dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8310          return _B2_PARM_NOT_SUPPORTED;
8311        }
8312
8313        dlc[5] = (byte)(b2_config->info[3]-1);
8314        dlc[6] = b2_config->info[4];
8315        if(dlc[6]>dlc[5]){
8316          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]));
8317          return _B2_PARM_NOT_SUPPORTED;
8318        }
8319 
8320        if(llc[1]==X75_V42BIS) {
8321          if (b2_config->length >= 10){
8322            dlc[ 7] = 6; 
8323            dlc[ 8] = 0; 
8324            dlc[ 9] = b2_config_parms[4].info[0];
8325            dlc[10] = b2_config_parms[4].info[1];
8326            dlc[11] = b2_config_parms[5].info[0];
8327            dlc[12] = b2_config_parms[5].info[1];
8328            dlc[13] = b2_config_parms[6].info[0];
8329            dlc[14] = b2_config_parms[6].info[1];
8330            dlc[ 0] = 14;
8331            dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8332            dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8333            dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8334          }
8335          else {
8336            dlc[ 6] = 14;
8337          }
8338
8339        }
8340        else {
8341          PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8342          for(i=0; i<b2_config_parms[4].length; i++)
8343            dlc[11+i] = b2_config_parms[4].info[1+i];
8344        }
8345      }
8346    }
8347  }
8348  add_p(plci, DLC, dlc);
8349
8350  b3_config = &bp_parms[5];
8351  if(b3_config->length)
8352  {
8353    if(plci->B3_prot == 4 
8354    || plci->B3_prot == 5)
8355    {
8356      if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8357      {
8358        return _WRONG_MESSAGE_FORMAT;
8359      }
8360      i = GET_WORD((byte   *)(b3_config_parms[0].info));
8361      ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8362        ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8363      ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info));
8364      fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8365      if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8366        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8367      if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8368      {
8369
8370        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8371          & (1L << PRIVATE_FAX_PAPER_FORMATS))
8372        {
8373          ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8374            T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8375            T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8376        }
8377
8378 ((T30_INFO *)&nlc[1])->recording_properties =
8379   T30_RECORDING_WIDTH_ISO_A3 |
8380   (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8381   (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8382      }
8383      if(plci->B3_prot == 5)
8384      {
8385        if (i & 0x0002) /* Accept incoming fax-polling requests */
8386          fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8387        if (i & 0x2000) /* Do not use MR compression */
8388          fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8389        if (i & 0x4000) /* Do not use MMR compression */
8390          fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8391        if (i & 0x8000) /* Do not use ECM */
8392          fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8393        if (plci->fax_connect_info_length != 0)
8394        {
8395          ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
8396          ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
8397          ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
8398          fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
8399            (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8400        }
8401      }
8402      /* copy station id to NLC */
8403      for(i=0; i < T30_MAX_STATION_ID_LENGTH; i++)
8404      {
8405        if(i<b3_config_parms[2].length)
8406        {
8407          ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
8408        }
8409        else
8410        {
8411          ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8412        }
8413      }
8414      ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8415      /* copy head line to NLC */
8416      if(b3_config_parms[3].length)
8417      {
8418
8419        pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8420        if (pos != 0)
8421        {
8422          if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8423            pos = 0;
8424          else
8425          {
8426            nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8427            nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8428            len = (byte)b3_config_parms[2].length;
8429            if (len > 20)
8430              len = 20;
8431            if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8432            {
8433              for (i = 0; i < len; i++)
8434                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8435              nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8436              nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8437            }
8438          }
8439        }
8440
8441        len = (byte)b3_config_parms[3].length;
8442        if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8443          len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8444        ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8445        nlc[0] += (byte)(pos + len);
8446        for (i = 0; i < len; i++)
8447          nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte   *)b3_config_parms[3].info)[1+i];
8448      } else
8449        ((T30_INFO *)&nlc[1])->head_line_len = 0;
8450
8451      plci->nsf_control_bits = 0;
8452      if(plci->B3_prot == 5)
8453      {
8454        if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8455         && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8456        {
8457          plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8458        }
8459        if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8460         && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8461        {
8462          plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8463        }
8464        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8465          & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8466        {
8467        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468          & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8469        {
8470          fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8471          if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8472            fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8473          }
8474            len = nlc[0];
8475          pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8476   if (pos < plci->fax_connect_info_length)
8477   {
8478     for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8479              nlc[++len] = plci->fax_connect_info_buffer[pos++];
8480          }
8481   else
8482     nlc[++len] = 0;
8483   if (pos < plci->fax_connect_info_length)
8484   {
8485     for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8486              nlc[++len] = plci->fax_connect_info_buffer[pos++];
8487          }
8488   else
8489     nlc[++len] = 0;
8490          if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8491            & (1L << PRIVATE_FAX_NONSTANDARD))
8492          {
8493     if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8494     {
8495              if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8496                plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8497       for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8498                nlc[++len] = plci->fax_connect_info_buffer[pos++];
8499            }
8500     else
8501     {
8502              if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8503              {
8504                dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8505                nlc[++len] = 0;
8506              }
8507       else
8508       {
8509                if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8510                  plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8511         nlc[++len] = (byte)(b3_config_parms[4].length);
8512         for (i = 0; i < b3_config_parms[4].length; i++)
8513    nlc[++len] = b3_config_parms[4].info[1+i];
8514       }
8515            }
8516          }
8517            nlc[0] = len;
8518   if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8519    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8520   {
8521            ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8522          }
8523        }
8524      }
8525
8526      PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8527      len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8528      for (i = 0; i < len; i++)
8529        plci->fax_connect_info_buffer[i] = nlc[1+i];
8530      ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8531      i += ((T30_INFO *)&nlc[1])->head_line_len;
8532      while (i < nlc[0])
8533        plci->fax_connect_info_buffer[len++] = nlc[++i];
8534      plci->fax_connect_info_length = len;
8535    }
8536    else
8537    {
8538      nlc[0] = 14;
8539      if(b3_config->length!=16)
8540        return _B3_PARM_NOT_SUPPORTED;
8541      for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8542      if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8543        return _B3_PARM_NOT_SUPPORTED;
8544      nlc[13] = b3_config->info[13];
8545      if(GET_WORD(&b3_config->info[15])>=nlc[13])
8546        return _B3_PARM_NOT_SUPPORTED;
8547      nlc[14] = b3_config->info[15];
8548    }
8549  }
8550  else
8551  {
8552    if (plci->B3_prot == 4 
8553     || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8554  }
8555  add_p(plci, NLC, nlc);
8556  return 0;
8557}
8558
8559/*----------------------------------------------------------------*/
8560/*      make the same as add_b23, but only for the modem related  */
8561/*      L2 and L3 B-Chan protocol.                                */
8562/*                                                                */
8563/*      Enabled L2 and L3 Configurations:                         */
8564/*        If L1 == Modem all negotiation                          */
8565/*          only L2 == Modem with full negotiation is allowed     */
8566/*        If L1 == Modem async or sync                            */
8567/*          only L2 == Transparent is allowed                     */
8568/*        L3 == Modem or L3 == Transparent are allowed            */
8569/*      B2 Configuration for modem:                               */
8570/*          word : enable/disable compression, bitoptions         */
8571/*      B3 Configuration for modem:                               */
8572/*          empty                                                 */
8573/*----------------------------------------------------------------*/
8574static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8575{
8576  static byte lli[12] = {1,1};
8577  static byte llc[3] = {2,0,0};
8578  static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8579    API_PARSE mdm_config[2];
8580  word i;
8581  word b2_config = 0;
8582
8583  for(i=0;i<2;i++) mdm_config[i].length = 0;
8584  for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8585
8586  if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8587    && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8588   || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8589    && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8590  {
8591    return (_B_STACK_NOT_SUPPORTED);
8592  }
8593  if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8594   && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8595  {
8596    return (_B_STACK_NOT_SUPPORTED);
8597  }
8598
8599  plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8600  plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8601
8602  if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8603  {
8604    if (api_parse (&bp_parms[4].info[1],
8605                  (word)bp_parms[4].length, "w",
8606                  mdm_config))
8607    {
8608      return (_WRONG_MESSAGE_FORMAT);
8609    }
8610    b2_config = GET_WORD(mdm_config[0].info);
8611  }
8612
8613  /* OK, L2 is modem */
8614
8615  lli[0] = 1;
8616  lli[1] = 1;
8617  if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8618    lli[1] |= 2;
8619  if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8620    lli[1] |= 4;
8621
8622  if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8623    lli[1] |= 0x10;
8624    if (plci->rx_dma_descriptor <= 0) {
8625      plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8626      if (plci->rx_dma_descriptor >= 0)
8627        plci->rx_dma_descriptor++;
8628    }
8629    if (plci->rx_dma_descriptor > 0) {
8630      lli[1] |= 0x40;
8631      lli[0] = 6;
8632      lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8633      lli[3] = (byte)plci->rx_dma_magic;
8634      lli[4] = (byte)(plci->rx_dma_magic >>  8);
8635      lli[5] = (byte)(plci->rx_dma_magic >> 16);
8636      lli[6] = (byte)(plci->rx_dma_magic >> 24);
8637    }
8638  }
8639
8640  if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8641    lli[1] |= 0x20;
8642  }
8643
8644  llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8645    /*V42*/ 10 : /*V42_IN*/ 9;
8646  llc[2] = 4;                      /* pass L3 always transparent */
8647  add_p(plci, LLI, lli);
8648  add_p(plci, LLC, llc);
8649  i =  1;
8650  PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8651  i += 2;
8652  if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8653  {
8654    if (bp_parms[4].length)
8655  {
8656    dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8657    dlc[i++] = 3; /* Addr A */
8658    dlc[i++] = 1; /* Addr B */
8659    dlc[i++] = 7; /* modulo mode */
8660    dlc[i++] = 7; /* window size */
8661    dlc[i++] = 0; /* XID len Lo  */
8662    dlc[i++] = 0; /* XID len Hi  */
8663
8664    if (b2_config & MDM_B2_DISABLE_V42bis)
8665    {
8666      dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8667    }
8668    if (b2_config & MDM_B2_DISABLE_MNP)
8669    {
8670      dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8671    }
8672    if (b2_config & MDM_B2_DISABLE_TRANS)
8673    {
8674      dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8675    }
8676    if (b2_config & MDM_B2_DISABLE_V42)
8677    {
8678      dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8679    }
8680    if (b2_config & MDM_B2_DISABLE_COMP)
8681    {
8682      dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8683    }
8684    i++;
8685  }
8686  }
8687  else
8688  {
8689    dlc[i++] = 3; /* Addr A */
8690    dlc[i++] = 1; /* Addr B */
8691    dlc[i++] = 7; /* modulo mode */
8692    dlc[i++] = 7; /* window size */
8693    dlc[i++] = 0; /* XID len Lo  */
8694    dlc[i++] = 0; /* XID len Hi  */
8695    dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8696               DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8697               DLC_MODEMPROT_DISABLE_V42_DETECT |
8698               DLC_MODEMPROT_DISABLE_COMPRESSION;
8699  }
8700  dlc[0] = (byte)(i - 1);
8701/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8702  add_p(plci, DLC, dlc);
8703  return (0);
8704}
8705
8706
8707/*------------------------------------------------------------------*/
8708/* send a request for the signaling entity                          */
8709/*------------------------------------------------------------------*/
8710
8711static void sig_req(PLCI *plci, byte req, byte Id)
8712{
8713  if(!plci) return;
8714  if(plci->adapter->adapter_disabled) return;
8715  dbug(1,dprintf("sig_req(%x)",req));
8716  if (req == REMOVE)
8717    plci->sig_remove_id = plci->Sig.Id;
8718  if(plci->req_in==plci->req_in_start) {
8719    plci->req_in +=2;
8720    plci->RBuffer[plci->req_in++] = 0;
8721  }
8722  PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8723  plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8724  plci->RBuffer[plci->req_in++] = req;  /* request */
8725  plci->RBuffer[plci->req_in++] = 0;    /* channel */
8726  plci->req_in_start = plci->req_in;
8727}
8728
8729/*------------------------------------------------------------------*/
8730/* send a request for the network layer entity                      */
8731/*------------------------------------------------------------------*/
8732
8733static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8734{
8735  if(!plci) return;
8736  if(plci->adapter->adapter_disabled) return;
8737  dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8738  if (req == REMOVE)
8739  {
8740    plci->nl_remove_id = plci->NL.Id;
8741    ncci_remove (plci, 0, (byte)(ncci != 0));
8742    ncci = 0;
8743  }
8744  if(plci->req_in==plci->req_in_start) {
8745    plci->req_in +=2;
8746    plci->RBuffer[plci->req_in++] = 0;
8747  }
8748  PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8749  plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8750  plci->RBuffer[plci->req_in++] = req;  /* request */
8751  plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8752  plci->req_in_start = plci->req_in;
8753}
8754
8755static void send_req(PLCI *plci)
8756{
8757  ENTITY   * e;
8758  word l;
8759/*  word i; */
8760
8761  if(!plci) return;
8762  if(plci->adapter->adapter_disabled) return;
8763  channel_xmit_xon (plci);
8764
8765        /* if nothing to do, return */
8766  if(plci->req_in==plci->req_out) return;
8767  dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8768
8769  if(plci->nl_req || plci->sig_req) return;
8770
8771  l = GET_WORD(&plci->RBuffer[plci->req_out]);
8772  plci->req_out += 2;
8773  plci->XData[0].P = &plci->RBuffer[plci->req_out];
8774  plci->req_out += l;
8775  if(plci->RBuffer[plci->req_out]==1)
8776  {
8777    e = &plci->NL;
8778    plci->req_out++;
8779    e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8780    e->ReqCh = plci->RBuffer[plci->req_out++];
8781    if(!(e->Id & 0x1f))
8782    {
8783      e->Id = NL_ID;
8784      plci->RBuffer[plci->req_out-4] = CAI;
8785      plci->RBuffer[plci->req_out-3] = 1;
8786      plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8787      plci->RBuffer[plci->req_out-1] = 0;
8788      l+=3;
8789      plci->nl_global_req = plci->nl_req;
8790    }
8791    dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8792  }
8793  else
8794  {
8795    e = &plci->Sig;
8796    if(plci->RBuffer[plci->req_out])
8797      e->Id = plci->RBuffer[plci->req_out];
8798    plci->req_out++;
8799    e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8800    e->ReqCh = plci->RBuffer[plci->req_out++];
8801    if(!(e->Id & 0x1f))
8802      plci->sig_global_req = plci->sig_req;
8803    dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8804  }
8805  plci->XData[0].PLength = l;
8806  e->X = plci->XData;
8807  plci->adapter->request(e);
8808  dbug(1,dprintf("send_ok"));
8809}
8810
8811static void send_data(PLCI *plci)
8812{
8813  DIVA_CAPI_ADAPTER   * a;
8814  DATA_B3_DESC   * data;
8815  NCCI   *ncci_ptr;
8816  word ncci;
8817
8818  if (!plci->nl_req && plci->ncci_ring_list)
8819  {
8820    a = plci->adapter;
8821    ncci = plci->ncci_ring_list;
8822    do
8823    {
8824      ncci = a->ncci_next[ncci];
8825      ncci_ptr = &(a->ncci[ncci]);
8826      if (!(a->ncci_ch[ncci]
8827         && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8828      {
8829        if (ncci_ptr->data_pending)
8830        {
8831          if ((a->ncci_state[ncci] == CONNECTED)
8832           || (a->ncci_state[ncci] == INC_ACT_PENDING)
8833           || (plci->send_disc == ncci))
8834          {
8835            data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8836            if ((plci->B2_prot == B2_V120_ASYNC)
8837             || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8838             || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8839            {
8840              plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8841              plci->NData[1].PLength = data->Length;
8842              if (data->Flags & 0x10)
8843                plci->NData[0].P = v120_break_header;
8844              else
8845                plci->NData[0].P = v120_default_header;
8846              plci->NData[0].PLength = 1 ;
8847              plci->NL.XNum = 2;
8848              plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8849            }
8850            else
8851            {
8852              plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8853              plci->NData[0].PLength = data->Length;
8854              if (data->Flags & 0x10)
8855                plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8856
8857              else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8858                plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8859
8860              else
8861                plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8862            }
8863            plci->NL.X = plci->NData;
8864            plci->NL.ReqCh = a->ncci_ch[ncci];
8865            dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8866            plci->data_sent = true;
8867            plci->data_sent_ptr = data->P;
8868            a->request(&plci->NL);
8869          }
8870          else {
8871            cleanup_ncci_data (plci, ncci);
8872          }
8873        }
8874        else if (plci->send_disc == ncci)
8875        {
8876          /* dprintf("N_DISC"); */
8877          plci->NData[0].PLength = 0;
8878          plci->NL.ReqCh = a->ncci_ch[ncci];
8879          plci->NL.Req = plci->nl_req = N_DISC;
8880          a->request(&plci->NL);
8881          plci->command = _DISCONNECT_B3_R;
8882          plci->send_disc = 0;
8883        }
8884      }
8885    } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8886    plci->ncci_ring_list = ncci;
8887  }
8888}
8889
8890static void listen_check(DIVA_CAPI_ADAPTER *a)
8891{
8892  word i,j;
8893  PLCI   * plci;
8894  byte activnotifiedcalls = 0;
8895
8896  dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8897  if (!remove_started && !a->adapter_disabled)
8898  {
8899    for(i=0;i<a->max_plci;i++)
8900    {
8901      plci = &(a->plci[i]);
8902      if(plci->notifiedcall) activnotifiedcalls++;
8903    }
8904    dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8905
8906    for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8907      if((j=get_plci(a))) {
8908        a->listen_active++;
8909        plci = &a->plci[j-1];
8910        plci->State = LISTENING;
8911
8912        add_p(plci,OAD,"\x01\xfd");
8913
8914        add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8915
8916        add_p(plci,CAI,"\x01\xc0");
8917        add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8918        add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8919        add_p(plci,SHIFT|6,NULL);
8920        add_p(plci,SIN,"\x02\x00\x00");
8921        plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8922        sig_req(plci,ASSIGN,DSIG_ID);
8923        send_req(plci);
8924      }
8925    }
8926  }
8927}
8928
8929/*------------------------------------------------------------------*/
8930/* functions for all parameters sent in INDs                        */
8931/*------------------------------------------------------------------*/
8932
8933static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8934{
8935  word ploc;            /* points to current location within packet */
8936  byte w;
8937  byte wlen;
8938  byte codeset,lock;
8939  byte   * in;
8940  word i;
8941  word code;
8942  word mIEindex = 0;
8943  ploc = 0;
8944  codeset = 0;
8945  lock = 0;
8946
8947  in = plci->Sig.RBuffer->P;
8948  for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8949  {                            /* element but parms array is larger      */
8950    parms[i] = (byte   *)"";
8951  }
8952  for(i=0; i<multiIEsize; i++)
8953  {
8954    parms[i] = (byte   *)"";
8955  }
8956
8957  while(ploc<plci->Sig.RBuffer->length-1) {
8958
8959        /* read information element id and length                   */
8960    w = in[ploc];
8961
8962    if(w & 0x80) {
8963/*    w &=0xf0; removed, cannot detect congestion levels */
8964/*    upper 4 bit masked with w==SHIFT now               */
8965      wlen = 0;
8966    }
8967    else {
8968      wlen = (byte)(in[ploc+1]+1);
8969    }
8970        /* check if length valid (not exceeding end of packet)      */
8971    if((ploc+wlen) > 270) return ;
8972    if(lock & 0x80) lock &=0x7f;
8973    else codeset = lock;
8974
8975    if((w&0xf0)==SHIFT) {
8976      codeset = in[ploc];
8977      if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8978      codeset &=7;
8979      lock |=0x80;
8980    }
8981    else {
8982      if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8983      else code = w;
8984      code |= (codeset<<8);
8985
8986      for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8987
8988      if(i<parms_id[0]+1) {
8989        if(!multiIEsize) { /* with multiIEs use next field index,          */
8990          mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8991        }
8992
8993        parms[mIEindex] = &in[ploc+1];
8994        dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8995        if(parms_id[i]==OAD
8996        || parms_id[i]==CONN_NR
8997        || parms_id[i]==CAD) {
8998          if(in[ploc+2] &0x80) {
8999            in[ploc+0] = (byte)(in[ploc+1]+1);
9000            in[ploc+1] = (byte)(in[ploc+2] &0x7f);
9001            in[ploc+2] = 0x80;
9002            parms[mIEindex] = &in[ploc];
9003          }
9004        }
9005        mIEindex++;       /* effects multiIEs only */
9006      }
9007    }
9008
9009    ploc +=(wlen+1);
9010  }
9011  return ;
9012}
9013
9014/*------------------------------------------------------------------*/
9015/* try to match a cip from received BC and HLC                      */
9016/*------------------------------------------------------------------*/
9017
9018static byte ie_compare(byte *ie1, byte *ie2)
9019{
9020  word i;
9021  if(!ie1 || ! ie2) return false;
9022  if(!ie1[0]) return false;
9023  for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9024  return true;
9025}
9026
9027static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9028{
9029  word i;
9030  word j;
9031
9032  for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9033
9034  for(j=16;j<29 &&
9035           (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9036  if(j==29) return i;
9037  return j;
9038}
9039
9040
9041static byte AddInfo(byte   **add_i,
9042                    byte   **fty_i,
9043                    byte   *esc_chi,
9044                    byte *facility)
9045{
9046  byte i;
9047  byte j;
9048  byte k;
9049  byte flen;
9050  byte len=0;
9051   /* facility is a nested structure */
9052   /* FTY can be more than once      */
9053
9054        if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9055  {
9056    add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9057  }
9058
9059  else
9060  {
9061    add_i[0] = (byte   *)"";
9062  }
9063  if(!fty_i[0][0])
9064  {
9065    add_i[3] = (byte   *)"";
9066  }
9067  else
9068  {    /* facility array found  */
9069    for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9070    {
9071      dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9072      len += fty_i[i][0];
9073      len += 2;
9074      flen=fty_i[i][0];
9075      facility[j++]=0x1c; /* copy fac IE */
9076      for(k=0;k<=flen;k++,j++)
9077      {
9078        facility[j]=fty_i[i][k];
9079/*      dbug(1,dprintf("%x ",facility[j])); */
9080      }
9081    }
9082    facility[0] = len;
9083    add_i[3] = facility;
9084  }
9085/*  dbug(1,dprintf("FacArrLen=%d ",len)); */
9086  len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9087  len += 4;                          /* calculate length of all */
9088  return(len);
9089}
9090
9091/*------------------------------------------------------------------*/
9092/* voice and codec features                                         */
9093/*------------------------------------------------------------------*/
9094
9095static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9096{
9097  byte voice_chi[] = "\x02\x18\x01";
9098  byte channel;
9099
9100  channel = chi[chi[0]]&0x3;
9101  dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9102  voice_chi[2] = (channel) ? channel : 1;
9103  add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
9104  add_p(plci,ESC,voice_chi);                  /* Channel */
9105  sig_req(plci,TEL_CTRL,0);
9106  send_req(plci);
9107  if(a->AdvSignalPLCI)
9108  {
9109    adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9110  }
9111}
9112
9113static void VoiceChannelOff(PLCI *plci)
9114{
9115  dbug(1,dprintf("ExtDevOFF"));
9116  add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
9117  sig_req(plci,TEL_CTRL,0);
9118  send_req(plci);
9119  if(plci->adapter->AdvSignalPLCI)
9120  {
9121    adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9122  }
9123}
9124
9125
9126static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9127                            byte hook_listen)
9128{
9129  word j;
9130  PLCI   *splci;
9131
9132  /* check if hardware supports handset with hook states (adv.codec) */
9133  /* or if just a on board codec is supported                        */
9134  /* the advanced codec plci is just for internal use                */
9135
9136  /* diva Pro with on-board codec:                                   */
9137  if(a->profile.Global_Options & HANDSET)
9138  {
9139    /* new call, but hook states are already signalled */
9140    if(a->AdvCodecFLAG)
9141    {
9142      if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9143      {
9144        dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9145        return 0x2001; /* codec in use by another application */
9146      }
9147      if(plci!=NULL)
9148      {
9149        a->AdvSignalPLCI = plci;
9150        plci->tel=ADV_VOICE;
9151      }
9152      return 0;                      /* adv codec still used */
9153    }
9154    if((j=get_plci(a)))
9155    {
9156      splci = &a->plci[j-1];
9157      splci->tel = CODEC_PERMANENT;
9158      /* hook_listen indicates if a facility_req with handset/hook support */
9159      /* was sent. Otherwise if just a call on an external device was made */
9160      /* the codec will be used but the hook info will be discarded (just  */
9161      /* the external controller is in use                                 */
9162      if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9163      else
9164      {
9165        splci->State = ADVANCED_VOICE_NOSIG;
9166        if(plci)
9167        {
9168          plci->spoofed_msg = SPOOFING_REQUIRED;
9169        }
9170                                               /* indicate D-ch connect if  */
9171      }                                        /* codec is connected OK     */
9172      if(plci!=NULL)
9173      {
9174        a->AdvSignalPLCI = plci;
9175        plci->tel=ADV_VOICE;
9176      }
9177      a->AdvSignalAppl = appl;
9178      a->AdvCodecFLAG = true;
9179      a->AdvCodecPLCI = splci;
9180      add_p(splci,CAI,"\x01\x15");
9181      add_p(splci,LLI,"\x01\x00");
9182      add_p(splci,ESC,"\x02\x18\x00");
9183      add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9184      splci->internal_command = PERM_COD_ASSIGN;
9185      dbug(1,dprintf("Codec Assign"));
9186      sig_req(splci,ASSIGN,DSIG_ID);
9187      send_req(splci);
9188    }
9189    else
9190    {
9191      return 0x2001; /* wrong state, no more plcis */
9192    }
9193  }
9194  else if(a->profile.Global_Options & ON_BOARD_CODEC)
9195  {
9196    if(hook_listen) return 0x300B;               /* Facility not supported */
9197                                                 /* no hook with SCOM      */
9198    if(plci!=NULL) plci->tel = CODEC;
9199    dbug(1,dprintf("S/SCOM codec"));
9200    /* first time we use the scom-s codec we must shut down the internal   */
9201    /* handset application of the card. This can be done by an assign with */
9202    /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9203    if(!a->scom_appl_disable){
9204      if((j=get_plci(a))) {
9205        splci = &a->plci[j-1];
9206        add_p(splci,CAI,"\x01\x80");
9207        add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9208        sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9209        send_req(splci);
9210        a->scom_appl_disable = true;
9211      }
9212      else{
9213        return 0x2001; /* wrong state, no more plcis */
9214      }
9215    }
9216  }
9217  else return 0x300B;               /* Facility not supported */
9218
9219  return 0;
9220}
9221
9222
9223static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9224{
9225
9226  dbug(1,dprintf("CodecIdCheck"));
9227
9228  if(a->AdvSignalPLCI == plci)
9229  {
9230    dbug(1,dprintf("PLCI owns codec"));
9231    VoiceChannelOff(a->AdvCodecPLCI);
9232    if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9233    {
9234      dbug(1,dprintf("remove temp codec PLCI"));
9235      plci_remove(a->AdvCodecPLCI);
9236      a->AdvCodecFLAG  = 0;
9237      a->AdvCodecPLCI  = NULL;
9238      a->AdvSignalAppl = NULL;
9239    }
9240    a->AdvSignalPLCI = NULL;
9241  }
9242}
9243
9244/* -------------------------------------------------------------------
9245    Ask for physical address of card on PCI bus
9246   ------------------------------------------------------------------- */
9247static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9248                                        IDI_SYNC_REQ  * preq) {
9249  a->sdram_bar = 0;
9250  if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9251    ENTITY   * e = (ENTITY   *)preq;
9252
9253    e->user[0] = a->Id - 1;
9254    preq->xdi_sdram_bar.info.bar    = 0;
9255    preq->xdi_sdram_bar.Req         = 0;
9256    preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9257
9258    (*(a->request))(e);
9259
9260    a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9261    dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9262  }
9263}
9264
9265/* -------------------------------------------------------------------
9266     Ask XDI about extended features
9267   ------------------------------------------------------------------- */
9268static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9269  IDI_SYNC_REQ   * preq;
9270    char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9271
9272    char features[4];
9273  preq = (IDI_SYNC_REQ   *)&buffer[0];
9274
9275  if (!diva_xdi_extended_features) {
9276    ENTITY   * e = (ENTITY   *)preq;
9277    diva_xdi_extended_features |= 0x80000000;
9278
9279    e->user[0] = a->Id - 1;
9280    preq->xdi_extended_features.Req = 0;
9281    preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9282    preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9283    preq->xdi_extended_features.info.features = &features[0];
9284
9285    (*(a->request))(e);
9286
9287    if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9288      /*
9289         Check features located in the byte '0'
9290         */
9291      if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9292        diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9293      }
9294      if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9295        diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9296        dbug(1,dprintf("XDI provides RxDMA"));
9297      }
9298      if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9299        diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9300      }
9301      if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9302        diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9303        dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9304      }
9305
9306    }
9307  }
9308
9309  diva_ask_for_xdi_sdram_bar (a, preq);
9310}
9311
9312/*------------------------------------------------------------------*/
9313/* automatic law                                                    */
9314/*------------------------------------------------------------------*/
9315/* called from OS specific part after init time to get the Law              */
9316/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9317void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9318{
9319  word j;
9320  PLCI   *splci;
9321
9322  if(a->automatic_law) {
9323    return;
9324  }
9325  if((j=get_plci(a))) {
9326    diva_get_extended_adapter_features (a);
9327    splci = &a->plci[j-1];
9328    a->automatic_lawPLCI = splci;
9329    a->automatic_law = 1;
9330    add_p(splci,CAI,"\x01\x80");
9331    add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9332    splci->internal_command = USELAW_REQ;
9333    splci->command = 0;
9334    splci->number = 0;
9335    sig_req(splci,ASSIGN,DSIG_ID);
9336    send_req(splci);
9337  }
9338}
9339
9340/* called from OS specific part if an application sends an Capi20Release */
9341word CapiRelease(word Id)
9342{
9343  word i, j, appls_found;
9344  PLCI   *plci;
9345  APPL   *this;
9346  DIVA_CAPI_ADAPTER   *a;
9347
9348  if (!Id)
9349  {
9350    dbug(0,dprintf("A: CapiRelease(Id==0)"));
9351    return (_WRONG_APPL_ID);
9352  }
9353
9354  this = &application[Id-1];               /* get application pointer */
9355
9356  for(i=0,appls_found=0; i<max_appl; i++)
9357  {
9358    if(application[i].Id)       /* an application has been found        */
9359    {
9360      appls_found++;
9361    }
9362  }
9363
9364  for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9365  {
9366    a = &adapter[i];
9367    if (a->request)
9368    {
9369      a->Info_Mask[Id-1] = 0;
9370      a->CIP_Mask[Id-1] = 0;
9371      a->Notification_Mask[Id-1] = 0;
9372      a->codec_listen[Id-1] = NULL;
9373      a->requested_options_table[Id-1] = 0;
9374      for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9375      {                                      /* with this application   */
9376        plci = &a->plci[j];
9377        if(plci->Id)                         /* if plci owns no application */
9378        {                                    /* it may be not jet connected */
9379          if(plci->State==INC_CON_PENDING
9380          || plci->State==INC_CON_ALERT)
9381          {
9382            if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9383            {
9384              clear_c_ind_mask_bit (plci, (word)(Id-1));
9385              if(c_ind_mask_empty (plci))
9386              {
9387                sig_req(plci,HANGUP,0);
9388                send_req(plci);
9389                plci->State = OUTG_DIS_PENDING;
9390              }
9391            }
9392          }
9393          if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9394          {
9395            clear_c_ind_mask_bit (plci, (word)(Id-1));
9396            if(c_ind_mask_empty (plci))
9397            {
9398              if(!plci->appl)
9399              {
9400                plci_remove(plci);
9401                plci->State = IDLE;
9402              }
9403            }
9404          }
9405          if(plci->appl==this)
9406          {
9407            plci->appl = NULL;
9408            plci_remove(plci);
9409            plci->State = IDLE;
9410          }
9411        }
9412      }
9413      listen_check(a);
9414
9415      if(a->flag_dynamic_l1_down)
9416      {
9417        if(appls_found==1)            /* last application does a capi release */
9418        {
9419          if((j=get_plci(a)))
9420          {
9421            plci = &a->plci[j-1];
9422            plci->command = 0;
9423            add_p(plci,OAD,"\x01\xfd");
9424            add_p(plci,CAI,"\x01\x80");
9425            add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9426            add_p(plci,SHIFT|6,NULL);
9427            add_p(plci,SIN,"\x02\x00\x00");
9428            plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9429            sig_req(plci,ASSIGN,DSIG_ID);
9430            add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9431            sig_req(plci,SIG_CTRL,0);
9432            send_req(plci);
9433          }
9434        }
9435      }
9436      if(a->AdvSignalAppl==this)
9437      {
9438        this->NullCREnable = false;
9439        if (a->AdvCodecPLCI)
9440        {
9441          plci_remove(a->AdvCodecPLCI);
9442          a->AdvCodecPLCI->tel = 0;
9443          a->AdvCodecPLCI->adv_nl = 0;
9444        }
9445        a->AdvSignalAppl = NULL;
9446        a->AdvSignalPLCI = NULL;
9447        a->AdvCodecFLAG = 0;
9448        a->AdvCodecPLCI = NULL;
9449      }
9450    }
9451  }
9452
9453  this->Id = 0;
9454
9455  return GOOD;
9456}
9457
9458static word plci_remove_check(PLCI   *plci)
9459{
9460  if(!plci) return true;
9461  if(!plci->NL.Id && c_ind_mask_empty (plci))
9462  {
9463    if(plci->Sig.Id == 0xff)
9464      plci->Sig.Id = 0;
9465    if(!plci->Sig.Id)
9466    {
9467      dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9468      dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9469      if (plci->Id)
9470      {
9471        CodecIdCheck(plci->adapter, plci);
9472        clear_b1_config (plci);
9473        ncci_remove (plci, 0, false);
9474        plci_free_msg_in_queue (plci);
9475        channel_flow_control_remove (plci);
9476        plci->Id = 0;
9477        plci->State = IDLE;
9478        plci->channels = 0;
9479        plci->appl = NULL;
9480        plci->notifiedcall = 0;
9481      }
9482      listen_check(plci->adapter);
9483      return true;
9484    }
9485  }
9486  return false;
9487}
9488
9489
9490/*------------------------------------------------------------------*/
9491
9492static byte plci_nl_busy (PLCI   *plci)
9493{
9494  /* only applicable for non-multiplexed protocols */
9495  return (plci->nl_req
9496    || (plci->ncci_ring_list
9497     && plci->adapter->ncci_ch[plci->ncci_ring_list]
9498     && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9499}
9500
9501
9502/*------------------------------------------------------------------*/
9503/* DTMF facilities                                                  */
9504/*------------------------------------------------------------------*/
9505
9506
9507static struct
9508{
9509  byte send_mask;
9510  byte listen_mask;
9511  byte character;
9512  byte code;
9513} dtmf_digit_map[] =
9514{
9515  { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9516  { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9517  { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9518  { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9519  { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9520  { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9521  { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9522  { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9523  { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9524  { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9525  { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9526  { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9527  { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9528  { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9529  { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9530  { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9531  { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9532  { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9533  { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9534  { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9535
9536  { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9537  { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9538  { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9539  { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9540  { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9541  { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9542  { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9543  { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9544  { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9545  { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9546  { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9547  { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9548  { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9549  { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9550  { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9551  { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9552  { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9553  { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9554  { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9555  { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9556  { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9557  { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9558  { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9559  { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9560  { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9561  { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9562  { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9563  { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9564  { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9565  { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9566  { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9567  { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9568  { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9569  { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9570  { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9571  { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9572  { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9573  { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9574  { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9575  { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9576  { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9577  { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9578  { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9579  { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9580  { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9581  { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9582  { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9583  { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9584  { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9585  { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9586  { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9587  { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9588
9589};
9590
9591#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9592
9593
9594static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9595{
9596  word min_digit_duration, min_gap_duration;
9597
9598  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9599    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9600    (char   *)(FILE_), __LINE__, enable_mask));
9601
9602  if (enable_mask != 0)
9603  {
9604    min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9605    min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9606    plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9607    PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9608    PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9609    plci->NData[0].PLength = 5;
9610
9611    PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9612    plci->NData[0].PLength += 2;
9613    capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9614
9615  }
9616  else
9617  {
9618    plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9619    plci->NData[0].PLength = 1;
9620
9621    capidtmf_recv_disable (&(plci->capidtmf_state));
9622
9623  }
9624  plci->NData[0].P = plci->internal_req_buffer;
9625  plci->NL.X = plci->NData;
9626  plci->NL.ReqCh = 0;
9627  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9628  plci->adapter->request (&plci->NL);
9629}
9630
9631
9632static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9633{
9634  word w, i;
9635
9636  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9637    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9638    (char   *)(FILE_), __LINE__, digit_count));
9639
9640  plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9641  w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9642  PUT_WORD (&plci->internal_req_buffer[1], w);
9643  w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9644  PUT_WORD (&plci->internal_req_buffer[3], w);
9645  for (i = 0; i < digit_count; i++)
9646  {
9647    w = 0;
9648    while ((w < DTMF_DIGIT_MAP_ENTRIES)
9649      && (digit_buffer[i] != dtmf_digit_map[w].character))
9650    {
9651      w++;
9652    }
9653    plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9654      dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9655  }
9656  plci->NData[0].PLength = 5 + digit_count;
9657  plci->NData[0].P = plci->internal_req_buffer;
9658  plci->NL.X = plci->NData;
9659  plci->NL.ReqCh = 0;
9660  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9661  plci->adapter->request (&plci->NL);
9662}
9663
9664
9665static void dtmf_rec_clear_config (PLCI   *plci)
9666{
9667
9668  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9669    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9670    (char   *)(FILE_), __LINE__));
9671
9672  plci->dtmf_rec_active = 0;
9673  plci->dtmf_rec_pulse_ms = 0;
9674  plci->dtmf_rec_pause_ms = 0;
9675
9676  capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9677
9678}
9679
9680
9681static void dtmf_send_clear_config (PLCI   *plci)
9682{
9683
9684  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9685    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9686    (char   *)(FILE_), __LINE__));
9687
9688  plci->dtmf_send_requests = 0;
9689  plci->dtmf_send_pulse_ms = 0;
9690  plci->dtmf_send_pause_ms = 0;
9691}
9692
9693
9694static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9695{
9696
9697  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9698    UnMapId (Id), (char   *)(FILE_), __LINE__));
9699
9700  while (plci->dtmf_send_requests != 0)
9701    dtmf_confirmation (Id, plci);
9702}
9703
9704
9705static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9706{
9707
9708  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9709    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9710
9711  return (GOOD);
9712}
9713
9714
9715static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9716{
9717  word Info;
9718
9719  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9720    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9721
9722  Info = GOOD;
9723  if (plci->B1_facilities & B1_FACILITY_DTMFR)
9724  {
9725    switch (plci->adjust_b_state)
9726    {
9727    case ADJUST_B_RESTORE_DTMF_1:
9728      plci->internal_command = plci->adjust_b_command;
9729      if (plci_nl_busy (plci))
9730      {
9731        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9732        break;
9733      }
9734      dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9735      plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9736      break;
9737    case ADJUST_B_RESTORE_DTMF_2:
9738      if ((Rc != OK) && (Rc != OK_FC))
9739      {
9740        dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9741          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9742        Info = _WRONG_STATE;
9743        break;
9744      }
9745      break;
9746    }
9747  }
9748  return (Info);
9749}
9750
9751
9752static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9753{
9754  word internal_command, Info;
9755  byte mask;
9756    byte result[4];
9757
9758  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9759    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9760    plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9761    plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9762
9763  Info = GOOD;
9764  result[0] = 2;
9765  PUT_WORD (&result[1], DTMF_SUCCESS);
9766  internal_command = plci->internal_command;
9767  plci->internal_command = 0;
9768  mask = 0x01;
9769  switch (plci->dtmf_cmd)
9770  {
9771
9772  case DTMF_LISTEN_TONE_START:
9773    mask <<= 1;
9774  case DTMF_LISTEN_MF_START:
9775    mask <<= 1;
9776
9777  case DTMF_LISTEN_START:
9778    switch (internal_command)
9779    {
9780    default:
9781      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9782        B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9783    case DTMF_COMMAND_1:
9784      if (adjust_b_process (Id, plci, Rc) != GOOD)
9785      {
9786        dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9787          UnMapId (Id), (char   *)(FILE_), __LINE__));
9788        Info = _FACILITY_NOT_SUPPORTED;
9789        break;
9790      }
9791      if (plci->internal_command)
9792        return;
9793    case DTMF_COMMAND_2:
9794      if (plci_nl_busy (plci))
9795      {
9796        plci->internal_command = DTMF_COMMAND_2;
9797        return;
9798      }
9799      plci->internal_command = DTMF_COMMAND_3;
9800      dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9801      return;
9802    case DTMF_COMMAND_3:
9803      if ((Rc != OK) && (Rc != OK_FC))
9804      {
9805        dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9806          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9807        Info = _FACILITY_NOT_SUPPORTED;
9808        break;
9809      }
9810
9811      plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9812
9813      plci->dtmf_rec_active |= mask;
9814      break;
9815    }
9816    break;
9817
9818
9819  case DTMF_LISTEN_TONE_STOP:
9820    mask <<= 1;
9821  case DTMF_LISTEN_MF_STOP:
9822    mask <<= 1;
9823
9824  case DTMF_LISTEN_STOP:
9825    switch (internal_command)
9826    {
9827    default:
9828      plci->dtmf_rec_active &= ~mask;
9829      if (plci->dtmf_rec_active)
9830        break;
9831/*
9832    case DTMF_COMMAND_1:
9833      if (plci->dtmf_rec_active)
9834      {
9835        if (plci_nl_busy (plci))
9836        {
9837          plci->internal_command = DTMF_COMMAND_1;
9838          return;
9839        }
9840        plci->dtmf_rec_active &= ~mask;
9841        plci->internal_command = DTMF_COMMAND_2;
9842        dtmf_enable_receiver (plci, false);
9843        return;
9844      }
9845      Rc = OK;
9846    case DTMF_COMMAND_2:
9847      if ((Rc != OK) && (Rc != OK_FC))
9848      {
9849        dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9850          UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9851        Info = _FACILITY_NOT_SUPPORTED;
9852        break;
9853      }
9854*/
9855      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9856        ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9857    case DTMF_COMMAND_3:
9858      if (adjust_b_process (Id, plci, Rc) != GOOD)
9859      {
9860        dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9861          UnMapId (Id), (char   *)(FILE_), __LINE__));
9862        Info = _FACILITY_NOT_SUPPORTED;
9863        break;
9864      }
9865      if (plci->internal_command)
9866        return;
9867      break;
9868    }
9869    break;
9870
9871
9872  case DTMF_SEND_TONE:
9873    mask <<= 1;
9874  case DTMF_SEND_MF:
9875    mask <<= 1;
9876
9877  case DTMF_DIGITS_SEND:
9878    switch (internal_command)
9879    {
9880    default:
9881      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9882        ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9883        DTMF_COMMAND_1);
9884    case DTMF_COMMAND_1:
9885      if (adjust_b_process (Id, plci, Rc) != GOOD)
9886      {
9887        dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9888          UnMapId (Id), (char   *)(FILE_), __LINE__));
9889        Info = _FACILITY_NOT_SUPPORTED;
9890        break;
9891      }
9892      if (plci->internal_command)
9893        return;
9894    case DTMF_COMMAND_2:
9895      if (plci_nl_busy (plci))
9896      {
9897        plci->internal_command = DTMF_COMMAND_2;
9898        return;
9899      }
9900      plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9901      plci->internal_command = DTMF_COMMAND_3;
9902      dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9903      return;
9904    case DTMF_COMMAND_3:
9905      if ((Rc != OK) && (Rc != OK_FC))
9906      {
9907        dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9908          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9909        if (plci->dtmf_send_requests != 0)
9910          (plci->dtmf_send_requests)--;
9911        Info = _FACILITY_NOT_SUPPORTED;
9912        break;
9913      }
9914      return;
9915    }
9916    break;
9917  }
9918  sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9919    "wws", Info, SELECTOR_DTMF, result);
9920}
9921
9922
9923static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9924{
9925  word Info;
9926  word i, j;
9927  byte mask;
9928    API_PARSE dtmf_parms[5];
9929    byte result[40];
9930
9931  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9932    UnMapId (Id), (char   *)(FILE_), __LINE__));
9933
9934  Info = GOOD;
9935  result[0] = 2;
9936  PUT_WORD (&result[1], DTMF_SUCCESS);
9937  if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9938  {
9939    dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9940      UnMapId (Id), (char   *)(FILE_), __LINE__));
9941    Info = _FACILITY_NOT_SUPPORTED;
9942  }
9943  else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9944  {
9945    dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9946      UnMapId (Id), (char   *)(FILE_), __LINE__));
9947    Info = _WRONG_MESSAGE_FORMAT;
9948  }
9949
9950  else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9951    || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9952  {
9953    if (!((a->requested_options_table[appl->Id-1])
9954        & (1L << PRIVATE_DTMF_TONE)))
9955    {
9956      dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9957        UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9958      PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9959    }
9960    else
9961    {
9962      for (i = 0; i < 32; i++)
9963        result[4 + i] = 0;
9964      if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9965      {
9966        for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9967        {
9968          if (dtmf_digit_map[i].listen_mask != 0)
9969            result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9970        }
9971      }
9972      else
9973      {
9974        for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9975        {
9976          if (dtmf_digit_map[i].send_mask != 0)
9977            result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9978        }
9979      }
9980      result[0] = 3 + 32;
9981      result[3] = 32;
9982    }
9983  }
9984
9985  else if (plci == NULL)
9986  {
9987    dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9988      UnMapId (Id), (char   *)(FILE_), __LINE__));
9989    Info = _WRONG_IDENTIFIER;
9990  }
9991  else
9992  {
9993    if (!plci->State
9994     || !plci->NL.Id || plci->nl_remove_id)
9995    {
9996      dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9997        UnMapId (Id), (char   *)(FILE_), __LINE__));
9998      Info = _WRONG_STATE;
9999    }
10000    else
10001    {
10002      plci->command = 0;
10003      plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
10004      mask = 0x01;
10005      switch (plci->dtmf_cmd)
10006      {
10007
10008      case DTMF_LISTEN_TONE_START:
10009      case DTMF_LISTEN_TONE_STOP:
10010        mask <<= 1;
10011      case DTMF_LISTEN_MF_START:
10012      case DTMF_LISTEN_MF_STOP:
10013        mask <<= 1;
10014        if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10015          & (1L << PRIVATE_DTMF_TONE)))
10016        {
10017          dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10018            UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10019          PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10020          break;
10021        }
10022
10023      case DTMF_LISTEN_START:
10024      case DTMF_LISTEN_STOP:
10025        if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10026         && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10027        {
10028          dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10029            UnMapId (Id), (char   *)(FILE_), __LINE__));
10030          Info = _FACILITY_NOT_SUPPORTED;
10031          break;
10032        }
10033        if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10034        {
10035          if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10036          {
10037            plci->dtmf_rec_pulse_ms = 0;
10038            plci->dtmf_rec_pause_ms = 0;
10039          }
10040          else
10041          {
10042            plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10043            plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10044          }
10045        }
10046        start_internal_command (Id, plci, dtmf_command);
10047        return (false);
10048
10049
10050      case DTMF_SEND_TONE:
10051        mask <<= 1;
10052      case DTMF_SEND_MF:
10053        mask <<= 1;
10054        if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10055          & (1L << PRIVATE_DTMF_TONE)))
10056        {
10057          dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10058            UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10059          PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10060          break;
10061        }
10062
10063      case DTMF_DIGITS_SEND:
10064        if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10065        {
10066          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10067            UnMapId (Id), (char   *)(FILE_), __LINE__));
10068          Info = _WRONG_MESSAGE_FORMAT;
10069          break;
10070        }
10071        if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10072        {
10073          plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10074          plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10075        }
10076        i = 0;
10077        j = 0;
10078        while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10079        {
10080          j = 0;
10081          while ((j < DTMF_DIGIT_MAP_ENTRIES)
10082            && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10083             || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10084          {
10085            j++;
10086          }
10087          i++;
10088        }
10089        if (j == DTMF_DIGIT_MAP_ENTRIES)
10090        {
10091          dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10092            UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10093          PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10094          break;
10095        }
10096        if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10097        {
10098          dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10099            UnMapId (Id), (char   *)(FILE_), __LINE__));
10100          Info = _WRONG_STATE;
10101          break;
10102        }
10103        api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10104        start_internal_command (Id, plci, dtmf_command);
10105        return (false);
10106
10107      default:
10108        dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10109          UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10110        PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10111      }
10112    }
10113  }
10114  sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10115    "wws", Info, SELECTOR_DTMF, result);
10116  return (false);
10117}
10118
10119
10120static void dtmf_confirmation (dword Id, PLCI   *plci)
10121{
10122  word Info;
10123  word i;
10124    byte result[4];
10125
10126  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10127    UnMapId (Id), (char   *)(FILE_), __LINE__));
10128
10129  Info = GOOD;
10130  result[0] = 2;
10131  PUT_WORD (&result[1], DTMF_SUCCESS);
10132  if (plci->dtmf_send_requests != 0)
10133  {
10134    sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10135      "wws", GOOD, SELECTOR_DTMF, result);
10136    (plci->dtmf_send_requests)--;
10137    for (i = 0; i < plci->dtmf_send_requests; i++)
10138      plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10139  }
10140}
10141
10142
10143static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10144{
10145  word i, j, n;
10146
10147  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10148    UnMapId (Id), (char   *)(FILE_), __LINE__));
10149
10150  n = 0;
10151  for (i = 1; i < length; i++)
10152  {
10153    j = 0;
10154    while ((j < DTMF_DIGIT_MAP_ENTRIES)
10155      && ((msg[i] != dtmf_digit_map[j].code)
10156       || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10157    {
10158      j++;
10159    }
10160    if (j < DTMF_DIGIT_MAP_ENTRIES)
10161    {
10162
10163      if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10164       && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10165       && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10166      {
10167        if (n + 1 == i)
10168        {
10169          for (i = length; i > n + 1; i--)
10170            msg[i] = msg[i - 1];
10171          length++;
10172          i++;
10173        }
10174        msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10175      }
10176      plci->tone_last_indication_code = dtmf_digit_map[j].character;
10177
10178      msg[++n] = dtmf_digit_map[j].character;
10179    }
10180  }
10181  if (n != 0)
10182  {
10183    msg[0] = (byte) n;
10184    sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10185  }
10186}
10187
10188
10189/*------------------------------------------------------------------*/
10190/* DTMF parameters                                                  */
10191/*------------------------------------------------------------------*/
10192
10193static void dtmf_parameter_write (PLCI   *plci)
10194{
10195  word i;
10196    byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10197
10198  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10199    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10200    (char   *)(FILE_), __LINE__));
10201
10202  parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10203  parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10204  for (i = 0; i < plci->dtmf_parameter_length; i++)
10205    parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10206  add_p (plci, FTY, parameter_buffer);
10207  sig_req (plci, TEL_CTRL, 0);
10208  send_req (plci);
10209}
10210
10211
10212static void dtmf_parameter_clear_config (PLCI   *plci)
10213{
10214
10215  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10216    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10217    (char   *)(FILE_), __LINE__));
10218
10219  plci->dtmf_parameter_length = 0;
10220}
10221
10222
10223static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10224{
10225
10226  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10227    UnMapId (Id), (char   *)(FILE_), __LINE__));
10228
10229}
10230
10231
10232static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10233{
10234
10235  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10236    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10237
10238  return (GOOD);
10239}
10240
10241
10242static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10243{
10244  word Info;
10245
10246  dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10247    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10248
10249  Info = GOOD;
10250  if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10251   && (plci->dtmf_parameter_length != 0))
10252  {
10253    switch (plci->adjust_b_state)
10254    {
10255    case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10256      plci->internal_command = plci->adjust_b_command;
10257      if (plci->sig_req)
10258      {
10259        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10260        break;
10261      }
10262      dtmf_parameter_write (plci);
10263      plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10264      break;
10265    case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10266      if ((Rc != OK) && (Rc != OK_FC))
10267      {
10268        dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10269          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10270        Info = _WRONG_STATE;
10271        break;
10272      }
10273      break;
10274    }
10275  }
10276  return (Info);
10277}
10278
10279
10280/*------------------------------------------------------------------*/
10281/* Line interconnect facilities                                     */
10282/*------------------------------------------------------------------*/
10283
10284
10285LI_CONFIG   *li_config_table;
10286word li_total_channels;
10287
10288
10289/*------------------------------------------------------------------*/
10290/* translate a CHI information element to a channel number          */
10291/* returns 0xff - any channel                                       */
10292/*         0xfe - chi wrong coding                                  */
10293/*         0xfd - D-channel                                         */
10294/*         0x00 - no channel                                        */
10295/*         else channel number / PRI: timeslot                      */
10296/* if channels is provided we accept more than one channel.         */
10297/*------------------------------------------------------------------*/
10298
10299static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10300{
10301  int p;
10302  int i;
10303  dword map;
10304  byte excl;
10305  byte ofs;
10306  byte ch;
10307
10308  if (pchannelmap) *pchannelmap = 0;
10309  if(!chi[0]) return 0xff;
10310  excl = 0;
10311
10312  if(chi[1] & 0x20) {
10313    if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10314    for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10315    if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10316    if((chi[1] |0xc8)!=0xe9) return 0xfe;
10317    if(chi[1] &0x08) excl = 0x40;
10318
10319        /* int. id present */
10320    if(chi[1] &0x40) {
10321      p=i+1;
10322      for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10323      if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10324    }
10325
10326        /* coding standard, Number/Map, Channel Type */
10327    p=i+1;
10328    for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10329    if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10330    if((chi[p]|0xd0)!=0xd3) return 0xfe;
10331
10332        /* Number/Map */
10333    if(chi[p] &0x10) {
10334
10335        /* map */
10336      if((chi[0]-p)==4) ofs = 0;
10337      else if((chi[0]-p)==3) ofs = 1;
10338      else return 0xfe;
10339      ch = 0;
10340      map = 0;
10341      for(i=0; i<4 && p<chi[0]; i++) {
10342        p++;
10343        ch += 8;
10344        map <<= 8;
10345        if(chi[p]) {
10346          for (ch=0; !(chi[p] & (1 << ch)); ch++);
10347          map |= chi[p];
10348        }
10349      }
10350      ch += ofs;
10351      map <<= ofs;
10352    }
10353    else {
10354
10355        /* number */
10356      p=i+1;
10357      ch = chi[p] &0x3f;
10358      if(pchannelmap) {
10359        if((byte)(chi[0]-p)>30) return 0xfe;
10360        map = 0;
10361        for(i=p; i<=chi[0]; i++) {
10362          if ((chi[i] &0x7f) > 31) return 0xfe;
10363          map |= (1L << (chi[i] &0x7f));
10364        }
10365      }
10366      else {
10367        if(p!=chi[0]) return 0xfe;
10368        if (ch > 31) return 0xfe;
10369        map = (1L << ch);
10370      }
10371      if(chi[p] &0x40) return 0xfe;
10372    }
10373    if (pchannelmap) *pchannelmap = map;
10374    else if (map != ((dword)(1L << ch))) return 0xfe;
10375    return (byte)(excl | ch);
10376  }
10377  else {  /* not PRI */
10378    for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10379    if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10380    if(chi[1] &0x08) excl = 0x40;
10381
10382    switch(chi[1] |0x98) {
10383    case 0x98: return 0;
10384    case 0x99:
10385      if (pchannelmap) *pchannelmap = 2;
10386      return excl |1;
10387    case 0x9a:
10388      if (pchannelmap) *pchannelmap = 4;
10389      return excl |2;
10390    case 0x9b: return 0xff;
10391    case 0x9c: return 0xfd; /* d-ch */
10392    default: return 0xfe;
10393    }
10394  }
10395}
10396
10397
10398static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10399{
10400  DIVA_CAPI_ADAPTER   *a;
10401  PLCI   *splci;
10402  byte old_id;
10403
10404  a = plci->adapter;
10405  old_id = plci->li_bchannel_id;
10406  if (a->li_pri)
10407  {
10408    if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10409      li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10410    plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10411    if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10412      li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10413  }
10414  else
10415  {
10416    if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10417    {
10418      if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10419        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10420      plci->li_bchannel_id = bchannel_id & 0x03;
10421      if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10422      {
10423        splci = a->AdvSignalPLCI;
10424        if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10425        {
10426          if ((splci->li_bchannel_id != 0)
10427           && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10428          {
10429            li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10430          }
10431          splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10432          li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10433          dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10434            (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10435            (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10436        }
10437      }
10438      if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10439        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10440    }
10441  }
10442  if ((old_id == 0) && (plci->li_bchannel_id != 0)
10443   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10444  {
10445    mixer_clear_config (plci);
10446  }
10447  dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10448    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10449    (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10450}
10451
10452
10453static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10454{
10455  DIVA_CAPI_ADAPTER   *a;
10456  PLCI   *splci;
10457  byte ch, old_id;
10458
10459  a = plci->adapter;
10460  old_id = plci->li_bchannel_id;
10461  ch = chi_to_channel (chi, NULL);
10462  if (!(ch & 0x80))
10463  {
10464    if (a->li_pri)
10465    {
10466      if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10467        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10468      plci->li_bchannel_id = (ch & 0x1f) + 1;
10469      if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10470        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10471    }
10472    else
10473    {
10474      if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10475      {
10476        if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10477          li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10478        plci->li_bchannel_id = ch & 0x1f;
10479        if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10480        {
10481          splci = a->AdvSignalPLCI;
10482          if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10483          {
10484            if ((splci->li_bchannel_id != 0)
10485             && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10486            {
10487              li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10488            }
10489            splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10490            li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10491            dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10492              (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10493              (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10494          }
10495        }
10496        if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10497          li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10498      }
10499    }
10500  }
10501  if ((old_id == 0) && (plci->li_bchannel_id != 0)
10502   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10503  {
10504    mixer_clear_config (plci);
10505  }
10506  dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10507    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10508    (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10509}
10510
10511
10512#define MIXER_MAX_DUMP_CHANNELS 34
10513
10514static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10515{
10516static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10517  word n, i, j;
10518  char *p;
10519    char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10520
10521  dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10522    (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10523
10524  for (i = 0; i < li_total_channels; i++)
10525  {
10526    li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10527    if (li_config_table[i].chflags != 0)
10528      li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10529    else
10530    {
10531      for (j = 0; j < li_total_channels; j++)
10532      {
10533        if (((li_config_table[i].flag_table[j]) != 0)
10534         || ((li_config_table[j].flag_table[i]) != 0))
10535        {
10536          li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10537        }
10538        if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10539         || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10540        {
10541          li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10542        }
10543      }
10544    }
10545  }
10546  for (i = 0; i < li_total_channels; i++)
10547  {
10548    for (j = 0; j < li_total_channels; j++)
10549    {
10550      li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10551      if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10552        li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10553    }
10554  }
10555  for (n = 0; n < li_total_channels; n++)
10556  {
10557    if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10558    {
10559      for (i = 0; i < li_total_channels; i++)
10560      {
10561        if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10562        {
10563          for (j = 0; j < li_total_channels; j++)
10564          {
10565            li_config_table[i].coef_table[j] |=
10566              li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10567          }
10568        }
10569      }
10570    }
10571  }
10572  for (i = 0; i < li_total_channels; i++)
10573  {
10574    if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10575    {
10576      li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10577      for (j = 0; j < li_total_channels; j++)
10578      {
10579        if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10580          li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10581      }
10582      if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10583        li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10584    }
10585  }
10586  for (i = 0; i < li_total_channels; i++)
10587  {
10588    if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10589    {
10590      for (j = 0; j < li_total_channels; j++)
10591      {
10592        if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10593          li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10594        if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10595          li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10596        if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10597          li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10598        if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10599          li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10600      }
10601      if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10602      {
10603        for (j = 0; j < li_total_channels; j++)
10604        {
10605          if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10606          {
10607            li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10608            if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10609              li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10610          }
10611        }
10612      }
10613      if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10614      {
10615        for (j = 0; j < li_total_channels; j++)
10616        {
10617          if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10618            li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10619        }
10620      }
10621      if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10622      {
10623        for (j = 0; j < li_total_channels; j++)
10624        {
10625          if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10626          {
10627            for (n = 0; n < li_total_channels; n++)
10628            {
10629              if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10630              {
10631                li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10632                if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10633                {
10634                  li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10635                  if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10636                    li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10637                }
10638                else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10639                  li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10640              }
10641            }
10642          }
10643        }
10644      }
10645    }
10646  }
10647  for (i = 0; i < li_total_channels; i++)
10648  {
10649    if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10650    {
10651      if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10652        li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10653      if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10654        li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10655      if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10656        li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10657      for (j = 0; j < li_total_channels; j++)
10658      {
10659        if ((li_config_table[i].flag_table[j] &
10660          (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10661         || (li_config_table[j].flag_table[i] &
10662          (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10663        {
10664          li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10665        }
10666        if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10667          li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10668        if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10669          li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10670      }
10671      if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10672      {
10673        li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10674        li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10675      }
10676    }
10677  }
10678  for (i = 0; i < li_total_channels; i++)
10679  {
10680    if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10681    {
10682      j = 0;
10683      while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10684        j++;
10685      if (j < li_total_channels)
10686      {
10687        for (j = 0; j < li_total_channels; j++)
10688        {
10689          li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10690          if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10691            li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10692        }
10693      }
10694    }
10695  }
10696  n = li_total_channels;
10697  if (n > MIXER_MAX_DUMP_CHANNELS)
10698    n = MIXER_MAX_DUMP_CHANNELS;
10699  p = hex_line;
10700  for (j = 0; j < n; j++)
10701  {
10702    if ((j & 0x7) == 0)
10703      *(p++) = ' ';
10704    *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10705    *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10706  }
10707  *p = '\0';
10708  dbug (1, dprintf ("[%06lx] CURRENT %s",
10709    (dword)(UnMapController (a->Id)), (char   *) hex_line));
10710  p = hex_line;
10711  for (j = 0; j < n; j++)
10712  {
10713    if ((j & 0x7) == 0)
10714      *(p++) = ' ';
10715    *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10716    *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10717  }
10718  *p = '\0';
10719  dbug (1, dprintf ("[%06lx] CHANNEL %s",
10720    (dword)(UnMapController (a->Id)), (char   *) hex_line));
10721  p = hex_line;
10722  for (j = 0; j < n; j++)
10723  {
10724    if ((j & 0x7) == 0)
10725      *(p++) = ' ';
10726    *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10727    *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10728  }
10729  *p = '\0';
10730  dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10731    (dword)(UnMapController (a->Id)), (char   *) hex_line));
10732  for (i = 0; i < n; i++)
10733  {
10734    p = hex_line;
10735    for (j = 0; j < n; j++)
10736    {
10737      if ((j & 0x7) == 0)
10738        *(p++) = ' ';
10739      *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10740      *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10741    }
10742    *p = '\0';
10743    dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10744      (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10745  }
10746  for (i = 0; i < n; i++)
10747  {
10748    p = hex_line;
10749    for (j = 0; j < n; j++)
10750    {
10751      if ((j & 0x7) == 0)
10752        *(p++) = ' ';
10753      *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10754      *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10755    }
10756    *p = '\0';
10757    dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10758      (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10759  }
10760}
10761
10762
10763static struct
10764{
10765  byte mask;
10766  byte line_flags;
10767} mixer_write_prog_pri[] =
10768{
10769  { LI_COEF_CH_CH, 0 },
10770  { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10771  { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10772  { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10773};
10774
10775static struct
10776{
10777  byte from_ch;
10778  byte to_ch;
10779  byte mask;
10780  byte xconnect_override;
10781} mixer_write_prog_bri[] =
10782{
10783  { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10784  { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10785  { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10786  { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10787  { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10788  { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10789  { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10790  { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10791  { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10792  { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10793  { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10794  { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10795  { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10796  { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10797  { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10798  { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10799  { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10800  { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10801  { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10802  { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10803  { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10804  { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10805  { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10806  { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10807  { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10808  { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10809  { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10810  { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10811  { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10812  { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10813  { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10814  { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10815  { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10816  { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10817  { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10818  { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10819};
10820
10821static byte mixer_swapped_index_bri[] =
10822{
10823  18,  /* B      to B      */
10824  19,  /* Alt B  to B      */
10825  20,  /* PC     to B      */
10826  21,  /* Alt PC to B      */
10827  22,  /* IC     to B      */
10828  23,  /* Alt IC to B      */
10829  24,  /* B      to PC     */
10830  25,  /* Alt B  to PC     */
10831  26,  /* PC     to PC     */
10832  27,  /* Alt PC to PC     */
10833  28,  /* IC     to PC     */
10834  29,  /* Alt IC to PC     */
10835  30,  /* B      to IC     */
10836  31,  /* Alt B  to IC     */
10837  32,  /* PC     to IC     */
10838  33,  /* Alt PC to IC     */
10839  34,  /* IC     to IC     */
10840  35,  /* Alt IC to IC     */
10841  0,   /* Alt B  to Alt B  */
10842  1,   /* B      to Alt B  */
10843  2,   /* Alt PC to Alt B  */
10844  3,   /* PC     to Alt B  */
10845  4,   /* Alt IC to Alt B  */
10846  5,   /* IC     to Alt B  */
10847  6,   /* Alt B  to Alt PC */
10848  7,   /* B      to Alt PC */
10849  8,   /* Alt PC to Alt PC */
10850  9,   /* PC     to Alt PC */
10851  10,  /* Alt IC to Alt PC */
10852  11,  /* IC     to Alt PC */
10853  12,  /* Alt B  to Alt IC */
10854  13,  /* B      to Alt IC */
10855  14,  /* Alt PC to Alt IC */
10856  15,  /* PC     to Alt IC */
10857  16,  /* Alt IC to Alt IC */
10858  17   /* IC     to Alt IC */
10859};
10860
10861static struct
10862{
10863  byte mask;
10864  byte from_pc;
10865  byte to_pc;
10866} xconnect_write_prog[] =
10867{
10868  { LI_COEF_CH_CH, false, false },
10869  { LI_COEF_CH_PC, false, true },
10870  { LI_COEF_PC_CH, true, false },
10871  { LI_COEF_PC_PC, true, true }
10872};
10873
10874
10875static void xconnect_query_addresses (PLCI   *plci)
10876{
10877  DIVA_CAPI_ADAPTER   *a;
10878  word w, ch;
10879  byte   *p;
10880
10881  dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10882    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10883    (char   *)(FILE_), __LINE__));
10884
10885  a = plci->adapter;
10886  if (a->li_pri && ((plci->li_bchannel_id == 0)
10887   || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10888  {
10889    dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10890      (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10891      (char   *)(FILE_), __LINE__));
10892    return;
10893  }
10894  p = plci->internal_req_buffer;
10895  ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10896  *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10897  w = ch;
10898  *(p++) = (byte) w;
10899  *(p++) = (byte)(w >> 8);
10900  w = ch | XCONNECT_CHANNEL_PORT_PC;
10901  *(p++) = (byte) w;
10902  *(p++) = (byte)(w >> 8);
10903  plci->NData[0].P = plci->internal_req_buffer;
10904  plci->NData[0].PLength = p - plci->internal_req_buffer;
10905  plci->NL.X = plci->NData;
10906  plci->NL.ReqCh = 0;
10907  plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10908  plci->adapter->request (&plci->NL);
10909}
10910
10911
10912static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10913{
10914
10915  dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10916    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10917    (char   *)(FILE_), __LINE__, internal_command));
10918
10919  plci->li_write_command = internal_command;
10920  plci->li_write_channel = 0;
10921}
10922
10923
10924static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10925{
10926  DIVA_CAPI_ADAPTER   *a;
10927  word w, n, i, j, r, s, to_ch;
10928  dword d;
10929  byte   *p;
10930  struct xconnect_transfer_address_s   *transfer_address;
10931  byte ch_map[MIXER_CHANNELS_BRI];
10932
10933  dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10934    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10935
10936  a = plci->adapter;
10937  if ((plci->li_bchannel_id == 0)
10938   || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10939  {
10940    dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10941      UnMapId (Id), (char   *)(FILE_), __LINE__));
10942    return (true);
10943  }
10944  i = a->li_base + (plci->li_bchannel_id - 1);
10945  j = plci->li_write_channel;
10946  p = plci->internal_req_buffer;
10947  if (j != 0)
10948  {
10949    if ((Rc != OK) && (Rc != OK_FC))
10950    {
10951      dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10952        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10953      return (false);
10954    }
10955  }
10956  if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10957  {
10958    r = 0;
10959    s = 0;
10960    if (j < li_total_channels)
10961    {
10962      if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10963      {
10964        s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10965            (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10966          ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10967            (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10968      }
10969      r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10970      while ((j < li_total_channels)
10971        && ((r == 0)
10972         || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10973         || (!li_config_table[j].adapter->li_pri
10974          && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10975         || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10976           || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10977          && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10978           || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10979         || ((li_config_table[j].adapter->li_base != a->li_base)
10980          && !(r & s &
10981            ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10982              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10983            ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10984              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10985      {
10986        j++;
10987        if (j < li_total_channels)
10988          r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10989      }
10990    }
10991    if (j < li_total_channels)
10992    {
10993      plci->internal_command = plci->li_write_command;
10994      if (plci_nl_busy (plci))
10995        return (true);
10996      to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10997      *(p++) = UDATA_REQUEST_XCONNECT_TO;
10998      do
10999      {
11000        if (li_config_table[j].adapter->li_base != a->li_base)
11001        {
11002          r &= s &
11003            ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11004              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11005            ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11006              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11007        }
11008        n = 0;
11009        do
11010        {
11011          if (r & xconnect_write_prog[n].mask)
11012          {
11013            if (xconnect_write_prog[n].from_pc)
11014              transfer_address = &(li_config_table[j].send_pc);
11015            else
11016              transfer_address = &(li_config_table[j].send_b);
11017            d = transfer_address->card_address.low;
11018            *(p++) = (byte) d;
11019            *(p++) = (byte)(d >> 8);
11020            *(p++) = (byte)(d >> 16);
11021            *(p++) = (byte)(d >> 24);
11022            d = transfer_address->card_address.high;
11023            *(p++) = (byte) d;
11024            *(p++) = (byte)(d >> 8);
11025            *(p++) = (byte)(d >> 16);
11026            *(p++) = (byte)(d >> 24);
11027            d = transfer_address->offset;
11028            *(p++) = (byte) d;
11029            *(p++) = (byte)(d >> 8);
11030            *(p++) = (byte)(d >> 16);
11031            *(p++) = (byte)(d >> 24);
11032            w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11033            *(p++) = (byte) w;
11034            *(p++) = (byte)(w >> 8);
11035            w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11036              (li_config_table[i].adapter->u_law ?
11037                 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11038                 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11039            *(p++) = (byte) w;
11040            *(p++) = (byte) 0;
11041            li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11042          }
11043          n++;
11044        } while ((n < ARRAY_SIZE(xconnect_write_prog))
11045          && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11046        if (n == ARRAY_SIZE(xconnect_write_prog))
11047        {
11048          do
11049          {
11050            j++;
11051            if (j < li_total_channels)
11052              r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11053          } while ((j < li_total_channels)
11054            && ((r == 0)
11055             || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11056             || (!li_config_table[j].adapter->li_pri
11057              && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11058             || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11059               || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11060              && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11061               || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11062             || ((li_config_table[j].adapter->li_base != a->li_base)
11063              && !(r & s &
11064                ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11065                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11066                ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11067                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11068        }
11069      } while ((j < li_total_channels)
11070        && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11071    }
11072    else if (j == li_total_channels)
11073    {
11074      plci->internal_command = plci->li_write_command;
11075      if (plci_nl_busy (plci))
11076        return (true);
11077      if (a->li_pri)
11078      {
11079        *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11080        w = 0;
11081        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11082          w |= MIXER_FEATURE_ENABLE_TX_DATA;
11083        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11084          w |= MIXER_FEATURE_ENABLE_RX_DATA;
11085        *(p++) = (byte) w;
11086        *(p++) = (byte)(w >> 8);
11087      }
11088      else
11089      {
11090        *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11091        w = 0;
11092        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11093         && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11094        {
11095          w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11096        }
11097        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11098          w |= MIXER_FEATURE_ENABLE_TX_DATA;
11099        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11100          w |= MIXER_FEATURE_ENABLE_RX_DATA;
11101        *(p++) = (byte) w;
11102        *(p++) = (byte)(w >> 8);
11103        for (j = 0; j < sizeof(ch_map); j += 2)
11104        {
11105          if (plci->li_bchannel_id == 2)
11106          {
11107            ch_map[j] = (byte)(j+1);
11108            ch_map[j+1] = (byte) j;
11109          }
11110          else
11111          {
11112            ch_map[j] = (byte) j;
11113            ch_map[j+1] = (byte)(j+1);
11114          }
11115        }
11116        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11117        {
11118          i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11119          j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11120          if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11121          {
11122            *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11123              mixer_write_prog_bri[n].xconnect_override :
11124              ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11125            if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11126            {
11127              w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11128              li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11129            }
11130          }
11131          else
11132          {
11133            *p = 0x00;
11134            if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11135            {
11136              w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11137              if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11138                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11139            }
11140          }
11141          p++;
11142        }
11143      }
11144      j = li_total_channels + 1;
11145    }
11146  }
11147  else
11148  {
11149    if (j <= li_total_channels)
11150    {
11151      plci->internal_command = plci->li_write_command;
11152      if (plci_nl_busy (plci))
11153        return (true);
11154      if (j < a->li_base)
11155        j = a->li_base;
11156      if (a->li_pri)
11157      {
11158        *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11159        w = 0;
11160        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11161          w |= MIXER_FEATURE_ENABLE_TX_DATA;
11162        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11163          w |= MIXER_FEATURE_ENABLE_RX_DATA;
11164        *(p++) = (byte) w;
11165        *(p++) = (byte)(w >> 8);
11166        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11167        {
11168          *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11169          for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11170          {
11171            w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11172            if (w & mixer_write_prog_pri[n].mask)
11173            {
11174              *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11175              li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11176            }
11177            else
11178              *(p++) = 0x00;
11179          }
11180          *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11181          for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11182          {
11183            w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11184            if (w & mixer_write_prog_pri[n].mask)
11185            {
11186              *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11187              li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11188            }
11189            else
11190              *(p++) = 0x00;
11191          }
11192        }
11193      }
11194      else
11195      {
11196        *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11197        w = 0;
11198        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11199         && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11200        {
11201          w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11202        }
11203        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11204          w |= MIXER_FEATURE_ENABLE_TX_DATA;
11205        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11206          w |= MIXER_FEATURE_ENABLE_RX_DATA;
11207        *(p++) = (byte) w;
11208        *(p++) = (byte)(w >> 8);
11209        for (j = 0; j < sizeof(ch_map); j += 2)
11210        {
11211          if (plci->li_bchannel_id == 2)
11212          {
11213            ch_map[j] = (byte)(j+1);
11214            ch_map[j+1] = (byte) j;
11215          }
11216          else
11217          {
11218            ch_map[j] = (byte) j;
11219            ch_map[j+1] = (byte)(j+1);
11220          }
11221        }
11222        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11223        {
11224          i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11225          j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11226          if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11227          {
11228            *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11229            w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11230            li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11231          }
11232          else
11233          {
11234            *p = 0x00;
11235            if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11236            {
11237              w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11238              if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11239                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11240            }
11241          }
11242          p++;
11243        }
11244      }
11245      j = li_total_channels + 1;
11246    }
11247  }
11248  plci->li_write_channel = j;
11249  if (p != plci->internal_req_buffer)
11250  {
11251    plci->NData[0].P = plci->internal_req_buffer;
11252    plci->NData[0].PLength = p - plci->internal_req_buffer;
11253    plci->NL.X = plci->NData;
11254    plci->NL.ReqCh = 0;
11255    plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11256    plci->adapter->request (&plci->NL);
11257  }
11258  return (true);
11259}
11260
11261
11262static void mixer_notify_update (PLCI   *plci, byte others)
11263{
11264  DIVA_CAPI_ADAPTER   *a;
11265  word i, w;
11266  PLCI   *notify_plci;
11267    byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11268
11269  dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11270    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11271    (char   *)(FILE_), __LINE__, others));
11272
11273  a = plci->adapter;
11274  if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11275  {
11276    if (others)
11277      plci->li_notify_update = true;
11278    i = 0;
11279    do
11280    {
11281      notify_plci = NULL;
11282      if (others)
11283      {
11284        while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11285          i++;
11286        if (i < li_total_channels)
11287          notify_plci = li_config_table[i++].plci;
11288      }
11289      else
11290      {
11291        if ((plci->li_bchannel_id != 0)
11292         && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11293        {
11294          notify_plci = plci;
11295        }
11296      }
11297      if ((notify_plci != NULL)
11298       && !notify_plci->li_notify_update
11299       && (notify_plci->appl != NULL)
11300       && (notify_plci->State)
11301       && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11302      {
11303        notify_plci->li_notify_update = true;
11304        ((CAPI_MSG *) msg)->header.length = 18;
11305        ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11306        ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11307        ((CAPI_MSG *) msg)->header.number = 0;
11308        ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11309        ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11310        ((CAPI_MSG *) msg)->header.ncci = 0;
11311        ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11312        ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11313        PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11314        ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11315        w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11316        if (w != _QUEUE_FULL)
11317        {
11318          if (w != 0)
11319          {
11320            dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11321              (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11322              (char   *)(FILE_), __LINE__,
11323              (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11324          }
11325          notify_plci->li_notify_update = false;
11326        }
11327      }
11328    } while (others && (notify_plci != NULL));
11329    if (others)
11330      plci->li_notify_update = false;
11331  }
11332}
11333
11334
11335static void mixer_clear_config (PLCI   *plci)
11336{
11337  DIVA_CAPI_ADAPTER   *a;
11338  word i, j;
11339
11340  dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11341    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11342    (char   *)(FILE_), __LINE__));
11343
11344  plci->li_notify_update = false;
11345  plci->li_plci_b_write_pos = 0;
11346  plci->li_plci_b_read_pos = 0;
11347  plci->li_plci_b_req_pos = 0;
11348  a = plci->adapter;
11349  if ((plci->li_bchannel_id != 0)
11350   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11351  {
11352    i = a->li_base + (plci->li_bchannel_id - 1);
11353    li_config_table[i].curchnl = 0;
11354    li_config_table[i].channel = 0;
11355    li_config_table[i].chflags = 0;
11356    for (j = 0; j < li_total_channels; j++)
11357    {
11358      li_config_table[j].flag_table[i] = 0;
11359      li_config_table[i].flag_table[j] = 0;
11360      li_config_table[i].coef_table[j] = 0;
11361      li_config_table[j].coef_table[i] = 0;
11362    }
11363    if (!a->li_pri)
11364    {
11365      li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11366      if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11367      {
11368        i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11369        li_config_table[i].curchnl = 0;
11370        li_config_table[i].channel = 0;
11371        li_config_table[i].chflags = 0;
11372        for (j = 0; j < li_total_channels; j++)
11373        {
11374          li_config_table[i].flag_table[j] = 0;
11375          li_config_table[j].flag_table[i] = 0;
11376          li_config_table[i].coef_table[j] = 0;
11377          li_config_table[j].coef_table[i] = 0;
11378        }
11379        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11380        {
11381          i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11382          li_config_table[i].curchnl = 0;
11383          li_config_table[i].channel = 0;
11384          li_config_table[i].chflags = 0;
11385          for (j = 0; j < li_total_channels; j++)
11386          {
11387            li_config_table[i].flag_table[j] = 0;
11388            li_config_table[j].flag_table[i] = 0;
11389            li_config_table[i].coef_table[j] = 0;
11390            li_config_table[j].coef_table[i] = 0;
11391          }
11392        }
11393      }
11394    }
11395  }
11396}
11397
11398
11399static void mixer_prepare_switch (dword Id, PLCI   *plci)
11400{
11401
11402  dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11403    UnMapId (Id), (char   *)(FILE_), __LINE__));
11404
11405  do
11406  {
11407    mixer_indication_coefs_set (Id, plci);
11408  } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11409}
11410
11411
11412static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11413{
11414  DIVA_CAPI_ADAPTER   *a;
11415  word i, j;
11416
11417  dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11418    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11419
11420  a = plci->adapter;
11421  if ((plci->li_bchannel_id != 0)
11422   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11423  {
11424    i = a->li_base + (plci->li_bchannel_id - 1);
11425    for (j = 0; j < li_total_channels; j++)
11426    {
11427      li_config_table[i].coef_table[j] &= 0xf;
11428      li_config_table[j].coef_table[i] &= 0xf;
11429    }
11430    if (!a->li_pri)
11431      li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11432  }
11433  return (GOOD);
11434}
11435
11436
11437static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11438{
11439  DIVA_CAPI_ADAPTER   *a;
11440  word Info;
11441
11442  dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11443    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11444
11445  Info = GOOD;
11446  a = plci->adapter;
11447  if ((plci->B1_facilities & B1_FACILITY_MIXER)
11448   && (plci->li_bchannel_id != 0)
11449   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11450  {
11451    switch (plci->adjust_b_state)
11452    {
11453    case ADJUST_B_RESTORE_MIXER_1:
11454      if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11455      {
11456        plci->internal_command = plci->adjust_b_command;
11457        if (plci_nl_busy (plci))
11458        {
11459          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11460          break;
11461        }
11462        xconnect_query_addresses (plci);
11463        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11464        break;
11465      }
11466      plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11467      Rc = OK;
11468    case ADJUST_B_RESTORE_MIXER_2:
11469    case ADJUST_B_RESTORE_MIXER_3:
11470    case ADJUST_B_RESTORE_MIXER_4:
11471      if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11472      {
11473        dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11474          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11475        Info = _WRONG_STATE;
11476        break;
11477      }
11478      if (Rc == OK)
11479      {
11480        if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11481          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11482        else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11483          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11484      }
11485      else if (Rc == 0)
11486      {
11487        if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11488          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11489        else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11490          plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11491      }
11492      if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11493      {
11494        plci->internal_command = plci->adjust_b_command;
11495        break;
11496      }
11497    case ADJUST_B_RESTORE_MIXER_5:
11498      xconnect_write_coefs (plci, plci->adjust_b_command);
11499      plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11500      Rc = OK;
11501    case ADJUST_B_RESTORE_MIXER_6:
11502      if (!xconnect_write_coefs_process (Id, plci, Rc))
11503      {
11504        dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11505          UnMapId (Id), (char   *)(FILE_), __LINE__));
11506        Info = _FACILITY_NOT_SUPPORTED;
11507        break;
11508      }
11509      if (plci->internal_command)
11510        break;
11511      plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11512    case ADJUST_B_RESTORE_MIXER_7:
11513      break;
11514    }
11515  }
11516  return (Info);
11517}
11518
11519
11520static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11521{
11522  DIVA_CAPI_ADAPTER   *a;
11523  word i, internal_command, Info;
11524
11525  dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11526    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11527    plci->li_cmd));
11528
11529  Info = GOOD;
11530  a = plci->adapter;
11531  internal_command = plci->internal_command;
11532  plci->internal_command = 0;
11533  switch (plci->li_cmd)
11534  {
11535  case LI_REQ_CONNECT:
11536  case LI_REQ_DISCONNECT:
11537  case LI_REQ_SILENT_UPDATE:
11538    switch (internal_command)
11539    {
11540    default:
11541      if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11542      {
11543        adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11544          B1_FACILITY_MIXER), MIXER_COMMAND_1);
11545      }
11546    case MIXER_COMMAND_1:
11547      if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11548      {
11549        if (adjust_b_process (Id, plci, Rc) != GOOD)
11550        {
11551          dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11552            UnMapId (Id), (char   *)(FILE_), __LINE__));
11553          Info = _FACILITY_NOT_SUPPORTED;
11554          break;
11555        }
11556        if (plci->internal_command)
11557          return;
11558      }
11559      plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11560      if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11561       || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11562        && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11563         ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11564      {
11565        xconnect_write_coefs (plci, MIXER_COMMAND_2);
11566      }
11567      else
11568      {
11569        do
11570        {
11571          mixer_indication_coefs_set (Id, plci);
11572        } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11573      }
11574    case MIXER_COMMAND_2:
11575      if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11576       || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11577        && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11578         ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11579      {
11580        if (!xconnect_write_coefs_process (Id, plci, Rc))
11581        {
11582          dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11583            UnMapId (Id), (char   *)(FILE_), __LINE__));
11584          if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11585          {
11586            do
11587            {
11588              plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11589                LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11590              i = (plci->li_plci_b_write_pos == 0) ?
11591                LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11592            } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11593              && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11594          }
11595          Info = _FACILITY_NOT_SUPPORTED;
11596          break;
11597        }
11598        if (plci->internal_command)
11599          return;
11600      }
11601      if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11602      {
11603        adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11604          ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11605      }
11606    case MIXER_COMMAND_3:
11607      if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11608      {
11609        if (adjust_b_process (Id, plci, Rc) != GOOD)
11610        {
11611          dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11612            UnMapId (Id), (char   *)(FILE_), __LINE__));
11613          Info = _FACILITY_NOT_SUPPORTED;
11614          break;
11615        }
11616        if (plci->internal_command)
11617          return;
11618      }
11619      break;
11620    }
11621    break;
11622  }
11623  if ((plci->li_bchannel_id == 0)
11624   || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11625  {
11626    dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11627      UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11628  }
11629  else
11630  {
11631    i = a->li_base + (plci->li_bchannel_id - 1);
11632    li_config_table[i].curchnl = plci->li_channel_bits;
11633    if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11634    {
11635      i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11636      li_config_table[i].curchnl = plci->li_channel_bits;
11637      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11638      {
11639        i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11640        li_config_table[i].curchnl = plci->li_channel_bits;
11641      }
11642    }
11643  }
11644}
11645
11646
11647static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11648  dword plci_b_id, byte connect, dword li_flags)
11649{
11650  word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11651  PLCI   *plci_b;
11652  DIVA_CAPI_ADAPTER   *a_b;
11653
11654  a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11655  plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11656  ch_a = a->li_base + (plci->li_bchannel_id - 1);
11657  if (!a->li_pri && (plci->tel == ADV_VOICE)
11658   && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11659  {
11660    ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11661    ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11662      a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11663  }
11664  else
11665  {
11666    ch_a_v = ch_a;
11667    ch_a_s = ch_a;
11668  }
11669  ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11670  if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11671   && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11672  {
11673    ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11674    ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11675      a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11676  }
11677  else
11678  {
11679    ch_b_v = ch_b;
11680    ch_b_s = ch_b;
11681  }
11682  if (connect)
11683  {
11684    li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11685    li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11686    li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11687    li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11688  }
11689  li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11690  li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11691  li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11692  li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11693  if (ch_a_v == ch_b_v)
11694  {
11695    li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11696    li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11697  }
11698  else
11699  {
11700    if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11701    {
11702      for (i = 0; i < li_total_channels; i++)
11703      {
11704        if (i != ch_a_v)
11705          li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11706      }
11707    }
11708    if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11709    {
11710      for (i = 0; i < li_total_channels; i++)
11711      {
11712        if (i != ch_a_s)
11713          li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11714      }
11715    }
11716    if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11717    {
11718      for (i = 0; i < li_total_channels; i++)
11719      {
11720        if (i != ch_a_v)
11721          li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11722      }
11723    }
11724    if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11725    {
11726      for (i = 0; i < li_total_channels; i++)
11727      {
11728        if (i != ch_a_s)
11729          li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11730      }
11731    }
11732  }
11733  if (li_flags & LI_FLAG_CONFERENCE_A_B)
11734  {
11735    li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11736    li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11737    li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11738    li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11739  }
11740  if (li_flags & LI_FLAG_CONFERENCE_B_A)
11741  {
11742    li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11743    li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11744    li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11745    li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11746  }
11747  if (li_flags & LI_FLAG_MONITOR_A)
11748  {
11749    li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11750    li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11751  }
11752  if (li_flags & LI_FLAG_MONITOR_B)
11753  {
11754    li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11755    li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11756  }
11757  if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11758  {
11759    li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11760    li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11761  }
11762  if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11763  {
11764    li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11765    li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11766  }
11767  if (li_flags & LI_FLAG_MIX_A)
11768  {
11769    li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11770    li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11771  }
11772  if (li_flags & LI_FLAG_MIX_B)
11773  {
11774    li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11775    li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11776  }
11777  if (ch_a_v != ch_a_s)
11778  {
11779    li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11780    li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11781  }
11782  if (ch_b_v != ch_b_s)
11783  {
11784    li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11785    li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11786  }
11787}
11788
11789
11790static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11791  dword plci_b_id, byte connect, dword li_flags)
11792{
11793  word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11794  PLCI   *plci_b;
11795  DIVA_CAPI_ADAPTER   *a_b;
11796
11797  a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11798  plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11799  ch_a = a->li_base + (plci->li_bchannel_id - 1);
11800  if (!a->li_pri && (plci->tel == ADV_VOICE)
11801   && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11802  {
11803    ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11804    ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11805      a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11806  }
11807  else
11808  {
11809    ch_a_v = ch_a;
11810    ch_a_s = ch_a;
11811  }
11812  ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11813  if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11814   && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11815  {
11816    ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11817    ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11818      a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11819  }
11820  else
11821  {
11822    ch_b_v = ch_b;
11823    ch_b_s = ch_b;
11824  }
11825  if (connect)
11826  {
11827    li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11828    li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11829    li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11830    li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11831    li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11832    li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11833  }
11834  li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11835  li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11836  li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11837  li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11838  li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11839  li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11840  li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11841  li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11842  if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11843  {
11844    li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11845    li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11846    li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11847    li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11848  }
11849  if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11850  {
11851    li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11852    li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11853    li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11854    li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11855  }
11856  if (li_flags & LI2_FLAG_MONITOR_B)
11857  {
11858    li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11859    li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11860  }
11861  if (li_flags & LI2_FLAG_MIX_B)
11862  {
11863    li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11864    li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11865  }
11866  if (li_flags & LI2_FLAG_MONITOR_X)
11867    li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11868  if (li_flags & LI2_FLAG_MIX_X)
11869    li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11870  if (li_flags & LI2_FLAG_LOOP_B)
11871  {
11872    li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11873    li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11874    li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11875    li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11876  }
11877  if (li_flags & LI2_FLAG_LOOP_PC)
11878    li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11879  if (li_flags & LI2_FLAG_LOOP_X)
11880    li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11881  if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11882    li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11883  if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11884    li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11885  if (ch_a_v != ch_a_s)
11886  {
11887    li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11888    li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11889  }
11890  if (ch_b_v != ch_b_s)
11891  {
11892    li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11893    li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11894  }
11895}
11896
11897
11898static word li_check_main_plci (dword Id, PLCI   *plci)
11899{
11900  if (plci == NULL)
11901  {
11902    dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11903      UnMapId (Id), (char   *)(FILE_), __LINE__));
11904    return (_WRONG_IDENTIFIER);
11905  }
11906  if (!plci->State
11907   || !plci->NL.Id || plci->nl_remove_id
11908   || (plci->li_bchannel_id == 0))
11909  {
11910    dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11911      UnMapId (Id), (char   *)(FILE_), __LINE__));
11912    return (_WRONG_STATE);
11913  }
11914  li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11915  return (GOOD);
11916}
11917
11918
11919static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11920  dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11921{
11922  byte ctlr_b;
11923  PLCI   *plci_b;
11924
11925  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11926    LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11927  {
11928    dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11929      UnMapId (Id), (char   *)(FILE_), __LINE__));
11930    PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11931    return (NULL);
11932  }
11933  ctlr_b = 0;
11934  if ((plci_b_id & 0x7f) != 0)
11935  {
11936    ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11937    if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11938      ctlr_b = 0;
11939  }
11940  if ((ctlr_b == 0)
11941   || (((plci_b_id >> 8) & 0xff) == 0)
11942   || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11943  {
11944    dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11945      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11946    PUT_WORD (p_result, _WRONG_IDENTIFIER);
11947    return (NULL);
11948  }
11949  plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11950  if (!plci_b->State
11951   || !plci_b->NL.Id || plci_b->nl_remove_id
11952   || (plci_b->li_bchannel_id == 0))
11953  {
11954    dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11955      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11956    PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11957    return (NULL);
11958  }
11959  li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11960  if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11961    ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11962   && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11963    || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11964  {
11965    dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11966      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11967    PUT_WORD (p_result, _WRONG_IDENTIFIER);
11968    return (NULL);
11969  }
11970  if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11971    (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11972  {
11973    dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11974      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11975    PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11976    return (NULL);
11977  }
11978  return (plci_b);
11979}
11980
11981
11982static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11983  dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11984{
11985  byte ctlr_b;
11986  PLCI   *plci_b;
11987
11988  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11989    LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11990  {
11991    dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11992      UnMapId (Id), (char   *)(FILE_), __LINE__));
11993    PUT_WORD (p_result, _WRONG_STATE);
11994    return (NULL);
11995  }
11996  ctlr_b = 0;
11997  if ((plci_b_id & 0x7f) != 0)
11998  {
11999    ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
12000    if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
12001      ctlr_b = 0;
12002  }
12003  if ((ctlr_b == 0)
12004   || (((plci_b_id >> 8) & 0xff) == 0)
12005   || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
12006  {
12007    dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
12008      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12009    PUT_WORD (p_result, _WRONG_IDENTIFIER);
12010    return (NULL);
12011  }
12012  plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12013  if (!plci_b->State
12014   || !plci_b->NL.Id || plci_b->nl_remove_id
12015   || (plci_b->li_bchannel_id == 0)
12016   || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12017  {
12018    dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12019      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12020    PUT_WORD (p_result, _WRONG_STATE);
12021    return (NULL);
12022  }
12023  if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12024    ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12025   && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12026    || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12027  {
12028    dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12029      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12030    PUT_WORD (p_result, _WRONG_IDENTIFIER);
12031    return (NULL);
12032  }
12033  if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12034    (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12035  {
12036    dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12037      UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12038    PUT_WORD (p_result, _WRONG_STATE);
12039    return (NULL);
12040  }
12041  return (plci_b);
12042}
12043
12044
12045static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12046{
12047  word Info;
12048  word i;
12049  dword d, li_flags, plci_b_id;
12050  PLCI   *plci_b;
12051    API_PARSE li_parms[3];
12052    API_PARSE li_req_parms[3];
12053    API_PARSE li_participant_struct[2];
12054    API_PARSE li_participant_parms[3];
12055  word participant_parms_pos;
12056  byte result_buffer[32];
12057  byte   *result;
12058  word result_pos;
12059  word plci_b_write_pos;
12060
12061  dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12062    UnMapId (Id), (char   *)(FILE_), __LINE__));
12063
12064  Info = GOOD;
12065  result = result_buffer;
12066  result_buffer[0] = 0;
12067  if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12068  {
12069    dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12070      UnMapId (Id), (char   *)(FILE_), __LINE__));
12071    Info = _FACILITY_NOT_SUPPORTED;
12072  }
12073  else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12074  {
12075    dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12076      UnMapId (Id), (char   *)(FILE_), __LINE__));
12077    Info = _WRONG_MESSAGE_FORMAT;
12078  }
12079  else
12080  {
12081    result_buffer[0] = 3;
12082    PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12083    result_buffer[3] = 0;
12084    switch (GET_WORD (li_parms[0].info))
12085    {
12086    case LI_GET_SUPPORTED_SERVICES:
12087      if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12088      {
12089        result_buffer[0] = 17;
12090        result_buffer[3] = 14;
12091        PUT_WORD (&result_buffer[4], GOOD);
12092        d = 0;
12093        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12094          d |= LI_CONFERENCING_SUPPORTED;
12095        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12096          d |= LI_MONITORING_SUPPORTED;
12097        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12098          d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12099        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12100          d |= LI_CROSS_CONTROLLER_SUPPORTED;
12101        PUT_DWORD (&result_buffer[6], d);
12102        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12103        {
12104          d = 0;
12105          for (i = 0; i < li_total_channels; i++)
12106          {
12107            if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12108             && (li_config_table[i].adapter->li_pri
12109              || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12110            {
12111              d++;
12112            }
12113          }
12114        }
12115        else
12116        {
12117          d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12118        }
12119        PUT_DWORD (&result_buffer[10], d / 2);
12120        PUT_DWORD (&result_buffer[14], d);
12121      }
12122      else
12123      {
12124        result_buffer[0] = 25;
12125        result_buffer[3] = 22;
12126        PUT_WORD (&result_buffer[4], GOOD);
12127        d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12128        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12129          d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12130        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12131          d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12132        if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12133          d |= LI2_PC_LOOPING_SUPPORTED;
12134        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12135          d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12136        PUT_DWORD (&result_buffer[6], d);
12137        d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12138        PUT_DWORD (&result_buffer[10], d / 2);
12139        PUT_DWORD (&result_buffer[14], d - 1);
12140        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12141        {
12142          d = 0;
12143          for (i = 0; i < li_total_channels; i++)
12144          {
12145            if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12146             && (li_config_table[i].adapter->li_pri
12147              || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12148            {
12149              d++;
12150            }
12151          }
12152        }
12153        PUT_DWORD (&result_buffer[18], d / 2);
12154        PUT_DWORD (&result_buffer[22], d - 1);
12155      }
12156      break;
12157
12158    case LI_REQ_CONNECT:
12159      if (li_parms[1].length == 8)
12160      {
12161        appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12162        if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12163        {
12164          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12165            UnMapId (Id), (char   *)(FILE_), __LINE__));
12166          Info = _WRONG_MESSAGE_FORMAT;
12167          break;
12168        }
12169        plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12170        li_flags = GET_DWORD (li_req_parms[1].info);
12171        Info = li_check_main_plci (Id, plci);
12172        result_buffer[0] = 9;
12173        result_buffer[3] = 6;
12174        PUT_DWORD (&result_buffer[4], plci_b_id);
12175        PUT_WORD (&result_buffer[8], GOOD);
12176        if (Info != GOOD)
12177          break;
12178        result = plci->saved_msg.info;
12179        for (i = 0; i <= result_buffer[0]; i++)
12180          result[i] = result_buffer[i];
12181        plci_b_write_pos = plci->li_plci_b_write_pos;
12182        plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12183        if (plci_b == NULL)
12184          break;
12185        li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12186        plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12187        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12188        plci->li_plci_b_write_pos = plci_b_write_pos;
12189      }
12190      else
12191      {
12192        appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12193        if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12194        {
12195          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12196            UnMapId (Id), (char   *)(FILE_), __LINE__));
12197          Info = _WRONG_MESSAGE_FORMAT;
12198          break;
12199        }
12200        li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12201        Info = li_check_main_plci (Id, plci);
12202        result_buffer[0] = 7;
12203        result_buffer[3] = 4;
12204        PUT_WORD (&result_buffer[4], Info);
12205        result_buffer[6] = 0;
12206        if (Info != GOOD)
12207          break;
12208        result = plci->saved_msg.info;
12209        for (i = 0; i <= result_buffer[0]; i++)
12210          result[i] = result_buffer[i];
12211        plci_b_write_pos = plci->li_plci_b_write_pos;
12212        participant_parms_pos = 0;
12213        result_pos = 7;
12214        li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12215        while (participant_parms_pos < li_req_parms[1].length)
12216        {
12217          result[result_pos] = 6;
12218          result_pos += 7;
12219          PUT_DWORD (&result[result_pos - 6], 0);
12220          PUT_WORD (&result[result_pos - 2], GOOD);
12221          if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12222            (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12223          {
12224            dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12225              UnMapId (Id), (char   *)(FILE_), __LINE__));
12226            PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12227            break;
12228          }
12229          if (api_parse (&li_participant_struct[0].info[1],
12230            li_participant_struct[0].length, "dd", li_participant_parms))
12231          {
12232            dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12233              UnMapId (Id), (char   *)(FILE_), __LINE__));
12234            PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12235            break;
12236          }
12237          plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12238          li_flags = GET_DWORD (li_participant_parms[1].info);
12239          PUT_DWORD (&result[result_pos - 6], plci_b_id);
12240          if (sizeof(result) - result_pos < 7)
12241          {
12242            dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12243              UnMapId (Id), (char   *)(FILE_), __LINE__));
12244            PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12245            break;
12246          }
12247          plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12248          if (plci_b != NULL)
12249          {
12250            li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12251            plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12252              ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12253              LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12254            plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12255          }
12256          participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12257            (&li_req_parms[1].info[1]));
12258        }
12259        result[0] = (byte)(result_pos - 1);
12260        result[3] = (byte)(result_pos - 4);
12261        result[6] = (byte)(result_pos - 7);
12262        i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12263        if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12264         || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12265        {
12266          plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12267          plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12268        }
12269        else
12270          plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12271        plci->li_plci_b_write_pos = plci_b_write_pos;
12272      }
12273      mixer_calculate_coefs (a);
12274      plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12275      mixer_notify_update (plci, true);
12276      sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12277        "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12278      plci->command = 0;
12279      plci->li_cmd = GET_WORD (li_parms[0].info);
12280      start_internal_command (Id, plci, mixer_command);
12281      return (false);
12282
12283    case LI_REQ_DISCONNECT:
12284      if (li_parms[1].length == 4)
12285      {
12286        appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12287        if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12288        {
12289          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12290            UnMapId (Id), (char   *)(FILE_), __LINE__));
12291          Info = _WRONG_MESSAGE_FORMAT;
12292          break;
12293        }
12294        plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12295        Info = li_check_main_plci (Id, plci);
12296        result_buffer[0] = 9;
12297        result_buffer[3] = 6;
12298        PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12299        PUT_WORD (&result_buffer[8], GOOD);
12300        if (Info != GOOD)
12301          break;
12302        result = plci->saved_msg.info;
12303        for (i = 0; i <= result_buffer[0]; i++)
12304          result[i] = result_buffer[i];
12305        plci_b_write_pos = plci->li_plci_b_write_pos;
12306        plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12307        if (plci_b == NULL)
12308          break;
12309        li_update_connect (Id, a, plci, plci_b_id, false, 0);
12310        plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12311        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12312        plci->li_plci_b_write_pos = plci_b_write_pos;
12313      }
12314      else
12315      {
12316        appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12317        if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12318        {
12319          dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12320            UnMapId (Id), (char   *)(FILE_), __LINE__));
12321          Info = _WRONG_MESSAGE_FORMAT;
12322          break;
12323        }
12324        Info = li_check_main_plci (Id, plci);
12325        result_buffer[0] = 7;
12326        result_buffer[3] = 4;
12327        PUT_WORD (&result_buffer[4], Info);
12328        result_buffer[6] = 0;
12329        if (Info != GOOD)
12330          break;
12331        result = plci->saved_msg.info;
12332        for (i = 0; i <= result_buffer[0]; i++)
12333          result[i] = result_buffer[i];
12334        plci_b_write_pos = plci->li_plci_b_write_pos;
12335        participant_parms_pos = 0;
12336        result_pos = 7;
12337        while (participant_parms_pos < li_req_parms[0].length)
12338        {
12339          result[result_pos] = 6;
12340          result_pos += 7;
12341          PUT_DWORD (&result[result_pos - 6], 0);
12342          PUT_WORD (&result[result_pos - 2], GOOD);
12343          if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12344            (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12345          {
12346            dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12347              UnMapId (Id), (char   *)(FILE_), __LINE__));
12348            PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12349            break;
12350          }
12351          if (api_parse (&li_participant_struct[0].info[1],
12352            li_participant_struct[0].length, "d", li_participant_parms))
12353          {
12354            dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12355              UnMapId (Id), (char   *)(FILE_), __LINE__));
12356            PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12357            break;
12358          }
12359          plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12360          PUT_DWORD (&result[result_pos - 6], plci_b_id);
12361          if (sizeof(result) - result_pos < 7)
12362          {
12363            dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12364              UnMapId (Id), (char   *)(FILE_), __LINE__));
12365            PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12366            break;
12367          }
12368          plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12369          if (plci_b != NULL)
12370          {
12371            li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12372            plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12373            plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12374          }
12375          participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12376            (&li_req_parms[0].info[1]));
12377        }
12378        result[0] = (byte)(result_pos - 1);
12379        result[3] = (byte)(result_pos - 4);
12380        result[6] = (byte)(result_pos - 7);
12381        i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12382        if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12383         || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12384        {
12385          plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12386          plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12387        }
12388        else
12389          plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12390        plci->li_plci_b_write_pos = plci_b_write_pos;
12391      }
12392      mixer_calculate_coefs (a);
12393      plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12394      mixer_notify_update (plci, true);
12395      sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12396        "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12397      plci->command = 0;
12398      plci->li_cmd = GET_WORD (li_parms[0].info);
12399      start_internal_command (Id, plci, mixer_command);
12400      return (false);
12401
12402    case LI_REQ_SILENT_UPDATE:
12403      if (!plci || !plci->State
12404       || !plci->NL.Id || plci->nl_remove_id
12405       || (plci->li_bchannel_id == 0)
12406       || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12407      {
12408        dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12409          UnMapId (Id), (char   *)(FILE_), __LINE__));
12410        return (false);
12411      }
12412      plci_b_write_pos = plci->li_plci_b_write_pos;
12413      if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12414        LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12415      {
12416        dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12417          UnMapId (Id), (char   *)(FILE_), __LINE__));
12418        return (false);
12419      }
12420      i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12421      if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12422       || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12423      {
12424        plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12425        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12426      }
12427      else
12428        plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12429      plci->li_plci_b_write_pos = plci_b_write_pos;
12430      plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12431      plci->command = 0;
12432      plci->li_cmd = GET_WORD (li_parms[0].info);
12433      start_internal_command (Id, plci, mixer_command);
12434      return (false);
12435
12436    default:
12437      dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12438        UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12439      Info = _FACILITY_NOT_SUPPORTED;
12440    }
12441  }
12442  sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12443    "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12444  return (false);
12445}
12446
12447
12448static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12449{
12450  dword d;
12451  DIVA_CAPI_ADAPTER   *a;
12452    byte result[12];
12453
12454  dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12455    UnMapId (Id), (char   *)(FILE_), __LINE__));
12456
12457  a = plci->adapter;
12458  if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12459  {
12460    do
12461    {
12462      d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12463      if (!(d & LI_PLCI_B_SKIP_FLAG))
12464      {
12465        if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12466        {
12467          if (d & LI_PLCI_B_DISC_FLAG)
12468          {
12469            result[0] = 5;
12470            PUT_WORD (&result[1], LI_IND_DISCONNECT);
12471            result[3] = 2;
12472            PUT_WORD (&result[4], _LI_USER_INITIATED);
12473          }
12474          else
12475          {
12476            result[0] = 7;
12477            PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12478            result[3] = 4;
12479            PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12480          }
12481        }
12482        else
12483        {
12484          if (d & LI_PLCI_B_DISC_FLAG)
12485          {
12486            result[0] = 9;
12487            PUT_WORD (&result[1], LI_IND_DISCONNECT);
12488            result[3] = 6;
12489            PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12490            PUT_WORD (&result[8], _LI_USER_INITIATED);
12491          }
12492          else
12493          {
12494            result[0] = 7;
12495            PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12496            result[3] = 4;
12497            PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12498          }
12499        }
12500        sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12501          "ws", SELECTOR_LINE_INTERCONNECT, result);
12502      }
12503      plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12504        0 : plci->li_plci_b_read_pos + 1;
12505    } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12506  }
12507}
12508
12509
12510static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12511{
12512  word i, j, ch;
12513  struct xconnect_transfer_address_s s,   *p;
12514  DIVA_CAPI_ADAPTER   *a;
12515
12516  dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12517    UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12518
12519  a = plci->adapter;
12520  i = 1;
12521  for (i = 1; i < length; i += 16)
12522  {
12523    s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12524    s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12525    s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12526    ch = msg[i+12] | (msg[i+13] << 8);
12527    j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12528    if (!a->li_pri && (plci->li_bchannel_id == 2))
12529      j = 1 - j;
12530    j += a->li_base;
12531    if (ch & XCONNECT_CHANNEL_PORT_PC)
12532      p = &(li_config_table[j].send_pc);
12533    else
12534      p = &(li_config_table[j].send_b);
12535    p->card_address.low = s.card_address.low;
12536    p->card_address.high = s.card_address.high;
12537    p->offset = s.offset;
12538    li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12539  }
12540  if (plci->internal_command_queue[0]
12541   && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12542    || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12543    || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12544  {
12545    (*(plci->internal_command_queue[0]))(Id, plci, 0);
12546    if (!plci->internal_command)
12547      next_internal_command (Id, plci);
12548  }
12549  mixer_notify_update (plci, true);
12550}
12551
12552
12553static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12554{
12555
12556  dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12557    UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12558
12559}
12560
12561
12562static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12563{
12564  word plci_b_write_pos;
12565
12566  plci_b_write_pos = plci->li_plci_b_write_pos;
12567  if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12568    LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12569  {
12570    dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12571      (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12572      (char   *)(FILE_), __LINE__));
12573    return (false);
12574  }
12575  plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12576  plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12577  plci->li_plci_b_write_pos = plci_b_write_pos;
12578  return (true);
12579}
12580
12581
12582static void mixer_remove (PLCI   *plci)
12583{
12584  DIVA_CAPI_ADAPTER   *a;
12585  PLCI   *notify_plci;
12586  dword plci_b_id;
12587  word i, j;
12588
12589  dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12590    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12591    (char   *)(FILE_), __LINE__));
12592
12593  a = plci->adapter;
12594  plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12595  if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12596  {
12597    if ((plci->li_bchannel_id != 0)
12598     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12599    {
12600      i = a->li_base + (plci->li_bchannel_id - 1);
12601      if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12602      {
12603        for (j = 0; j < li_total_channels; j++)
12604        {
12605          if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12606           || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12607          {
12608            notify_plci = li_config_table[j].plci;
12609            if ((notify_plci != NULL)
12610             && (notify_plci != plci)
12611             && (notify_plci->appl != NULL)
12612             && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12613             && (notify_plci->State)
12614             && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12615            {
12616              mixer_notify_source_removed (notify_plci, plci_b_id);
12617            }
12618          }
12619        }
12620        mixer_clear_config (plci);
12621        mixer_calculate_coefs (a);
12622        mixer_notify_update (plci, true);
12623      }
12624      li_config_table[i].plci = NULL;
12625      plci->li_bchannel_id = 0;
12626    }
12627  }
12628}
12629
12630
12631/*------------------------------------------------------------------*/
12632/* Echo canceller facilities                                        */
12633/*------------------------------------------------------------------*/
12634
12635
12636static void ec_write_parameters (PLCI   *plci)
12637{
12638  word w;
12639    byte parameter_buffer[6];
12640
12641  dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12642    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12643    (char   *)(FILE_), __LINE__));
12644
12645  parameter_buffer[0] = 5;
12646  parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12647  PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12648  plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12649  w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12650  PUT_WORD (&parameter_buffer[4], w);
12651  add_p (plci, FTY, parameter_buffer);
12652  sig_req (plci, TEL_CTRL, 0);
12653  send_req (plci);
12654}
12655
12656
12657static void ec_clear_config (PLCI   *plci)
12658{
12659
12660  dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12661    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12662    (char   *)(FILE_), __LINE__));
12663
12664  plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12665    LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12666  plci->ec_tail_length = 0;
12667}
12668
12669
12670static void ec_prepare_switch (dword Id, PLCI   *plci)
12671{
12672
12673  dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12674    UnMapId (Id), (char   *)(FILE_), __LINE__));
12675
12676}
12677
12678
12679static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12680{
12681
12682  dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12683    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12684
12685  return (GOOD);
12686}
12687
12688
12689static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12690{
12691  word Info;
12692
12693  dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12694    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12695
12696  Info = GOOD;
12697  if (plci->B1_facilities & B1_FACILITY_EC)
12698  {
12699    switch (plci->adjust_b_state)
12700    {
12701    case ADJUST_B_RESTORE_EC_1:
12702      plci->internal_command = plci->adjust_b_command;
12703      if (plci->sig_req)
12704      {
12705        plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12706        break;
12707      }
12708      ec_write_parameters (plci);
12709      plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12710      break;
12711    case ADJUST_B_RESTORE_EC_2:
12712      if ((Rc != OK) && (Rc != OK_FC))
12713      {
12714        dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12715          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12716        Info = _WRONG_STATE;
12717        break;
12718      }
12719      break;
12720    }
12721  }
12722  return (Info);
12723}
12724
12725
12726static void ec_command (dword Id, PLCI   *plci, byte Rc)
12727{
12728  word internal_command, Info;
12729    byte result[8];
12730
12731  dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12732    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12733    plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12734
12735  Info = GOOD;
12736  if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12737  {
12738    result[0] = 2;
12739    PUT_WORD (&result[1], EC_SUCCESS);
12740  }
12741  else
12742  {
12743    result[0] = 5;
12744    PUT_WORD (&result[1], plci->ec_cmd);
12745    result[3] = 2;
12746    PUT_WORD (&result[4], GOOD);
12747  }
12748  internal_command = plci->internal_command;
12749  plci->internal_command = 0;
12750  switch (plci->ec_cmd)
12751  {
12752  case EC_ENABLE_OPERATION:
12753  case EC_FREEZE_COEFFICIENTS:
12754  case EC_RESUME_COEFFICIENT_UPDATE:
12755  case EC_RESET_COEFFICIENTS:
12756    switch (internal_command)
12757    {
12758    default:
12759      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12760        B1_FACILITY_EC), EC_COMMAND_1);
12761    case EC_COMMAND_1:
12762      if (adjust_b_process (Id, plci, Rc) != GOOD)
12763      {
12764        dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12765          UnMapId (Id), (char   *)(FILE_), __LINE__));
12766        Info = _FACILITY_NOT_SUPPORTED;
12767        break;
12768      }
12769      if (plci->internal_command)
12770        return;
12771    case EC_COMMAND_2:
12772      if (plci->sig_req)
12773      {
12774        plci->internal_command = EC_COMMAND_2;
12775        return;
12776      }
12777      plci->internal_command = EC_COMMAND_3;
12778      ec_write_parameters (plci);
12779      return;
12780    case EC_COMMAND_3:
12781      if ((Rc != OK) && (Rc != OK_FC))
12782      {
12783        dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12784          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12785        Info = _FACILITY_NOT_SUPPORTED;
12786        break;
12787      }
12788      break;
12789    }
12790    break;
12791
12792  case EC_DISABLE_OPERATION:
12793    switch (internal_command)
12794    {
12795    default:
12796    case EC_COMMAND_1:
12797      if (plci->B1_facilities & B1_FACILITY_EC)
12798      {
12799        if (plci->sig_req)
12800        {
12801          plci->internal_command = EC_COMMAND_1;
12802          return;
12803        }
12804        plci->internal_command = EC_COMMAND_2;
12805        ec_write_parameters (plci);
12806        return;
12807      }
12808      Rc = OK;
12809    case EC_COMMAND_2:
12810      if ((Rc != OK) && (Rc != OK_FC))
12811      {
12812        dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12813          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12814        Info = _FACILITY_NOT_SUPPORTED;
12815        break;
12816      }
12817      adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12818        ~B1_FACILITY_EC), EC_COMMAND_3);
12819    case EC_COMMAND_3:
12820      if (adjust_b_process (Id, plci, Rc) != GOOD)
12821      {
12822        dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12823          UnMapId (Id), (char   *)(FILE_), __LINE__));
12824        Info = _FACILITY_NOT_SUPPORTED;
12825        break;
12826      }
12827      if (plci->internal_command)
12828        return;
12829      break;
12830    }
12831    break;
12832  }
12833  sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12834    "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12835    PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12836}
12837
12838
12839static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12840{
12841  word Info;
12842  word opt;
12843    API_PARSE ec_parms[3];
12844    byte result[16];
12845
12846  dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12847    UnMapId (Id), (char   *)(FILE_), __LINE__));
12848
12849  Info = GOOD;
12850  result[0] = 0;
12851  if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12852  {
12853    dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12854      UnMapId (Id), (char   *)(FILE_), __LINE__));
12855    Info = _FACILITY_NOT_SUPPORTED;
12856  }
12857  else
12858  {
12859    if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12860    {
12861      if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12862      {
12863        dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12864          UnMapId (Id), (char   *)(FILE_), __LINE__));
12865        Info = _WRONG_MESSAGE_FORMAT;
12866      }
12867      else
12868      {
12869        if (plci == NULL)
12870        {
12871          dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12872            UnMapId (Id), (char   *)(FILE_), __LINE__));
12873          Info = _WRONG_IDENTIFIER;
12874        }
12875        else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12876        {
12877          dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12878            UnMapId (Id), (char   *)(FILE_), __LINE__));
12879          Info = _WRONG_STATE;
12880        }
12881        else
12882        {
12883          plci->command = 0;
12884          plci->ec_cmd = GET_WORD (ec_parms[0].info);
12885          plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12886          result[0] = 2;
12887          PUT_WORD (&result[1], EC_SUCCESS);
12888          if (msg[1].length >= 4)
12889          {
12890            opt = GET_WORD (&ec_parms[0].info[2]);
12891            plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12892              LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12893            if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12894              plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12895            if (opt & EC_DETECT_DISABLE_TONE)
12896              plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12897            if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12898              plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12899            if (msg[1].length >= 6)
12900            {
12901              plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12902            }
12903          }
12904          switch (plci->ec_cmd)
12905          {
12906          case EC_ENABLE_OPERATION:
12907            plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12908            start_internal_command (Id, plci, ec_command);
12909            return (false);
12910
12911          case EC_DISABLE_OPERATION:
12912            plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12913              LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12914              LEC_RESET_COEFFICIENTS;
12915            start_internal_command (Id, plci, ec_command);
12916            return (false);
12917
12918          case EC_FREEZE_COEFFICIENTS:
12919            plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12920            start_internal_command (Id, plci, ec_command);
12921            return (false);
12922
12923          case EC_RESUME_COEFFICIENT_UPDATE:
12924            plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12925            start_internal_command (Id, plci, ec_command);
12926            return (false);
12927
12928          case EC_RESET_COEFFICIENTS:
12929            plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12930            start_internal_command (Id, plci, ec_command);
12931            return (false);
12932
12933          default:
12934            dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12935              UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12936            PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12937          }
12938        }
12939      }
12940    }
12941    else
12942    {
12943      if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12944      {
12945        dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12946          UnMapId (Id), (char   *)(FILE_), __LINE__));
12947        Info = _WRONG_MESSAGE_FORMAT;
12948      }
12949      else
12950      {
12951        if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12952        {
12953          result[0] = 11;
12954          PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12955          result[3] = 8;
12956          PUT_WORD (&result[4], GOOD);
12957          PUT_WORD (&result[6], 0x0007);
12958          PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12959          PUT_WORD (&result[10], 0);
12960        }
12961        else if (plci == NULL)
12962        {
12963          dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12964            UnMapId (Id), (char   *)(FILE_), __LINE__));
12965          Info = _WRONG_IDENTIFIER;
12966        }
12967        else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12968        {
12969          dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12970            UnMapId (Id), (char   *)(FILE_), __LINE__));
12971          Info = _WRONG_STATE;
12972        }
12973        else
12974        {
12975          plci->command = 0;
12976          plci->ec_cmd = GET_WORD (ec_parms[0].info);
12977          plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12978          result[0] = 5;
12979          PUT_WORD (&result[1], plci->ec_cmd);
12980          result[3] = 2;
12981          PUT_WORD (&result[4], GOOD);
12982          plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12983            LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12984          plci->ec_tail_length = 0;
12985          if (ec_parms[1].length >= 2)
12986          {
12987            opt = GET_WORD (&ec_parms[1].info[1]);
12988            if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12989              plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12990            if (opt & EC_DETECT_DISABLE_TONE)
12991              plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12992            if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12993              plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12994            if (ec_parms[1].length >= 4)
12995            {
12996              plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12997            }
12998          }
12999          switch (plci->ec_cmd)
13000          {
13001          case EC_ENABLE_OPERATION:
13002            plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
13003            start_internal_command (Id, plci, ec_command);
13004            return (false);
13005
13006          case EC_DISABLE_OPERATION:
13007            plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
13008              LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
13009              LEC_RESET_COEFFICIENTS;
13010            start_internal_command (Id, plci, ec_command);
13011            return (false);
13012
13013          default:
13014            dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
13015              UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
13016            PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13017          }
13018        }
13019      }
13020    }
13021  }
13022  sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13023    "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13024    PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13025  return (false);
13026}
13027
13028
13029static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13030{
13031    byte result[8];
13032
13033  dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13034    UnMapId (Id), (char   *)(FILE_), __LINE__));
13035
13036  if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13037  {
13038    if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13039    {
13040      result[0] = 2;
13041      PUT_WORD (&result[1], 0);
13042      switch (msg[1])
13043      {
13044      case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13045        PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13046        break;
13047      case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13048        PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13049        break;
13050      case LEC_DISABLE_RELEASED:
13051        PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13052        break;
13053      }
13054    }
13055    else
13056    {
13057      result[0] = 5;
13058      PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13059      result[3] = 2;
13060      PUT_WORD (&result[4], 0);
13061      switch (msg[1])
13062      {
13063      case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13064        PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13065        break;
13066      case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13067        PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13068        break;
13069      case LEC_DISABLE_RELEASED:
13070        PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13071        break;
13072      }
13073    }
13074    sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13075      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13076  }
13077}
13078
13079
13080
13081/*------------------------------------------------------------------*/
13082/* Advanced voice                                                   */
13083/*------------------------------------------------------------------*/
13084
13085static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13086{
13087  DIVA_CAPI_ADAPTER   *a;
13088  word i;
13089  byte *p;
13090
13091  word w, n, j, k;
13092  byte ch_map[MIXER_CHANNELS_BRI];
13093
13094    byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13095
13096  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13097    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13098    (char   *)(FILE_), __LINE__, write_command));
13099
13100  a = plci->adapter;
13101  p = coef_buffer + 1;
13102  *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13103  i = 0;
13104  while (i + sizeof(word) <= a->adv_voice_coef_length)
13105  {
13106    PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13107    p += 2;
13108    i += 2;
13109  }
13110  while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13111  {
13112    PUT_WORD (p, 0x8000);
13113    p += 2;
13114    i += 2;
13115  }
13116
13117  if (!a->li_pri && (plci->li_bchannel_id == 0))
13118  {
13119    if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13120    {
13121      plci->li_bchannel_id = 1;
13122      li_config_table[a->li_base].plci = plci;
13123      dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13124        (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13125        (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13126    }
13127    else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13128    {
13129      plci->li_bchannel_id = 2;
13130      li_config_table[a->li_base + 1].plci = plci;
13131      dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13132        (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13133        (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13134    }
13135  }
13136  if (!a->li_pri && (plci->li_bchannel_id != 0)
13137   && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13138  {
13139    i = a->li_base + (plci->li_bchannel_id - 1);
13140    switch (write_command)
13141    {
13142    case ADV_VOICE_WRITE_ACTIVATION:
13143      j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13144      k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13145      if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13146      {
13147        li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13148        li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13149      }
13150      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13151      {
13152        li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13153        li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13154        li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13155        li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13156      }
13157      mixer_calculate_coefs (a);
13158      li_config_table[i].curchnl = li_config_table[i].channel;
13159      li_config_table[j].curchnl = li_config_table[j].channel;
13160      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13161        li_config_table[k].curchnl = li_config_table[k].channel;
13162      break;
13163
13164    case ADV_VOICE_WRITE_DEACTIVATION:
13165      for (j = 0; j < li_total_channels; j++)
13166      {
13167        li_config_table[i].flag_table[j] = 0;
13168        li_config_table[j].flag_table[i] = 0;
13169      }
13170      k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13171      for (j = 0; j < li_total_channels; j++)
13172      {
13173        li_config_table[k].flag_table[j] = 0;
13174        li_config_table[j].flag_table[k] = 0;
13175      }
13176      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13177      {
13178        k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13179        for (j = 0; j < li_total_channels; j++)
13180        {
13181          li_config_table[k].flag_table[j] = 0;
13182          li_config_table[j].flag_table[k] = 0;
13183        }
13184      }
13185      mixer_calculate_coefs (a);
13186      break;
13187    }
13188    if (plci->B1_facilities & B1_FACILITY_MIXER)
13189    {
13190      w = 0;
13191      if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13192        w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13193      if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13194        w |= MIXER_FEATURE_ENABLE_TX_DATA;
13195      if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13196        w |= MIXER_FEATURE_ENABLE_RX_DATA;
13197      *(p++) = (byte) w;
13198      *(p++) = (byte)(w >> 8);
13199      for (j = 0; j < sizeof(ch_map); j += 2)
13200      {
13201        ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13202        ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13203      }
13204      for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13205      {
13206        i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13207        j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13208        if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13209        {
13210          *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13211          w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13212          li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13213        }
13214        else
13215        {
13216          *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13217            a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13218        }
13219      }
13220    }
13221    else
13222    {
13223      for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13224        *(p++) = a->adv_voice_coef_buffer[i];
13225    }
13226  }
13227  else
13228
13229  {
13230    for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13231      *(p++) = a->adv_voice_coef_buffer[i];
13232  }
13233  coef_buffer[0] = (p - coef_buffer) - 1;
13234  add_p (plci, FTY, coef_buffer);
13235  sig_req (plci, TEL_CTRL, 0);
13236  send_req (plci);
13237}
13238
13239
13240static void adv_voice_clear_config (PLCI   *plci)
13241{
13242  DIVA_CAPI_ADAPTER   *a;
13243
13244  word i, j;
13245
13246
13247  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13248    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13249    (char   *)(FILE_), __LINE__));
13250
13251  a = plci->adapter;
13252  if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13253  {
13254    a->adv_voice_coef_length = 0;
13255
13256    if (!a->li_pri && (plci->li_bchannel_id != 0)
13257     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13258    {
13259      i = a->li_base + (plci->li_bchannel_id - 1);
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      li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13271      i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13272      li_config_table[i].curchnl = 0;
13273      li_config_table[i].channel = 0;
13274      li_config_table[i].chflags = 0;
13275      for (j = 0; j < li_total_channels; j++)
13276      {
13277        li_config_table[i].flag_table[j] = 0;
13278        li_config_table[j].flag_table[i] = 0;
13279        li_config_table[i].coef_table[j] = 0;
13280        li_config_table[j].coef_table[i] = 0;
13281      }
13282      if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13283      {
13284        i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13285        li_config_table[i].curchnl = 0;
13286        li_config_table[i].channel = 0;
13287        li_config_table[i].chflags = 0;
13288        for (j = 0; j < li_total_channels; j++)
13289        {
13290          li_config_table[i].flag_table[j] = 0;
13291          li_config_table[j].flag_table[i] = 0;
13292          li_config_table[i].coef_table[j] = 0;
13293          li_config_table[j].coef_table[i] = 0;
13294        }
13295      }
13296    }
13297
13298  }
13299}
13300
13301
13302static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13303{
13304
13305  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13306    UnMapId (Id), (char   *)(FILE_), __LINE__));
13307
13308}
13309
13310
13311static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13312{
13313
13314  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13315    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13316
13317  return (GOOD);
13318}
13319
13320
13321static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13322{
13323  DIVA_CAPI_ADAPTER   *a;
13324  word Info;
13325
13326  dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13327    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13328
13329  Info = GOOD;
13330  a = plci->adapter;
13331  if ((plci->B1_facilities & B1_FACILITY_VOICE)
13332   && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13333  {
13334    switch (plci->adjust_b_state)
13335    {
13336    case ADJUST_B_RESTORE_VOICE_1:
13337      plci->internal_command = plci->adjust_b_command;
13338      if (plci->sig_req)
13339      {
13340        plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13341        break;
13342      }
13343      adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13344      plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13345      break;
13346    case ADJUST_B_RESTORE_VOICE_2:
13347      if ((Rc != OK) && (Rc != OK_FC))
13348      {
13349        dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13350          UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13351        Info = _WRONG_STATE;
13352        break;
13353      }
13354      break;
13355    }
13356  }
13357  return (Info);
13358}
13359
13360
13361
13362
13363/*------------------------------------------------------------------*/
13364/* B1 resource switching                                            */
13365/*------------------------------------------------------------------*/
13366
13367static byte b1_facilities_table[] =
13368{
13369  0x00,  /* 0  No bchannel resources      */
13370  0x00,  /* 1  Codec (automatic law)      */
13371  0x00,  /* 2  Codec (A-law)              */
13372  0x00,  /* 3  Codec (y-law)              */
13373  0x00,  /* 4  HDLC for X.21              */
13374  0x00,  /* 5  HDLC                       */
13375  0x00,  /* 6  External Device 0          */
13376  0x00,  /* 7  External Device 1          */
13377  0x00,  /* 8  HDLC 56k                   */
13378  0x00,  /* 9  Transparent                */
13379  0x00,  /* 10 Loopback to network        */
13380  0x00,  /* 11 Test pattern to net        */
13381  0x00,  /* 12 Rate adaptation sync       */
13382  0x00,  /* 13 Rate adaptation async      */
13383  0x00,  /* 14 R-Interface                */
13384  0x00,  /* 15 HDLC 128k leased line      */
13385  0x00,  /* 16 FAX                        */
13386  0x00,  /* 17 Modem async                */
13387  0x00,  /* 18 Modem sync HDLC            */
13388  0x00,  /* 19 V.110 async HDLC           */
13389  0x12,  /* 20 Adv voice (Trans,mixer)    */
13390  0x00,  /* 21 Codec connected to IC      */
13391  0x0c,  /* 22 Trans,DTMF                 */
13392  0x1e,  /* 23 Trans,DTMF+mixer           */
13393  0x1f,  /* 24 Trans,DTMF+mixer+local     */
13394  0x13,  /* 25 Trans,mixer+local          */
13395  0x12,  /* 26 HDLC,mixer                 */
13396  0x12,  /* 27 HDLC 56k,mixer             */
13397  0x2c,  /* 28 Trans,LEC+DTMF             */
13398  0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13399  0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13400  0x2c,  /* 31 RTP,LEC+DTMF               */
13401  0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13402  0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13403  0x00,  /* 34 Signaling task             */
13404  0x00,  /* 35 PIAFS                      */
13405  0x0c,  /* 36 Trans,DTMF+TONE            */
13406  0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13407  0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13408};
13409
13410
13411static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13412{
13413  word b1_facilities;
13414
13415  b1_facilities = b1_facilities_table[b1_resource];
13416  if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13417  {
13418
13419    if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13420       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13421
13422    {
13423      if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13424        b1_facilities |= B1_FACILITY_DTMFX;
13425      if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13426        b1_facilities |= B1_FACILITY_DTMFR;
13427    }
13428  }
13429  if ((b1_resource == 17) || (b1_resource == 18))
13430  {
13431    if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13432      b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13433  }
13434/*
13435  dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13436    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13437    (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13438*/
13439  return (b1_facilities);
13440}
13441
13442
13443static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13444{
13445  byte b;
13446
13447  switch (b1_resource)
13448  {
13449  case 5:
13450  case 26:
13451    if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13452      b = 26;
13453    else
13454      b = 5;
13455    break;
13456
13457  case 8:
13458  case 27:
13459    if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13460      b = 27;
13461    else
13462      b = 8;
13463    break;
13464
13465  case 9:
13466  case 20:
13467  case 22:
13468  case 23:
13469  case 24:
13470  case 25:
13471  case 28:
13472  case 29:
13473  case 30:
13474  case 36:
13475  case 37:
13476  case 38:
13477    if (b1_facilities & B1_FACILITY_EC)
13478    {
13479      if (b1_facilities & B1_FACILITY_LOCAL)
13480        b = 30;
13481      else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13482        b = 29;
13483      else
13484        b = 28;
13485    }
13486
13487    else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13488      && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13489       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13490    {
13491      if (b1_facilities & B1_FACILITY_LOCAL)
13492        b = 38;
13493      else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13494        b = 37;
13495      else
13496        b = 36;
13497    }
13498
13499    else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13500      && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13501     || ((b1_facilities & B1_FACILITY_DTMFR)
13502      && ((b1_facilities & B1_FACILITY_MIXER)
13503       || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13504     || ((b1_facilities & B1_FACILITY_DTMFX)
13505      && ((b1_facilities & B1_FACILITY_MIXER)
13506       || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13507    {
13508      if (b1_facilities & B1_FACILITY_LOCAL)
13509        b = 24;
13510      else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13511        b = 23;
13512      else
13513        b = 22;
13514    }
13515    else
13516    {
13517      if (b1_facilities & B1_FACILITY_LOCAL)
13518        b = 25;
13519      else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13520        b = 20;
13521      else
13522        b = 9;
13523    }
13524    break;
13525
13526  case 31:
13527  case 32:
13528  case 33:
13529    if (b1_facilities & B1_FACILITY_LOCAL)
13530      b = 33;
13531    else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13532      b = 32;
13533    else
13534      b = 31;
13535    break;
13536
13537  default:
13538    b = b1_resource;
13539  }
13540  dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13541    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13542    (char   *)(FILE_), __LINE__,
13543    b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13544  return (b);
13545}
13546
13547
13548static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13549{
13550  word removed_facilities;
13551
13552  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13553    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13554    (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13555    new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13556
13557  new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13558  removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13559
13560  if (removed_facilities & B1_FACILITY_EC)
13561    ec_clear_config (plci);
13562
13563
13564  if (removed_facilities & B1_FACILITY_DTMFR)
13565  {
13566    dtmf_rec_clear_config (plci);
13567    dtmf_parameter_clear_config (plci);
13568  }
13569  if (removed_facilities & B1_FACILITY_DTMFX)
13570    dtmf_send_clear_config (plci);
13571
13572
13573  if (removed_facilities & B1_FACILITY_MIXER)
13574    mixer_clear_config (plci);
13575
13576  if (removed_facilities & B1_FACILITY_VOICE)
13577    adv_voice_clear_config (plci);
13578  plci->B1_facilities = new_b1_facilities;
13579}
13580
13581
13582static void adjust_b_clear (PLCI   *plci)
13583{
13584
13585  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13586    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13587    (char   *)(FILE_), __LINE__));
13588
13589  plci->adjust_b_restore = false;
13590}
13591
13592
13593static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13594{
13595  word Info;
13596  byte b1_resource;
13597  NCCI   * ncci_ptr;
13598    API_PARSE bp[2];
13599
13600  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13601    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13602
13603  Info = GOOD;
13604  switch (plci->adjust_b_state)
13605  {
13606  case ADJUST_B_START:
13607    if ((plci->adjust_b_parms_msg == NULL)
13608     && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13609     && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13610      ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13611    {
13612      b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13613        0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13614      if (b1_resource == plci->B1_resource)
13615      {
13616        adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13617        break;
13618      }
13619      if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13620      {
13621        dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13622          UnMapId (Id), (char   *)(FILE_), __LINE__,
13623          plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13624        Info = _WRONG_STATE;
13625        break;
13626      }
13627    }
13628    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13629    {
13630
13631      mixer_prepare_switch (Id, plci);
13632
13633
13634      dtmf_prepare_switch (Id, plci);
13635      dtmf_parameter_prepare_switch (Id, plci);
13636
13637
13638      ec_prepare_switch (Id, plci);
13639
13640      adv_voice_prepare_switch (Id, plci);
13641    }
13642    plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13643    Rc = OK;
13644  case ADJUST_B_SAVE_MIXER_1:
13645    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13646    {
13647
13648      Info = mixer_save_config (Id, plci, Rc);
13649      if ((Info != GOOD) || plci->internal_command)
13650        break;
13651
13652    }
13653    plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13654    Rc = OK;
13655  case ADJUST_B_SAVE_DTMF_1:
13656    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13657    {
13658
13659      Info = dtmf_save_config (Id, plci, Rc);
13660      if ((Info != GOOD) || plci->internal_command)
13661        break;
13662
13663    }
13664    plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13665  case ADJUST_B_REMOVE_L23_1:
13666    if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13667     && plci->NL.Id && !plci->nl_remove_id)
13668    {
13669      plci->internal_command = plci->adjust_b_command;
13670      if (plci->adjust_b_ncci != 0)
13671      {
13672        ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13673        while (ncci_ptr->data_pending)
13674        {
13675          plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13676          data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13677        }
13678        while (ncci_ptr->data_ack_pending)
13679          data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13680      }
13681      nl_req_ncci (plci, REMOVE,
13682        (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13683      send_req (plci);
13684      plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13685      break;
13686    }
13687    plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13688    Rc = OK;
13689  case ADJUST_B_REMOVE_L23_2:
13690    if ((Rc != OK) && (Rc != OK_FC))
13691    {
13692      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13693        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13694      Info = _WRONG_STATE;
13695      break;
13696    }
13697    if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13698    {
13699      if (plci_nl_busy (plci))
13700      {
13701        plci->internal_command = plci->adjust_b_command;
13702        break;
13703      }
13704    }
13705    plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13706    Rc = OK;
13707  case ADJUST_B_SAVE_EC_1:
13708    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13709    {
13710
13711      Info = ec_save_config (Id, plci, Rc);
13712      if ((Info != GOOD) || plci->internal_command)
13713        break;
13714
13715    }
13716    plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13717    Rc = OK;
13718  case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13719    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13720    {
13721
13722      Info = dtmf_parameter_save_config (Id, plci, Rc);
13723      if ((Info != GOOD) || plci->internal_command)
13724        break;
13725
13726    }
13727    plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13728    Rc = OK;
13729  case ADJUST_B_SAVE_VOICE_1:
13730    if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13731    {
13732      Info = adv_voice_save_config (Id, plci, Rc);
13733      if ((Info != GOOD) || plci->internal_command)
13734        break;
13735    }
13736    plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13737  case ADJUST_B_SWITCH_L1_1:
13738    if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13739    {
13740      if (plci->sig_req)
13741      {
13742        plci->internal_command = plci->adjust_b_command;
13743        break;
13744      }
13745      if (plci->adjust_b_parms_msg != NULL)
13746        api_load_msg (plci->adjust_b_parms_msg, bp);
13747      else
13748        api_load_msg (&plci->B_protocol, bp);
13749      Info = add_b1 (plci, bp,
13750        (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13751        plci->adjust_b_facilities);
13752      if (Info != GOOD)
13753      {
13754        dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13755          UnMapId (Id), (char   *)(FILE_), __LINE__,
13756          plci->B1_resource, plci->adjust_b_facilities));
13757        break;
13758      }
13759      plci->internal_command = plci->adjust_b_command;
13760      sig_req (plci, RESOURCES, 0);
13761      send_req (plci);
13762      plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13763      break;
13764    }
13765    plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13766    Rc = OK;
13767  case ADJUST_B_SWITCH_L1_2:
13768    if ((Rc != OK) && (Rc != OK_FC))
13769    {
13770      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13771        UnMapId (Id), (char   *)(FILE_), __LINE__,
13772        Rc, plci->B1_resource, plci->adjust_b_facilities));
13773      Info = _WRONG_STATE;
13774      break;
13775    }
13776    plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13777    Rc = OK;
13778  case ADJUST_B_RESTORE_VOICE_1:
13779  case ADJUST_B_RESTORE_VOICE_2:
13780    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13781    {
13782      Info = adv_voice_restore_config (Id, plci, Rc);
13783      if ((Info != GOOD) || plci->internal_command)
13784        break;
13785    }
13786    plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13787    Rc = OK;
13788  case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13789  case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13790    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13791    {
13792
13793      Info = dtmf_parameter_restore_config (Id, plci, Rc);
13794      if ((Info != GOOD) || plci->internal_command)
13795        break;
13796
13797    }
13798    plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13799    Rc = OK;
13800  case ADJUST_B_RESTORE_EC_1:
13801  case ADJUST_B_RESTORE_EC_2:
13802    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13803    {
13804
13805      Info = ec_restore_config (Id, plci, Rc);
13806      if ((Info != GOOD) || plci->internal_command)
13807        break;
13808
13809    }
13810    plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13811  case ADJUST_B_ASSIGN_L23_1:
13812    if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13813    {
13814      if (plci_nl_busy (plci))
13815      {
13816        plci->internal_command = plci->adjust_b_command;
13817        break;
13818      }
13819      if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13820        plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13821      if (plci->adjust_b_parms_msg != NULL)
13822        api_load_msg (plci->adjust_b_parms_msg, bp);
13823      else
13824        api_load_msg (&plci->B_protocol, bp);
13825      Info = add_b23 (plci, bp);
13826      if (Info != GOOD)
13827      {
13828        dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13829          UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13830        break;
13831      }
13832      plci->internal_command = plci->adjust_b_command;
13833      nl_req_ncci (plci, ASSIGN, 0);
13834      send_req (plci);
13835      plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13836      break;
13837    }
13838    plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13839    Rc = ASSIGN_OK;
13840  case ADJUST_B_ASSIGN_L23_2:
13841    if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13842    {
13843      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13844        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13845      Info = _WRONG_STATE;
13846      break;
13847    }
13848    if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13849    {
13850      if (Rc != ASSIGN_OK)
13851      {
13852        plci->internal_command = plci->adjust_b_command;
13853        break;
13854      }
13855    }
13856    if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13857    {
13858      plci->adjust_b_restore = true;
13859      break;
13860    }
13861    plci->adjust_b_state = ADJUST_B_CONNECT_1;
13862  case ADJUST_B_CONNECT_1:
13863    if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13864    {
13865      plci->internal_command = plci->adjust_b_command;
13866      if (plci_nl_busy (plci))
13867        break;
13868      nl_req_ncci (plci, N_CONNECT, 0);
13869      send_req (plci);
13870      plci->adjust_b_state = ADJUST_B_CONNECT_2;
13871      break;
13872    }
13873    plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13874    Rc = OK;
13875  case ADJUST_B_CONNECT_2:
13876  case ADJUST_B_CONNECT_3:
13877  case ADJUST_B_CONNECT_4:
13878    if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13879    {
13880      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13881        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13882      Info = _WRONG_STATE;
13883      break;
13884    }
13885    if (Rc == OK)
13886    {
13887      if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13888      {
13889        get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13890        Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13891      }
13892      if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13893        plci->adjust_b_state = ADJUST_B_CONNECT_3;
13894      else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13895        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13896    }
13897    else if (Rc == 0)
13898    {
13899      if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13900        plci->adjust_b_state = ADJUST_B_CONNECT_4;
13901      else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13902        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13903    }
13904    if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13905    {
13906      plci->internal_command = plci->adjust_b_command;
13907      break;
13908    }
13909    Rc = OK;
13910  case ADJUST_B_RESTORE_DTMF_1:
13911  case ADJUST_B_RESTORE_DTMF_2:
13912    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13913    {
13914
13915      Info = dtmf_restore_config (Id, plci, Rc);
13916      if ((Info != GOOD) || plci->internal_command)
13917        break;
13918
13919    }
13920    plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13921    Rc = OK;
13922  case ADJUST_B_RESTORE_MIXER_1:
13923  case ADJUST_B_RESTORE_MIXER_2:
13924  case ADJUST_B_RESTORE_MIXER_3:
13925  case ADJUST_B_RESTORE_MIXER_4:
13926  case ADJUST_B_RESTORE_MIXER_5:
13927  case ADJUST_B_RESTORE_MIXER_6:
13928  case ADJUST_B_RESTORE_MIXER_7:
13929    if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13930    {
13931
13932      Info = mixer_restore_config (Id, plci, Rc);
13933      if ((Info != GOOD) || plci->internal_command)
13934        break;
13935
13936    }
13937    plci->adjust_b_state = ADJUST_B_END;
13938  case ADJUST_B_END:
13939    break;
13940  }
13941  return (Info);
13942}
13943
13944
13945static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13946{
13947
13948  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13949    UnMapId (Id), (char   *)(FILE_), __LINE__,
13950    plci->B1_resource, b1_facilities));
13951
13952  plci->adjust_b_parms_msg = bp_msg;
13953  plci->adjust_b_facilities = b1_facilities;
13954  plci->adjust_b_command = internal_command;
13955  plci->adjust_b_ncci = (word)(Id >> 16);
13956  if ((bp_msg == NULL) && (plci->B1_resource == 0))
13957    plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13958  else
13959    plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13960  plci->adjust_b_state = ADJUST_B_START;
13961  dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13962    UnMapId (Id), (char   *)(FILE_), __LINE__,
13963    plci->B1_resource, b1_facilities));
13964}
13965
13966
13967static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13968{
13969  word internal_command;
13970
13971  dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13972    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13973
13974  internal_command = plci->internal_command;
13975  plci->internal_command = 0;
13976  switch (internal_command)
13977  {
13978  default:
13979    plci->command = 0;
13980    if (plci->req_in != 0)
13981    {
13982      plci->internal_command = ADJUST_B_RESTORE_1;
13983      break;
13984    }
13985    Rc = OK;
13986  case ADJUST_B_RESTORE_1:
13987    if ((Rc != OK) && (Rc != OK_FC))
13988    {
13989      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13990        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13991    }
13992    plci->adjust_b_parms_msg = NULL;
13993    plci->adjust_b_facilities = plci->B1_facilities;
13994    plci->adjust_b_command = ADJUST_B_RESTORE_2;
13995    plci->adjust_b_ncci = (word)(Id >> 16);
13996    plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13997    plci->adjust_b_state = ADJUST_B_START;
13998    dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13999      UnMapId (Id), (char   *)(FILE_), __LINE__));
14000  case ADJUST_B_RESTORE_2:
14001    if (adjust_b_process (Id, plci, Rc) != GOOD)
14002    {
14003      dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
14004        UnMapId (Id), (char   *)(FILE_), __LINE__));
14005    }
14006    if (plci->internal_command)
14007      break;
14008    break;
14009  }
14010}
14011
14012
14013static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
14014{
14015  word Info;
14016  word internal_command;
14017
14018  dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14019    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14020
14021  Info = GOOD;
14022  internal_command = plci->internal_command;
14023  plci->internal_command = 0;
14024  switch (internal_command)
14025  {
14026  default:
14027    plci->command = 0;
14028    plci->adjust_b_parms_msg = NULL;
14029    plci->adjust_b_facilities = plci->B1_facilities;
14030    plci->adjust_b_command = RESET_B3_COMMAND_1;
14031    plci->adjust_b_ncci = (word)(Id >> 16);
14032    plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14033    plci->adjust_b_state = ADJUST_B_START;
14034    dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14035      UnMapId (Id), (char   *)(FILE_), __LINE__));
14036  case RESET_B3_COMMAND_1:
14037    Info = adjust_b_process (Id, plci, Rc);
14038    if (Info != GOOD)
14039    {
14040      dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14041        UnMapId (Id), (char   *)(FILE_), __LINE__));
14042      break;
14043    }
14044    if (plci->internal_command)
14045      return;
14046    break;
14047  }
14048/*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14049  sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14050}
14051
14052
14053static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14054{
14055  word Info;
14056  word internal_command;
14057  byte esc_chi[3];
14058
14059  dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14060    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14061
14062  Info = GOOD;
14063  internal_command = plci->internal_command;
14064  plci->internal_command = 0;
14065  switch (internal_command)
14066  {
14067  default:
14068    plci->command = 0;
14069    plci->adjust_b_parms_msg = &plci->saved_msg;
14070    if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14071      plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14072    else
14073      plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14074    plci->adjust_b_command = SELECT_B_COMMAND_1;
14075    plci->adjust_b_ncci = (word)(Id >> 16);
14076    if (plci->saved_msg.parms[0].length == 0)
14077    {
14078      plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14079        ADJUST_B_MODE_NO_RESOURCE;
14080    }
14081    else
14082    {
14083      plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14084        ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14085    }
14086    plci->adjust_b_state = ADJUST_B_START;
14087    dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14088      UnMapId (Id), (char   *)(FILE_), __LINE__));
14089  case SELECT_B_COMMAND_1:
14090    Info = adjust_b_process (Id, plci, Rc);
14091    if (Info != GOOD)
14092    {
14093      dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14094        UnMapId (Id), (char   *)(FILE_), __LINE__));
14095      break;
14096    }
14097    if (plci->internal_command)
14098      return;
14099    if (plci->tel == ADV_VOICE)
14100    {
14101      esc_chi[0] = 0x02;
14102      esc_chi[1] = 0x18;
14103      esc_chi[2] = plci->b_channel;
14104      SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14105    }
14106    break;
14107  }
14108  sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14109}
14110
14111
14112static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14113{
14114  word Info;
14115  word internal_command;
14116
14117  dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14118    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14119
14120  Info = GOOD;
14121  internal_command = plci->internal_command;
14122  plci->internal_command = 0;
14123  switch (internal_command)
14124  {
14125  default:
14126    plci->command = 0;
14127  case FAX_CONNECT_ACK_COMMAND_1:
14128    if (plci_nl_busy (plci))
14129    {
14130      plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14131      return;
14132    }
14133    plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14134    plci->NData[0].P = plci->fax_connect_info_buffer;
14135    plci->NData[0].PLength = plci->fax_connect_info_length;
14136    plci->NL.X = plci->NData;
14137    plci->NL.ReqCh = 0;
14138    plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14139    plci->adapter->request (&plci->NL);
14140    return;
14141  case FAX_CONNECT_ACK_COMMAND_2:
14142    if ((Rc != OK) && (Rc != OK_FC))
14143    {
14144      dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14145        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14146      break;
14147    }
14148  }
14149  if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14150   && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14151  {
14152    if (plci->B3_prot == 4)
14153      sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14154    else
14155      sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14156    plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14157  }
14158}
14159
14160
14161static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14162{
14163  word Info;
14164  word internal_command;
14165
14166  dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14167    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14168
14169  Info = GOOD;
14170  internal_command = plci->internal_command;
14171  plci->internal_command = 0;
14172  switch (internal_command)
14173  {
14174  default:
14175    plci->command = 0;
14176  case FAX_EDATA_ACK_COMMAND_1:
14177    if (plci_nl_busy (plci))
14178    {
14179      plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14180      return;
14181    }
14182    plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14183    plci->NData[0].P = plci->fax_connect_info_buffer;
14184    plci->NData[0].PLength = plci->fax_edata_ack_length;
14185    plci->NL.X = plci->NData;
14186    plci->NL.ReqCh = 0;
14187    plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14188    plci->adapter->request (&plci->NL);
14189    return;
14190  case FAX_EDATA_ACK_COMMAND_2:
14191    if ((Rc != OK) && (Rc != OK_FC))
14192    {
14193      dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14194        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14195      break;
14196    }
14197  }
14198}
14199
14200
14201static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14202{
14203  word Info;
14204  word internal_command;
14205
14206  dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14207    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14208
14209  Info = GOOD;
14210  internal_command = plci->internal_command;
14211  plci->internal_command = 0;
14212  switch (internal_command)
14213  {
14214  default:
14215    plci->command = 0;
14216  case FAX_CONNECT_INFO_COMMAND_1:
14217    if (plci_nl_busy (plci))
14218    {
14219      plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14220      return;
14221    }
14222    plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14223    plci->NData[0].P = plci->fax_connect_info_buffer;
14224    plci->NData[0].PLength = plci->fax_connect_info_length;
14225    plci->NL.X = plci->NData;
14226    plci->NL.ReqCh = 0;
14227    plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14228    plci->adapter->request (&plci->NL);
14229    return;
14230  case FAX_CONNECT_INFO_COMMAND_2:
14231    if ((Rc != OK) && (Rc != OK_FC))
14232    {
14233      dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14234        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14235      Info = _WRONG_STATE;
14236      break;
14237    }
14238    if (plci_nl_busy (plci))
14239    {
14240      plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14241      return;
14242    }
14243    plci->command = _CONNECT_B3_R;
14244    nl_req_ncci (plci, N_CONNECT, 0);
14245    send_req (plci);
14246    return;
14247  }
14248  sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14249}
14250
14251
14252static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14253{
14254  word Info;
14255  word internal_command;
14256
14257  dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14258    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14259
14260  Info = GOOD;
14261  internal_command = plci->internal_command;
14262  plci->internal_command = 0;
14263  switch (internal_command)
14264  {
14265  default:
14266    plci->command = 0;
14267    plci->adjust_b_parms_msg = NULL;
14268    plci->adjust_b_facilities = plci->B1_facilities;
14269    plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14270    plci->adjust_b_ncci = (word)(Id >> 16);
14271    plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14272    plci->adjust_b_state = ADJUST_B_START;
14273    dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14274      UnMapId (Id), (char   *)(FILE_), __LINE__));
14275  case FAX_ADJUST_B23_COMMAND_1:
14276    Info = adjust_b_process (Id, plci, Rc);
14277    if (Info != GOOD)
14278    {
14279      dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14280        UnMapId (Id), (char   *)(FILE_), __LINE__));
14281      break;
14282    }
14283    if (plci->internal_command)
14284      return;
14285  case FAX_ADJUST_B23_COMMAND_2:
14286    if (plci_nl_busy (plci))
14287    {
14288      plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14289      return;
14290    }
14291    plci->command = _CONNECT_B3_R;
14292    nl_req_ncci (plci, N_CONNECT, 0);
14293    send_req (plci);
14294    return;
14295  }
14296  sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14297}
14298
14299
14300static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14301{
14302  word internal_command;
14303
14304  dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14305    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14306
14307  internal_command = plci->internal_command;
14308  plci->internal_command = 0;
14309  switch (internal_command)
14310  {
14311  default:
14312    plci->command = 0;
14313    plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14314    return;
14315  case FAX_DISCONNECT_COMMAND_1:
14316  case FAX_DISCONNECT_COMMAND_2:
14317  case FAX_DISCONNECT_COMMAND_3:
14318    if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14319    {
14320      dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14321        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14322      break;
14323    }
14324    if (Rc == OK)
14325    {
14326      if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14327       || (internal_command == FAX_DISCONNECT_COMMAND_2))
14328      {
14329        plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14330      }
14331    }
14332    else if (Rc == 0)
14333    {
14334      if (internal_command == FAX_DISCONNECT_COMMAND_1)
14335        plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14336    }
14337    return;
14338  }
14339}
14340
14341
14342
14343static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14344{
14345  word Info;
14346  word internal_command;
14347
14348  dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14349    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14350
14351  Info = GOOD;
14352  internal_command = plci->internal_command;
14353  plci->internal_command = 0;
14354  switch (internal_command)
14355  {
14356  default:
14357    plci->command = 0;
14358  case RTP_CONNECT_B3_REQ_COMMAND_1:
14359    if (plci_nl_busy (plci))
14360    {
14361      plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14362      return;
14363    }
14364    plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14365    nl_req_ncci (plci, N_CONNECT, 0);
14366    send_req (plci);
14367    return;
14368  case RTP_CONNECT_B3_REQ_COMMAND_2:
14369    if ((Rc != OK) && (Rc != OK_FC))
14370    {
14371      dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14372        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14373      Info = _WRONG_STATE;
14374      break;
14375    }
14376    if (plci_nl_busy (plci))
14377    {
14378      plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14379      return;
14380    }
14381    plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14382    plci->NData[0].PLength = plci->internal_req_buffer[0];
14383    plci->NData[0].P = plci->internal_req_buffer + 1;
14384    plci->NL.X = plci->NData;
14385    plci->NL.ReqCh = 0;
14386    plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14387    plci->adapter->request (&plci->NL);
14388    break;
14389  case RTP_CONNECT_B3_REQ_COMMAND_3:
14390    return;
14391  }
14392  sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14393}
14394
14395
14396static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14397{
14398  word Info;
14399  word internal_command;
14400
14401  dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14402    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14403
14404  Info = GOOD;
14405  internal_command = plci->internal_command;
14406  plci->internal_command = 0;
14407  switch (internal_command)
14408  {
14409  default:
14410    plci->command = 0;
14411  case RTP_CONNECT_B3_RES_COMMAND_1:
14412    if (plci_nl_busy (plci))
14413    {
14414      plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14415      return;
14416    }
14417    plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14418    nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14419    send_req (plci);
14420    return;
14421  case RTP_CONNECT_B3_RES_COMMAND_2:
14422    if ((Rc != OK) && (Rc != OK_FC))
14423    {
14424      dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14425        UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14426      Info = _WRONG_STATE;
14427      break;
14428    }
14429    if (plci_nl_busy (plci))
14430    {
14431      plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14432      return;
14433    }
14434    sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14435    plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14436    plci->NData[0].PLength = plci->internal_req_buffer[0];
14437    plci->NData[0].P = plci->internal_req_buffer + 1;
14438    plci->NL.X = plci->NData;
14439    plci->NL.ReqCh = 0;
14440    plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14441    plci->adapter->request (&plci->NL);
14442    return;
14443  case RTP_CONNECT_B3_RES_COMMAND_3:
14444    return;
14445  }
14446}
14447
14448
14449
14450static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14451{
14452    byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14453  word Info;
14454  word internal_command;
14455
14456  dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14457    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14458
14459  Info = GOOD;
14460  internal_command = plci->internal_command;
14461  plci->internal_command = 0;
14462  switch (internal_command)
14463  {
14464  default:
14465    if (!plci->NL.Id)
14466      break;
14467    plci->command = 0;
14468    plci->adjust_b_parms_msg = NULL;
14469    plci->adjust_b_facilities = plci->B1_facilities;
14470    plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14471    plci->adjust_b_ncci = (word)(Id >> 16);
14472    plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14473    plci->adjust_b_state = ADJUST_B_START;
14474    dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14475      UnMapId (Id), (char   *)(FILE_), __LINE__));
14476  case HOLD_SAVE_COMMAND_1:
14477    Info = adjust_b_process (Id, plci, Rc);
14478    if (Info != GOOD)
14479    {
14480      dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14481        UnMapId (Id), (char   *)(FILE_), __LINE__));
14482      break;
14483    }
14484    if (plci->internal_command)
14485      return;
14486  }
14487  sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14488}
14489
14490
14491static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14492{
14493    byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14494  word Info;
14495  word internal_command;
14496
14497  dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14498    UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14499
14500  Info = GOOD;
14501  internal_command = plci->internal_command;
14502  plci->internal_command = 0;
14503  switch (internal_command)
14504  {
14505  default:
14506    plci->command = 0;
14507    plci->adjust_b_parms_msg = NULL;
14508    plci->adjust_b_facilities = plci->B1_facilities;
14509    plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14510    plci->adjust_b_ncci = (word)(Id >> 16);
14511    plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14512    plci->adjust_b_state = ADJUST_B_START;
14513    dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14514      UnMapId (Id), (char   *)(FILE_), __LINE__));
14515  case RETRIEVE_RESTORE_COMMAND_1:
14516    Info = adjust_b_process (Id, plci, Rc);
14517    if (Info != GOOD)
14518    {
14519      dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14520        UnMapId (Id), (char   *)(FILE_), __LINE__));
14521      break;
14522    }
14523    if (plci->internal_command)
14524      return;
14525  }
14526  sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14527}
14528
14529
14530static void init_b1_config (PLCI   *plci)
14531{
14532
14533  dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14534    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14535    (char   *)(FILE_), __LINE__));
14536
14537  plci->B1_resource = 0;
14538  plci->B1_facilities = 0;
14539
14540  plci->li_bchannel_id = 0;
14541  mixer_clear_config (plci);
14542
14543
14544  ec_clear_config (plci);
14545
14546
14547  dtmf_rec_clear_config (plci);
14548  dtmf_send_clear_config (plci);
14549  dtmf_parameter_clear_config (plci);
14550
14551  adv_voice_clear_config (plci);
14552  adjust_b_clear (plci);
14553}
14554
14555
14556static void clear_b1_config (PLCI   *plci)
14557{
14558
14559  dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14560    (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14561    (char   *)(FILE_), __LINE__));
14562
14563  adv_voice_clear_config (plci);
14564  adjust_b_clear (plci);
14565
14566  ec_clear_config (plci);
14567
14568
14569  dtmf_rec_clear_config (plci);
14570  dtmf_send_clear_config (plci);
14571  dtmf_parameter_clear_config (plci);
14572
14573
14574  if ((plci->li_bchannel_id != 0)
14575   && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14576  {
14577    mixer_clear_config (plci);
14578    li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14579    plci->li_bchannel_id = 0;
14580  }
14581
14582  plci->B1_resource = 0;
14583  plci->B1_facilities = 0;
14584}
14585
14586
14587/* -----------------------------------------------------------------
14588                XON protocol local helpers
14589   ----------------------------------------------------------------- */
14590static void channel_flow_control_remove (PLCI   * plci) {
14591  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14592  word i;
14593  for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14594    if (a->ch_flow_plci[i] == plci->Id) {
14595      a->ch_flow_plci[i] = 0;
14596      a->ch_flow_control[i] = 0;
14597    }
14598  }
14599}
14600
14601static void channel_x_on (PLCI   * plci, byte ch) {
14602  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14603  if (a->ch_flow_control[ch] & N_XON_SENT) {
14604    a->ch_flow_control[ch] &= ~N_XON_SENT;
14605  }
14606}
14607
14608static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14609  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14610  if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14611    a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14612    a->ch_flow_plci[ch] = plci->Id;
14613    a->ch_flow_control_pending++;
14614  }
14615}
14616
14617static void channel_request_xon (PLCI   * plci, byte ch) {
14618  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14619
14620  if (a->ch_flow_control[ch] & N_CH_XOFF) {
14621    a->ch_flow_control[ch] |= N_XON_REQ;
14622    a->ch_flow_control[ch] &= ~N_CH_XOFF;
14623    a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14624  }
14625}
14626
14627static void channel_xmit_extended_xon (PLCI   * plci) {
14628  DIVA_CAPI_ADAPTER   * a;
14629  int max_ch = ARRAY_SIZE(a->ch_flow_control);
14630  int i, one_requested = 0;
14631
14632  if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14633    return;
14634  }
14635
14636  for (i = 0; i < max_ch; i++) {
14637    if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14638        (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14639        (plci->Id == a->ch_flow_plci[i])) {
14640      channel_request_xon (plci, (byte)i);
14641      one_requested = 1;
14642    }
14643  }
14644
14645  if (one_requested) {
14646    channel_xmit_xon (plci);
14647  }
14648}
14649
14650/*
14651  Try to xmit next X_ON
14652  */
14653static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14654  int max_ch = ARRAY_SIZE(a->ch_flow_control);
14655  int i;
14656
14657  if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14658    return (0);
14659  }
14660
14661  if (a->last_flow_control_ch >= max_ch) {
14662    a->last_flow_control_ch = 1;
14663  }
14664  for (i=a->last_flow_control_ch; i < max_ch; i++) {
14665    if ((a->ch_flow_control[i] & N_XON_REQ) &&
14666        (plci->Id == a->ch_flow_plci[i])) {
14667      a->last_flow_control_ch = i+1;
14668      return (i);
14669    }
14670  }
14671
14672  for (i = 1; i < a->last_flow_control_ch; i++) {
14673    if ((a->ch_flow_control[i] & N_XON_REQ) &&
14674        (plci->Id == a->ch_flow_plci[i])) {
14675      a->last_flow_control_ch = i+1;
14676      return (i);
14677    }
14678  }
14679
14680  return (0);
14681}
14682
14683static void channel_xmit_xon (PLCI   * plci) {
14684  DIVA_CAPI_ADAPTER   * a = plci->adapter;
14685  byte ch;
14686
14687  if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14688    return;
14689  }
14690  if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14691    return;
14692  }
14693  a->ch_flow_control[ch] &= ~N_XON_REQ;
14694  a->ch_flow_control[ch] |= N_XON_SENT;
14695
14696  plci->NL.Req = plci->nl_req = (byte)N_XON;
14697  plci->NL.ReqCh         = ch;
14698  plci->NL.X             = plci->NData;
14699  plci->NL.XNum          = 1;
14700  plci->NData[0].P       = &plci->RBuffer[0];
14701  plci->NData[0].PLength = 0;
14702
14703  plci->adapter->request(&plci->NL);
14704}
14705
14706static int channel_can_xon (PLCI   * plci, byte ch) {
14707  APPL   * APPLptr;
14708  DIVA_CAPI_ADAPTER   * a;
14709  word NCCIcode;
14710  dword count;
14711  word Num;
14712  word i;
14713
14714  APPLptr = plci->appl;
14715  a = plci->adapter;
14716
14717  if (!APPLptr)
14718    return (0);
14719
14720  NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14721
14722                /* count all buffers within the Application pool    */
14723                /* belonging to the same NCCI. XON if a first is    */
14724                /* used.                                            */
14725  count = 0;
14726  Num = 0xffff;
14727  for(i=0; i<APPLptr->MaxBuffer; i++) {
14728    if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14729    if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14730  }
14731  if ((count > 2) || (Num == 0xffff)) {
14732    return (0);
14733  }
14734  return (1);
14735}
14736
14737
14738/*------------------------------------------------------------------*/
14739
14740static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14741{
14742  return 1;
14743}
14744
14745
14746
14747/**********************************************************************************/
14748/* function groups the listening applications according to the CIP mask and the   */
14749/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14750/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14751/* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14752/* function must be enabled by setting "a->group_optimization_enabled" from the   */
14753/* OS specific part (per adapter).                                                */
14754/**********************************************************************************/
14755static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14756{
14757  word i,j,k,busy,group_found;
14758  dword info_mask_group[MAX_CIP_TYPES];
14759  dword cip_mask_group[MAX_CIP_TYPES];
14760  word appl_number_group_type[MAX_APPL];
14761  PLCI   *auxplci;
14762
14763  set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14764
14765  if(!a->group_optimization_enabled)
14766  {
14767    dbug(1,dprintf("No group optimization"));
14768    return;
14769  }
14770
14771  dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14772
14773  for(i=0;i<MAX_CIP_TYPES;i++)
14774  {
14775    info_mask_group[i] = 0;
14776    cip_mask_group [i] = 0;
14777  }
14778  for(i=0;i<MAX_APPL;i++)
14779  {
14780    appl_number_group_type[i] = 0;
14781  }
14782  for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14783  {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14784    if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14785    {
14786      dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14787      return; /* allow good application unfiltered access */
14788    }
14789  }
14790  for(i=0; i<max_appl; i++) /* Build CIP Groups */
14791  {
14792    if(application[i].Id && a->CIP_Mask[i] )
14793    {
14794      for(k=0,busy=false; k<a->max_plci; k++)
14795      {
14796        if(a->plci[k].Id) 
14797        {
14798          auxplci = &a->plci[k];
14799          if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14800          {
14801            busy = true;
14802            dbug(1,dprintf("Appl 0x%x is busy",i+1));
14803          }
14804          else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14805          {
14806            busy = true;
14807            dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14808          }
14809        }
14810      }
14811
14812      for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14813      {
14814        if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14815        {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14816          appl_number_group_type[i] = MAX_CIP_TYPES;
14817          group_found=true;
14818          dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14819        }
14820        else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14821        {                                      /* is group already present ?                  */
14822          appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14823          group_found=true;
14824          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]));
14825        }
14826        else if(!info_mask_group[j])
14827        {                                      /* establish a new group                       */
14828          appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14829          info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14830          cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14831          group_found=true;
14832          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]));
14833        }
14834      }
14835    }
14836  }
14837        
14838  for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14839  {
14840    if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14841    {
14842      if(appl_number_group_type[i] == MAX_CIP_TYPES)
14843      {
14844        dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14845      }
14846      else
14847      {
14848        dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14849        for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14850        {
14851          if(appl_number_group_type[i] == appl_number_group_type[j]) 
14852          {
14853            dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14854            clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14855            appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14856          }
14857        }
14858      }
14859    }
14860    else                                                 /* application should not get a call */
14861    {
14862      clear_group_ind_mask_bit (plci, i);
14863    }
14864  }
14865
14866}
14867
14868
14869
14870/* OS notifies the driver about a application Capi_Register */
14871word CapiRegister(word id)
14872{
14873  word i,j,appls_found;
14874
14875  PLCI   *plci;
14876  DIVA_CAPI_ADAPTER   *a;
14877
14878  for(i=0,appls_found=0; i<max_appl; i++)
14879  {
14880    if( application[i].Id && (application[i].Id!=id) )
14881    {
14882      appls_found++;                       /* an application has been found */
14883    }
14884  }
14885
14886  if(appls_found) return true;
14887  for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14888  {
14889    a = &adapter[i];
14890    if(a->request)
14891    {
14892      if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14893      {
14894        if(!appls_found)           /* first application does a capi register   */
14895        {
14896          if((j=get_plci(a)))                    /* activate L1 of all adapters */
14897          {
14898            plci = &a->plci[j-1];
14899            plci->command = 0;
14900            add_p(plci,OAD,"\x01\xfd");
14901            add_p(plci,CAI,"\x01\x80");
14902            add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14903            add_p(plci,SHIFT|6,NULL);
14904            add_p(plci,SIN,"\x02\x00\x00");
14905            plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14906            sig_req(plci,ASSIGN,DSIG_ID);
14907            add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14908            sig_req(plci,SIG_CTRL,0);
14909            send_req(plci);
14910          }
14911        }
14912      }
14913    }
14914  }
14915  return false;
14916}
14917
14918/*------------------------------------------------------------------*/
14919
14920/* Functions for virtual Switching e.g. Transfer by join, Conference */
14921
14922static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14923{
14924 word i;
14925 /* Format of vswitch_t:
14926 0 byte length
14927 1 byte VSWITCHIE
14928 2 byte VSWITCH_REQ/VSWITCH_IND
14929 3 byte reserved
14930 4 word VSwitchcommand
14931 6 word returnerror
14932 8... Params
14933 */
14934 if(!plci ||
14935  !plci->appl ||
14936  !plci->State ||
14937  plci->Sig.Ind==NCR_FACILITY
14938  )
14939  return;
14940 
14941 for(i=0;i<MAX_MULTI_IE;i++)
14942 {
14943        if(!parms[i][0]) continue;
14944  if(parms[i][0]<7)
14945  {
14946   parms[i][0]=0; /* kill it */
14947   continue;
14948  }
14949  dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14950  switch(parms[i][4])
14951  {
14952  case VSJOIN:
14953   if(!plci->relatedPTYPLCI ||
14954    (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14955   { /* Error */
14956    break;
14957   }
14958   /* remember all necessary informations */
14959   if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14960   {
14961    break;
14962   }
14963   if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14964   {   /* first indication after ECT-Request on Consultation Call */
14965    plci->vswitchstate=parms[i][9];
14966    parms[i][9]=2; /* State */
14967    /* now ask first Call to join */
14968   }
14969   else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14970   { /* Answer of VSWITCH_REQ from first Call */
14971    plci->vswitchstate=parms[i][9];
14972    /* tell consultation call to join
14973    and the protocol capabilities of the first call */
14974   }
14975   else
14976   { /* Error */
14977    break;
14978   }    
14979   plci->vsprot=parms[i][10]; /* protocol */
14980   plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14981   /* send join request to related PLCI */
14982   parms[i][1]=VSWITCHIE;
14983   parms[i][2]=VSWITCH_REQ;
14984   
14985   plci->relatedPTYPLCI->command = 0;
14986   plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14987   add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14988   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14989   send_req(plci->relatedPTYPLCI);
14990   break;
14991  case VSTRANSPORT:
14992  default:
14993   if(plci->relatedPTYPLCI &&
14994    plci->vswitchstate==3 &&
14995    plci->relatedPTYPLCI->vswitchstate==3)
14996   {
14997    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14998    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14999    send_req(plci->relatedPTYPLCI);
15000   }
15001   break;
15002  }  
15003  parms[i][0]=0; /* kill it */
15004 }
15005}
15006
15007
15008/*------------------------------------------------------------------*/
15009
15010static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
15011  ENTITY e;
15012  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15013
15014  if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15015    return (-1);
15016  }
15017
15018  pReq->xdi_dma_descriptor_operation.Req = 0;
15019  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15020
15021  pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15022  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15023  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15024  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15025
15026  e.user[0] = plci->adapter->Id - 1;
15027  plci->adapter->request((ENTITY*)pReq);
15028
15029  if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15030      (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15031      pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15032    *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15033    dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15034         plci->adapter->Id,
15035         pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15036         *dma_magic));
15037    return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15038  } else {
15039    dbug(1,dprintf("dma_alloc failed"));
15040    return (-1);
15041  }
15042}
15043
15044static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15045  ENTITY e;
15046  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15047
15048  if (nr < 0) {
15049    return;
15050  }
15051
15052  pReq->xdi_dma_descriptor_operation.Req = 0;
15053  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15054
15055  pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15056  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15057  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15058  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15059
15060  e.user[0] = plci->adapter->Id - 1;
15061  plci->adapter->request((ENTITY*)pReq);
15062
15063  if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15064    dbug(1,dprintf("dma_free(%d)", nr));
15065  } else {
15066    dbug(1,dprintf("dma_free failed (%d)", nr));
15067  }
15068}
15069
15070/*------------------------------------------------------------------*/
15071