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;
 555      i<(sizeof(ftable)/sizeof(struct _ftable));
 556      i++) {
 557
 558    if(ftable[i].command==msg->header.command) {
 559      /* break loop if the message is correct, otherwise continue scan  */
 560      /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
 561      if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
 562        ret = 0;
 563        break;
 564      }
 565      for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
 566    }
 567  }
 568  if(ret) {
 569    dbug(1,dprintf("BAD_MSG"));
 570    if(plci) plci->command = 0;
 571    return ret;
 572  }
 573
 574
 575  c = ftable[i].function(GET_DWORD(&msg->header.controller),
 576                         msg->header.number,
 577                         a,
 578                         plci,
 579                         appl,
 580                         msg_parms);
 581
 582  channel_xmit_extended_xon (plci);
 583
 584  if(c==1) send_req(plci);
 585  if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
 586  if(plci && !plci->req_in) plci->command = 0;
 587  return 0;
 588}
 589
 590
 591/*------------------------------------------------------------------*/
 592/* api_parse function, check the format of api messages             */
 593/*------------------------------------------------------------------*/
 594
 595word api_parse(byte   * msg, word length, byte * format, API_PARSE * parms)
 596{
 597  word i;
 598  word p;
 599
 600  for(i=0,p=0; format[i]; i++) {
 601    if(parms)
 602    {
 603      parms[i].info = &msg[p];
 604    }
 605    switch(format[i]) {
 606    case 'b':
 607      p +=1;
 608      break;
 609    case 'w':
 610      p +=2;
 611      break;
 612    case 'd':
 613      p +=4;
 614      break;
 615    case 's':
 616      if(msg[p]==0xff) {
 617        parms[i].info +=2;
 618        parms[i].length = msg[p+1] + (msg[p+2]<<8);
 619        p +=(parms[i].length +3);
 620      }
 621      else {
 622        parms[i].length = msg[p];
 623        p +=(parms[i].length +1);
 624      }
 625      break;
 626    }
 627
 628    if(p>length) return true;
 629  }
 630  if(parms) parms[i].info = NULL;
 631  return false;
 632}
 633
 634void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out)
 635{
 636  word i, j, n = 0;
 637  byte   *p;
 638
 639  p = out->info;
 640  for (i = 0; format[i] != '\0'; i++)
 641  {
 642    out->parms[i].info = p;
 643    out->parms[i].length = in[i].length;
 644    switch (format[i])
 645    {
 646    case 'b':
 647      n = 1;
 648      break;
 649    case 'w':
 650      n = 2;
 651      break;
 652    case 'd':
 653      n = 4;
 654      break;
 655    case 's':
 656      n = in[i].length + 1;
 657      break;
 658    }
 659    for (j = 0; j < n; j++)
 660      *(p++) = in[i].info[j];
 661  }
 662  out->parms[i].info = NULL;
 663  out->parms[i].length = 0;
 664}
 665
 666void api_load_msg(API_SAVE   *in, API_PARSE   *out)
 667{
 668  word i;
 669
 670  i = 0;
 671  do
 672  {
 673    out[i].info = in->parms[i].info;
 674    out[i].length = in->parms[i].length;
 675  } while (in->parms[i++].info);
 676}
 677
 678
 679/*------------------------------------------------------------------*/
 680/* CAPI remove function                                             */
 681/*------------------------------------------------------------------*/
 682
 683word api_remove_start(void)
 684{
 685  word i;
 686  word j;
 687
 688  if(!remove_started) {
 689    remove_started = true;
 690    for(i=0;i<max_adapter;i++) {
 691      if(adapter[i].request) {
 692        for(j=0;j<adapter[i].max_plci;j++) {
 693          if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
 694        }
 695      }
 696    }
 697    return 1;
 698  }
 699  else {
 700    for(i=0;i<max_adapter;i++) {
 701      if(adapter[i].request) {
 702        for(j=0;j<adapter[i].max_plci;j++) {
 703          if(adapter[i].plci[j].Sig.Id) return 1;
 704        }
 705      }
 706    }
 707  }
 708  api_remove_complete();
 709  return 0;
 710}
 711
 712
 713/*------------------------------------------------------------------*/
 714/* internal command queue                                           */
 715/*------------------------------------------------------------------*/
 716
 717static void init_internal_command_queue (PLCI   *plci)
 718{
 719  word i;
 720
 721  dbug (1, dprintf ("%s,%d: init_internal_command_queue",
 722    (char   *)(FILE_), __LINE__));
 723
 724  plci->internal_command = 0;
 725  for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
 726    plci->internal_command_queue[i] = NULL;
 727}
 728
 729
 730static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
 731{
 732  word i;
 733
 734  dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
 735    UnMapId (Id), (char   *)(FILE_), __LINE__));
 736
 737  if (plci->internal_command == 0)
 738  {
 739    plci->internal_command_queue[0] = command_function;
 740    (* command_function)(Id, plci, OK);
 741  }
 742  else
 743  {
 744    i = 1;
 745    while (plci->internal_command_queue[i] != NULL)
 746      i++;
 747    plci->internal_command_queue[i] = command_function;
 748  }
 749}
 750
 751
 752static void next_internal_command (dword Id, PLCI   *plci)
 753{
 754  word i;
 755
 756  dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
 757    UnMapId (Id), (char   *)(FILE_), __LINE__));
 758
 759  plci->internal_command = 0;
 760  plci->internal_command_queue[0] = NULL;
 761  while (plci->internal_command_queue[1] != NULL)
 762  {
 763    for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
 764      plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
 765    plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
 766    (*(plci->internal_command_queue[0]))(Id, plci, OK);
 767    if (plci->internal_command != 0)
 768      return;
 769    plci->internal_command_queue[0] = NULL;
 770  }
 771}
 772
 773
 774/*------------------------------------------------------------------*/
 775/* NCCI allocate/remove function                                    */
 776/*------------------------------------------------------------------*/
 777
 778static dword ncci_mapping_bug = 0;
 779
 780static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
 781{
 782  DIVA_CAPI_ADAPTER   *a;
 783  word ncci, i, j, k;
 784
 785  a = plci->adapter;
 786  if (!ch || a->ch_ncci[ch])
 787  {
 788    ncci_mapping_bug++;
 789    dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
 790      ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
 791    ncci = ch;
 792  }
 793  else
 794  {
 795    if (force_ncci)
 796      ncci = force_ncci;
 797    else
 798    {
 799      if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
 800        ncci = ch;
 801      else
 802      {
 803        ncci = 1;
 804        while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
 805          ncci++;
 806        if (ncci == MAX_NCCI+1)
 807        {
 808          ncci_mapping_bug++;
 809          i = 1;
 810          do
 811          {
 812            j = 1;
 813            while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
 814              j++;
 815            k = j;
 816            if (j < MAX_NCCI+1)
 817            {
 818              do
 819              {
 820                j++;
 821              } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
 822            }
 823          } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
 824          if (i < MAX_NL_CHANNEL+1)
 825          {
 826            dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
 827              ncci_mapping_bug, ch, force_ncci, i, k, j));
 828          }
 829          else
 830          {
 831            dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
 832              ncci_mapping_bug, ch, force_ncci));
 833          }
 834          ncci = ch;
 835        }
 836      }
 837      a->ncci_plci[ncci] = plci->Id;
 838      a->ncci_state[ncci] = IDLE;
 839      if (!plci->ncci_ring_list)
 840        plci->ncci_ring_list = ncci;
 841      else
 842        a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
 843      a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
 844    }
 845    a->ncci_ch[ncci] = ch;
 846    a->ch_ncci[ch] = (byte) ncci;
 847    dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
 848      ncci_mapping_bug, ch, force_ncci, ch, ncci));
 849  }
 850  return (ncci);
 851}
 852
 853
 854static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
 855{
 856  DIVA_CAPI_ADAPTER   *a;
 857  APPL   *appl;
 858  word i, ncci_code;
 859  dword Id;
 860
 861  a = plci->adapter;
 862  Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
 863  if (ncci)
 864  {
 865    if (a->ncci_plci[ncci] == plci->Id)
 866    {
 867      if (!plci->appl)
 868      {
 869        ncci_mapping_bug++;
 870        dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
 871          ncci_mapping_bug, Id));
 872      }
 873      else
 874      {
 875        appl = plci->appl;
 876        ncci_code = ncci | (((word) a->Id) << 8);
 877        for (i = 0; i < appl->MaxBuffer; i++)
 878        {
 879          if ((appl->DataNCCI[i] == ncci_code)
 880           && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
 881          {
 882            appl->DataNCCI[i] = 0;
 883          }
 884        }
 885      }
 886    }
 887  }
 888  else
 889  {
 890    for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
 891    {
 892      if (a->ncci_plci[ncci] == plci->Id)
 893      {
 894        if (!plci->appl)
 895        {
 896          ncci_mapping_bug++;
 897          dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
 898            ncci_mapping_bug, Id));
 899        }
 900        else
 901        {
 902          appl = plci->appl;
 903          ncci_code = ncci | (((word) a->Id) << 8);
 904          for (i = 0; i < appl->MaxBuffer; i++)
 905          {
 906            if ((appl->DataNCCI[i] == ncci_code)
 907             && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
 908            {
 909              appl->DataNCCI[i] = 0;
 910            }
 911          }
 912        }
 913      }
 914    }
 915  }
 916}
 917
 918
 919static void cleanup_ncci_data (PLCI   *plci, word ncci)
 920{
 921  NCCI   *ncci_ptr;
 922
 923  if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
 924  {
 925    ncci_ptr = &(plci->adapter->ncci[ncci]);
 926    if (plci->appl)
 927    {
 928      while (ncci_ptr->data_pending != 0)
 929      {
 930        if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
 931          TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
 932        (ncci_ptr->data_out)++;
 933        if (ncci_ptr->data_out == MAX_DATA_B3)
 934          ncci_ptr->data_out = 0;
 935        (ncci_ptr->data_pending)--;
 936      }
 937    }
 938    ncci_ptr->data_out = 0;
 939    ncci_ptr->data_pending = 0;
 940    ncci_ptr->data_ack_out = 0;
 941    ncci_ptr->data_ack_pending = 0;
 942  }
 943}
 944
 945
 946static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
 947{
 948  DIVA_CAPI_ADAPTER   *a;
 949  dword Id;
 950  word i;
 951
 952  a = plci->adapter;
 953  Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
 954  if (!preserve_ncci)
 955    ncci_free_receive_buffers (plci, ncci);
 956  if (ncci)
 957  {
 958    if (a->ncci_plci[ncci] != plci->Id)
 959    {
 960      ncci_mapping_bug++;
 961      dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
 962        ncci_mapping_bug, Id, preserve_ncci));
 963    }
 964    else
 965    {
 966      cleanup_ncci_data (plci, ncci);
 967      dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
 968        ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
 969      a->ch_ncci[a->ncci_ch[ncci]] = 0;
 970      if (!preserve_ncci)
 971      {
 972        a->ncci_ch[ncci] = 0;
 973        a->ncci_plci[ncci] = 0;
 974        a->ncci_state[ncci] = IDLE;
 975        i = plci->ncci_ring_list;
 976        while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
 977          i = a->ncci_next[i];
 978        if ((i != 0) && (a->ncci_next[i] == ncci))
 979        {
 980          if (i == ncci)
 981            plci->ncci_ring_list = 0;
 982          else if (plci->ncci_ring_list == ncci)
 983            plci->ncci_ring_list = i;
 984          a->ncci_next[i] = a->ncci_next[ncci];
 985        }
 986        a->ncci_next[ncci] = 0;
 987      }
 988    }
 989  }
 990  else
 991  {
 992    for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
 993    {
 994      if (a->ncci_plci[ncci] == plci->Id)
 995      {
 996        cleanup_ncci_data (plci, ncci);
 997        dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
 998          ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
 999        a->ch_ncci[a->ncci_ch[ncci]] = 0;
1000        if (!preserve_ncci)
1001        {
1002          a->ncci_ch[ncci] = 0;
1003          a->ncci_plci[ncci] = 0;
1004          a->ncci_state[ncci] = IDLE;
1005          a->ncci_next[ncci] = 0;
1006        }
1007      }
1008    }
1009    if (!preserve_ncci)
1010      plci->ncci_ring_list = 0;
1011  }
1012}
1013
1014
1015/*------------------------------------------------------------------*/
1016/* PLCI remove function                                             */
1017/*------------------------------------------------------------------*/
1018
1019static void plci_free_msg_in_queue (PLCI   *plci)
1020{
1021  word i;
1022
1023  if (plci->appl)
1024  {
1025    i = plci->msg_in_read_pos;
1026    while (i != plci->msg_in_write_pos)
1027    {
1028      if (i == plci->msg_in_wrap_pos)
1029        i = 0;
1030      if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031      {
1032
1033        TransmitBufferFree (plci->appl,
1034          (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1035
1036      }
1037
1038      i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1039        MSG_IN_OVERHEAD + 3) & 0xfffc;
1040
1041    }
1042  }
1043  plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1044  plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1045  plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1046}
1047
1048
1049static void plci_remove(PLCI   * plci)
1050{
1051
1052  if(!plci) {
1053    dbug(1,dprintf("plci_remove(no plci)"));
1054    return;
1055  }
1056  init_internal_command_queue (plci);
1057  dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1058  if(plci_remove_check(plci))
1059  {
1060    return;
1061  }
1062  if (plci->Sig.Id == 0xff)
1063  {
1064    dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1065    if (plci->NL.Id && !plci->nl_remove_id)
1066    {
1067      nl_req_ncci(plci,REMOVE,0);
1068      send_req(plci);
1069    }
1070  }
1071  else
1072  {
1073    if (!plci->sig_remove_id
1074     && (plci->Sig.Id
1075      || (plci->req_in!=plci->req_out)
1076      || (plci->nl_req || plci->sig_req)))
1077    {
1078      sig_req(plci,HANGUP,0);
1079      send_req(plci);
1080    }
1081  }
1082  ncci_remove (plci, 0, false);
1083  plci_free_msg_in_queue (plci);
1084
1085  plci->channels = 0;
1086  plci->appl = NULL;
1087  if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1088    plci->State = OUTG_DIS_PENDING;
1089}
1090
1091/*------------------------------------------------------------------*/
1092/* Application Group function helpers                               */
1093/*------------------------------------------------------------------*/
1094
1095static void set_group_ind_mask (PLCI   *plci)
1096{
1097  word i;
1098
1099  for (i = 0; i < C_IND_MASK_DWORDS; i++)
1100    plci->group_optimization_mask_table[i] = 0xffffffffL;
1101}
1102
1103static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1104{
1105  plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106}
1107
1108static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1109{
1110  return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111}
1112
1113/*------------------------------------------------------------------*/
1114/* c_ind_mask operations for arbitrary MAX_APPL                     */
1115/*------------------------------------------------------------------*/
1116
1117static void clear_c_ind_mask (PLCI   *plci)
1118{
1119  word i;
1120
1121  for (i = 0; i < C_IND_MASK_DWORDS; i++)
1122    plci->c_ind_mask_table[i] = 0;
1123}
1124
1125static byte c_ind_mask_empty (PLCI   *plci)
1126{
1127  word i;
1128
1129  i = 0;
1130  while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1131    i++;
1132  return (i == C_IND_MASK_DWORDS);
1133}
1134
1135static void set_c_ind_mask_bit (PLCI   *plci, word b)
1136{
1137  plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138}
1139
1140static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1141{
1142  plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143}
1144
1145static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1146{
1147  return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148}
1149
1150static void dump_c_ind_mask (PLCI   *plci)
1151{
1152static char hex_digit_table[0x10] =
1153  {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1154  word i, j, k;
1155  dword d;
1156    char *p;
1157    char buf[40];
1158
1159  for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1160  {
1161    p = buf + 36;
1162    *p = '\0';
1163    for (j = 0; j < 4; j++)
1164    {
1165      if (i+j < C_IND_MASK_DWORDS)
1166      {
1167        d = plci->c_ind_mask_table[i+j];
1168        for (k = 0; k < 8; k++)
1169        {
1170          *(--p) = hex_digit_table[d & 0xf];
1171          d >>= 4;
1172        }
1173      }
1174      else if (i != 0)
1175      {
1176        for (k = 0; k < 8; k++)
1177          *(--p) = ' ';
1178      }
1179      *(--p) = ' ';
1180    }
1181    dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1182  }
1183}
1184
1185
1186
1187
1188
1189#define dump_plcis(a)
1190
1191
1192
1193/*------------------------------------------------------------------*/
1194/* translation function for each message                            */
1195/*------------------------------------------------------------------*/
1196
1197byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1198{
1199  word ch;
1200  word i;
1201  word Info;
1202  word CIP;
1203  byte LinkLayer;
1204  API_PARSE * ai;
1205  API_PARSE * bp;
1206    API_PARSE ai_parms[5];
1207  word channel = 0;
1208  dword ch_mask;
1209  byte m;
1210  static byte esc_chi[35] = {0x02,0x18,0x01};
1211  static byte lli[2] = {0x01,0x00};
1212  byte noCh = 0;
1213  word dir = 0;
1214  byte   *p_chi = "";
1215
1216  for(i=0;i<5;i++) ai_parms[i].length = 0;
1217
1218  dbug(1,dprintf("connect_req(%d)",parms->length));
1219  Info = _WRONG_IDENTIFIER;
1220  if(a)
1221  {
1222    if(a->adapter_disabled)
1223    {
1224      dbug(1,dprintf("adapter disabled"));
1225      Id = ((word)1<<8)|a->Id;
1226      sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1227      sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1228      return false;
1229    }
1230    Info = _OUT_OF_PLCI;
1231    if((i=get_plci(a)))
1232    {
1233      Info = 0;
1234      plci = &a->plci[i-1];
1235      plci->appl = appl;
1236      plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1237      /* check 'external controller' bit for codec support */
1238      if(Id & EXT_CONTROLLER)
1239      {
1240        if(AdvCodecSupport(a, plci, appl, 0) )
1241        {
1242          plci->Id = 0;
1243          sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1244          return 2;
1245        }
1246      }
1247      ai = &parms[9];
1248      bp = &parms[5];
1249      ch = 0;
1250      if(bp->length)LinkLayer = bp->info[3];
1251      else LinkLayer = 0;
1252      if(ai->length)
1253      {
1254        ch=0xffff;
1255        if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1256        {
1257          ch = 0;
1258          if(ai_parms[0].length)
1259          {
1260            ch = GET_WORD(ai_parms[0].info+1);
1261            if(ch>4) ch=0; /* safety -> ignore ChannelID */
1262            if(ch==4) /* explizit CHI in message */
1263            {
1264              /* check length of B-CH struct */
1265              if((ai_parms[0].info)[3]>=1)
1266              {
1267                if((ai_parms[0].info)[4]==CHI)
1268                {
1269                  p_chi = &((ai_parms[0].info)[5]);
1270                }
1271                else
1272                {
1273                  p_chi = &((ai_parms[0].info)[3]);
1274                }
1275                if(p_chi[0]>35) /* check length of channel ID */
1276                {
1277                  Info = _WRONG_MESSAGE_FORMAT;    
1278                }
1279              }
1280              else Info = _WRONG_MESSAGE_FORMAT;    
1281            }
1282
1283            if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1284            {
1285              dir = GET_WORD(ai_parms[0].info+3);
1286              ch_mask = 0;
1287              m = 0x3f;
1288              for(i=0; i+5<=ai_parms[0].length; i++)
1289              {
1290                if(ai_parms[0].info[i+5]!=0)
1291                {
1292                  if((ai_parms[0].info[i+5] | m) != 0xff)
1293                    Info = _WRONG_MESSAGE_FORMAT;
1294                  else
1295                  {
1296                    if (ch_mask == 0)
1297                      channel = i;
1298                    ch_mask |= 1L << i;
1299                  }
1300                }
1301                m = 0;
1302              }
1303              if (ch_mask == 0)
1304                Info = _WRONG_MESSAGE_FORMAT;
1305              if (!Info)
1306              {
1307                if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1308                {
1309                  esc_chi[0] = (byte)(ai_parms[0].length - 2);
1310                  for(i=0; i+5<=ai_parms[0].length; i++)
1311                    esc_chi[i+3] = ai_parms[0].info[i+5];
1312                }
1313                else
1314                  esc_chi[0] = 2;
1315                esc_chi[2] = (byte)channel;
1316                plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1317                add_p(plci,LLI,lli);
1318                add_p(plci,ESC,esc_chi);
1319                plci->State = LOCAL_CONNECT;
1320                if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1321              }
1322            }
1323          }
1324        }
1325        else  Info = _WRONG_MESSAGE_FORMAT;
1326      }
1327
1328      dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1329      plci->command = _CONNECT_R;
1330      plci->number = Number;
1331      /* x.31 or D-ch free SAPI in LinkLayer? */
1332      if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1333      if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1334      {
1335        /* B-channel used for B3 connections (ch==0), or no B channel    */
1336        /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1337        if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1338        else     Info = add_b1(plci,&parms[5],ch,0); 
1339        add_s(plci,OAD,&parms[2]);
1340        add_s(plci,OSA,&parms[4]);
1341        add_s(plci,BC,&parms[6]);
1342        add_s(plci,LLC,&parms[7]);
1343        add_s(plci,HLC,&parms[8]);
1344        CIP = GET_WORD(parms[0].info);
1345        if (a->Info_Mask[appl->Id-1] & 0x200)
1346        {
1347          /* early B3 connect (CIP mask bit 9) no release after a disc */
1348          add_p(plci,LLI,"\x01\x01");
1349        }
1350        if(GET_WORD(parms[0].info)<29) {
1351          add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1352          add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1353        }
1354        add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1355        sig_req(plci,ASSIGN,DSIG_ID);
1356      }
1357      else if(ch==1) {
1358
1359        /* D-Channel used for B3 connections */
1360        plci->Sig.Id = 0xff;
1361        Info = 0;
1362      }
1363
1364      if(!Info && ch!=2 && !noCh ) {
1365        Info = add_b23(plci,&parms[5]);
1366        if(!Info) {
1367          if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1368        }
1369      }
1370
1371      if(!Info)
1372      {
1373        if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1374        {
1375          if(plci->spoofed_msg==SPOOFING_REQUIRED)
1376          {
1377            api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1378            plci->spoofed_msg = CALL_REQ;
1379            plci->internal_command = BLOCK_PLCI;
1380            plci->command = 0;
1381            dbug(1,dprintf("Spoof"));
1382            send_req(plci);
1383            return false;
1384          }
1385          if(ch==4)add_p(plci,CHI,p_chi);
1386          add_s(plci,CPN,&parms[1]);
1387          add_s(plci,DSA,&parms[3]);
1388          if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1389          add_ai(plci,&parms[9]);
1390          if(!dir)sig_req(plci,CALL_REQ,0);
1391          else
1392          {
1393            plci->command = PERM_LIST_REQ;
1394            plci->appl = appl;
1395            sig_req(plci,LISTEN_REQ,0);
1396            send_req(plci);
1397            return false;
1398          }
1399        }
1400        send_req(plci);
1401        return false;
1402      }
1403      plci->Id = 0;
1404    }
1405  }
1406  sendf(appl,
1407        _CONNECT_R|CONFIRM,
1408        Id,
1409        Number,
1410        "w",Info);
1411  return 2;
1412}
1413
1414byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1415{
1416  word i, Info;
1417  word Reject;
1418  static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1419  static byte esc_t[] = {0x03,0x08,0x00,0x00};
1420  API_PARSE * ai;
1421    API_PARSE ai_parms[5];
1422  word ch=0;
1423
1424  if(!plci) {
1425    dbug(1,dprintf("connect_res(no plci)"));
1426    return 0;  /* no plci, no send */
1427  }
1428
1429  dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1430  for(i=0;i<5;i++) ai_parms[i].length = 0;
1431  ai = &parms[5];
1432  dbug(1,dprintf("ai->length=%d",ai->length));
1433
1434  if(ai->length)
1435  {
1436    if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1437    {
1438      dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1439      ch = 0;
1440      if(ai_parms[0].length)
1441      {
1442        ch = GET_WORD(ai_parms[0].info+1);
1443        dbug(1,dprintf("BCH-I=0x%x",ch));
1444      }
1445    }
1446  }
1447
1448  if(plci->State==INC_CON_CONNECTED_ALERT)
1449  {
1450    dbug(1,dprintf("Connected Alert Call_Res"));
1451    if (a->Info_Mask[appl->Id-1] & 0x200)
1452    {
1453    /* early B3 connect (CIP mask bit 9) no release after a disc */
1454      add_p(plci,LLI,"\x01\x01");
1455    }
1456    add_s(plci, CONN_NR, &parms[2]);
1457    add_s(plci, LLC, &parms[4]);
1458    add_ai(plci, &parms[5]);
1459    plci->State = INC_CON_ACCEPT;
1460    sig_req(plci, CALL_RES,0);
1461    return 1;
1462  }
1463  else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1464    clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1465    dump_c_ind_mask (plci);
1466    Reject = GET_WORD(parms[0].info);
1467    dbug(1,dprintf("Reject=0x%x",Reject));
1468    if(Reject) 
1469    {
1470      if(c_ind_mask_empty (plci)) 
1471      {
1472        if((Reject&0xff00)==0x3400) 
1473        {
1474          esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1475          add_p(plci,ESC,esc_t);
1476          add_ai(plci, &parms[5]);
1477          sig_req(plci,REJECT,0);
1478        }      
1479        else if(Reject==1 || Reject>9) 
1480        {
1481          add_ai(plci, &parms[5]);
1482          sig_req(plci,HANGUP,0);
1483        }
1484        else 
1485        {
1486          esc_t[2] = cau_t[(Reject&0x000f)];
1487          add_p(plci,ESC,esc_t);
1488          add_ai(plci, &parms[5]);
1489          sig_req(plci,REJECT,0);
1490        }
1491        plci->appl = appl;
1492      }
1493      else 
1494      {
1495        sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1496      }
1497    }
1498    else {
1499      plci->appl = appl;
1500      if(Id & EXT_CONTROLLER){
1501        if(AdvCodecSupport(a, plci, appl, 0)){
1502          dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1503          sig_req(plci,HANGUP,0);
1504          return 1;
1505        }
1506        if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1507        {
1508          Info = add_b23(plci, &parms[1]);
1509          if (Info)
1510          {
1511            dbug(1,dprintf("connect_res(error from add_b23)"));
1512            sig_req(plci,HANGUP,0);
1513            return 1;
1514          }
1515          if(plci->adv_nl)
1516          {
1517            nl_req_ncci(plci, ASSIGN, 0);
1518          }
1519        }
1520      }
1521      else
1522      {
1523        plci->tel = 0;
1524        if(ch!=2)
1525        {
1526          Info = add_b23(plci, &parms[1]);
1527          if (Info)
1528          {
1529            dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530            sig_req(plci,HANGUP,0);
1531            return 1;
1532          }
1533        }
1534        nl_req_ncci(plci, ASSIGN, 0);
1535      }
1536
1537      if(plci->spoofed_msg==SPOOFING_REQUIRED)
1538      {
1539        api_save_msg(parms, "wsssss", &plci->saved_msg);
1540        plci->spoofed_msg = CALL_RES;
1541        plci->internal_command = BLOCK_PLCI;
1542        plci->command = 0;
1543        dbug(1,dprintf("Spoof"));
1544      }
1545      else
1546      {
1547        add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548        if (a->Info_Mask[appl->Id-1] & 0x200)
1549        {
1550          /* early B3 connect (CIP mask bit 9) no release after a disc */
1551          add_p(plci,LLI,"\x01\x01");
1552        }
1553        add_s(plci, CONN_NR, &parms[2]);
1554        add_s(plci, LLC, &parms[4]);
1555        add_ai(plci, &parms[5]);
1556        plci->State = INC_CON_ACCEPT;
1557        sig_req(plci, CALL_RES,0);
1558      }
1559
1560      for(i=0; i<max_appl; i++) {
1561        if(test_c_ind_mask_bit (plci, i)) {
1562          sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1563        }
1564      }
1565    }
1566  }
1567  return 1;
1568}
1569
1570byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1571{
1572  dbug(1,dprintf("connect_a_res"));
1573  return false;
1574}
1575
1576byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1577{
1578  word Info;
1579  word i;
1580
1581  dbug(1,dprintf("disconnect_req"));
1582
1583  Info = _WRONG_IDENTIFIER;
1584
1585  if(plci)
1586  {
1587    if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1588    {
1589      clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1590      plci->appl = appl;
1591      for(i=0; i<max_appl; i++)
1592      {
1593        if(test_c_ind_mask_bit (plci, i))
1594          sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595      }
1596      plci->State = OUTG_DIS_PENDING;
1597    }
1598    if(plci->Sig.Id && plci->appl)
1599    {
1600      Info = 0;
1601        if(plci->Sig.Id!=0xff)
1602        {
1603          if(plci->State!=INC_DIS_PENDING)
1604          {
1605            add_ai(plci, &msg[0]);
1606            sig_req(plci,HANGUP,0);
1607            plci->State = OUTG_DIS_PENDING;
1608            return 1;
1609          }
1610        }
1611        else
1612        {
1613          if (plci->NL.Id && !plci->nl_remove_id)
1614          {
1615            mixer_remove (plci);
1616            nl_req_ncci(plci,REMOVE,0);
1617          sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1618          sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619          plci->State = INC_DIS_PENDING;
1620          }
1621          return 1;
1622        }
1623      }
1624    }
1625
1626  if(!appl)  return false;
1627  sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1628  return false;
1629}
1630
1631byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1632{
1633  dbug(1,dprintf("disconnect_res"));
1634  if(plci)
1635  {
1636        /* clear ind mask bit, just in case of collsion of          */
1637        /* DISCONNECT_IND and CONNECT_RES                           */
1638    clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1639    ncci_free_receive_buffers (plci, 0);
1640    if(plci_remove_check(plci))
1641    {
1642      return 0;
1643    }
1644    if(plci->State==INC_DIS_PENDING
1645    || plci->State==SUSPENDING) {
1646      if(c_ind_mask_empty (plci)) {
1647        if(plci->State!=SUSPENDING)plci->State = IDLE;
1648        dbug(1,dprintf("chs=%d",plci->channels));
1649        if(!plci->channels) {
1650          plci_remove(plci);
1651        }
1652      }
1653    }
1654  }
1655  return 0;
1656}
1657
1658byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1659{
1660  word Info;
1661  byte i;
1662
1663  dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1664
1665  Info = _WRONG_IDENTIFIER;
1666  if(a) {
1667    Info = 0;
1668    a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1669    a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1670    dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1671    if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1672      a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1673    }
1674
1675    /* check if external controller listen and switch listen on or off*/
1676    if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1677      if(a->profile.Global_Options & ON_BOARD_CODEC) {
1678        dummy_plci.State = IDLE;
1679        a->codec_listen[appl->Id-1] = &dummy_plci;
1680        a->TelOAD[0] = (byte)(parms[3].length);
1681        for(i=1;parms[3].length>=i && i<22;i++) {
1682          a->TelOAD[i] = parms[3].info[i];
1683        }
1684        a->TelOAD[i] = 0;
1685        a->TelOSA[0] = (byte)(parms[4].length);
1686        for(i=1;parms[4].length>=i && i<22;i++) {
1687          a->TelOSA[i] = parms[4].info[i];
1688        }
1689        a->TelOSA[i] = 0;
1690      }
1691      else Info = 0x2002; /* wrong controller, codec not supported */
1692    }
1693    else{               /* clear listen */
1694      a->codec_listen[appl->Id-1] = (PLCI   *)0;
1695    }
1696  }
1697  sendf(appl,
1698        _LISTEN_R|CONFIRM,
1699        Id,
1700        Number,
1701        "w",Info);
1702
1703  if (a) listen_check(a);
1704  return false;
1705}
1706
1707byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1708{
1709  word i;
1710  API_PARSE * ai;
1711  PLCI   * rc_plci = NULL;
1712    API_PARSE ai_parms[5];
1713  word Info = 0;
1714
1715  dbug(1,dprintf("info_req"));
1716  for(i=0;i<5;i++) ai_parms[i].length = 0;
1717
1718  ai = &msg[1];
1719
1720  if(ai->length)
1721  {
1722    if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1723    {
1724      dbug(1,dprintf("AddInfo wrong"));
1725      Info = _WRONG_MESSAGE_FORMAT;
1726    }
1727  }
1728  if(!a) Info = _WRONG_STATE;
1729
1730  if(!Info && plci)
1731  {                /* no fac, with CPN, or KEY */
1732    rc_plci = plci;
1733    if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1734    {
1735      /* overlap sending option */
1736      dbug(1,dprintf("OvlSnd"));
1737      add_s(plci,CPN,&msg[0]);
1738      add_s(plci,KEY,&ai_parms[1]);
1739      sig_req(plci,INFO_REQ,0);
1740      send_req(plci);
1741      return false;
1742    }
1743
1744    if(plci->State && ai_parms[2].length)
1745    {
1746      /* User_Info option */
1747      dbug(1,dprintf("UUI"));
1748      add_s(plci,UUI,&ai_parms[2]);
1749      sig_req(plci,USER_DATA,0);
1750    }
1751    else if(plci->State && ai_parms[3].length)
1752    {
1753      /* Facility option */
1754      dbug(1,dprintf("FAC"));
1755      add_s(plci,CPN,&msg[0]);
1756      add_ai(plci, &msg[1]);
1757      sig_req(plci,FACILITY_REQ,0);
1758    }
1759    else
1760    {
1761      Info = _WRONG_STATE;
1762    }
1763  }
1764  else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1765  {
1766    /* NCR_Facility option -> send UUI and Keypad too */
1767    dbug(1,dprintf("NCR_FAC"));
1768    if((i=get_plci(a)))
1769    {
1770      rc_plci = &a->plci[i-1];
1771      appl->NullCREnable  = true;
1772      rc_plci->internal_command = C_NCR_FAC_REQ;
1773      rc_plci->appl = appl;
1774      add_p(rc_plci,CAI,"\x01\x80");
1775      add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1776      sig_req(rc_plci,ASSIGN,DSIG_ID);
1777      send_req(rc_plci);
1778    }
1779    else
1780    {
1781      Info = _OUT_OF_PLCI;
1782    }
1783
1784    if(!Info)
1785    {
1786      add_s(rc_plci,CPN,&msg[0]);
1787      add_ai(rc_plci, &msg[1]);
1788      sig_req(rc_plci,NCR_FACILITY,0);
1789      send_req(rc_plci);
1790      return false;
1791     /* for application controlled supplementary services    */
1792    }
1793  }
1794
1795  if (!rc_plci)
1796  {
1797    Info = _WRONG_MESSAGE_FORMAT;
1798  }
1799
1800  if(!Info)
1801  {
1802    send_req(rc_plci);
1803  }
1804  else
1805  {  /* appl is not assigned to a PLCI or error condition */
1806    dbug(1,dprintf("localInfoCon"));
1807    sendf(appl,
1808          _INFO_R|CONFIRM,
1809          Id,
1810          Number,
1811          "w",Info);
1812  }
1813  return false;
1814}
1815
1816byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1817{
1818  dbug(1,dprintf("info_res"));
1819  return false;
1820}
1821
1822byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1823{
1824  word Info;
1825  byte ret;
1826
1827  dbug(1,dprintf("alert_req"));
1828
1829  Info = _WRONG_IDENTIFIER;
1830  ret = false;
1831  if(plci) {
1832    Info = _ALERT_IGNORED;
1833    if(plci->State!=INC_CON_ALERT) {
1834      Info = _WRONG_STATE;
1835      if(plci->State==INC_CON_PENDING) {
1836        Info = 0;
1837        plci->State=INC_CON_ALERT;
1838        add_ai(plci, &msg[0]);
1839        sig_req(plci,CALL_ALERT,0);
1840        ret = 1;
1841      }
1842    }
1843  }
1844  sendf(appl,
1845        _ALERT_R|CONFIRM,
1846        Id,
1847        Number,
1848        "w",Info);
1849  return ret;
1850}
1851
1852byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1853{
1854  word Info = 0;
1855  word i    = 0;
1856
1857  word selector;
1858  word SSreq;
1859  long relatedPLCIvalue;
1860  DIVA_CAPI_ADAPTER   * relatedadapter;
1861  byte * SSparms  = "";
1862    byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1863    byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1864  API_PARSE * parms;
1865    API_PARSE ss_parms[11];
1866  PLCI   *rplci;
1867    byte cai[15];
1868  dword d;
1869    API_PARSE dummy;
1870
1871  dbug(1,dprintf("facility_req"));
1872  for(i=0;i<9;i++) ss_parms[i].length = 0;
1873
1874  parms = &msg[1];
1875
1876  if(!a)
1877  {
1878    dbug(1,dprintf("wrong Ctrl"));
1879    Info = _WRONG_IDENTIFIER;
1880  }
1881
1882  selector = GET_WORD(msg[0].info);
1883
1884  if(!Info)
1885  {
1886    switch(selector)
1887    {
1888      case SELECTOR_HANDSET:
1889        Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1890        break;
1891
1892      case SELECTOR_SU_SERV:
1893        if(!msg[1].length)
1894        {
1895          Info = _WRONG_MESSAGE_FORMAT;
1896          break;
1897        }
1898        SSreq = GET_WORD(&(msg[1].info[1]));
1899        PUT_WORD(&RCparms[1],SSreq);
1900        SSparms = RCparms;
1901        switch(SSreq)
1902        {
1903          case S_GET_SUPPORTED_SERVICES:
1904            if((i=get_plci(a)))
1905            {
1906              rplci = &a->plci[i-1];
1907              rplci->appl = appl;
1908              add_p(rplci,CAI,"\x01\x80");
1909              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1910              sig_req(rplci,ASSIGN,DSIG_ID);
1911              send_req(rplci);
1912            }
1913            else
1914            {
1915              PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1916              SSparms = (byte *)SSstruct;
1917              break;
1918            }
1919            rplci->internal_command = GETSERV_REQ_PEND;
1920            rplci->number = Number;
1921            rplci->appl = appl;
1922            sig_req(rplci,S_SUPPORTED,0);
1923            send_req(rplci);
1924            return false;
1925            break;
1926
1927          case S_LISTEN:
1928            if(parms->length==7)
1929            {
1930              if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1931              {
1932                dbug(1,dprintf("format wrong"));
1933                Info = _WRONG_MESSAGE_FORMAT;
1934                break;
1935              }
1936            }
1937            else
1938            {
1939              Info = _WRONG_MESSAGE_FORMAT;
1940              break;
1941            }
1942            a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1943            if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1944            {
1945              if((i=get_plci(a)))
1946              {
1947                rplci = &a->plci[i-1];
1948                rplci->appl = appl;
1949                add_p(rplci,CAI,"\x01\x80");
1950                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1951                sig_req(rplci,ASSIGN,DSIG_ID);
1952                send_req(rplci);
1953              }
1954              else
1955              {
1956                break;
1957              }
1958              rplci->internal_command = GET_MWI_STATE;
1959              rplci->number = Number;
1960              sig_req(rplci,MWI_POLL,0);
1961              send_req(rplci);
1962            }
1963            break;
1964
1965          case S_HOLD:
1966            api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1967            if(plci && plci->State && plci->SuppState==IDLE)
1968            {
1969              plci->SuppState = HOLD_REQUEST;
1970              plci->command = C_HOLD_REQ;
1971              add_s(plci,CAI,&ss_parms[1]);
1972              sig_req(plci,CALL_HOLD,0);
1973              send_req(plci);
1974              return false;
1975            }
1976            else Info = 0x3010;                    /* wrong state           */
1977            break;
1978          case S_RETRIEVE:
1979            if(plci && plci->State && plci->SuppState==CALL_HELD)
1980            {
1981              if(Id & EXT_CONTROLLER)
1982              {
1983                if(AdvCodecSupport(a, plci, appl, 0))
1984                {
1985                  Info = 0x3010;                    /* wrong state           */
1986                  break;
1987                }
1988              }
1989              else plci->tel = 0;
1990
1991              plci->SuppState = RETRIEVE_REQUEST;
1992              plci->command = C_RETRIEVE_REQ;
1993              if(plci->spoofed_msg==SPOOFING_REQUIRED)
1994              {
1995                plci->spoofed_msg = CALL_RETRIEVE;
1996                plci->internal_command = BLOCK_PLCI;
1997                plci->command = 0;
1998                dbug(1,dprintf("Spoof"));
1999                return false;
2000              }
2001              else
2002              {
2003                sig_req(plci,CALL_RETRIEVE,0);
2004                send_req(plci);
2005                return false;
2006              }
2007            }
2008            else Info = 0x3010;                    /* wrong state           */
2009            break;
2010          case S_SUSPEND:
2011            if(parms->length)
2012            {
2013              if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2014              {
2015                dbug(1,dprintf("format wrong"));
2016                Info = _WRONG_MESSAGE_FORMAT;
2017                break;
2018              }
2019            }
2020            if(plci && plci->State)
2021            {
2022              add_s(plci,CAI,&ss_parms[2]);
2023              plci->command = SUSPEND_REQ;
2024              sig_req(plci,SUSPEND,0);
2025              plci->State = SUSPENDING;
2026              send_req(plci);
2027            }
2028            else Info = 0x3010;                    /* wrong state           */
2029            break;
2030
2031          case S_RESUME:
2032            if(!(i=get_plci(a)) )
2033            {
2034              Info = _OUT_OF_PLCI;
2035              break;
2036            }
2037            rplci = &a->plci[i-1];
2038            rplci->appl = appl;
2039            rplci->number = Number;
2040            rplci->tel = 0;
2041            rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2042            /* check 'external controller' bit for codec support */
2043            if(Id & EXT_CONTROLLER)
2044            {
2045              if(AdvCodecSupport(a, rplci, appl, 0) )
2046              {
2047                rplci->Id = 0;
2048                Info = 0x300A;
2049                break;
2050              }
2051            }
2052            if(parms->length)
2053            {
2054              if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2055              {
2056                dbug(1,dprintf("format wrong"));
2057                rplci->Id = 0;
2058                Info = _WRONG_MESSAGE_FORMAT;
2059                break;
2060              }
2061            }
2062            dummy.length = 0;
2063            dummy.info = "\x00";
2064            add_b1(rplci, &dummy, 0, 0);
2065            if (a->Info_Mask[appl->Id-1] & 0x200)
2066            {
2067              /* early B3 connect (CIP mask bit 9) no release after a disc */
2068              add_p(rplci,LLI,"\x01\x01");
2069            }
2070            add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2071            sig_req(rplci,ASSIGN,DSIG_ID);
2072            send_req(rplci);
2073            add_s(rplci,CAI,&ss_parms[2]);
2074            rplci->command = RESUME_REQ;
2075            sig_req(rplci,RESUME,0);
2076            rplci->State = RESUMING;
2077            send_req(rplci);
2078            break;
2079
2080          case S_CONF_BEGIN: /* Request */
2081          case S_CONF_DROP:
2082          case S_CONF_ISOLATE:
2083          case S_CONF_REATTACH:
2084            if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2085            {
2086              dbug(1,dprintf("format wrong"));
2087              Info = _WRONG_MESSAGE_FORMAT;
2088              break;
2089            }
2090            if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2091            {
2092              d = GET_DWORD(ss_parms[2].info);     
2093              if(d>=0x80)
2094              {
2095                dbug(1,dprintf("format wrong"));
2096                Info = _WRONG_MESSAGE_FORMAT;
2097                break;
2098              }
2099              plci->ptyState = (byte)SSreq;
2100              plci->command = 0;
2101              cai[0] = 2;
2102              switch(SSreq)
2103              {
2104              case S_CONF_BEGIN:
2105                  cai[1] = CONF_BEGIN;
2106                  plci->internal_command = CONF_BEGIN_REQ_PEND;
2107                  break;
2108              case S_CONF_DROP:
2109                  cai[1] = CONF_DROP;
2110                  plci->internal_command = CONF_DROP_REQ_PEND;
2111                  break;
2112              case S_CONF_ISOLATE:
2113                  cai[1] = CONF_ISOLATE;
2114                  plci->internal_command = CONF_ISOLATE_REQ_PEND;
2115                  break;
2116              case S_CONF_REATTACH:
2117                  cai[1] = CONF_REATTACH;
2118                  plci->internal_command = CONF_REATTACH_REQ_PEND;
2119                  break;
2120              }
2121              cai[2] = (byte)d; /* Conference Size resp. PartyId */
2122              add_p(plci,CAI,cai);
2123              sig_req(plci,S_SERVICE,0);
2124              send_req(plci);
2125              return false;
2126            }
2127            else Info = 0x3010;                    /* wrong state           */
2128            break;
2129
2130          case S_ECT:
2131          case S_3PTY_BEGIN:
2132          case S_3PTY_END:
2133          case S_CONF_ADD:
2134            if(parms->length==7)
2135            {
2136              if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2137              {
2138                dbug(1,dprintf("format wrong"));
2139                Info = _WRONG_MESSAGE_FORMAT;
2140                break;
2141              }
2142            }
2143            else if(parms->length==8) /* workaround for the T-View-S */
2144            {
2145              if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2146              {
2147                dbug(1,dprintf("format wrong"));
2148                Info = _WRONG_MESSAGE_FORMAT;
2149                break;
2150              }
2151            }
2152            else
2153            {
2154              Info = _WRONG_MESSAGE_FORMAT;
2155              break;
2156            }
2157            if(!msg[1].length)
2158            {
2159              Info = _WRONG_MESSAGE_FORMAT;
2160              break;
2161            }
2162            if (!plci)
2163            {
2164              Info = _WRONG_IDENTIFIER;
2165              break;
2166            }
2167            relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2168            relatedPLCIvalue &= 0x0000FFFF;
2169            dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2170            /* controller starts with 0 up to (max_adapter - 1) */
2171            if (((relatedPLCIvalue & 0x7f) == 0)
2172             || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2173             || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2174            {
2175              if(SSreq==S_3PTY_END)
2176              {
2177                dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2178                rplci = plci;
2179              }
2180              else
2181              {
2182                Info = 0x3010;                    /* wrong state           */
2183                break;
2184              }
2185            }
2186            else
2187            {  
2188              relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2189              relatedPLCIvalue >>=8;
2190              /* find PLCI PTR*/
2191              for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2192              {
2193                if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2194                {
2195                  rplci = &relatedadapter->plci[i];
2196                }
2197              }
2198              if(!rplci || !relatedPLCIvalue)
2199              {
2200                if(SSreq==S_3PTY_END)
2201                {
2202                  dbug(1, dprintf("use 2nd PLCI=PLCI"));
2203                  rplci = plci;
2204                }
2205                else
2206                {
2207                  Info = 0x3010;                    /* wrong state           */
2208                  break;
2209                }
2210              }
2211            }
2212/*
2213            dbug(1,dprintf("rplci:%x",rplci));
2214            dbug(1,dprintf("plci:%x",plci));
2215            dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2216            dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2217            dbug(1,dprintf("SSreq:%x",SSreq));
2218            dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2219            dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2220            dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2221*/
2222            /* send PTY/ECT req, cannot check all states because of US stuff */
2223            if( !rplci->internal_command && rplci->appl )
2224            {
2225              plci->command = 0;
2226              rplci->relatedPTYPLCI = plci;
2227              plci->relatedPTYPLCI = rplci;
2228              rplci->ptyState = (byte)SSreq;
2229              if(SSreq==S_ECT)
2230              {
2231                rplci->internal_command = ECT_REQ_PEND;
2232                cai[1] = ECT_EXECUTE;
2233
2234                rplci->vswitchstate=0;
2235                rplci->vsprot=0;
2236                rplci->vsprotdialect=0;
2237                plci->vswitchstate=0;
2238                plci->vsprot=0;
2239                plci->vsprotdialect=0;
2240
2241              }
2242              else if(SSreq==S_CONF_ADD)
2243              {
2244                rplci->internal_command = CONF_ADD_REQ_PEND;
2245                cai[1] = CONF_ADD;
2246              }
2247              else
2248              {
2249                rplci->internal_command = PTY_REQ_PEND;
2250                cai[1] = (byte)(SSreq-3);
2251              }
2252              rplci->number = Number;
2253              if(plci!=rplci) /* explicit invocation */
2254              {
2255                cai[0] = 2;
2256                cai[2] = plci->Sig.Id;
2257                dbug(1,dprintf("explicit invocation"));
2258              }
2259              else
2260              {
2261                dbug(1,dprintf("implicit invocation"));
2262                cai[0] = 1;
2263              }
2264              add_p(rplci,CAI,cai);
2265              sig_req(rplci,S_SERVICE,0);
2266              send_req(rplci);
2267              return false;
2268            }
2269            else
2270            {
2271              dbug(0,dprintf("Wrong line"));
2272              Info = 0x3010;                    /* wrong state           */
2273              break;
2274            }
2275            break;
2276
2277          case S_CALL_DEFLECTION:
2278            if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2279            {
2280              dbug(1,dprintf("format wrong"));
2281              Info = _WRONG_MESSAGE_FORMAT;
2282              break;
2283            }
2284            if (!plci)
2285            {
2286              Info = _WRONG_IDENTIFIER;
2287              break;
2288            }
2289            /* reuse unused screening indicator */
2290            ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2291            plci->command = 0;
2292            plci->internal_command = CD_REQ_PEND;
2293            appl->CDEnable = true;
2294            cai[0] = 1;
2295            cai[1] = CALL_DEFLECTION;
2296            add_p(plci,CAI,cai);
2297            add_p(plci,CPN,ss_parms[3].info);
2298            sig_req(plci,S_SERVICE,0);
2299            send_req(plci);
2300            return false;
2301            break;
2302
2303          case S_CALL_FORWARDING_START:
2304            if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2305            {
2306              dbug(1,dprintf("format wrong"));
2307              Info = _WRONG_MESSAGE_FORMAT;
2308              break;
2309            }
2310
2311            if((i=get_plci(a)))
2312            {
2313              rplci = &a->plci[i-1];
2314              rplci->appl = appl;
2315              add_p(rplci,CAI,"\x01\x80");
2316              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2317              sig_req(rplci,ASSIGN,DSIG_ID);
2318              send_req(rplci);
2319            }
2320            else
2321            {
2322              Info = _OUT_OF_PLCI;
2323              break;
2324            }
2325
2326            /* reuse unused screening indicator */
2327            rplci->internal_command = CF_START_PEND;
2328            rplci->appl = appl;
2329            rplci->number = Number;
2330            appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2331            cai[0] = 2;
2332            cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2333            cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334            add_p(rplci,CAI,cai);
2335            add_p(rplci,OAD,ss_parms[5].info);
2336            add_p(rplci,CPN,ss_parms[6].info);
2337            sig_req(rplci,S_SERVICE,0);
2338            send_req(rplci);
2339            return false;
2340            break;
2341
2342          case S_INTERROGATE_DIVERSION:
2343          case S_INTERROGATE_NUMBERS:
2344          case S_CALL_FORWARDING_STOP:
2345          case S_CCBS_REQUEST:
2346          case S_CCBS_DEACTIVATE:
2347          case S_CCBS_INTERROGATE:
2348            switch(SSreq)
2349            {
2350            case S_INTERROGATE_NUMBERS:
2351                if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2352                {
2353                  dbug(0,dprintf("format wrong"));
2354                  Info = _WRONG_MESSAGE_FORMAT;
2355                }
2356                break;
2357            case S_CCBS_REQUEST:
2358            case S_CCBS_DEACTIVATE:
2359                if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2360                {
2361                  dbug(0,dprintf("format wrong"));
2362                  Info = _WRONG_MESSAGE_FORMAT;
2363                }
2364                break;
2365            case S_CCBS_INTERROGATE:
2366                if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2367                {
2368                  dbug(0,dprintf("format wrong"));
2369                  Info = _WRONG_MESSAGE_FORMAT;
2370                }
2371                break;
2372            default:
2373            if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2374            {
2375              dbug(0,dprintf("format wrong"));
2376              Info = _WRONG_MESSAGE_FORMAT;
2377              break;
2378            }
2379                break;
2380            }
2381
2382            if(Info) break;
2383            if((i=get_plci(a)))
2384            {
2385              rplci = &a->plci[i-1];
2386              switch(SSreq)
2387              {
2388                case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2389                  cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2390                  rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2391                  break;
2392                case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2393                  cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2394                  rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2395                  break;
2396                case S_CALL_FORWARDING_STOP:
2397                  rplci->internal_command = CF_STOP_PEND;
2398                  cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2399                  break;
2400                case S_CCBS_REQUEST:
2401                  cai[1] = CCBS_REQUEST;
2402                  rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2403                  break;
2404                case S_CCBS_DEACTIVATE:
2405                  cai[1] = CCBS_DEACTIVATE;
2406                  rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2407                  break;
2408                case S_CCBS_INTERROGATE:
2409                  cai[1] = CCBS_INTERROGATE;
2410                  rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2411                  break;
2412                default:
2413                  cai[1] = 0;
2414                break;
2415              }
2416              rplci->appl = appl;
2417              rplci->number = Number;
2418              add_p(rplci,CAI,"\x01\x80");
2419              add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2420              sig_req(rplci,ASSIGN,DSIG_ID);
2421              send_req(rplci);
2422            }
2423            else
2424            {
2425              Info = _OUT_OF_PLCI;
2426              break;
2427            }
2428
2429            appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2430            switch(SSreq)
2431            {
2432            case S_INTERROGATE_NUMBERS:
2433                cai[0] = 1;
2434                add_p(rplci,CAI,cai);
2435                break;
2436            case S_CCBS_REQUEST:
2437            case S_CCBS_DEACTIVATE:
2438                cai[0] = 3;
2439                PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2440                add_p(rplci,CAI,cai);
2441                break;
2442            case S_CCBS_INTERROGATE:
2443                cai[0] = 3;
2444                PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2445                add_p(rplci,CAI,cai);
2446                add_p(rplci,OAD,ss_parms[4].info);
2447                break;
2448            default:
2449            cai[0] = 2;
2450            cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2451            add_p(rplci,CAI,cai);
2452            add_p(rplci,OAD,ss_parms[5].info);
2453                break;
2454            }
2455                        
2456            sig_req(rplci,S_SERVICE,0);
2457            send_req(rplci);
2458            return false;
2459            break;
2460
2461          case S_MWI_ACTIVATE:
2462            if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2463            {
2464              dbug(1,dprintf("format wrong"));
2465              Info = _WRONG_MESSAGE_FORMAT;
2466              break;
2467            }
2468            if(!plci)
2469            {                               
2470              if((i=get_plci(a)))
2471              {
2472                rplci = &a->plci[i-1];
2473                rplci->appl = appl;
2474                rplci->cr_enquiry=true;
2475                add_p(rplci,CAI,"\x01\x80");
2476                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2477                sig_req(rplci,ASSIGN,DSIG_ID);
2478                send_req(rplci);
2479              }
2480              else
2481              {
2482                Info = _OUT_OF_PLCI;
2483                break;
2484              }
2485            }
2486            else
2487            {
2488              rplci = plci;
2489              rplci->cr_enquiry=false;
2490            }
2491
2492            rplci->command = 0;
2493            rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2494            rplci->appl = appl;
2495            rplci->number = Number;
2496
2497            cai[0] = 13;
2498            cai[1] = ACTIVATION_MWI; /* Function */
2499            PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2500            PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2501            PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2502            PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2503            PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2504            add_p(rplci,CAI,cai);
2505            add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2506            add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2507            add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2508            add_p(rplci,UID,ss_parms[10].info); /* Time */
2509            sig_req(rplci,S_SERVICE,0);
2510            send_req(rplci);
2511            return false;
2512
2513          case S_MWI_DEACTIVATE:
2514            if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2515            {
2516              dbug(1,dprintf("format wrong"));
2517              Info = _WRONG_MESSAGE_FORMAT;
2518              break;
2519            }
2520            if(!plci)
2521            {                               
2522              if((i=get_plci(a)))
2523              {
2524                rplci = &a->plci[i-1];
2525                rplci->appl = appl;
2526                rplci->cr_enquiry=true;
2527                add_p(rplci,CAI,"\x01\x80");
2528                add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2529                sig_req(rplci,ASSIGN,DSIG_ID);
2530                send_req(rplci);
2531              }
2532              else
2533              {
2534                Info = _OUT_OF_PLCI;
2535                break;
2536              }
2537            }
2538            else
2539            {
2540              rplci = plci;
2541              rplci->cr_enquiry=false;
2542            }
2543
2544            rplci->command = 0;
2545            rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2546            rplci->appl = appl;
2547            rplci->number = Number;
2548
2549            cai[0] = 5;
2550            cai[1] = DEACTIVATION_MWI; /* Function */
2551            PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2552            PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2553            add_p(rplci,CAI,cai);
2554            add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2555            add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2556            sig_req(rplci,S_SERVICE,0);
2557            send_req(rplci);
2558            return false;
2559
2560          default:
2561            Info = 0x300E;  /* not supported */
2562            break;
2563        }
2564        break; /* case SELECTOR_SU_SERV: end */
2565
2566
2567      case SELECTOR_DTMF:
2568        return (dtmf_request (Id, Number, a, plci, appl, msg));
2569
2570
2571
2572      case SELECTOR_LINE_INTERCONNECT:
2573        return (mixer_request (Id, Number, a, plci, appl, msg));
2574
2575
2576
2577      case PRIV_SELECTOR_ECHO_CANCELLER:
2578        appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2579        return (ec_request (Id, Number, a, plci, appl, msg));
2580
2581      case SELECTOR_ECHO_CANCELLER:
2582        appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2583        return (ec_request (Id, Number, a, plci, appl, msg));
2584
2585
2586      case SELECTOR_V42BIS:
2587      default:
2588        Info = _FACILITY_NOT_SUPPORTED;
2589        break;
2590    } /* end of switch(selector) */
2591  }
2592
2593  dbug(1,dprintf("SendFacRc"));
2594  sendf(appl,
2595        _FACILITY_R|CONFIRM,
2596        Id,
2597        Number,
2598        "wws",Info,selector,SSparms);
2599  return false;
2600}
2601
2602byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
2603{
2604  dbug(1,dprintf("facility_res"));
2605  return false;
2606}
2607
2608byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2609{
2610  word Info = 0;
2611  byte req;
2612  byte len;
2613  word w;
2614  word fax_control_bits, fax_feature_bits, fax_info_change;
2615  API_PARSE * ncpi;
2616    byte pvc[2];
2617
2618    API_PARSE fax_parms[9];
2619  word i;
2620
2621
2622  dbug(1,dprintf("connect_b3_req"));
2623  if(plci)
2624  {
2625    if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2626     || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2627    {
2628      Info = _WRONG_STATE;
2629    }
2630    else
2631    {
2632      /* local reply if assign unsuccessfull
2633         or B3 protocol allows only one layer 3 connection
2634           and already connected
2635             or B2 protocol not any LAPD
2636               and connect_b3_req contradicts originate/answer direction */
2637      if (!plci->NL.Id
2638       || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2639        && ((plci->channels != 0)
2640         || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2641          && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2642      {
2643        dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2644                       plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2645        Info = _WRONG_STATE;
2646        sendf(appl,                                                        
2647              _CONNECT_B3_R|CONFIRM,
2648              Id,
2649              Number,
2650              "w",Info);
2651        return false;
2652      }
2653      plci->requested_options_conn = 0;
2654
2655      req = N_CONNECT;
2656      ncpi = &parms[0];
2657      if(plci->B3_prot==2 || plci->B3_prot==3)
2658      {
2659        if(ncpi->length>2)
2660        {
2661          /* check for PVC */
2662          if(ncpi->info[2] || ncpi->info[3])
2663          {
2664            pvc[0] = ncpi->info[3];
2665            pvc[1] = ncpi->info[2];
2666            add_d(plci,2,pvc);
2667            req = N_RESET;
2668          }
2669          else
2670          {
2671            if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2672            add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2673          }
2674        }
2675      }
2676      else if(plci->B3_prot==5)
2677      {
2678        if (plci->NL.Id && !plci->nl_remove_id)
2679        {
2680          fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2681          fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2682          if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2683           || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2684          {
2685            len = (byte)(&(((T30_INFO *) 0)->universal_6));
2686            fax_info_change = false;
2687            if (ncpi->length >= 4)
2688            {
2689              w = GET_WORD(&ncpi->info[3]);
2690              if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2691              {
2692                ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2693                  (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2694                  ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2695                fax_info_change = true;
2696              }
2697              fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2698              if (w & 0x0002)  /* Fax-polling request */
2699                fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2700              if ((w & 0x0004) /* Request to send / poll another document */
2701               && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2702              {
2703                fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2704              }
2705              if (ncpi->length >= 6)
2706              {
2707                w = GET_WORD(&ncpi->info[5]);
2708                if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2709                {
2710                  ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2711                  fax_info_change = true;
2712                }
2713
2714                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2715                 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2716                {
2717                  plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2718                }
2719                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2720                 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2721                {
2722                  plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2723                }
2724                fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2725                  T30_CONTROL_BIT_ACCEPT_PASSWORD);
2726                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2727                  & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2728                {
2729                  if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2730                    Info = _WRONG_MESSAGE_FORMAT;
2731                  else
2732                  {
2733                    if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734                      & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2735      {
2736                    fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2737                    if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2738                      fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2739      }
2740                    w = fax_parms[4].length;
2741                    if (w > 20)
2742                      w = 20;
2743                    ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2744                    for (i = 0; i < w; i++)
2745                      ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2746                    ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2747                    len = (byte)(((T30_INFO *) 0)->station_id + 20);
2748                    w = fax_parms[5].length;
2749                    if (w > 20)
2750                      w = 20;
2751                    plci->fax_connect_info_buffer[len++] = (byte) w;
2752                    for (i = 0; i < w; i++)
2753                      plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2754                    w = fax_parms[6].length;
2755                    if (w > 20)
2756                      w = 20;
2757                    plci->fax_connect_info_buffer[len++] = (byte) w;
2758                    for (i = 0; i < w; i++)
2759                      plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2760                    if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2761                      & (1L << PRIVATE_FAX_NONSTANDARD))
2762      {
2763                      if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2764        {
2765                        dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2766                        plci->fax_connect_info_buffer[len++] = 0;
2767        }
2768                      else
2769                      {
2770          if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2771            plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2772   plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2773          for (i = 0; i < fax_parms[7].length; i++)
2774     plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2775                      }
2776                    }
2777                  }
2778                }
2779                else
2780                {
2781                  len = (byte)(&(((T30_INFO *) 0)->universal_6));
2782                }
2783                fax_info_change = true;
2784
2785              }
2786              if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2787              {
2788                PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2789                fax_info_change = true;
2790              }
2791            }
2792            if (Info == GOOD)
2793            {
2794              plci->fax_connect_info_length = len;
2795              if (fax_info_change)
2796              {
2797                if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2798                {
2799                  start_internal_command (Id, plci, fax_connect_info_command);
2800                  return false;
2801                }
2802                else
2803                {
2804                  start_internal_command (Id, plci, fax_adjust_b23_command);
2805                  return false;
2806                }
2807              }
2808            }
2809          }
2810          else  Info = _WRONG_STATE;
2811        }
2812        else  Info = _WRONG_STATE;
2813      }
2814
2815      else if (plci->B3_prot == B3_RTP)
2816      {
2817        plci->internal_req_buffer[0] = ncpi->length + 1;
2818        plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2819        for (w = 0; w < ncpi->length; w++)
2820          plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2821        start_internal_command (Id, plci, rtp_connect_b3_req_command);
2822        return false;
2823      }
2824
2825      if(!Info)
2826      {
2827        nl_req_ncci(plci,req,0);
2828        return 1;
2829      }
2830    }
2831  }
2832  else Info = _WRONG_IDENTIFIER;
2833
2834  sendf(appl,
2835        _CONNECT_B3_R|CONFIRM,
2836        Id,
2837        Number,
2838        "w",Info);
2839  return false;
2840}
2841
2842byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2843{
2844  word ncci;
2845  API_PARSE * ncpi;
2846  byte req;
2847
2848  word w;
2849
2850
2851    API_PARSE fax_parms[9];
2852  word i;
2853  byte len;
2854
2855
2856  dbug(1,dprintf("connect_b3_res"));
2857
2858  ncci = (word)(Id>>16);
2859  if(plci && ncci) {
2860    if(a->ncci_state[ncci]==INC_CON_PENDING) {
2861      if (GET_WORD (&parms[0].info[0]) != 0)
2862      {
2863        a->ncci_state[ncci] = OUTG_REJ_PENDING;
2864        channel_request_xon (plci, a->ncci_ch[ncci]);
2865        channel_xmit_xon (plci);
2866        cleanup_ncci_data (plci, ncci);
2867        nl_req_ncci(plci,N_DISC,(byte)ncci);
2868        return 1;
2869      }
2870      a->ncci_state[ncci] = INC_ACT_PENDING;
2871
2872      req = N_CONNECT_ACK;
2873      ncpi = &parms[1];
2874      if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2875      {
2876
2877        if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2878          & (1L << PRIVATE_FAX_NONSTANDARD))
2879 {
2880   if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2881    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2882    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2883   {
2884            len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2885            if (plci->fax_connect_info_length < len)
2886            {
2887              ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2888              ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2889            }
2890            if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2891            {
2892              dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2893            }
2894            else
2895            {
2896              if (plci->fax_connect_info_length <= len)
2897                plci->fax_connect_info_buffer[len] = 0;
2898              len += 1 + plci->fax_connect_info_buffer[len];
2899              if (plci->fax_connect_info_length <= len)
2900                plci->fax_connect_info_buffer[len] = 0;
2901              len += 1 + plci->fax_connect_info_buffer[len];
2902              if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2903                plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2904              plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2905              for (i = 0; i < fax_parms[7].length; i++)
2906                plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2907            }
2908            plci->fax_connect_info_length = len;
2909            ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2910            start_internal_command (Id, plci, fax_connect_ack_command);
2911     return false;
2912          }
2913        }
2914
2915        nl_req_ncci(plci,req,(byte)ncci);
2916        if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2917         && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2918        {
2919          if (plci->B3_prot == 4)
2920            sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2921          else
2922            sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2923          plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2924        }
2925      }
2926
2927      else if (plci->B3_prot == B3_RTP)
2928      {
2929        plci->internal_req_buffer[0] = ncpi->length + 1;
2930        plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2931        for (w = 0; w < ncpi->length; w++)
2932          plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2933        start_internal_command (Id, plci, rtp_connect_b3_res_command);
2934        return false;
2935      }
2936
2937      else
2938      {
2939        if(ncpi->length>2) {
2940          if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2941          add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2942        }
2943        nl_req_ncci(plci,req,(byte)ncci);
2944        sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2945        if (plci->adjust_b_restore)
2946        {
2947          plci->adjust_b_restore = false;
2948          start_internal_command (Id, plci, adjust_b_restore);
2949        }
2950      }
2951      return 1;
2952    }
2953  }
2954  return false;
2955}
2956
2957byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2958{
2959  word ncci;
2960
2961  ncci = (word)(Id>>16);
2962  dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2963
2964  if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2965   && (plci->State != OUTG_DIS_PENDING))
2966  {
2967    if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2968      a->ncci_state[ncci] = CONNECTED;
2969      if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2970      channel_request_xon (plci, a->ncci_ch[ncci]);
2971      channel_xmit_xon (plci);
2972    }
2973  }
2974  return false;
2975}
2976
2977byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2978{
2979  word Info;
2980  word ncci;
2981  API_PARSE * ncpi;
2982
2983  dbug(1,dprintf("disconnect_b3_req"));
2984
2985  Info = _WRONG_IDENTIFIER;
2986  ncci = (word)(Id>>16);
2987  if (plci && ncci)
2988  {
2989    Info = _WRONG_STATE;
2990    if ((a->ncci_state[ncci] == CONNECTED)
2991     || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2992     || (a->ncci_state[ncci] == INC_CON_PENDING)
2993     || (a->ncci_state[ncci] == INC_ACT_PENDING))
2994    {
2995      a->ncci_state[ncci] = OUTG_DIS_PENDING;
2996      channel_request_xon (plci, a->ncci_ch[ncci]);
2997      channel_xmit_xon (plci);
2998
2999      if (a->ncci[ncci].data_pending
3000       && ((plci->B3_prot == B3_TRANSPARENT)
3001        || (plci->B3_prot == B3_T30)
3002        || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3003      {
3004        plci->send_disc = (byte)ncci;
3005        plci->command = 0;
3006        return false;
3007      }
3008      else
3009      {
3010        cleanup_ncci_data (plci, ncci);
3011
3012        if(plci->B3_prot==2 || plci->B3_prot==3)
3013        {
3014          ncpi = &parms[0];
3015          if(ncpi->length>3)
3016          {
3017            add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3018          }
3019        }
3020        nl_req_ncci(plci,N_DISC,(byte)ncci);
3021      }
3022      return 1;
3023    }
3024  }
3025  sendf(appl,
3026        _DISCONNECT_B3_R|CONFIRM,
3027        Id,
3028        Number,
3029        "w",Info);
3030  return false;
3031}
3032
3033byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3034{
3035  word ncci;
3036  word i;
3037
3038  ncci = (word)(Id>>16);
3039  dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3040  if(plci && ncci) {
3041    plci->requested_options_conn = 0;
3042    plci->fax_connect_info_length = 0;
3043    plci->ncpi_state = 0x00;
3044    if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3045      && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3046    {
3047      plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3048    }
3049    for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3050    if(i<MAX_CHANNELS_PER_PLCI) {
3051      if(plci->channels)plci->channels--;
3052      for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3053      plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3054
3055      ncci_free_receive_buffers (plci, ncci);
3056
3057      if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3058        if(plci->State == SUSPENDING){
3059          sendf(plci->appl,
3060                _FACILITY_I,
3061                Id & 0xffffL,
3062                0,
3063                "ws", (word)3, "\x03\x04\x00\x00");
3064          sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3065        }
3066        plci_remove(plci);
3067        plci->State=IDLE;
3068      }
3069    }
3070    else
3071    {
3072      if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3073       && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3074       && (a->ncci_state[ncci] == INC_DIS_PENDING))
3075      {
3076        ncci_free_receive_buffers (plci, ncci);
3077
3078        nl_req_ncci(plci,N_EDATA,(byte)ncci);
3079
3080        plci->adapter->ncci_state[ncci] = IDLE;
3081        start_internal_command (Id, plci, fax_disconnect_command);
3082        return 1;
3083      }
3084    }
3085  }
3086  return false;
3087}
3088
3089byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3090{
3091  NCCI   *ncci_ptr;
3092  DATA_B3_DESC   *data;
3093  word Info;
3094  word ncci;
3095  word i;
3096
3097  dbug(1,dprintf("data_b3_req"));
3098
3099  Info = _WRONG_IDENTIFIER;
3100  ncci = (word)(Id>>16);
3101  dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3102
3103  if (plci && ncci)
3104  {
3105    Info = _WRONG_STATE;
3106    if ((a->ncci_state[ncci] == CONNECTED)
3107     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3108    {
3109        /* queue data */
3110      ncci_ptr = &(a->ncci[ncci]);
3111      i = ncci_ptr->data_out + ncci_ptr->data_pending;
3112      if (i >= MAX_DATA_B3)
3113        i -= MAX_DATA_B3;
3114      data = &(ncci_ptr->DBuffer[i]);
3115      data->Number = Number;
3116      if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3117       && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3118      {
3119
3120        data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3121
3122      }
3123      else
3124        data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3125      data->Length = GET_WORD(parms[1].info);
3126      data->Handle = GET_WORD(parms[2].info);
3127      data->Flags = GET_WORD(parms[3].info);
3128      (ncci_ptr->data_pending)++;
3129
3130        /* check for delivery confirmation */
3131      if (data->Flags & 0x0004)
3132      {
3133        i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3134        if (i >= MAX_DATA_ACK)
3135          i -= MAX_DATA_ACK;
3136        ncci_ptr->DataAck[i].Number = data->Number;
3137        ncci_ptr->DataAck[i].Handle = data->Handle;
3138        (ncci_ptr->data_ack_pending)++;
3139      }
3140
3141      send_data(plci);
3142      return false;
3143    }
3144  }
3145  if (appl)
3146  {
3147    if (plci)
3148    {
3149      if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3150       && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3151      {
3152
3153        TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3154
3155      }
3156    }
3157    sendf(appl,
3158          _DATA_B3_R|CONFIRM,
3159          Id,
3160          Number,
3161          "ww",GET_WORD(parms[2].info),Info);
3162  }
3163  return false;
3164}
3165
3166byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3167{
3168  word n;
3169  word ncci;
3170  word NCCIcode;
3171
3172  dbug(1,dprintf("data_b3_res"));
3173
3174  ncci = (word)(Id>>16);
3175  if(plci && ncci) {
3176    n = GET_WORD(parms[0].info);
3177    dbug(1,dprintf("free(%d)",n));
3178    NCCIcode = ncci | (((word) a->Id) << 8);
3179    if(n<appl->MaxBuffer &&
3180       appl->DataNCCI[n]==NCCIcode &&
3181       (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3182      dbug(1,dprintf("found"));
3183      appl->DataNCCI[n] = 0;
3184
3185      if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3186        channel_request_xon (plci, a->ncci_ch[ncci]);
3187      }
3188      channel_xmit_xon (plci);
3189
3190      if(appl->DataFlags[n] &4) {
3191        nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3192        return 1;
3193      }
3194    }
3195  }
3196  return false;
3197}
3198
3199byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3200{
3201  word Info;
3202  word ncci;
3203
3204  dbug(1,dprintf("reset_b3_req"));
3205
3206  Info = _WRONG_IDENTIFIER;
3207  ncci = (word)(Id>>16);
3208  if(plci && ncci)
3209  {
3210    Info = _WRONG_STATE;
3211    switch (plci->B3_prot)
3212    {
3213    case B3_ISO8208:
3214    case B3_X25_DCE:
3215      if(a->ncci_state[ncci]==CONNECTED)
3216      {
3217        nl_req_ncci(plci,N_RESET,(byte)ncci);
3218        send_req(plci);
3219        Info = GOOD;
3220      }
3221      break;
3222    case B3_TRANSPARENT:
3223      if(a->ncci_state[ncci]==CONNECTED)
3224      {
3225        start_internal_command (Id, plci, reset_b3_command);
3226        Info = GOOD;
3227      }
3228      break;
3229    }
3230  }
3231  /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3232  sendf(appl,
3233        _RESET_B3_R|CONFIRM,
3234        Id,
3235        Number,
3236        "w",Info);
3237  return false;
3238}
3239
3240byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3241{
3242  word ncci;
3243
3244  dbug(1,dprintf("reset_b3_res"));
3245
3246  ncci = (word)(Id>>16);
3247  if(plci && ncci) {
3248    switch (plci->B3_prot)
3249    {
3250    case B3_ISO8208:
3251    case B3_X25_DCE:
3252      if(a->ncci_state[ncci]==INC_RES_PENDING)
3253      {
3254        a->ncci_state[ncci] = CONNECTED;
3255        nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3256        return true;
3257      }
3258    break;
3259    }
3260  }
3261  return false;
3262}
3263
3264byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3265{
3266  word ncci;
3267  API_PARSE * ncpi;
3268  byte req;
3269
3270  dbug(1,dprintf("connect_b3_t90_a_res"));
3271
3272  ncci = (word)(Id>>16);
3273  if(plci && ncci) {
3274    if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3275      a->ncci_state[ncci] = CONNECTED;
3276    }
3277    else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3278      a->ncci_state[ncci] = CONNECTED;
3279
3280      req = N_CONNECT_ACK;
3281
3282        /* parms[0]==0 for CAPI original message definition! */
3283      if(parms[0].info) {
3284        ncpi = &parms[1];
3285        if(ncpi->length>2) {
3286          if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3287          add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3288        }
3289      }
3290      nl_req_ncci(plci,req,(byte)ncci);
3291      return 1;
3292    }
3293  }
3294  return false;
3295}
3296
3297
3298byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3299{
3300  word Info=0;
3301  word i;
3302  byte tel;
3303    API_PARSE bp_parms[7];
3304
3305  if(!plci || !msg)
3306  {
3307    Info = _WRONG_IDENTIFIER;
3308  }
3309  else
3310  {
3311    dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3312                   msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3313    dbug(1,dprintf("PlciState=0x%x",plci->State));
3314    for(i=0;i<7;i++) bp_parms[i].length = 0;
3315
3316    /* check if no channel is open, no B3 connected only */
3317    if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3318     || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3319    {
3320      Info = _WRONG_STATE;
3321    }
3322    /* check message format and fill bp_parms pointer */
3323    else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3324    {
3325      Info = _WRONG_MESSAGE_FORMAT;
3326    }
3327    else
3328    {
3329      if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3330      {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3331        if(Id & EXT_CONTROLLER)
3332        {
3333          sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3334          return 0;
3335        }
3336        plci->State=INC_CON_CONNECTED_ALERT;
3337        plci->appl = appl;
3338        clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3339        dump_c_ind_mask (plci);
3340        for(i=0; i<max_appl; i++) /* disconnect the other appls */
3341        {                         /* its quasi a connect        */
3342          if(test_c_ind_mask_bit (plci, i))
3343            sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3344        }
3345      }
3346
3347      api_save_msg(msg, "s", &plci->saved_msg);
3348      tel = plci->tel;
3349      if(Id & EXT_CONTROLLER)
3350      {
3351        if(tel) /* external controller in use by this PLCI */
3352        {
3353          if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3354          {
3355            dbug(1,dprintf("Ext_Ctrl in use 1"));
3356            Info = _WRONG_STATE;
3357          }
3358        }
3359        else  /* external controller NOT in use by this PLCI ? */
3360        {
3361          if(a->AdvSignalPLCI)
3362          {
3363            dbug(1,dprintf("Ext_Ctrl in use 2"));
3364            Info = _WRONG_STATE;
3365          }
3366          else /* activate the codec */
3367          {
3368            dbug(1,dprintf("Ext_Ctrl start"));
3369            if(AdvCodecSupport(a, plci, appl, 0) )
3370            {
3371              dbug(1,dprintf("Error in codec procedures"));
3372              Info = _WRONG_STATE;
3373            }
3374            else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3375            {
3376              plci->spoofed_msg = AWAITING_SELECT_B;
3377              plci->internal_command = BLOCK_PLCI; /* lock other commands */
3378              plci->command = 0;
3379              dbug(1,dprintf("continue if codec loaded"));
3380              return false;
3381            }
3382          }
3383        }
3384      }
3385      else /* external controller bit is OFF */
3386      {
3387        if(tel) /* external controller in use, need to switch off */
3388        {
3389          if(a->AdvSignalAppl==appl)
3390          {
3391            CodecIdCheck(a, plci);
3392            plci->tel = 0;
3393            plci->adv_nl = 0;
3394            dbug(1,dprintf("Ext_Ctrl disable"));
3395          }
3396          else
3397          {
3398            dbug(1,dprintf("Ext_Ctrl not requested"));
3399          }
3400        }
3401      }
3402      if (!Info)
3403      {
3404        if (plci->call_dir & CALL_DIR_OUT)
3405          plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3406        else if (plci->call_dir & CALL_DIR_IN)
3407          plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3408        start_internal_command (Id, plci, select_b_command);
3409        return false;
3410      }
3411    }
3412  }
3413  sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3414  return false;
3415}
3416
3417byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3418{
3419  word command;
3420  word i;
3421  word ncci;
3422  API_PARSE * m;
3423    API_PARSE m_parms[5];
3424  word codec;
3425  byte req;
3426  byte ch;
3427  byte dir;
3428  static byte chi[2] = {0x01,0x00};
3429  static byte lli[2] = {0x01,0x00};
3430  static byte codec_cai[2] = {0x01,0x01};
3431  static byte null_msg = {0};
3432  static API_PARSE null_parms = { 0, &null_msg };
3433  PLCI   * v_plci;
3434  word Info=0;
3435
3436  dbug(1,dprintf("manufacturer_req"));
3437  for(i=0;i<5;i++) m_parms[i].length = 0;
3438
3439  if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3440    Info = _WRONG_MESSAGE_FORMAT;
3441  }
3442  command = GET_WORD(parms[1].info);
3443  m = &parms[2];
3444  if (!Info)
3445  {
3446    switch(command) {
3447    case _DI_ASSIGN_PLCI:
3448      if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3449        Info = _WRONG_MESSAGE_FORMAT;
3450        break;
3451      }
3452      codec = GET_WORD(m_parms[0].info);
3453      ch = m_parms[1].info[0];
3454      dir = m_parms[2].info[0];
3455      if((i=get_plci(a))) {
3456        plci = &a->plci[i-1];
3457        plci->appl = appl;
3458        plci->command = _MANUFACTURER_R;
3459        plci->m_command = command;
3460        plci->number = Number;
3461        plci->State = LOCAL_CONNECT;
3462        Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3463        dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3464
3465        if((ch==1 || ch==2) && (dir<=2)) {
3466          chi[1] = (byte)(0x80|ch);
3467          lli[1] = 0;
3468          plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3469          switch(codec)
3470          {
3471          case 0:
3472            Info = add_b1(plci,&m_parms[3],0,0);
3473            break;
3474          case 1:
3475            add_p(plci,CAI,codec_cai);
3476            break;
3477          /* manual 'swich on' to the codec support without signalling */
3478          /* first 'assign plci' with this function, then use */
3479          case 2:
3480            if(AdvCodecSupport(a, plci, appl, 0) ) {
3481              Info = _RESOURCE_ERROR;
3482            }
3483            else {
3484              Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3485              lli[1] = 0x10; /* local call codec stream */
3486            }
3487            break;
3488          }
3489
3490          plci->State = LOCAL_CONNECT;
3491          plci->manufacturer = true;
3492          plci->command = _MANUFACTURER_R;
3493          plci->m_command = command;
3494          plci->number = Number;
3495
3496          if(!Info)
3497          {
3498            add_p(plci,LLI,lli);
3499            add_p(plci,CHI,chi);
3500            add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3501            sig_req(plci,ASSIGN,DSIG_ID);
3502
3503            if(!codec)
3504            {
3505              Info = add_b23(plci,&m_parms[3]);
3506              if(!Info)
3507              {
3508                nl_req_ncci(plci,ASSIGN,0);
3509                send_req(plci);
3510              }
3511            }
3512            if(!Info)
3513            {
3514              dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3515              if (plci->spoofed_msg==SPOOFING_REQUIRED)
3516              {
3517                api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3518                plci->spoofed_msg = AWAITING_MANUF_CON;
3519                plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3520                plci->command = 0;
3521                send_req(plci);
3522                return false;
3523              }
3524              if(dir==1) {
3525                sig_req(plci,CALL_REQ,0);
3526              }
3527              else if(!dir){
3528                sig_req(plci,LISTEN_REQ,0);
3529              }
3530              send_req(plci);
3531            }
3532            else
3533            {
3534              sendf(appl,
3535                    _MANUFACTURER_R|CONFIRM,
3536                    Id,
3537                    Number,
3538                    "dww",_DI_MANU_ID,command,Info);
3539              return 2;
3540            }
3541          }
3542        }
3543      }
3544      else  Info = _OUT_OF_PLCI;
3545      break;
3546
3547    case _DI_IDI_CTRL:
3548      if(!plci)
3549      {
3550        Info = _WRONG_IDENTIFIER;
3551        break;
3552      }
3553      if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3554        Info = _WRONG_MESSAGE_FORMAT;
3555        break;
3556      }
3557      req = m_parms[0].info[0];
3558      plci->command = _MANUFACTURER_R;
3559      plci->m_command = command;
3560      plci->number = Number;
3561      if(req==CALL_REQ)
3562      {
3563        plci->b_channel = getChannel(&m_parms[1]);
3564        mixer_set_bchannel_id_esc (plci, plci->b_channel);
3565        if(plci->spoofed_msg==SPOOFING_REQUIRED)
3566        {
3567          plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3568          plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3569          plci->command = 0;
3570          break;
3571        }
3572      }
3573      else if(req==LAW_REQ)
3574      {
3575        plci->cr_enquiry = true;
3576      }
3577      add_ss(plci,FTY,&m_parms[1]);
3578      sig_req(plci,req,0);
3579      send_req(plci);
3580      if(req==HANGUP)
3581      {      
3582        if (plci->NL.Id && !plci->nl_remove_id)
3583        {
3584          if (plci->channels)
3585          {
3586            for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3587            {
3588              if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3589              {
3590                a->ncci_state[ncci] = OUTG_DIS_PENDING;
3591                cleanup_ncci_data (plci, ncci);
3592                nl_req_ncci(plci,N_DISC,(byte)ncci);
3593              }
3594            }
3595          }
3596          mixer_remove (plci);
3597          nl_req_ncci(plci,REMOVE,0);
3598          send_req(plci);
3599        }  
3600      }
3601      break;
3602
3603    case _DI_SIG_CTRL:
3604    /* signalling control for loop activation B-channel */
3605      if(!plci)
3606      {
3607        Info = _WRONG_IDENTIFIER;
3608        break;
3609      }
3610      if(m->length){
3611        plci->command = _MANUFACTURER_R;
3612        plci->number = Number;
3613        add_ss(plci,FTY,m);
3614        sig_req(plci,SIG_CTRL,0);
3615        send_req(plci);
3616      }
3617      else Info = _WRONG_MESSAGE_FORMAT;
3618      break;
3619
3620    case _DI_RXT_CTRL:
3621    /* activation control for receiver/transmitter B-channel */
3622      if(!plci)
3623      {
3624        Info = _WRONG_IDENTIFIER;
3625        break;
3626      }
3627      if(m->length){
3628        plci->command = _MANUFACTURER_R;
3629        plci->number = Number;
3630        add_ss(plci,FTY,m);
3631        sig_req(plci,DSP_CTRL,0);
3632        send_req(plci);
3633      }
3634      else Info = _WRONG_MESSAGE_FORMAT;
3635      break;
3636
3637    case _DI_ADV_CODEC:
3638    case _DI_DSP_CTRL:
3639      /* TEL_CTRL commands to support non standard adjustments: */
3640      /* Ring on/off, Handset micro volume, external micro vol. */
3641      /* handset+external speaker volume, receiver+transm. gain,*/
3642      /* handsfree on (hookinfo off), set mixer command         */
3643
3644      if(command == _DI_ADV_CODEC)
3645      {
3646        if(!a->AdvCodecPLCI) {
3647          Info = _WRONG_STATE;
3648          break;
3649        }
3650        v_plci = a->AdvCodecPLCI;
3651      }
3652      else
3653      {
3654        if (plci
3655         && (m->length >= 3)
3656         && (m->info[1] == 0x1c)
3657         && (m->info[2] >= 1))
3658        {
3659          if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3660          {
3661            if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3662            {
3663              Info = _WRONG_STATE;
3664              break;
3665            }
3666            a->adv_voice_coef_length = m->info[2] - 1;
3667            if (a->adv_voice_coef_length > m->length - 3)
3668              a->adv_voice_coef_length = (byte)(m->length - 3);
3669            if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3670              a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3671            for (i = 0; i < a->adv_voice_coef_length; i++)
3672              a->adv_voice_coef_buffer[i] = m->info[4 + i];
3673            if (plci->B1_facilities & B1_FACILITY_VOICE)
3674              adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3675            break;
3676          }
3677          else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3678          {
3679            if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3680            {
3681              Info = _FACILITY_NOT_SUPPORTED;
3682              break;
3683            }
3684
3685            plci->dtmf_parameter_length = m->info[2] - 1;
3686            if (plci->dtmf_parameter_length > m->length - 3)
3687              plci->dtmf_parameter_length = (byte)(m->length - 3);
3688            if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3689              plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3690            for (i = 0; i < plci->dtmf_parameter_length; i++)
3691              plci->dtmf_parameter_buffer[i] = m->info[4+i];
3692            if (plci->B1_facilities & B1_FACILITY_DTMFR)
3693              dtmf_parameter_write (plci);
3694            break;
3695
3696          }
3697        }
3698        v_plci = plci;
3699      }
3700
3701      if(!v_plci)
3702      {
3703        Info = _WRONG_IDENTIFIER;
3704        break;
3705      }
3706      if(m->length){
3707        add_ss(v_plci,FTY,m);
3708        sig_req(v_plci,TEL_CTRL,0);
3709        send_req(v_plci);
3710      }
3711      else Info = _WRONG_MESSAGE_FORMAT;
3712
3713      break;
3714
3715    case _DI_OPTIONS_REQUEST:
3716      if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3717        Info = _WRONG_MESSAGE_FORMAT;
3718        break;
3719      }
3720      if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3721      {
3722        Info = _FACILITY_NOT_SUPPORTED;
3723        break;
3724      }
3725      a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3726      break;
3727
3728
3729
3730    default:
3731      Info = _WRONG_MESSAGE_FORMAT;
3732      break;
3733    }
3734  }
3735
3736  sendf(appl,
3737        _MANUFACTURER_R|CONFIRM,
3738        Id,
3739        Number,
3740        "dww",_DI_MANU_ID,command,Info);
3741  return false;
3742}
3743
3744
3745byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3746{
3747  word indication;
3748
3749    API_PARSE m_parms[3];
3750  API_PARSE *ncpi;
3751    API_PARSE fax_parms[9];
3752  word i;
3753  byte len;
3754
3755
3756  dbug(1,dprintf("manufacturer_res"));
3757
3758  if ((msg[0].length == 0)
3759   || (msg[1].length == 0)
3760   || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3761  {
3762    return false;
3763  }
3764  indication = GET_WORD(msg[1].info);
3765  switch (indication)
3766  {
3767
3768  case _DI_NEGOTIATE_B3:
3769    if(!plci)
3770      break;
3771    if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3772     || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3773    {
3774      dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3775      break;
3776    }
3777    if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3778    {
3779      dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3780      break;
3781    }
3782    ncpi = &m_parms[1];
3783    len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3784    if (plci->fax_connect_info_length < len)
3785    {
3786      ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3787      ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3788    }
3789    if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3790    {
3791      dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3792    }
3793    else
3794    {
3795      if (plci->fax_connect_info_length <= len)
3796        plci->fax_connect_info_buffer[len] = 0;
3797      len += 1 + plci->fax_connect_info_buffer[len];
3798      if (plci->fax_connect_info_length <= len)
3799        plci->fax_connect_info_buffer[len] = 0;
3800      len += 1 + plci->fax_connect_info_buffer[len];
3801      if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3802        plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3803      plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3804      for (i = 0; i < fax_parms[7].length; i++)
3805        plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3806    }
3807    plci->fax_connect_info_length = len;
3808    plci->fax_edata_ack_length = plci->fax_connect_info_length;
3809    start_internal_command (Id, plci, fax_edata_ack_command);
3810    break;
3811
3812  }
3813  return false;
3814}
3815
3816/*------------------------------------------------------------------*/
3817/* IDI callback function                                            */
3818/*------------------------------------------------------------------*/
3819
3820void   callback(ENTITY   * e)
3821{
3822  DIVA_CAPI_ADAPTER   * a;
3823  APPL   * appl;
3824  PLCI   * plci;
3825  CAPI_MSG   *m;
3826  word i, j;
3827  byte rc;
3828  byte ch;
3829  byte req;
3830  byte global_req;
3831  int no_cancel_rc;
3832
3833  dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3834                 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3835
3836  a = &(adapter[(byte)e->user[0]]);
3837  plci = &(a->plci[e->user[1]]);
3838  no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3839
3840  /*
3841     If new protocol code and new XDI is used then CAPI should work
3842     fully in accordance with IDI cpec an look on callback field instead
3843     of Rc field for return codes.
3844   */
3845  if (((e->complete == 0xff) && no_cancel_rc) ||
3846      (e->Rc && !no_cancel_rc)) {
3847    rc = e->Rc;
3848    ch = e->RcCh;
3849    req = e->Req;
3850    e->Rc = 0;
3851
3852    if (e->user[0] & 0x8000)
3853    {
3854      /*
3855         If REMOVE request was sent then we have to wait until
3856         return code with Id set to zero arrives.
3857         All other return codes should be ignored.
3858         */
3859      if (req == REMOVE)
3860      {
3861        if (e->Id)
3862        {
3863          dbug(1,dprintf("cancel RC in REMOVE state"));
3864          return;
3865        }
3866        channel_flow_control_remove (plci);
3867        for (i = 0; i < 256; i++)
3868        {
3869          if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3870            a->FlowControlIdTable[i] = 0;
3871        }
3872        plci->nl_remove_id = 0;
3873        if (plci->rx_dma_descriptor > 0) {
3874          diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3875          plci->rx_dma_descriptor = 0;
3876        }
3877      }
3878      if (rc == OK_FC)
3879      {
3880        a->FlowControlIdTable[ch] = e->Id;
3881        a->FlowControlSkipTable[ch] = 0;
3882
3883        a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3884        a->ch_flow_plci[ch] = plci->Id;
3885        plci->nl_req = 0;
3886      }
3887      else
3888      {
3889        /*
3890          Cancel return codes self, if feature was requested
3891          */
3892        if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3893          a->FlowControlIdTable[ch] = 0;
3894          if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3895            dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3896            return;
3897          }
3898        }
3899
3900        if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3901        {
3902          a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3903          if (ch == e->ReqCh)
3904            plci->nl_req = 0;
3905        }
3906        else
3907          plci->nl_req = 0;
3908      }
3909      if (plci->nl_req)
3910        control_rc (plci, 0, rc, ch, 0, true);
3911      else
3912      {
3913        if (req == N_XON)
3914        {
3915          channel_x_on (plci, ch);
3916          if (plci->internal_command)
3917            control_rc (plci, req, rc, ch, 0, true);
3918        }
3919        else
3920        {
3921          if (plci->nl_global_req)
3922          {
3923            global_req = plci->nl_global_req;
3924            plci->nl_global_req = 0;
3925            if (rc != ASSIGN_OK) {
3926              e->Id = 0;
3927              if (plci->rx_dma_descriptor > 0) {
3928                diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3929                plci->rx_dma_descriptor = 0;
3930              }
3931            }
3932            channel_xmit_xon (plci);
3933            control_rc (plci, 0, rc, ch, global_req, true);
3934          }
3935          else if (plci->data_sent)
3936          {
3937            channel_xmit_xon (plci);
3938            plci->data_sent = false;
3939            plci->NL.XNum = 1;
3940            data_rc (plci, ch);
3941            if (plci->internal_command)
3942              control_rc (plci, req, rc, ch, 0, true);
3943          }
3944          else
3945          {
3946            channel_xmit_xon (plci);
3947            control_rc (plci, req, rc, ch, 0, true);
3948          }
3949        }
3950      }
3951    }
3952    else
3953    {
3954      /*
3955         If REMOVE request was sent then we have to wait until
3956         return code with Id set to zero arrives.
3957         All other return codes should be ignored.
3958         */
3959      if (req == REMOVE)
3960      {
3961        if (e->Id)
3962        {
3963          dbug(1,dprintf("cancel RC in REMOVE state"));
3964          return;
3965        }
3966        plci->sig_remove_id = 0;
3967      }
3968      plci->sig_req = 0;
3969      if (plci->sig_global_req)
3970      {
3971        global_req = plci->sig_global_req;
3972        plci->sig_global_req = 0;
3973        if (rc != ASSIGN_OK)
3974          e->Id = 0;
3975        channel_xmit_xon (plci);
3976        control_rc (plci, 0, rc, ch, global_req, false);
3977      }
3978      else
3979      {
3980        channel_xmit_xon (plci);
3981        control_rc (plci, req, rc, ch, 0, false);
3982      }
3983    }
3984    /*
3985      Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3986      same callback. Also if new XDI and protocol code used then jump
3987      direct to finish.
3988      */
3989    if (no_cancel_rc) {
3990      channel_xmit_xon(plci);
3991      goto capi_callback_suffix;
3992    }
3993  }
3994
3995  channel_xmit_xon(plci);
3996
3997  if (e->Ind) {
3998    if (e->user[0] &0x8000) {
3999      byte Ind = e->Ind & 0x0f;
4000      byte Ch = e->IndCh;
4001      if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4002          (a->ch_flow_plci[Ch] == plci->Id)) {
4003        if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4004          dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4005        }
4006        a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4007      }
4008      nl_ind(plci);
4009      if ((e->RNR != 1) &&
4010          (a->ch_flow_plci[Ch] == plci->Id) &&
4011          (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4012        a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4013        dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4014      }
4015    } else {
4016      sig_ind(plci);
4017    }
4018    e->Ind = 0;
4019  }
4020
4021capi_callback_suffix:
4022
4023  while (!plci->req_in
4024   && !plci->internal_command
4025   && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4026  {
4027    j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4028
4029    i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4030
4031    m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4032    appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4033    dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4034      m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4035    if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4036    {
4037      plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4038      plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4039    }
4040    else
4041    {
4042      plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4043    }
4044    if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4045    {
4046      plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4047      plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4048    }
4049    else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4050    {
4051      plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4052      plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4053    }
4054    i = api_put (appl, m);
4055    if (i != 0)
4056    {
4057      if (m->header.command == _DATA_B3_R)
4058
4059        TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4060
4061      dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4062      break;
4063    }
4064
4065    if (plci->li_notify_update)
4066    {
4067      plci->li_notify_update = false;
4068      mixer_notify_update (plci, false);
4069    }
4070
4071  }
4072  send_data(plci);
4073  send_req(plci);
4074}
4075
4076
4077void control_rc(PLCI   * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4078{
4079  dword Id;
4080  dword rId;
4081  word Number;
4082  word Info=0;
4083  word i;
4084  word ncci;
4085  DIVA_CAPI_ADAPTER   * a;
4086  APPL   * appl;
4087  PLCI   * rplci;
4088    byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4089    byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4090
4091  if (!plci) {
4092    dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4093    return;
4094  }
4095  dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4096  if(plci->req_in!=plci->req_out)
4097  {
4098    if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4099    {
4100      dbug(1,dprintf("req_1return"));
4101      return;
4102    }
4103    /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4104  }
4105  plci->req_in = plci->req_in_start = plci->req_out = 0;
4106  dbug(1,dprintf("control_rc"));
4107
4108  appl = plci->appl;
4109  a = plci->adapter;
4110  ncci = a->ch_ncci[ch];
4111  if(appl)
4112  {
4113    Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4114    if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4115    Number = plci->number;
4116    dbug(1,dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x",Id,plci->Id,plci->tel,plci->Sig.Id,plci->command,plci->internal_command));
4117    dbug(1,dprintf("channels=0x%x",plci->channels));
4118    if (plci_remove_check(plci))
4119      return;
4120    if(req==REMOVE && rc==ASSIGN_OK)
4121    {
4122      sig_req(plci,HANGUP,0);
4123      sig_req(plci,REMOVE,0);
4124      send_req(plci);
4125    }
4126    if(plci->command)
4127    {
4128      switch(plci->command)
4129      {
4130      case C_HOLD_REQ:
4131        dbug(1,dprintf("HoldRC=0x%x",rc));
4132        SSparms[1] = (byte)S_HOLD;
4133        if(rc!=OK)
4134        {
4135          plci->SuppState = IDLE;
4136          Info = 0x2001;
4137        }
4138        sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4139        break;
4140
4141      case C_RETRIEVE_REQ:
4142        dbug(1,dprintf("RetrieveRC=0x%x",rc));
4143        SSparms[1] = (byte)S_RETRIEVE;
4144        if(rc!=OK)
4145        {
4146          plci->SuppState = CALL_HELD;
4147          Info = 0x2001;
4148        }
4149        sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4150        break;
4151
4152      case _INFO_R:
4153        dbug(1,dprintf("InfoRC=0x%x",rc));
4154        if(rc!=OK) Info=_WRONG_STATE;
4155        sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4156        break;
4157
4158      case _CONNECT_R:
4159        dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4160        if (plci->State == INC_DIS_PENDING)
4161          break;
4162        if(plci->Sig.Id!=0xff)
4163        {
4164          if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4165           || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4166          {
4167            dbug(1,dprintf("No more IDs/Call_Req failed"));
4168            sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4169            plci_remove(plci);
4170            plci->State = IDLE;
4171            break;
4172          }
4173          if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4174          sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4175        }
4176        else /* D-ch activation */
4177        {
4178          if (rc != ASSIGN_OK)
4179          {
4180            dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4181            sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4182            plci_remove(plci);
4183            plci->State = IDLE;
4184            break;
4185          }
4186          sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4187          sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4188          plci->State = INC_ACT_PENDING;
4189        }
4190        break;
4191
4192      case _CONNECT_I|RESPONSE:
4193        if (plci->State != INC_DIS_PENDING)
4194          plci->State = INC_CON_ACCEPT;
4195        break;
4196
4197      case _DISCONNECT_R:
4198        if (plci->State == INC_DIS_PENDING)
4199          break;
4200        if(plci->Sig.Id!=0xff)
4201        {
4202          plci->State = OUTG_DIS_PENDING;
4203          sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4204        }
4205        break;
4206
4207      case SUSPEND_REQ:
4208        break;
4209
4210      case RESUME_REQ:
4211        break;
4212
4213      case _CONNECT_B3_R:
4214        if(rc!=OK)
4215        {
4216          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4217          break;
4218        }
4219        ncci = get_ncci (plci, ch, 0);
4220        Id = (Id & 0xffff) | (((dword) ncci) << 16);
4221        plci->channels++;
4222        if(req==N_RESET)
4223        {
4224          a->ncci_state[ncci] = INC_ACT_PENDING;
4225          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4226          sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4227        }
4228        else
4229        {
4230          a->ncci_state[ncci] = OUTG_CON_PENDING;
4231          sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4232        }
4233        break;
4234
4235      case _CONNECT_B3_I|RESPONSE:
4236        break;
4237
4238      case _RESET_B3_R:
4239/*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4240        break;
4241
4242      case _DISCONNECT_B3_R:
4243        sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4244        break;
4245
4246      case _MANUFACTURER_R:
4247        break;
4248
4249      case PERM_LIST_REQ:
4250        if(rc!=OK)
4251        {
4252          Info = _WRONG_IDENTIFIER;
4253          sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4254          plci_remove(plci);
4255        }
4256        else
4257          sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4258        break;
4259
4260      default:
4261        break;
4262      }
4263      plci->command = 0;
4264    }
4265    else if (plci->internal_command)
4266    {
4267      switch(plci->internal_command)
4268      {
4269      case BLOCK_PLCI:
4270        return;
4271
4272      case GET_MWI_STATE:
4273        if(rc==OK) /* command supported, wait for indication */
4274        {
4275          return;
4276        }
4277        plci_remove(plci);
4278        break;
4279
4280        /* Get Supported Services */
4281      case GETSERV_REQ_PEND:
4282        if(rc==OK) /* command supported, wait for indication */
4283        {
4284          break;
4285        }
4286        PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4287        sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4288        plci_remove(plci);
4289        break;
4290
4291      case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4292      case INTERR_NUMBERS_REQ_PEND:
4293      case CF_START_PEND:                  /* Call Forwarding Start pending */
4294      case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4295      case CCBS_REQUEST_REQ_PEND:
4296      case CCBS_DEACTIVATE_REQ_PEND:
4297      case CCBS_INTERROGATE_REQ_PEND:
4298        switch(plci->internal_command)
4299        {
4300          case INTERR_DIVERSION_REQ_PEND:
4301            SSparms[1] = S_INTERROGATE_DIVERSION;
4302            break;
4303          case INTERR_NUMBERS_REQ_PEND:
4304            SSparms[1] = S_INTERROGATE_NUMBERS;
4305            break;
4306          case CF_START_PEND:
4307            SSparms[1] = S_CALL_FORWARDING_START;
4308            break;
4309          case CF_STOP_PEND:
4310            SSparms[1] = S_CALL_FORWARDING_STOP;
4311            break;
4312          case CCBS_REQUEST_REQ_PEND:
4313            SSparms[1] = S_CCBS_REQUEST;
4314            break;
4315          case CCBS_DEACTIVATE_REQ_PEND:
4316            SSparms[1] = S_CCBS_DEACTIVATE;
4317            break;
4318          case CCBS_INTERROGATE_REQ_PEND:
4319            SSparms[1] = S_CCBS_INTERROGATE;
4320            break;
4321        }
4322        if(global_req==ASSIGN)
4323        {
4324          dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4325          return;
4326        }
4327        if(!plci->appl) break;
4328        if(rc==ISDN_GUARD_REJ)
4329        {
4330          Info = _CAPI_GUARD_ERROR;
4331        }
4332        else if(rc!=OK)
4333        {
4334          Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4335        }
4336        sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4337              plci->number,"wws",Info,(word)3,SSparms);
4338        if(Info) plci_remove(plci);
4339        break;
4340
4341        /* 3pty conference pending */
4342      case PTY_REQ_PEND:
4343        if(!plci->relatedPTYPLCI) break;
4344        rplci = plci->relatedPTYPLCI;
4345        SSparms[1] = plci->ptyState;
4346        rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4347        if(rplci->tel) rId|=EXT_CONTROLLER;
4348        if(rc!=OK)
4349        {
4350          Info = 0x300E; /* not supported */
4351          plci->relatedPTYPLCI = NULL;
4352          plci->ptyState = 0;
4353        }
4354        sendf(rplci->appl,
4355              _FACILITY_R|CONFIRM,
4356              rId,
4357              plci->number,
4358              "wws",Info,(word)3,SSparms);
4359        break;
4360
4361        /* Explicit Call Transfer pending */
4362      case ECT_REQ_PEND:
4363        dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4364        if(!plci->relatedPTYPLCI) break;
4365        rplci = plci->relatedPTYPLCI;
4366        SSparms[1] = S_ECT;
4367        rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4368        if(rplci->tel) rId|=EXT_CONTROLLER;
4369        if(rc!=OK)
4370        {
4371          Info = 0x300E; /* not supported */
4372          plci->relatedPTYPLCI = NULL;
4373          plci->ptyState = 0;
4374        }
4375        sendf(rplci->appl,
4376              _FACILITY_R|CONFIRM,
4377              rId,
4378              plci->number,
4379              "wws",Info,(word)3,SSparms);
4380        break;
4381
4382      case _MANUFACTURER_R:
4383        dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4384        if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4385        {
4386          dbug(1,dprintf("No more IDs"));
4387          sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4388          plci_remove(plci);  /* after codec init, internal codec commands pending */
4389        }
4390        break;
4391
4392      case _CONNECT_R:
4393        dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4394        if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4395        {
4396          dbug(1,dprintf("No more IDs"));
4397          sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4398          plci_remove(plci);  /* after codec init, internal codec commands pending */
4399        }
4400        break;
4401
4402      case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4403        return;
4404
4405      case PERM_COD_CALL:
4406        dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4407        plci->internal_command = PERM_COD_CONN_PEND;
4408        return;
4409
4410      case PERM_COD_ASSIGN:
4411        dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4412        if(rc!=ASSIGN_OK) break;
4413        sig_req(plci,CALL_REQ,0);
4414        send_req(plci);
4415        plci->internal_command = PERM_COD_CALL;
4416        return;
4417
4418        /* Null Call Reference Request pending */
4419      case C_NCR_FAC_REQ:
4420        dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4421        if(global_req==ASSIGN)
4422        {
4423          if(rc==ASSIGN_OK)
4424          {
4425            return;
4426          }
4427          else
4428          {
4429            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4430            appl->NullCREnable = false;
4431            plci_remove(plci);
4432          }
4433        }
4434        else if(req==NCR_FACILITY)
4435        {
4436          if(rc==OK)
4437          {
4438            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4439          }
4440          else
4441          {
4442            sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4443            appl->NullCREnable = false;
4444          }
4445          plci_remove(plci);
4446        }
4447        break;
4448
4449      case HOOK_ON_REQ:
4450        if(plci->channels)
4451        {
4452          if(a->ncci_state[ncci]==CONNECTED)
4453          {
4454            a->ncci_state[ncci] = OUTG_DIS_PENDING;
4455            cleanup_ncci_data (plci, ncci);
4456            nl_req_ncci(plci,N_DISC,(byte)ncci);
4457          }
4458          break;
4459        }
4460        break;
4461
4462      case HOOK_OFF_REQ:
4463        if (plci->State == INC_DIS_PENDING)
4464          break;
4465        sig_req(plci,CALL_REQ,0);
4466        send_req(plci);
4467        plci->State=OUTG_CON_PENDING;
4468        break;
4469
4470
4471      case MWI_ACTIVATE_REQ_PEND:
4472      case MWI_DEACTIVATE_REQ_PEND:
4473        if(global_req == ASSIGN && rc==ASSIGN_OK)
4474        {
4475          dbug(1,dprintf("MWI_REQ assigned"));
4476          return;
4477        }
4478        else if(rc!=OK)
4479        {                 
4480          if(rc==WRONG_IE)
4481          {
4482            Info = 0x2007; /* Illegal message parameter coding */
4483            dbug(1,dprintf("MWI_REQ invalid parameter"));
4484          }
4485          else
4486          {
4487            Info = 0x300B; /* not supported */                      
4488            dbug(1,dprintf("MWI_REQ not supported"));
4489          }
4490          /* 0x3010: Request not allowed in this state */
4491          PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4492                    
4493        }
4494        if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4495        {
4496          PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4497        }
4498        else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4499
4500        if(plci->cr_enquiry)
4501        {
4502          sendf(plci->appl,
4503                _FACILITY_R|CONFIRM,
4504                Id&0xf,
4505                plci->number,
4506                "wws",Info,(word)3,SSparms);
4507          if(rc!=OK) plci_remove(plci);
4508        }
4509        else
4510        {
4511          sendf(plci->appl,
4512                _FACILITY_R|CONFIRM,
4513                Id,
4514                plci->number,
4515                "wws",Info,(word)3,SSparms);
4516        }
4517        break;
4518
4519      case CONF_BEGIN_REQ_PEND:
4520      case CONF_ADD_REQ_PEND:
4521      case CONF_SPLIT_REQ_PEND:
4522      case CONF_DROP_REQ_PEND:
4523      case CONF_ISOLATE_REQ_PEND:
4524      case CONF_REATTACH_REQ_PEND:
4525        dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4526        if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4527        rplci = plci;
4528        rId = Id;
4529        switch(plci->internal_command)
4530        {
4531          case CONF_BEGIN_REQ_PEND:
4532            SSparms[1] = S_CONF_BEGIN;
4533            break;
4534          case CONF_ADD_REQ_PEND:
4535            SSparms[1] = S_CONF_ADD;
4536            rplci = plci->relatedPTYPLCI;
4537            rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4538            break;
4539          case CONF_SPLIT_REQ_PEND:
4540            SSparms[1] = S_CONF_SPLIT;
4541            break;
4542          case CONF_DROP_REQ_PEND:
4543            SSparms[1] = S_CONF_DROP;
4544            break;
4545          case CONF_ISOLATE_REQ_PEND:
4546            SSparms[1] = S_CONF_ISOLATE;
4547            break;
4548          case CONF_REATTACH_REQ_PEND:
4549            SSparms[1] = S_CONF_REATTACH;
4550            break;
4551        }
4552        
4553        if(rc!=OK)
4554        {
4555          Info = 0x300E; /* not supported */
4556          plci->relatedPTYPLCI = NULL;
4557          plci->ptyState = 0;
4558        }
4559        sendf(rplci->appl,
4560              _FACILITY_R|CONFIRM,
4561              rId,
4562              plci->number,
4563              "wws",Info,(word)3,SSparms);
4564        break;
4565
4566      case VSWITCH_REQ_PEND:
4567        if(rc!=OK)
4568        {
4569          if(plci->relatedPTYPLCI)
4570          {
4571            plci->relatedPTYPLCI->vswitchstate=0;
4572            plci->relatedPTYPLCI->vsprot=0;
4573            plci->relatedPTYPLCI->vsprotdialect=0;    
4574          }
4575          plci->vswitchstate=0;
4576          plci->vsprot=0;
4577          plci->vsprotdialect=0;
4578        }
4579        else
4580        {
4581          if(plci->relatedPTYPLCI &&
4582             plci->vswitchstate==1 &&
4583             plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4584            plci->vswitchstate=3;
4585        }
4586        break;
4587
4588  /* Call Deflection Request pending (SSCT) */
4589      case CD_REQ_PEND:
4590        SSparms[1] = S_CALL_DEFLECTION;
4591        if(rc!=OK)
4592        {
4593          Info = 0x300E; /* not supported */
4594          plci->appl->CDEnable = 0;
4595        }  
4596        sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4597          plci->number,"wws",Info,(word)3,SSparms);
4598        break;
4599
4600      case RTP_CONNECT_B3_REQ_COMMAND_2:
4601        if (rc == OK)
4602        {
4603          ncci = get_ncci (plci, ch, 0);
4604          Id = (Id & 0xffff) | (((dword) ncci) << 16);
4605          plci->channels++;
4606          a->ncci_state[ncci] = OUTG_CON_PENDING;
4607        }
4608
4609      default:
4610        if (plci->internal_command_queue[0])
4611        {
4612          (*(plci->internal_command_queue[0]))(Id, plci, rc);
4613          if (plci->internal_command)
4614            return;
4615        }
4616        break;
4617      }
4618      next_internal_command (Id, plci);
4619    }
4620  }
4621  else /* appl==0 */
4622  {
4623    Id = ((word)plci->Id<<8)|plci->adapter->Id;
4624    if(plci->tel) Id|=EXT_CONTROLLER;
4625
4626    switch(plci->internal_command)
4627    {
4628    case BLOCK_PLCI:
4629      return;
4630
4631    case START_L1_SIG_ASSIGN_PEND:
4632    case REM_L1_SIG_ASSIGN_PEND:
4633      if(global_req == ASSIGN)
4634      {
4635        break;
4636      }
4637      else
4638      {
4639        dbug(1,dprintf("***L1 Req rem PLCI"));
4640        plci->internal_command = 0;
4641        sig_req(plci,REMOVE,0);
4642        send_req(plci);
4643      }
4644      break;
4645
4646      /* Call Deflection Request pending, just no appl ptr assigned */
4647    case CD_REQ_PEND:
4648      SSparms[1] = S_CALL_DEFLECTION;
4649      if(rc!=OK)
4650      {
4651        Info = 0x300E; /* not supported */
4652      }
4653      for(i=0; i<max_appl; i++)
4654      {
4655        if(application[i].CDEnable)
4656        {
4657          if(!application[i].Id) application[i].CDEnable = 0;
4658          else
4659          {
4660            sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4661                  plci->number,"wws",Info,(word)3,SSparms);
4662            if(Info) application[i].CDEnable = 0;
4663          }
4664        }
4665      }
4666      plci->internal_command = 0;
4667      break;
4668
4669    case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4670      return;
4671
4672    case PERM_COD_CALL:
4673      plci->internal_command = PERM_COD_CONN_PEND;
4674      dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4675      return;
4676
4677    case PERM_COD_ASSIGN:
4678      dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4679      plci->internal_command = 0;
4680      if(rc!=ASSIGN_OK) break;
4681      plci->internal_command = PERM_COD_CALL;
4682      sig_req(plci,CALL_REQ,0);
4683      send_req(plci);
4684      return;
4685
4686    case LISTEN_SIG_ASSIGN_PEND:
4687      if(rc == ASSIGN_OK)
4688      {
4689        plci->internal_command = 0;
4690        dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4691        add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4692        sig_req(plci,INDICATE_REQ,0);
4693        send_req(plci);
4694      }
4695      else
4696      {
4697        dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4698        a->listen_active--;
4699        plci_remove(plci);
4700        plci->State = IDLE;
4701      }
4702      break;
4703
4704    case USELAW_REQ:
4705      if(global_req == ASSIGN)
4706      {
4707        if (rc==ASSIGN_OK)
4708      {
4709        sig_req(plci,LAW_REQ,0);
4710        send_req(plci);
4711        dbug(1,dprintf("Auto-Law assigned"));
4712        }
4713        else
4714        {
4715          dbug(1,dprintf("Auto-Law assign failed"));
4716          a->automatic_law = 3;
4717          plci->internal_command = 0;
4718          a->automatic_lawPLCI = NULL;
4719        }
4720        break;
4721      }
4722      else if(req == LAW_REQ && rc==OK)
4723      {
4724        dbug(1,dprintf("Auto-Law initiated"));
4725        a->automatic_law = 2;
4726        plci->internal_command = 0;
4727      }
4728      else
4729      {
4730        dbug(1,dprintf("Auto-Law not supported"));
4731        a->automatic_law = 3;
4732        plci->internal_command = 0;
4733        sig_req(