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#include <linux/bitmap.h>
  27
  28#include "platform.h"
  29#include "di_defs.h"
  30#include "pc.h"
  31#include "capi20.h"
  32#include "divacapi.h"
  33#include "mdm_msg.h"
  34#include "divasync.h"
  35
  36#define FILE_ "MESSAGE.C"
  37#define dprintf
  38
  39/*------------------------------------------------------------------*/
  40/* This is options supported for all adapters that are server by    */
  41/* XDI driver. Allo it is not necessary to ask it from every adapter*/
  42/* and it is not necessary to save it separate for every adapter    */
  43/* Macrose defined here have only local meaning                     */
  44/*------------------------------------------------------------------*/
  45static dword diva_xdi_extended_features = 0;
  46
  47#define DIVA_CAPI_USE_CMA                 0x00000001
  48#define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
  49#define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
  50#define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
  51
  52/*
  53  CAPI can request to process all return codes self only if:
  54  protocol code supports this && xdi supports this
  55*/
  56#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))
  57
  58/*------------------------------------------------------------------*/
  59/* local function prototypes                                        */
  60/*------------------------------------------------------------------*/
  61
  62static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
  63void AutomaticLaw(DIVA_CAPI_ADAPTER *);
  64word CapiRelease(word);
  65word CapiRegister(word);
  66word api_put(APPL *, CAPI_MSG *);
  67static word api_parse(byte *, word, byte *, API_PARSE *);
  68static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
  69static void api_load_msg(API_SAVE *in, API_PARSE *out);
  70
  71word api_remove_start(void);
  72void api_remove_complete(void);
  73
  74static void plci_remove(PLCI *);
  75static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
  76static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
  77
  78void callback(ENTITY *);
  79
  80static void control_rc(PLCI *, byte, byte, byte, byte, byte);
  81static void data_rc(PLCI *, byte);
  82static void data_ack(PLCI *, byte);
  83static void sig_ind(PLCI *);
  84static void SendInfo(PLCI *, dword, byte **, byte);
  85static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
  86static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
  87
  88static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
  89
  90static void nl_ind(PLCI *);
  91
  92static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
  93static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
  94static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
  95static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
  96static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
  97static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
  98static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
  99static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 100static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 101static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 102static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 103static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 104static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 105static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 106static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 107static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 108static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 109static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 110static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 111static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 112static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 113static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 114static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 115static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 116
 117static word get_plci(DIVA_CAPI_ADAPTER *);
 118static void add_p(PLCI *, byte, byte *);
 119static void add_s(PLCI *plci, byte code, API_PARSE *p);
 120static void add_ss(PLCI *plci, byte code, API_PARSE *p);
 121static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
 122static void add_d(PLCI *, word, byte *);
 123static void add_ai(PLCI *, API_PARSE *);
 124static word add_b1(PLCI *, API_PARSE *, word, word);
 125static word add_b23(PLCI *, API_PARSE *);
 126static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
 127static void sig_req(PLCI *, byte, byte);
 128static void nl_req_ncci(PLCI *, byte, byte);
 129static void send_req(PLCI *);
 130static void send_data(PLCI *);
 131static word plci_remove_check(PLCI *);
 132static void listen_check(DIVA_CAPI_ADAPTER *);
 133static byte AddInfo(byte **, byte **, byte *, byte *);
 134static byte getChannel(API_PARSE *);
 135static void IndParse(PLCI *, const word *, byte **, byte);
 136static byte ie_compare(byte *, byte *);
 137static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
 138static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
 139
 140/*
 141  XON protocol helpers
 142*/
 143static void channel_flow_control_remove(PLCI *plci);
 144static void channel_x_off(PLCI *plci, byte ch, byte flag);
 145static void channel_x_on(PLCI *plci, byte ch);
 146static void channel_request_xon(PLCI *plci, byte ch);
 147static void channel_xmit_xon(PLCI *plci);
 148static int channel_can_xon(PLCI *plci, byte ch);
 149static void channel_xmit_extended_xon(PLCI *plci);
 150
 151static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
 152static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
 153static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
 154static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
 155static void VoiceChannelOff(PLCI *plci);
 156static void adv_voice_write_coefs(PLCI *plci, word write_command);
 157static void adv_voice_clear_config(PLCI *plci);
 158
 159static word get_b1_facilities(PLCI *plci, byte b1_resource);
 160static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
 161static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
 162static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
 163static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
 164static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
 165static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
 166static void select_b_command(dword Id, PLCI *plci, byte Rc);
 167static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
 168static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
 169static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
 170static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
 171static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
 172static void hold_save_command(dword Id, PLCI *plci, byte Rc);
 173static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
 174static void init_b1_config(PLCI *plci);
 175static void clear_b1_config(PLCI *plci);
 176
 177static void dtmf_command(dword Id, PLCI *plci, byte Rc);
 178static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
 179static void dtmf_confirmation(dword Id, PLCI *plci);
 180static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
 181static void dtmf_parameter_write(PLCI *plci);
 182
 183
 184static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
 185static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
 186static void mixer_clear_config(PLCI *plci);
 187static void mixer_notify_update(PLCI *plci, byte others);
 188static void mixer_command(dword Id, PLCI *plci, byte Rc);
 189static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
 190static void mixer_indication_coefs_set(dword Id, PLCI *plci);
 191static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
 192static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
 193static void mixer_remove(PLCI *plci);
 194
 195
 196static void ec_command(dword Id, PLCI *plci, byte Rc);
 197static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
 198static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
 199
 200
 201static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
 202static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
 203
 204
 205static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
 206static void diva_free_dma_descriptor(PLCI *plci, int nr);
 207
 208/*------------------------------------------------------------------*/
 209/* external function prototypes                                     */
 210/*------------------------------------------------------------------*/
 211
 212extern byte MapController(byte);
 213extern byte UnMapController(byte);
 214#define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
 215#define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
 216
 217void sendf(APPL *, word, dword, word, byte *, ...);
 218void *TransmitBufferSet(APPL *appl, dword ref);
 219void *TransmitBufferGet(APPL *appl, void *p);
 220void TransmitBufferFree(APPL *appl, void *p);
 221void *ReceiveBufferGet(APPL *appl, int Num);
 222
 223int fax_head_line_time(char *buffer);
 224
 225
 226/*------------------------------------------------------------------*/
 227/* Global data definitions                                          */
 228/*------------------------------------------------------------------*/
 229extern byte max_adapter;
 230extern byte max_appl;
 231extern DIVA_CAPI_ADAPTER *adapter;
 232extern APPL *application;
 233
 234
 235
 236
 237
 238
 239
 240static byte remove_started = false;
 241static PLCI dummy_plci;
 242
 243
 244static struct _ftable {
 245        word command;
 246        byte *format;
 247        byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 248} ftable[] = {
 249        {_DATA_B3_R,                          "dwww",         data_b3_req},
 250        {_DATA_B3_I | RESPONSE,               "w",            data_b3_res},
 251        {_INFO_R,                             "ss",           info_req},
 252        {_INFO_I | RESPONSE,                  "",             info_res},
 253        {_CONNECT_R,                          "wsssssssss",   connect_req},
 254        {_CONNECT_I | RESPONSE,               "wsssss",       connect_res},
 255        {_CONNECT_ACTIVE_I | RESPONSE,        "",             connect_a_res},
 256        {_DISCONNECT_R,                       "s",            disconnect_req},
 257        {_DISCONNECT_I | RESPONSE,            "",             disconnect_res},
 258        {_LISTEN_R,                           "dddss",        listen_req},
 259        {_ALERT_R,                            "s",            alert_req},
 260        {_FACILITY_R,                         "ws",           facility_req},
 261        {_FACILITY_I | RESPONSE,              "ws",           facility_res},
 262        {_CONNECT_B3_R,                       "s",            connect_b3_req},
 263        {_CONNECT_B3_I | RESPONSE,            "ws",           connect_b3_res},
 264        {_CONNECT_B3_ACTIVE_I | RESPONSE,     "",             connect_b3_a_res},
 265        {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
 266        {_DISCONNECT_B3_I | RESPONSE,         "",             disconnect_b3_res},
 267        {_RESET_B3_R,                         "s",            reset_b3_req},
 268        {_RESET_B3_I | RESPONSE,              "",             reset_b3_res},
 269        {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws",           connect_b3_t90_a_res},
 270        {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "",             connect_b3_t90_a_res},
 271        {_SELECT_B_REQ,                       "s",            select_b_req},
 272        {_MANUFACTURER_R,                     "dws",          manufacturer_req},
 273        {_MANUFACTURER_I | RESPONSE,          "dws",          manufacturer_res},
 274        {_MANUFACTURER_I | RESPONSE,          "",             manufacturer_res}
 275};
 276
 277static byte *cip_bc[29][2] = {
 278        { "",                     ""                     }, /* 0 */
 279        { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
 280        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
 281        { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
 282        { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
 283        { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
 284        { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
 285        { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
 286        { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
 287        { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
 288        { "",                     ""                     }, /* 10 */
 289        { "",                     ""                     }, /* 11 */
 290        { "",                     ""                     }, /* 12 */
 291        { "",                     ""                     }, /* 13 */
 292        { "",                     ""                     }, /* 14 */
 293        { "",                     ""                     }, /* 15 */
 294
 295        { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
 296        { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
 297        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
 298        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
 299        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
 300        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
 301        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
 302        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
 303        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
 304        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
 305        { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
 306        { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
 307        { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
 308};
 309
 310static byte *cip_hlc[29] = {
 311        "",                           /* 0 */
 312        "",                           /* 1 */
 313        "",                           /* 2 */
 314        "",                           /* 3 */
 315        "",                           /* 4 */
 316        "",                           /* 5 */
 317        "",                           /* 6 */
 318        "",                           /* 7 */
 319        "",                           /* 8 */
 320        "",                           /* 9 */
 321        "",                           /* 10 */
 322        "",                           /* 11 */
 323        "",                           /* 12 */
 324        "",                           /* 13 */
 325        "",                           /* 14 */
 326        "",                           /* 15 */
 327
 328        "\x02\x91\x81",               /* 16 */
 329        "\x02\x91\x84",               /* 17 */
 330        "\x02\x91\xa1",               /* 18 */
 331        "\x02\x91\xa4",               /* 19 */
 332        "\x02\x91\xa8",               /* 20 */
 333        "\x02\x91\xb1",               /* 21 */
 334        "\x02\x91\xb2",               /* 22 */
 335        "\x02\x91\xb5",               /* 23 */
 336        "\x02\x91\xb8",               /* 24 */
 337        "\x02\x91\xc1",               /* 25 */
 338        "\x02\x91\x81",               /* 26 */
 339        "\x03\x91\xe0\x01",           /* 27 */
 340        "\x03\x91\xe0\x02"            /* 28 */
 341};
 342
 343/*------------------------------------------------------------------*/
 344
 345#define V120_HEADER_LENGTH 1
 346#define V120_HEADER_EXTEND_BIT  0x80
 347#define V120_HEADER_BREAK_BIT   0x40
 348#define V120_HEADER_C1_BIT      0x04
 349#define V120_HEADER_C2_BIT      0x08
 350#define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
 351
 352static byte v120_default_header[] =
 353{
 354
 355        0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
 356
 357};
 358
 359static byte v120_break_header[] =
 360{
 361
 362        0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
 363
 364};
 365
 366
 367/*------------------------------------------------------------------*/
 368/* API_PUT function                                                 */
 369/*------------------------------------------------------------------*/
 370
 371word api_put(APPL *appl, CAPI_MSG *msg)
 372{
 373        word i, j, k, l, n;
 374        word ret;
 375        byte c;
 376        byte controller;
 377        DIVA_CAPI_ADAPTER *a;
 378        PLCI *plci;
 379        NCCI *ncci_ptr;
 380        word ncci;
 381        CAPI_MSG *m;
 382        API_PARSE msg_parms[MAX_MSG_PARMS + 1];
 383
 384        if (msg->header.length < sizeof(msg->header) ||
 385            msg->header.length > MAX_MSG_SIZE) {
 386                dbug(1, dprintf("bad len"));
 387                return _BAD_MSG;
 388        }
 389
 390        controller = (byte)((msg->header.controller & 0x7f) - 1);
 391
 392        /* controller starts with 0 up to (max_adapter - 1) */
 393        if (controller >= max_adapter)
 394        {
 395                dbug(1, dprintf("invalid ctrl"));
 396                return _BAD_MSG;
 397        }
 398
 399        a = &adapter[controller];
 400        plci = NULL;
 401        if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
 402        {
 403                dbug(1, dprintf("plci=%x", msg->header.plci));
 404                plci = &a->plci[msg->header.plci - 1];
 405                ncci = GET_WORD(&msg->header.ncci);
 406                if (plci->Id
 407                    && (plci->appl
 408                        || (plci->State == INC_CON_PENDING)
 409                        || (plci->State == INC_CON_ALERT)
 410                        || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
 411                    && ((ncci == 0)
 412                        || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
 413                        || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
 414                {
 415                        i = plci->msg_in_read_pos;
 416                        j = plci->msg_in_write_pos;
 417                        if (j >= i)
 418                        {
 419                                if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
 420                                        i += MSG_IN_QUEUE_SIZE - j;
 421                                else
 422                                        j = 0;
 423                        }
 424                        else
 425                        {
 426
 427                                n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
 428
 429                                if (i > MSG_IN_QUEUE_SIZE - n)
 430                                        i = MSG_IN_QUEUE_SIZE - n + 1;
 431                                i -= j;
 432                        }
 433
 434                        if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
 435
 436                        {
 437                                dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
 438                                                msg->header.length, plci->msg_in_write_pos,
 439                                                plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
 440
 441                                return _QUEUE_FULL;
 442                        }
 443                        c = false;
 444                        if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
 445                            || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
 446                        {
 447                                if (plci->msg_in_write_pos != plci->msg_in_read_pos)
 448                                        c = true;
 449                        }
 450                        if (msg->header.command == _DATA_B3_R)
 451                        {
 452                                if (msg->header.length < 20)
 453                                {
 454                                        dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
 455                                        return _BAD_MSG;
 456                                }
 457                                ncci_ptr = &(a->ncci[ncci]);
 458                                n = ncci_ptr->data_pending;
 459                                l = ncci_ptr->data_ack_pending;
 460                                k = plci->msg_in_read_pos;
 461                                while (k != plci->msg_in_write_pos)
 462                                {
 463                                        if (k == plci->msg_in_wrap_pos)
 464                                                k = 0;
 465                                        if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
 466                                            && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
 467                                        {
 468                                                n++;
 469                                                if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
 470                                                        l++;
 471                                        }
 472
 473                                        k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
 474                                              MSG_IN_OVERHEAD + 3) & 0xfffc;
 475
 476                                }
 477                                if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
 478                                {
 479                                        dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
 480                                                        ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
 481
 482                                        return _QUEUE_FULL;
 483                                }
 484                                if (plci->req_in || plci->internal_command)
 485                                {
 486                                        if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
 487                                            && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
 488                                        {
 489                                                dbug(0, dprintf("Q-FULL3(requeue)"));
 490
 491                                                return _QUEUE_FULL;
 492                                        }
 493                                        c = true;
 494                                }
 495                        }
 496                        else
 497                        {
 498                                if (plci->req_in || plci->internal_command)
 499                                        c = true;
 500                                else
 501                                {
 502                                        plci->command = msg->header.command;
 503                                        plci->number = msg->header.number;
 504                                }
 505                        }
 506                        if (c)
 507                        {
 508                                dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
 509                                                msg->header.command, plci->req_in, plci->internal_command,
 510                                                msg->header.length, plci->msg_in_write_pos,
 511                                                plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
 512                                if (j == 0)
 513                                        plci->msg_in_wrap_pos = plci->msg_in_write_pos;
 514                                m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
 515                                for (i = 0; i < msg->header.length; i++)
 516                                        ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
 517                                if (m->header.command == _DATA_B3_R)
 518                                {
 519
 520                                        m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
 521
 522                                }
 523
 524                                j = (j + 3) & 0xfffc;
 525
 526                                *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
 527                                plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
 528                                return 0;
 529                        }
 530                }
 531                else
 532                {
 533                        plci = NULL;
 534                }
 535        }
 536        dbug(1, dprintf("com=%x", msg->header.command));
 537
 538        for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
 539        for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
 540
 541                if (ftable[i].command == msg->header.command) {
 542                        /* break loop if the message is correct, otherwise continue scan  */
 543                        /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
 544                        if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
 545                                ret = 0;
 546                                break;
 547                        }
 548                        for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
 549                }
 550        }
 551        if (ret) {
 552                dbug(1, dprintf("BAD_MSG"));
 553                if (plci) plci->command = 0;
 554                return ret;
 555        }
 556
 557
 558        c = ftable[i].function(GET_DWORD(&msg->header.controller),
 559                               msg->header.number,
 560                               a,
 561                               plci,
 562                               appl,
 563                               msg_parms);
 564
 565        channel_xmit_extended_xon(plci);
 566
 567        if (c == 1) send_req(plci);
 568        if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
 569        if (plci && !plci->req_in) plci->command = 0;
 570        return 0;
 571}
 572
 573
 574/*------------------------------------------------------------------*/
 575/* api_parse function, check the format of api messages             */
 576/*------------------------------------------------------------------*/
 577
 578static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
 579{
 580        word i;
 581        word p;
 582
 583        for (i = 0, p = 0; format[i]; i++) {
 584                if (parms)
 585                {
 586                        parms[i].info = &msg[p];
 587                }
 588                switch (format[i]) {
 589                case 'b':
 590                        p += 1;
 591                        break;
 592                case 'w':
 593                        p += 2;
 594                        break;
 595                case 'd':
 596                        p += 4;
 597                        break;
 598                case 's':
 599                        if (msg[p] == 0xff) {
 600                                parms[i].info += 2;
 601                                parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
 602                                p += (parms[i].length + 3);
 603                        }
 604                        else {
 605                                parms[i].length = msg[p];
 606                                p += (parms[i].length + 1);
 607                        }
 608                        break;
 609                }
 610
 611                if (p > length) return true;
 612        }
 613        if (parms) parms[i].info = NULL;
 614        return false;
 615}
 616
 617static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
 618{
 619        word i, j, n = 0;
 620        byte *p;
 621
 622        p = out->info;
 623        for (i = 0; format[i] != '\0'; i++)
 624        {
 625                out->parms[i].info = p;
 626                out->parms[i].length = in[i].length;
 627                switch (format[i])
 628                {
 629                case 'b':
 630                        n = 1;
 631                        break;
 632                case 'w':
 633                        n = 2;
 634                        break;
 635                case 'd':
 636                        n = 4;
 637                        break;
 638                case 's':
 639                        n = in[i].length + 1;
 640                        break;
 641                }
 642                for (j = 0; j < n; j++)
 643                        *(p++) = in[i].info[j];
 644        }
 645        out->parms[i].info = NULL;
 646        out->parms[i].length = 0;
 647}
 648
 649static void api_load_msg(API_SAVE *in, API_PARSE *out)
 650{
 651        word i;
 652
 653        i = 0;
 654        do
 655        {
 656                out[i].info = in->parms[i].info;
 657                out[i].length = in->parms[i].length;
 658        } while (in->parms[i++].info);
 659}
 660
 661
 662/*------------------------------------------------------------------*/
 663/* CAPI remove function                                             */
 664/*------------------------------------------------------------------*/
 665
 666word api_remove_start(void)
 667{
 668        word i;
 669        word j;
 670
 671        if (!remove_started) {
 672                remove_started = true;
 673                for (i = 0; i < max_adapter; i++) {
 674                        if (adapter[i].request) {
 675                                for (j = 0; j < adapter[i].max_plci; j++) {
 676                                        if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
 677                                }
 678                        }
 679                }
 680                return 1;
 681        }
 682        else {
 683                for (i = 0; i < max_adapter; i++) {
 684                        if (adapter[i].request) {
 685                                for (j = 0; j < adapter[i].max_plci; j++) {
 686                                        if (adapter[i].plci[j].Sig.Id) return 1;
 687                                }
 688                        }
 689                }
 690        }
 691        api_remove_complete();
 692        return 0;
 693}
 694
 695
 696/*------------------------------------------------------------------*/
 697/* internal command queue                                           */
 698/*------------------------------------------------------------------*/
 699
 700static void init_internal_command_queue(PLCI *plci)
 701{
 702        word i;
 703
 704        dbug(1, dprintf("%s,%d: init_internal_command_queue",
 705                        (char *)(FILE_), __LINE__));
 706
 707        plci->internal_command = 0;
 708        for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
 709                plci->internal_command_queue[i] = NULL;
 710}
 711
 712
 713static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
 714{
 715        word i;
 716
 717        dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
 718                        UnMapId(Id), (char *)(FILE_), __LINE__));
 719
 720        if (plci->internal_command == 0)
 721        {
 722                plci->internal_command_queue[0] = command_function;
 723                (*command_function)(Id, plci, OK);
 724        }
 725        else
 726        {
 727                i = 1;
 728                while (plci->internal_command_queue[i] != NULL)
 729                        i++;
 730                plci->internal_command_queue[i] = command_function;
 731        }
 732}
 733
 734
 735static void next_internal_command(dword Id, PLCI *plci)
 736{
 737        word i;
 738
 739        dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
 740                        UnMapId(Id), (char *)(FILE_), __LINE__));
 741
 742        plci->internal_command = 0;
 743        plci->internal_command_queue[0] = NULL;
 744        while (plci->internal_command_queue[1] != NULL)
 745        {
 746                for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
 747                        plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
 748                plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
 749                (*(plci->internal_command_queue[0]))(Id, plci, OK);
 750                if (plci->internal_command != 0)
 751                        return;
 752                plci->internal_command_queue[0] = NULL;
 753        }
 754}
 755
 756
 757/*------------------------------------------------------------------*/
 758/* NCCI allocate/remove function                                    */
 759/*------------------------------------------------------------------*/
 760
 761static dword ncci_mapping_bug = 0;
 762
 763static word get_ncci(PLCI *plci, byte ch, word force_ncci)
 764{
 765        DIVA_CAPI_ADAPTER *a;
 766        word ncci, i, j, k;
 767
 768        a = plci->adapter;
 769        if (!ch || a->ch_ncci[ch])
 770        {
 771                ncci_mapping_bug++;
 772                dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
 773                                ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
 774                ncci = ch;
 775        }
 776        else
 777        {
 778                if (force_ncci)
 779                        ncci = force_ncci;
 780                else
 781                {
 782                        if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
 783                                ncci = ch;
 784                        else
 785                        {
 786                                ncci = 1;
 787                                while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
 788                                        ncci++;
 789                                if (ncci == MAX_NCCI + 1)
 790                                {
 791                                        ncci_mapping_bug++;
 792                                        i = 1;
 793                                        do
 794                                        {
 795                                                j = 1;
 796                                                while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
 797                                                        j++;
 798                                                k = j;
 799                                                if (j < MAX_NCCI + 1)
 800                                                {
 801                                                        do
 802                                                        {
 803                                                                j++;
 804                                                        } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
 805                                                }
 806                                        } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
 807                                        if (i < MAX_NL_CHANNEL + 1)
 808                                        {
 809                                                dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
 810                                                                ncci_mapping_bug, ch, force_ncci, i, k, j));
 811                                        }
 812                                        else
 813                                        {
 814                                                dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
 815                                                                ncci_mapping_bug, ch, force_ncci));
 816                                        }
 817                                        ncci = ch;
 818                                }
 819                        }
 820                        a->ncci_plci[ncci] = plci->Id;
 821                        a->ncci_state[ncci] = IDLE;
 822                        if (!plci->ncci_ring_list)
 823                                plci->ncci_ring_list = ncci;
 824                        else
 825                                a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
 826                        a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
 827                }
 828                a->ncci_ch[ncci] = ch;
 829                a->ch_ncci[ch] = (byte) ncci;
 830                dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
 831                                ncci_mapping_bug, ch, force_ncci, ch, ncci));
 832        }
 833        return (ncci);
 834}
 835
 836
 837static void ncci_free_receive_buffers(PLCI *plci, word ncci)
 838{
 839        DIVA_CAPI_ADAPTER *a;
 840        APPL *appl;
 841        word i, ncci_code;
 842        dword Id;
 843
 844        a = plci->adapter;
 845        Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
 846        if (ncci)
 847        {
 848                if (a->ncci_plci[ncci] == plci->Id)
 849                {
 850                        if (!plci->appl)
 851                        {
 852                                ncci_mapping_bug++;
 853                                dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
 854                                                ncci_mapping_bug, Id));
 855                        }
 856                        else
 857                        {
 858                                appl = plci->appl;
 859                                ncci_code = ncci | (((word) a->Id) << 8);
 860                                for (i = 0; i < appl->MaxBuffer; i++)
 861                                {
 862                                        if ((appl->DataNCCI[i] == ncci_code)
 863                                            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
 864                                        {
 865                                                appl->DataNCCI[i] = 0;
 866                                        }
 867                                }
 868                        }
 869                }
 870        }
 871        else
 872        {
 873                for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
 874                {
 875                        if (a->ncci_plci[ncci] == plci->Id)
 876                        {
 877                                if (!plci->appl)
 878                                {
 879                                        ncci_mapping_bug++;
 880                                        dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
 881                                                        ncci_mapping_bug, Id));
 882                                }
 883                                else
 884                                {
 885                                        appl = plci->appl;
 886                                        ncci_code = ncci | (((word) a->Id) << 8);
 887                                        for (i = 0; i < appl->MaxBuffer; i++)
 888                                        {
 889                                                if ((appl->DataNCCI[i] == ncci_code)
 890                                                    && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
 891                                                {
 892                                                        appl->DataNCCI[i] = 0;
 893                                                }
 894                                        }
 895                                }
 896                        }
 897                }
 898        }
 899}
 900
 901
 902static void cleanup_ncci_data(PLCI *plci, word ncci)
 903{
 904        NCCI *ncci_ptr;
 905
 906        if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
 907        {
 908                ncci_ptr = &(plci->adapter->ncci[ncci]);
 909                if (plci->appl)
 910                {
 911                        while (ncci_ptr->data_pending != 0)
 912                        {
 913                                if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
 914                                        TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
 915                                (ncci_ptr->data_out)++;
 916                                if (ncci_ptr->data_out == MAX_DATA_B3)
 917                                        ncci_ptr->data_out = 0;
 918                                (ncci_ptr->data_pending)--;
 919                        }
 920                }
 921                ncci_ptr->data_out = 0;
 922                ncci_ptr->data_pending = 0;
 923                ncci_ptr->data_ack_out = 0;
 924                ncci_ptr->data_ack_pending = 0;
 925        }
 926}
 927
 928
 929static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
 930{
 931        DIVA_CAPI_ADAPTER *a;
 932        dword Id;
 933        word i;
 934
 935        a = plci->adapter;
 936        Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
 937        if (!preserve_ncci)
 938                ncci_free_receive_buffers(plci, ncci);
 939        if (ncci)
 940        {
 941                if (a->ncci_plci[ncci] != plci->Id)
 942                {
 943                        ncci_mapping_bug++;
 944                        dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
 945                                        ncci_mapping_bug, Id, preserve_ncci));
 946                }
 947                else
 948                {
 949                        cleanup_ncci_data(plci, ncci);
 950                        dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
 951                                        ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
 952                        a->ch_ncci[a->ncci_ch[ncci]] = 0;
 953                        if (!preserve_ncci)
 954                        {
 955                                a->ncci_ch[ncci] = 0;
 956                                a->ncci_plci[ncci] = 0;
 957                                a->ncci_state[ncci] = IDLE;
 958                                i = plci->ncci_ring_list;
 959                                while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
 960                                        i = a->ncci_next[i];
 961                                if ((i != 0) && (a->ncci_next[i] == ncci))
 962                                {
 963                                        if (i == ncci)
 964                                                plci->ncci_ring_list = 0;
 965                                        else if (plci->ncci_ring_list == ncci)
 966                                                plci->ncci_ring_list = i;
 967                                        a->ncci_next[i] = a->ncci_next[ncci];
 968                                }
 969                                a->ncci_next[ncci] = 0;
 970                        }
 971                }
 972        }
 973        else
 974        {
 975                for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
 976                {
 977                        if (a->ncci_plci[ncci] == plci->Id)
 978                        {
 979                                cleanup_ncci_data(plci, ncci);
 980                                dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
 981                                                ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
 982                                a->ch_ncci[a->ncci_ch[ncci]] = 0;
 983                                if (!preserve_ncci)
 984                                {
 985                                        a->ncci_ch[ncci] = 0;
 986                                        a->ncci_plci[ncci] = 0;
 987                                        a->ncci_state[ncci] = IDLE;
 988                                        a->ncci_next[ncci] = 0;
 989                                }
 990                        }
 991                }
 992                if (!preserve_ncci)
 993                        plci->ncci_ring_list = 0;
 994        }
 995}
 996
 997
 998/*------------------------------------------------------------------*/
 999/* PLCI remove function                                             */
1000/*------------------------------------------------------------------*/
1001
1002static void plci_free_msg_in_queue(PLCI *plci)
1003{
1004        word i;
1005
1006        if (plci->appl)
1007        {
1008                i = plci->msg_in_read_pos;
1009                while (i != plci->msg_in_write_pos)
1010                {
1011                        if (i == plci->msg_in_wrap_pos)
1012                                i = 0;
1013                        if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1014                        {
1015
1016                                TransmitBufferFree(plci->appl,
1017                                                   (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1018
1019                        }
1020
1021                        i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1022                              MSG_IN_OVERHEAD + 3) & 0xfffc;
1023
1024                }
1025        }
1026        plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1027        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1028        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1029}
1030
1031
1032static void plci_remove(PLCI *plci)
1033{
1034
1035        if (!plci) {
1036                dbug(1, dprintf("plci_remove(no plci)"));
1037                return;
1038        }
1039        init_internal_command_queue(plci);
1040        dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1041        if (plci_remove_check(plci))
1042        {
1043                return;
1044        }
1045        if (plci->Sig.Id == 0xff)
1046        {
1047                dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1048                if (plci->NL.Id && !plci->nl_remove_id)
1049                {
1050                        nl_req_ncci(plci, REMOVE, 0);
1051                        send_req(plci);
1052                }
1053        }
1054        else
1055        {
1056                if (!plci->sig_remove_id
1057                    && (plci->Sig.Id
1058                        || (plci->req_in != plci->req_out)
1059                        || (plci->nl_req || plci->sig_req)))
1060                {
1061                        sig_req(plci, HANGUP, 0);
1062                        send_req(plci);
1063                }
1064        }
1065        ncci_remove(plci, 0, false);
1066        plci_free_msg_in_queue(plci);
1067
1068        plci->channels = 0;
1069        plci->appl = NULL;
1070        if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1071                plci->State = OUTG_DIS_PENDING;
1072}
1073
1074/*------------------------------------------------------------------*/
1075/* translation function for each message                            */
1076/*------------------------------------------------------------------*/
1077
1078static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1079                        PLCI *plci, APPL *appl, API_PARSE *parms)
1080{
1081        word ch;
1082        word i;
1083        word Info;
1084        byte LinkLayer;
1085        API_PARSE *ai;
1086        API_PARSE *bp;
1087        API_PARSE ai_parms[5];
1088        word channel = 0;
1089        dword ch_mask;
1090        byte m;
1091        static byte esc_chi[35] = {0x02, 0x18, 0x01};
1092        static byte lli[2] = {0x01, 0x00};
1093        byte noCh = 0;
1094        word dir = 0;
1095        byte *p_chi = "";
1096
1097        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1098
1099        dbug(1, dprintf("connect_req(%d)", parms->length));
1100        Info = _WRONG_IDENTIFIER;
1101        if (a)
1102        {
1103                if (a->adapter_disabled)
1104                {
1105                        dbug(1, dprintf("adapter disabled"));
1106                        Id = ((word)1 << 8) | a->Id;
1107                        sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1108                        sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1109                        return false;
1110                }
1111                Info = _OUT_OF_PLCI;
1112                if ((i = get_plci(a)))
1113                {
1114                        Info = 0;
1115                        plci = &a->plci[i - 1];
1116                        plci->appl = appl;
1117                        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1118                        /* check 'external controller' bit for codec support */
1119                        if (Id & EXT_CONTROLLER)
1120                        {
1121                                if (AdvCodecSupport(a, plci, appl, 0))
1122                                {
1123                                        plci->Id = 0;
1124                                        sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1125                                        return 2;
1126                                }
1127                        }
1128                        ai = &parms[9];
1129                        bp = &parms[5];
1130                        ch = 0;
1131                        if (bp->length)LinkLayer = bp->info[3];
1132                        else LinkLayer = 0;
1133                        if (ai->length)
1134                        {
1135                                ch = 0xffff;
1136                                if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1137                                {
1138                                        ch = 0;
1139                                        if (ai_parms[0].length)
1140                                        {
1141                                                ch = GET_WORD(ai_parms[0].info + 1);
1142                                                if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1143                                                if (ch == 4) /* explizit CHI in message */
1144                                                {
1145                                                        /* check length of B-CH struct */
1146                                                        if ((ai_parms[0].info)[3] >= 1)
1147                                                        {
1148                                                                if ((ai_parms[0].info)[4] == CHI)
1149                                                                {
1150                                                                        p_chi = &((ai_parms[0].info)[5]);
1151                                                                }
1152                                                                else
1153                                                                {
1154                                                                        p_chi = &((ai_parms[0].info)[3]);
1155                                                                }
1156                                                                if (p_chi[0] > 35) /* check length of channel ID */
1157                                                                {
1158                                                                        Info = _WRONG_MESSAGE_FORMAT;
1159                                                                }
1160                                                        }
1161                                                        else Info = _WRONG_MESSAGE_FORMAT;
1162                                                }
1163
1164                                                if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1165                                                {
1166                                                        dir = GET_WORD(ai_parms[0].info + 3);
1167                                                        ch_mask = 0;
1168                                                        m = 0x3f;
1169                                                        for (i = 0; i + 5 <= ai_parms[0].length; i++)
1170                                                        {
1171                                                                if (ai_parms[0].info[i + 5] != 0)
1172                                                                {
1173                                                                        if ((ai_parms[0].info[i + 5] | m) != 0xff)
1174                                                                                Info = _WRONG_MESSAGE_FORMAT;
1175                                                                        else
1176                                                                        {
1177                                                                                if (ch_mask == 0)
1178                                                                                        channel = i;
1179                                                                                ch_mask |= 1L << i;
1180                                                                        }
1181                                                                }
1182                                                                m = 0;
1183                                                        }
1184                                                        if (ch_mask == 0)
1185                                                                Info = _WRONG_MESSAGE_FORMAT;
1186                                                        if (!Info)
1187                                                        {
1188                                                                if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1189                                                                {
1190                                                                        esc_chi[0] = (byte)(ai_parms[0].length - 2);
1191                                                                        for (i = 0; i + 5 <= ai_parms[0].length; i++)
1192                                                                                esc_chi[i + 3] = ai_parms[0].info[i + 5];
1193                                                                }
1194                                                                else
1195                                                                        esc_chi[0] = 2;
1196                                                                esc_chi[2] = (byte)channel;
1197                                                                plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1198                                                                add_p(plci, LLI, lli);
1199                                                                add_p(plci, ESC, esc_chi);
1200                                                                plci->State = LOCAL_CONNECT;
1201                                                                if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1202                                                        }
1203                                                }
1204                                        }
1205                                }
1206                                else  Info = _WRONG_MESSAGE_FORMAT;
1207                        }
1208
1209                        dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1210                        plci->command = _CONNECT_R;
1211                        plci->number = Number;
1212                        /* x.31 or D-ch free SAPI in LinkLayer? */
1213                        if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1214                        if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1215                        {
1216                                /* B-channel used for B3 connections (ch==0), or no B channel    */
1217                                /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1218                                if (noCh) Info = add_b1(plci, &parms[5], 2, 0);    /* no resource    */
1219                                else     Info = add_b1(plci, &parms[5], ch, 0);
1220                                add_s(plci, OAD, &parms[2]);
1221                                add_s(plci, OSA, &parms[4]);
1222                                add_s(plci, BC, &parms[6]);
1223                                add_s(plci, LLC, &parms[7]);
1224                                add_s(plci, HLC, &parms[8]);
1225                                if (a->Info_Mask[appl->Id - 1] & 0x200)
1226                                {
1227                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
1228                                        add_p(plci, LLI, "\x01\x01");
1229                                }
1230                                if (GET_WORD(parms[0].info) < 29) {
1231                                        add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1232                                        add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1233                                }
1234                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1235                                sig_req(plci, ASSIGN, DSIG_ID);
1236                        }
1237                        else if (ch == 1) {
1238
1239                                /* D-Channel used for B3 connections */
1240                                plci->Sig.Id = 0xff;
1241                                Info = 0;
1242                        }
1243
1244                        if (!Info && ch != 2 && !noCh) {
1245                                Info = add_b23(plci, &parms[5]);
1246                                if (!Info) {
1247                                        if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1248                                }
1249                        }
1250
1251                        if (!Info)
1252                        {
1253                                if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1254                                {
1255                                        if (plci->spoofed_msg == SPOOFING_REQUIRED)
1256                                        {
1257                                                api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1258                                                plci->spoofed_msg = CALL_REQ;
1259                                                plci->internal_command = BLOCK_PLCI;
1260                                                plci->command = 0;
1261                                                dbug(1, dprintf("Spoof"));
1262                                                send_req(plci);
1263                                                return false;
1264                                        }
1265                                        if (ch == 4)add_p(plci, CHI, p_chi);
1266                                        add_s(plci, CPN, &parms[1]);
1267                                        add_s(plci, DSA, &parms[3]);
1268                                        if (noCh) add_p(plci, ESC, "\x02\x18\xfd");  /* D-channel, no B-L3 */
1269                                        add_ai(plci, &parms[9]);
1270                                        if (!dir)sig_req(plci, CALL_REQ, 0);
1271                                        else
1272                                        {
1273                                                plci->command = PERM_LIST_REQ;
1274                                                plci->appl = appl;
1275                                                sig_req(plci, LISTEN_REQ, 0);
1276                                                send_req(plci);
1277                                                return false;
1278                                        }
1279                                }
1280                                send_req(plci);
1281                                return false;
1282                        }
1283                        plci->Id = 0;
1284                }
1285        }
1286        sendf(appl,
1287              _CONNECT_R | CONFIRM,
1288              Id,
1289              Number,
1290              "w", Info);
1291        return 2;
1292}
1293
1294static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1295                        PLCI *plci, APPL *appl, API_PARSE *parms)
1296{
1297        word i, Info;
1298        word Reject;
1299        static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1300        static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1301        API_PARSE *ai;
1302        API_PARSE ai_parms[5];
1303        word ch = 0;
1304
1305        if (!plci) {
1306                dbug(1, dprintf("connect_res(no plci)"));
1307                return 0;  /* no plci, no send */
1308        }
1309
1310        dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1311        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1312        ai = &parms[5];
1313        dbug(1, dprintf("ai->length=%d", ai->length));
1314
1315        if (ai->length)
1316        {
1317                if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1318                {
1319                        dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1320                        ch = 0;
1321                        if (ai_parms[0].length)
1322                        {
1323                                ch = GET_WORD(ai_parms[0].info + 1);
1324                                dbug(1, dprintf("BCH-I=0x%x", ch));
1325                        }
1326                }
1327        }
1328
1329        if (plci->State == INC_CON_CONNECTED_ALERT)
1330        {
1331                dbug(1, dprintf("Connected Alert Call_Res"));
1332                if (a->Info_Mask[appl->Id - 1] & 0x200)
1333                {
1334                        /* early B3 connect (CIP mask bit 9) no release after a disc */
1335                        add_p(plci, LLI, "\x01\x01");
1336                }
1337                add_s(plci, CONN_NR, &parms[2]);
1338                add_s(plci, LLC, &parms[4]);
1339                add_ai(plci, &parms[5]);
1340                plci->State = INC_CON_ACCEPT;
1341                sig_req(plci, CALL_RES, 0);
1342                return 1;
1343        }
1344        else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1345                __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1346                dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
1347                Reject = GET_WORD(parms[0].info);
1348                dbug(1, dprintf("Reject=0x%x", Reject));
1349                if (Reject)
1350                {
1351                        if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
1352                        {
1353                                if ((Reject & 0xff00) == 0x3400)
1354                                {
1355                                        esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1356                                        add_p(plci, ESC, esc_t);
1357                                        add_ai(plci, &parms[5]);
1358                                        sig_req(plci, REJECT, 0);
1359                                }
1360                                else if (Reject == 1 || Reject >= 9)
1361                                {
1362                                        add_ai(plci, &parms[5]);
1363                                        sig_req(plci, HANGUP, 0);
1364                                }
1365                                else
1366                                {
1367                                        esc_t[2] = cau_t[(Reject&0x000f)];
1368                                        add_p(plci, ESC, esc_t);
1369                                        add_ai(plci, &parms[5]);
1370                                        sig_req(plci, REJECT, 0);
1371                                }
1372                                plci->appl = appl;
1373                        }
1374                        else
1375                        {
1376                                sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1377                        }
1378                }
1379                else {
1380                        plci->appl = appl;
1381                        if (Id & EXT_CONTROLLER) {
1382                                if (AdvCodecSupport(a, plci, appl, 0)) {
1383                                        dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1384                                        sig_req(plci, HANGUP, 0);
1385                                        return 1;
1386                                }
1387                                if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1388                                {
1389                                        Info = add_b23(plci, &parms[1]);
1390                                        if (Info)
1391                                        {
1392                                                dbug(1, dprintf("connect_res(error from add_b23)"));
1393                                                sig_req(plci, HANGUP, 0);
1394                                                return 1;
1395                                        }
1396                                        if (plci->adv_nl)
1397                                        {
1398                                                nl_req_ncci(plci, ASSIGN, 0);
1399                                        }
1400                                }
1401                        }
1402                        else
1403                        {
1404                                plci->tel = 0;
1405                                if (ch != 2)
1406                                {
1407                                        Info = add_b23(plci, &parms[1]);
1408                                        if (Info)
1409                                        {
1410                                                dbug(1, dprintf("connect_res(error from add_b23 2)"));
1411                                                sig_req(plci, HANGUP, 0);
1412                                                return 1;
1413                                        }
1414                                }
1415                                nl_req_ncci(plci, ASSIGN, 0);
1416                        }
1417
1418                        if (plci->spoofed_msg == SPOOFING_REQUIRED)
1419                        {
1420                                api_save_msg(parms, "wsssss", &plci->saved_msg);
1421                                plci->spoofed_msg = CALL_RES;
1422                                plci->internal_command = BLOCK_PLCI;
1423                                plci->command = 0;
1424                                dbug(1, dprintf("Spoof"));
1425                        }
1426                        else
1427                        {
1428                                add_b1(plci, &parms[1], ch, plci->B1_facilities);
1429                                if (a->Info_Mask[appl->Id - 1] & 0x200)
1430                                {
1431                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
1432                                        add_p(plci, LLI, "\x01\x01");
1433                                }
1434                                add_s(plci, CONN_NR, &parms[2]);
1435                                add_s(plci, LLC, &parms[4]);
1436                                add_ai(plci, &parms[5]);
1437                                plci->State = INC_CON_ACCEPT;
1438                                sig_req(plci, CALL_RES, 0);
1439                        }
1440
1441                        for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1442                                sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1443                }
1444        }
1445        return 1;
1446}
1447
1448static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1449                          PLCI *plci, APPL *appl, API_PARSE *msg)
1450{
1451        dbug(1, dprintf("connect_a_res"));
1452        return false;
1453}
1454
1455static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1456                           PLCI *plci, APPL *appl, API_PARSE *msg)
1457{
1458        word Info;
1459        word i;
1460
1461        dbug(1, dprintf("disconnect_req"));
1462
1463        Info = _WRONG_IDENTIFIER;
1464
1465        if (plci)
1466        {
1467                if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1468                {
1469                        __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1470                        plci->appl = appl;
1471                        for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1472                                sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1473                        plci->State = OUTG_DIS_PENDING;
1474                }
1475                if (plci->Sig.Id && plci->appl)
1476                {
1477                        Info = 0;
1478                        if (plci->Sig.Id != 0xff)
1479                        {
1480                                if (plci->State != INC_DIS_PENDING)
1481                                {
1482                                        add_ai(plci, &msg[0]);
1483                                        sig_req(plci, HANGUP, 0);
1484                                        plci->State = OUTG_DIS_PENDING;
1485                                        return 1;
1486                                }
1487                        }
1488                        else
1489                        {
1490                                if (plci->NL.Id && !plci->nl_remove_id)
1491                                {
1492                                        mixer_remove(plci);
1493                                        nl_req_ncci(plci, REMOVE, 0);
1494                                        sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1495                                        sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1496                                        plci->State = INC_DIS_PENDING;
1497                                }
1498                                return 1;
1499                        }
1500                }
1501        }
1502
1503        if (!appl)  return false;
1504        sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1505        return false;
1506}
1507
1508static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1509                           PLCI *plci, APPL *appl, API_PARSE *msg)
1510{
1511        dbug(1, dprintf("disconnect_res"));
1512        if (plci)
1513        {
1514                /* clear ind mask bit, just in case of collsion of          */
1515                /* DISCONNECT_IND and CONNECT_RES                           */
1516                __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1517                ncci_free_receive_buffers(plci, 0);
1518                if (plci_remove_check(plci))
1519                {
1520                        return 0;
1521                }
1522                if (plci->State == INC_DIS_PENDING
1523                    || plci->State == SUSPENDING) {
1524                        if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
1525                                if (plci->State != SUSPENDING) plci->State = IDLE;
1526                                dbug(1, dprintf("chs=%d", plci->channels));
1527                                if (!plci->channels) {
1528                                        plci_remove(plci);
1529                                }
1530                        }
1531                }
1532        }
1533        return 0;
1534}
1535
1536static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1537                       PLCI *plci, APPL *appl, API_PARSE *parms)
1538{
1539        word Info;
1540        byte i;
1541
1542        dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1543
1544        Info = _WRONG_IDENTIFIER;
1545        if (a) {
1546                Info = 0;
1547                a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1548                a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1549                dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1550                if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1551                        a->Info_Mask[appl->Id - 1] |=  0x10;   /* call progression infos    */
1552                }
1553
1554                /* check if external controller listen and switch listen on or off*/
1555                if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1556                        if (a->profile.Global_Options & ON_BOARD_CODEC) {
1557                                dummy_plci.State = IDLE;
1558                                a->codec_listen[appl->Id - 1] = &dummy_plci;
1559                                a->TelOAD[0] = (byte)(parms[3].length);
1560                                for (i = 1; parms[3].length >= i && i < 22; i++) {
1561                                        a->TelOAD[i] = parms[3].info[i];
1562                                }
1563                                a->TelOAD[i] = 0;
1564                                a->TelOSA[0] = (byte)(parms[4].length);
1565                                for (i = 1; parms[4].length >= i && i < 22; i++) {
1566                                        a->TelOSA[i] = parms[4].info[i];
1567                                }
1568                                a->TelOSA[i] = 0;
1569                        }
1570                        else Info = 0x2002; /* wrong controller, codec not supported */
1571                }
1572                else{               /* clear listen */
1573                        a->codec_listen[appl->Id - 1] = (PLCI *)0;
1574                }
1575        }
1576        sendf(appl,
1577              _LISTEN_R | CONFIRM,
1578              Id,
1579              Number,
1580              "w", Info);
1581
1582        if (a) listen_check(a);
1583        return false;
1584}
1585
1586static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1587                     PLCI *plci, APPL *appl, API_PARSE *msg)
1588{
1589        word i;
1590        API_PARSE *ai;
1591        PLCI *rc_plci = NULL;
1592        API_PARSE ai_parms[5];
1593        word Info = 0;
1594
1595        dbug(1, dprintf("info_req"));
1596        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1597
1598        ai = &msg[1];
1599
1600        if (ai->length)
1601        {
1602                if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1603                {
1604                        dbug(1, dprintf("AddInfo wrong"));
1605                        Info = _WRONG_MESSAGE_FORMAT;
1606                }
1607        }
1608        if (!a) Info = _WRONG_STATE;
1609
1610        if (!Info && plci)
1611        {                /* no fac, with CPN, or KEY */
1612                rc_plci = plci;
1613                if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1614                {
1615                        /* overlap sending option */
1616                        dbug(1, dprintf("OvlSnd"));
1617                        add_s(plci, CPN, &msg[0]);
1618                        add_s(plci, KEY, &ai_parms[1]);
1619                        sig_req(plci, INFO_REQ, 0);
1620                        send_req(plci);
1621                        return false;
1622                }
1623
1624                if (plci->State && ai_parms[2].length)
1625                {
1626                        /* User_Info option */
1627                        dbug(1, dprintf("UUI"));
1628                        add_s(plci, UUI, &ai_parms[2]);
1629                        sig_req(plci, USER_DATA, 0);
1630                }
1631                else if (plci->State && ai_parms[3].length)
1632                {
1633                        /* Facility option */
1634                        dbug(1, dprintf("FAC"));
1635                        add_s(plci, CPN, &msg[0]);
1636                        add_ai(plci, &msg[1]);
1637                        sig_req(plci, FACILITY_REQ, 0);
1638                }
1639                else
1640                {
1641                        Info = _WRONG_STATE;
1642                }
1643        }
1644        else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1645        {
1646                /* NCR_Facility option -> send UUI and Keypad too */
1647                dbug(1, dprintf("NCR_FAC"));
1648                if ((i = get_plci(a)))
1649                {
1650                        rc_plci = &a->plci[i - 1];
1651                        appl->NullCREnable = true;
1652                        rc_plci->internal_command = C_NCR_FAC_REQ;
1653                        rc_plci->appl = appl;
1654                        add_p(rc_plci, CAI, "\x01\x80");
1655                        add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1656                        sig_req(rc_plci, ASSIGN, DSIG_ID);
1657                        send_req(rc_plci);
1658                }
1659                else
1660                {
1661                        Info = _OUT_OF_PLCI;
1662                }
1663
1664                if (!Info)
1665                {
1666                        add_s(rc_plci, CPN, &msg[0]);
1667                        add_ai(rc_plci, &msg[1]);
1668                        sig_req(rc_plci, NCR_FACILITY, 0);
1669                        send_req(rc_plci);
1670                        return false;
1671                        /* for application controlled supplementary services    */
1672                }
1673        }
1674
1675        if (!rc_plci)
1676        {
1677                Info = _WRONG_MESSAGE_FORMAT;
1678        }
1679
1680        if (!Info)
1681        {
1682                send_req(rc_plci);
1683        }
1684        else
1685        {  /* appl is not assigned to a PLCI or error condition */
1686                dbug(1, dprintf("localInfoCon"));
1687                sendf(appl,
1688                      _INFO_R | CONFIRM,
1689                      Id,
1690                      Number,
1691                      "w", Info);
1692        }
1693        return false;
1694}
1695
1696static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1697                     PLCI *plci, APPL *appl, API_PARSE *msg)
1698{
1699        dbug(1, dprintf("info_res"));
1700        return false;
1701}
1702
1703static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1704                      PLCI *plci, APPL *appl, API_PARSE *msg)
1705{
1706        word Info;
1707        byte ret;
1708
1709        dbug(1, dprintf("alert_req"));
1710
1711        Info = _WRONG_IDENTIFIER;
1712        ret = false;
1713        if (plci) {
1714                Info = _ALERT_IGNORED;
1715                if (plci->State != INC_CON_ALERT) {
1716                        Info = _WRONG_STATE;
1717                        if (plci->State == INC_CON_PENDING) {
1718                                Info = 0;
1719                                plci->State = INC_CON_ALERT;
1720                                add_ai(plci, &msg[0]);
1721                                sig_req(plci, CALL_ALERT, 0);
1722                                ret = 1;
1723                        }
1724                }
1725        }
1726        sendf(appl,
1727              _ALERT_R | CONFIRM,
1728              Id,
1729              Number,
1730              "w", Info);
1731        return ret;
1732}
1733
1734static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1735                         PLCI *plci, APPL *appl, API_PARSE *msg)
1736{
1737        word Info = 0;
1738        word i    = 0;
1739
1740        word selector;
1741        word SSreq;
1742        long relatedPLCIvalue;
1743        DIVA_CAPI_ADAPTER *relatedadapter;
1744        byte *SSparms  = "";
1745        byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1746        byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1747        API_PARSE *parms;
1748        API_PARSE ss_parms[11];
1749        PLCI *rplci;
1750        byte cai[15];
1751        dword d;
1752        API_PARSE dummy;
1753
1754        dbug(1, dprintf("facility_req"));
1755        for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1756
1757        parms = &msg[1];
1758
1759        if (!a)
1760        {
1761                dbug(1, dprintf("wrong Ctrl"));
1762                Info = _WRONG_IDENTIFIER;
1763        }
1764
1765        selector = GET_WORD(msg[0].info);
1766
1767        if (!Info)
1768        {
1769                switch (selector)
1770                {
1771                case SELECTOR_HANDSET:
1772                        Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1773                        break;
1774
1775                case SELECTOR_SU_SERV:
1776                        if (!msg[1].length)
1777                        {
1778                                Info = _WRONG_MESSAGE_FORMAT;
1779                                break;
1780                        }
1781                        SSreq = GET_WORD(&(msg[1].info[1]));
1782                        PUT_WORD(&RCparms[1], SSreq);
1783                        SSparms = RCparms;
1784                        switch (SSreq)
1785                        {
1786                        case S_GET_SUPPORTED_SERVICES:
1787                                if ((i = get_plci(a)))
1788                                {
1789                                        rplci = &a->plci[i - 1];
1790                                        rplci->appl = appl;
1791                                        add_p(rplci, CAI, "\x01\x80");
1792                                        add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1793                                        sig_req(rplci, ASSIGN, DSIG_ID);
1794                                        send_req(rplci);
1795                                }
1796                                else
1797                                {
1798                                        PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1799                                        SSparms = (byte *)SSstruct;
1800                                        break;
1801                                }
1802                                rplci->internal_command = GETSERV_REQ_PEND;
1803                                rplci->number = Number;
1804                                rplci->appl = appl;
1805                                sig_req(rplci, S_SUPPORTED, 0);
1806                                send_req(rplci);
1807                                return false;
1808                                break;
1809
1810                        case S_LISTEN:
1811                                if (parms->length == 7)
1812                                {
1813                                        if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1814                                        {
1815                                                dbug(1, dprintf("format wrong"));
1816                                                Info = _WRONG_MESSAGE_FORMAT;
1817                                                break;
1818                                        }
1819                                }
1820                                else
1821                                {
1822                                        Info = _WRONG_MESSAGE_FORMAT;
1823                                        break;
1824                                }
1825                                a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1826                                if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1827                                {
1828                                        if ((i = get_plci(a)))
1829                                        {
1830                                                rplci = &a->plci[i - 1];
1831                                                rplci->appl = appl;
1832                                                add_p(rplci, CAI, "\x01\x80");
1833                                                add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1834                                                sig_req(rplci, ASSIGN, DSIG_ID);
1835                                                send_req(rplci);
1836                                        }
1837                                        else
1838                                        {
1839                                                break;
1840                                        }
1841                                        rplci->internal_command = GET_MWI_STATE;
1842                                        rplci->number = Number;
1843                                        sig_req(rplci, MWI_POLL, 0);
1844                                        send_req(rplci);
1845                                }
1846                                break;
1847
1848                        case S_HOLD:
1849                                api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1850                                if (plci && plci->State && plci->SuppState == IDLE)
1851                                {
1852                                        plci->SuppState = HOLD_REQUEST;
1853                                        plci->command = C_HOLD_REQ;
1854                                        add_s(plci, CAI, &ss_parms[1]);
1855                                        sig_req(plci, CALL_HOLD, 0);
1856                                        send_req(plci);
1857                                        return false;
1858                                }
1859                                else Info = 0x3010;                    /* wrong state           */
1860                                break;
1861                        case S_RETRIEVE:
1862                                if (plci && plci->State && plci->SuppState == CALL_HELD)
1863                                {
1864                                        if (Id & EXT_CONTROLLER)
1865                                        {
1866                                                if (AdvCodecSupport(a, plci, appl, 0))
1867                                                {
1868                                                        Info = 0x3010;                    /* wrong state           */
1869                                                        break;
1870                                                }
1871                                        }
1872                                        else plci->tel = 0;
1873
1874                                        plci->SuppState = RETRIEVE_REQUEST;
1875                                        plci->command = C_RETRIEVE_REQ;
1876                                        if (plci->spoofed_msg == SPOOFING_REQUIRED)
1877                                        {
1878                                                plci->spoofed_msg = CALL_RETRIEVE;
1879                                                plci->internal_command = BLOCK_PLCI;
1880                                                plci->command = 0;
1881                                                dbug(1, dprintf("Spoof"));
1882                                                return false;
1883                                        }
1884                                        else
1885                                        {
1886                                                sig_req(plci, CALL_RETRIEVE, 0);
1887                                                send_req(plci);
1888                                                return false;
1889                                        }
1890                                }
1891                                else Info = 0x3010;                    /* wrong state           */
1892                                break;
1893                        case S_SUSPEND:
1894                                if (parms->length)
1895                                {
1896                                        if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1897                                        {
1898                                                dbug(1, dprintf("format wrong"));
1899                                                Info = _WRONG_MESSAGE_FORMAT;
1900                                                break;
1901                                        }
1902                                }
1903                                if (plci && plci->State)
1904                                {
1905                                        add_s(plci, CAI, &ss_parms[2]);
1906                                        plci->command = SUSPEND_REQ;
1907                                        sig_req(plci, SUSPEND, 0);
1908                                        plci->State = SUSPENDING;
1909                                        send_req(plci);
1910                                }
1911                                else Info = 0x3010;                    /* wrong state           */
1912                                break;
1913
1914                        case S_RESUME:
1915                                if (!(i = get_plci(a)))
1916                                {
1917                                        Info = _OUT_OF_PLCI;
1918                                        break;
1919                                }
1920                                rplci = &a->plci[i - 1];
1921                                rplci->appl = appl;
1922                                rplci->number = Number;
1923                                rplci->tel = 0;
1924                                rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1925                                /* check 'external controller' bit for codec support */
1926                                if (Id & EXT_CONTROLLER)
1927                                {
1928                                        if (AdvCodecSupport(a, rplci, appl, 0))
1929                                        {
1930                                                rplci->Id = 0;
1931                                                Info = 0x300A;
1932                                                break;
1933                                        }
1934                                }
1935                                if (parms->length)
1936                                {
1937                                        if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1938                                        {
1939                                                dbug(1, dprintf("format wrong"));
1940                                                rplci->Id = 0;
1941                                                Info = _WRONG_MESSAGE_FORMAT;
1942                                                break;
1943                                        }
1944                                }
1945                                dummy.length = 0;
1946                                dummy.info = "\x00";
1947                                add_b1(rplci, &dummy, 0, 0);
1948                                if (a->Info_Mask[appl->Id - 1] & 0x200)
1949                                {
1950                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
1951                                        add_p(rplci, LLI, "\x01\x01");
1952                                }
1953                                add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1954                                sig_req(rplci, ASSIGN, DSIG_ID);
1955                                send_req(rplci);
1956                                add_s(rplci, CAI, &ss_parms[2]);
1957                                rplci->command = RESUME_REQ;
1958                                sig_req(rplci, RESUME, 0);
1959                                rplci->State = RESUMING;
1960                                send_req(rplci);
1961                                break;
1962
1963                        case S_CONF_BEGIN: /* Request */
1964                        case S_CONF_DROP:
1965                        case S_CONF_ISOLATE:
1966                        case S_CONF_REATTACH:
1967                                if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1968                                {
1969                                        dbug(1, dprintf("format wrong"));
1970                                        Info = _WRONG_MESSAGE_FORMAT;
1971                                        break;
1972                                }
1973                                if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
1974                                {
1975                                        d = GET_DWORD(ss_parms[2].info);
1976                                        if (d >= 0x80)
1977                                        {
1978                                                dbug(1, dprintf("format wrong"));
1979                                                Info = _WRONG_MESSAGE_FORMAT;
1980                                                break;
1981                                        }
1982                                        plci->ptyState = (byte)SSreq;
1983                                        plci->command = 0;
1984                                        cai[0] = 2;
1985                                        switch (SSreq)
1986                                        {
1987                                        case S_CONF_BEGIN:
1988                                                cai[1] = CONF_BEGIN;
1989                                                plci->internal_command = CONF_BEGIN_REQ_PEND;
1990                                                break;
1991                                        case S_CONF_DROP:
1992                                                cai[1] = CONF_DROP;
1993                                                plci->internal_command = CONF_DROP_REQ_PEND;
1994                                                break;
1995                                        case S_CONF_ISOLATE:
1996                                                cai[1] = CONF_ISOLATE;
1997                                                plci->internal_command = CONF_ISOLATE_REQ_PEND;
1998                                                break;
1999                                        case S_CONF_REATTACH:
2000                                                cai[1] = CONF_REATTACH;
2001                                                plci->internal_command = CONF_REATTACH_REQ_PEND;
2002                                                break;
2003                                        }
2004                                        cai[2] = (byte)d; /* Conference Size resp. PartyId */
2005                                        add_p(plci, CAI, cai);
2006                                        sig_req(plci, S_SERVICE, 0);
2007                                        send_req(plci);
2008                                        return false;
2009                                }
2010                                else Info = 0x3010;                    /* wrong state           */
2011                                break;
2012
2013                        case S_ECT:
2014                        case S_3PTY_BEGIN:
2015                        case S_3PTY_END:
2016                        case S_CONF_ADD:
2017                                if (parms->length == 7)
2018                                {
2019                                        if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2020                                        {
2021                                                dbug(1, dprintf("format wrong"));
2022                                                Info = _WRONG_MESSAGE_FORMAT;
2023                                                break;
2024                                        }
2025                                }
2026                                else if (parms->length == 8) /* workaround for the T-View-S */
2027                                {
2028                                        if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2029                                        {
2030                                                dbug(1, dprintf("format wrong"));
2031                                                Info = _WRONG_MESSAGE_FORMAT;
2032                                                break;
2033                                        }
2034                                }
2035                                else
2036                                {
2037                                        Info = _WRONG_MESSAGE_FORMAT;
2038                                        break;
2039                                }
2040                                if (!msg[1].length)
2041                                {
2042                                        Info = _WRONG_MESSAGE_FORMAT;
2043                                        break;
2044                                }
2045                                if (!plci)
2046                                {
2047                                        Info = _WRONG_IDENTIFIER;
2048                                        break;
2049                                }
2050                                relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2051                                relatedPLCIvalue &= 0x0000FFFF;
2052                                dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2053                                /* controller starts with 0 up to (max_adapter - 1) */
2054                                if (((relatedPLCIvalue & 0x7f) == 0)
2055                                    || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2056                                    || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2057                                {
2058                                        if (SSreq == S_3PTY_END)
2059                                        {
2060                                                dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2061                                                rplci = plci;
2062                                        }
2063                                        else
2064                                        {
2065                                                Info = 0x3010;                    /* wrong state           */
2066                                                break;
2067                                        }
2068                                }
2069                                else
2070                                {
2071                                        relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2072                                        relatedPLCIvalue >>= 8;
2073                                        /* find PLCI PTR*/
2074                                        for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2075                                        {
2076                                                if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2077                                                {
2078                                                        rplci = &relatedadapter->plci[i];
2079                                                }
2080                                        }
2081                                        if (!rplci || !relatedPLCIvalue)
2082                                        {
2083                                                if (SSreq == S_3PTY_END)
2084                                                {
2085                                                        dbug(1, dprintf("use 2nd PLCI=PLCI"));
2086                                                        rplci = plci;
2087                                                }
2088                                                else
2089                                                {
2090                                                        Info = 0x3010;                    /* wrong state           */
2091                                                        break;
2092                                                }
2093                                        }
2094                                }
2095/*
2096  dbug(1, dprintf("rplci:%x", rplci));
2097  dbug(1, dprintf("plci:%x", plci));
2098  dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2099  dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2100  dbug(1, dprintf("SSreq:%x", SSreq));
2101  dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2102  dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2103  dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2104*/
2105                                /* send PTY/ECT req, cannot check all states because of US stuff */
2106                                if (!rplci->internal_command && rplci->appl)
2107                                {
2108                                        plci->command = 0;
2109                                        rplci->relatedPTYPLCI = plci;
2110                                        plci->relatedPTYPLCI = rplci;
2111                                        rplci->ptyState = (byte)SSreq;
2112                                        if (SSreq == S_ECT)
2113                                        {
2114                                                rplci->internal_command = ECT_REQ_PEND;
2115                                                cai[1] = ECT_EXECUTE;
2116
2117                                                rplci->vswitchstate = 0;
2118                                                rplci->vsprot = 0;
2119                                                rplci->vsprotdialect = 0;
2120                                                plci->vswitchstate = 0;
2121                                                plci->vsprot = 0;
2122                                                plci->vsprotdialect = 0;
2123
2124                                        }
2125                                        else if (SSreq == S_CONF_ADD)
2126                                        {
2127                                                rplci->internal_command = CONF_ADD_REQ_PEND;
2128                                                cai[1] = CONF_ADD;
2129                                        }
2130                                        else
2131                                        {
2132                                                rplci->internal_command = PTY_REQ_PEND;
2133                                                cai[1] = (byte)(SSreq - 3);
2134                                        }
2135                                        rplci->number = Number;
2136                                        if (plci != rplci) /* explicit invocation */
2137                                        {
2138                                                cai[0] = 2;
2139                                                cai[2] = plci->Sig.Id;
2140                                                dbug(1, dprintf("explicit invocation"));
2141                                        }
2142                                        else
2143                                        {
2144                                                dbug(1, dprintf("implicit invocation"));
2145                                                cai[0] = 1;
2146                                        }
2147                                        add_p(rplci, CAI, cai);
2148                                        sig_req(rplci, S_SERVICE, 0);
2149                                        send_req(rplci);
2150                                        return false;
2151                                }
2152                                else
2153                                {
2154                                        dbug(0, dprintf("Wrong line"));
2155                                        Info = 0x3010;                    /* wrong state           */
2156                                        break;
2157                                }
2158                                break;
2159
2160                        case S_CALL_DEFLECTION:
2161                                if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2162                                {
2163                                        dbug(1, dprintf("format wrong"));
2164                                        Info = _WRONG_MESSAGE_FORMAT;
2165                                        break;
2166                                }
2167                                if (!plci)
2168                                {
2169                                        Info = _WRONG_IDENTIFIER;
2170                                        break;
2171                                }
2172                                /* reuse unused screening indicator */
2173                                ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2174                                plci->command = 0;
2175                                plci->internal_command = CD_REQ_PEND;
2176                                appl->CDEnable = true;
2177                                cai[0] = 1;
2178                                cai[1] = CALL_DEFLECTION;
2179                                add_p(plci, CAI, cai);
2180                                add_p(plci, CPN, ss_parms[3].info);
2181                                sig_req(plci, S_SERVICE, 0);
2182                                send_req(plci);
2183                                return false;
2184                                break;
2185
2186                        case S_CALL_FORWARDING_START:
2187                                if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2188                                {
2189                                        dbug(1, dprintf("format wrong"));
2190                                        Info = _WRONG_MESSAGE_FORMAT;
2191                                        break;
2192                                }
2193
2194                                if ((i = get_plci(a)))
2195                                {
2196                                        rplci = &a->plci[i - 1];
2197                                        rplci->appl = appl;
2198                                        add_p(rplci, CAI, "\x01\x80");
2199                                        add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2200                                        sig_req(rplci, ASSIGN, DSIG_ID);
2201                                        send_req(rplci);
2202                                }
2203                                else
2204                                {
2205                                        Info = _OUT_OF_PLCI;
2206                                        break;
2207                                }
2208
2209                                /* reuse unused screening indicator */
2210                                rplci->internal_command = CF_START_PEND;
2211                                rplci->appl = appl;
2212                                rplci->number = Number;
2213                                appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2214                                cai[0] = 2;
2215                                cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2216                                cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2217                                add_p(rplci, CAI, cai);
2218                                add_p(rplci, OAD, ss_parms[5].info);
2219                                add_p(rplci, CPN, ss_parms[6].info);
2220                                sig_req(rplci, S_SERVICE, 0);
2221                                send_req(rplci);
2222                                return false;
2223                                break;
2224
2225                        case S_INTERROGATE_DIVERSION:
2226                        case S_INTERROGATE_NUMBERS:
2227                        case S_CALL_FORWARDING_STOP:
2228                        case S_CCBS_REQUEST:
2229                        case S_CCBS_DEACTIVATE:
2230                        case S_CCBS_INTERROGATE:
2231                                switch (SSreq)
2232                                {
2233                                case S_INTERROGATE_NUMBERS:
2234                                        if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2235                                        {
2236                                                dbug(0, dprintf("format wrong"));
2237                                                Info = _WRONG_MESSAGE_FORMAT;
2238                                        }
2239                                        break;
2240                                case S_CCBS_REQUEST:
2241                                case S_CCBS_DEACTIVATE:
2242                                        if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2243                                        {
2244                                                dbug(0, dprintf("format wrong"));
2245                                                Info = _WRONG_MESSAGE_FORMAT;
2246                                        }
2247                                        break;
2248                                case S_CCBS_INTERROGATE:
2249                                        if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2250                                        {
2251                                                dbug(0, dprintf("format wrong"));
2252                                                Info = _WRONG_MESSAGE_FORMAT;
2253                                        }
2254                                        break;
2255                                default:
2256                                        if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2257                                        {
2258                                                dbug(0, dprintf("format wrong"));
2259                                                Info = _WRONG_MESSAGE_FORMAT;
2260                                                break;
2261                                        }
2262                                        break;
2263                                }
2264
2265                                if (Info) break;
2266                                if ((i = get_plci(a)))
2267                                {
2268                                        rplci = &a->plci[i - 1];
2269                                        switch (SSreq)
2270                                        {
2271                                        case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2272                                                cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2273                                                rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2274                                                break;
2275                                        case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2276                                                cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2277                                                rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2278                                                break;
2279                                        case S_CALL_FORWARDING_STOP:
2280                                                rplci->internal_command = CF_STOP_PEND;
2281                                                cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2282                                                break;
2283                                        case S_CCBS_REQUEST:
2284                                                cai[1] = CCBS_REQUEST;
2285                                                rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2286                                                break;
2287                                        case S_CCBS_DEACTIVATE:
2288                                                cai[1] = CCBS_DEACTIVATE;
2289                                                rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2290                                                break;
2291                                        case S_CCBS_INTERROGATE:
2292                                                cai[1] = CCBS_INTERROGATE;
2293                                                rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2294                                                break;
2295                                        default:
2296                                                cai[1] = 0;
2297                                                break;
2298                                        }
2299                                        rplci->appl = appl;
2300                                        rplci->number = Number;
2301                                        add_p(rplci, CAI, "\x01\x80");
2302                                        add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2303                                        sig_req(rplci, ASSIGN, DSIG_ID);
2304                                        send_req(rplci);
2305                                }
2306                                else
2307                                {
2308                                        Info = _OUT_OF_PLCI;
2309                                        break;
2310                                }
2311
2312                                appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2313                                switch (SSreq)
2314                                {
2315                                case S_INTERROGATE_NUMBERS:
2316                                        cai[0] = 1;
2317                                        add_p(rplci, CAI, cai);
2318                                        break;
2319                                case S_CCBS_REQUEST:
2320                                case S_CCBS_DEACTIVATE:
2321                                        cai[0] = 3;
2322                                        PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2323                                        add_p(rplci, CAI, cai);
2324                                        break;
2325                                case S_CCBS_INTERROGATE:
2326                                        cai[0] = 3;
2327                                        PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2328                                        add_p(rplci, CAI, cai);
2329                                        add_p(rplci, OAD, ss_parms[4].info);
2330                                        break;
2331                                default:
2332                                        cai[0] = 2;
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                                        break;
2337                                }
2338
2339                                sig_req(rplci, S_SERVICE, 0);
2340                                send_req(rplci);
2341                                return false;
2342                                break;
2343
2344                        case S_MWI_ACTIVATE:
2345                                if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2346                                {
2347                                        dbug(1, dprintf("format wrong"));
2348                                        Info = _WRONG_MESSAGE_FORMAT;
2349                                        break;
2350                                }
2351                                if (!plci)
2352                                {
2353                                        if ((i = get_plci(a)))
2354                                        {
2355                                                rplci = &a->plci[i - 1];
2356                                                rplci->appl = appl;
2357                                                rplci->cr_enquiry = true;
2358                                                add_p(rplci, CAI, "\x01\x80");
2359                                                add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2360                                                sig_req(rplci, ASSIGN, DSIG_ID);
2361                                                send_req(rplci);
2362                                        }
2363                                        else
2364                                        {
2365                                                Info = _OUT_OF_PLCI;
2366                                                break;
2367                                        }
2368                                }
2369                                else
2370                                {
2371                                        rplci = plci;
2372                                        rplci->cr_enquiry = false;
2373                                }
2374
2375                                rplci->command = 0;
2376                                rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2377                                rplci->appl = appl;
2378                                rplci->number = Number;
2379
2380                                cai[0] = 13;
2381                                cai[1] = ACTIVATION_MWI; /* Function */
2382                                PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2383                                PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2384                                PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2385                                PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2386                                PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2387                                add_p(rplci, CAI, cai);
2388                                add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2389                                add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2390                                add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2391                                add_p(rplci, UID, ss_parms[10].info); /* Time */
2392                                sig_req(rplci, S_SERVICE, 0);
2393                                send_req(rplci);
2394                                return false;
2395
2396                        case S_MWI_DEACTIVATE:
2397                                if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2398                                {
2399                                        dbug(1, dprintf("format wrong"));
2400                                        Info = _WRONG_MESSAGE_FORMAT;
2401                                        break;
2402                                }
2403                                if (!plci)
2404                                {
2405                                        if ((i = get_plci(a)))
2406                                        {
2407                                                rplci = &a->plci[i - 1];
2408                                                rplci->appl = appl;
2409                                                rplci->cr_enquiry = true;
2410                                                add_p(rplci, CAI, "\x01\x80");
2411                                                add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2412                                                sig_req(rplci, ASSIGN, DSIG_ID);
2413                                                send_req(rplci);
2414                                        }
2415                                        else
2416                                        {
2417                                                Info = _OUT_OF_PLCI;
2418                                                break;
2419                                        }
2420                                }
2421                                else
2422                                {
2423                                        rplci = plci;
2424                                        rplci->cr_enquiry = false;
2425                                }
2426
2427                                rplci->command = 0;
2428                                rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2429                                rplci->appl = appl;
2430                                rplci->number = Number;
2431
2432                                cai[0] = 5;
2433                                cai[1] = DEACTIVATION_MWI; /* Function */
2434                                PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2435                                PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2436                                add_p(rplci, CAI, cai);
2437                                add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2438                                add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2439                                sig_req(rplci, S_SERVICE, 0);
2440                                send_req(rplci);
2441                                return false;
2442
2443                        default:
2444                                Info = 0x300E;  /* not supported */
2445                                break;
2446                        }
2447                        break; /* case SELECTOR_SU_SERV: end */
2448
2449
2450                case SELECTOR_DTMF:
2451                        return (dtmf_request(Id, Number, a, plci, appl, msg));
2452
2453
2454
2455                case SELECTOR_LINE_INTERCONNECT:
2456                        return (mixer_request(Id, Number, a, plci, appl, msg));
2457
2458
2459
2460                case PRIV_SELECTOR_ECHO_CANCELLER:
2461                        appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2462                        return (ec_request(Id, Number, a, plci, appl, msg));
2463
2464                case SELECTOR_ECHO_CANCELLER:
2465                        appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2466                        return (ec_request(Id, Number, a, plci, appl, msg));
2467
2468
2469                case SELECTOR_V42BIS:
2470                default:
2471                        Info = _FACILITY_NOT_SUPPORTED;
2472                        break;
2473                } /* end of switch (selector) */
2474        }
2475
2476        dbug(1, dprintf("SendFacRc"));
2477        sendf(appl,
2478              _FACILITY_R | CONFIRM,
2479              Id,
2480              Number,
2481              "wws", Info, selector, SSparms);
2482        return false;
2483}
2484
2485static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2486                         PLCI *plci, APPL *appl, API_PARSE *msg)
2487{
2488        dbug(1, dprintf("facility_res"));
2489        return false;
2490}
2491
2492static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2493                           PLCI *plci, APPL *appl, API_PARSE *parms)
2494{
2495        word Info = 0;
2496        byte req;
2497        byte len;
2498        word w;
2499        word fax_control_bits, fax_feature_bits, fax_info_change;
2500        API_PARSE *ncpi;
2501        byte pvc[2];
2502
2503        API_PARSE fax_parms[9];
2504        word i;
2505
2506
2507        dbug(1, dprintf("connect_b3_req"));
2508        if (plci)
2509        {
2510                if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2511                    || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2512                {
2513                        Info = _WRONG_STATE;
2514                }
2515                else
2516                {
2517                        /* local reply if assign unsuccessful
2518                           or B3 protocol allows only one layer 3 connection
2519                           and already connected
2520                           or B2 protocol not any LAPD
2521                           and connect_b3_req contradicts originate/answer direction */
2522                        if (!plci->NL.Id
2523                            || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2524                                && ((plci->channels != 0)
2525                                    || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2526                                        && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2527                        {
2528                                dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2529                                                plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2530                                Info = _WRONG_STATE;
2531                                sendf(appl,
2532                                      _CONNECT_B3_R | CONFIRM,
2533                                      Id,
2534                                      Number,
2535                                      "w", Info);
2536                                return false;
2537                        }
2538                        plci->requested_options_conn = 0;
2539
2540                        req = N_CONNECT;
2541                        ncpi = &parms[0];
2542                        if (plci->B3_prot == 2 || plci->B3_prot == 3)
2543                        {
2544                                if (ncpi->length > 2)
2545                                {
2546                                        /* check for PVC */
2547                                        if (ncpi->info[2] || ncpi->info[3])
2548                                        {
2549                                                pvc[0] = ncpi->info[3];
2550                                                pvc[1] = ncpi->info[2];
2551                                                add_d(plci, 2, pvc);
2552                                                req = N_RESET;
2553                                        }
2554                                        else
2555                                        {
2556                                                if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2557                                                add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2558                                        }
2559                                }
2560                        }
2561                        else if (plci->B3_prot == 5)
2562                        {
2563                                if (plci->NL.Id && !plci->nl_remove_id)
2564                                {
2565                                        fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2566                                        fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2567                                        if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2568                                            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2569                                        {
2570                                                len = offsetof(T30_INFO, universal_6);
2571                                                fax_info_change = false;
2572                                                if (ncpi->length >= 4)
2573                                                {
2574                                                        w = GET_WORD(&ncpi->info[3]);
2575                                                        if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2576                                                        {
2577                                                                ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2578                                                                        (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2579                                                                               ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2580                                                                fax_info_change = true;
2581                                                        }
2582                                                        fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2583                                                        if (w & 0x0002)  /* Fax-polling request */
2584                                                                fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2585                                                        if ((w & 0x0004) /* Request to send / poll another document */
2586                                                            && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2587                                                        {
2588                                                                fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2589                                                        }
2590                                                        if (ncpi->length >= 6)
2591                                                        {
2592                                                                w = GET_WORD(&ncpi->info[5]);
2593                                                                if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2594                                                                {
2595                                                                        ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2596                                                                        fax_info_change = true;
2597                                                                }
2598
2599                                                                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2600                                                                    && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2601                                                                {
2602                                                                        plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2603                                                                }
2604                                                                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2605                                                                    && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2606                                                                {
2607                                                                        plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2608                                                                }
2609                                                                fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2610                                                                                      T30_CONTROL_BIT_ACCEPT_PASSWORD);
2611                                                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2612                                                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2613                                                                {
2614                                                                        if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2615                                                                                Info = _WRONG_MESSAGE_FORMAT;
2616                                                                        else
2617                                                                        {
2618                                                                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2619                                                                                    & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2620                                                                                {
2621                                                                                        fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2622                                                                                        if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2623                                                                                                fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2624                                                                                }
2625                                                                                w = fax_parms[4].length;
2626                                                                                if (w > 20)
2627                                                                                        w = 20;
2628                                                                                ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2629                                                                                for (i = 0; i < w; i++)
2630                                                                                        ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2631                                                                                ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2632                                                                                len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2633                                                                                w = fax_parms[5].length;
2634                                                                                if (w > 20)
2635                                                                                        w = 20;
2636                                                                                plci->fax_connect_info_buffer[len++] = (byte) w;
2637                                                                                for (i = 0; i < w; i++)
2638                                                                                        plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2639                                                                                w = fax_parms[6].length;
2640                                                                                if (w > 20)
2641                                                                                        w = 20;
2642                                                                                plci->fax_connect_info_buffer[len++] = (byte) w;
2643                                                                                for (i = 0; i < w; i++)
2644                                                                                        plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2645                                                                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2646                                                                                    & (1L << PRIVATE_FAX_NONSTANDARD))
2647                                                                                {
2648                                                                                        if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2649                                                                                        {
2650                                                                                                dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2651                                                                                                plci->fax_connect_info_buffer[len++] = 0;
2652                                                                                        }
2653                                                                                        else
2654                                                                                        {
2655                                                                                                if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2656                                                                                                        plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2657                                                                                                plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2658                                                                                                for (i = 0; i < fax_parms[7].length; i++)
2659                                                                                                        plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2660                                                                                        }
2661                                                                                }
2662                                                                        }
2663                                                                }
2664                                                                else
2665                                                                {
2666                                                                        len = offsetof(T30_INFO, universal_6);
2667                                                                }
2668                                                                fax_info_change = true;
2669
2670                                                        }
2671                                                        if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2672                                                        {
2673                                                                PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2674                                                                fax_info_change = true;
2675                                                        }
2676                                                }
2677                                                if (Info == GOOD)
2678                                                {
2679                                                        plci->fax_connect_info_length = len;
2680                                                        if (fax_info_change)
2681                                                        {
2682                                                                if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2683                                                                {
2684                                                                        start_internal_command(Id, plci, fax_connect_info_command);
2685                                                                        return false;
2686                                                                }
2687                                                                else
2688                                                                {
2689                                                                        start_internal_command(Id, plci, fax_adjust_b23_command);
2690                                                                        return false;
2691                                                                }
2692                                                        }
2693                                                }
2694                                        }
2695                                        else  Info = _WRONG_STATE;
2696                                }
2697                                else  Info = _WRONG_STATE;
2698                        }
2699
2700                        else if (plci->B3_prot == B3_RTP)
2701                        {
2702                                plci->internal_req_buffer[0] = ncpi->length + 1;
2703                                plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2704                                for (w = 0; w < ncpi->length; w++)
2705                                        plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2706                                start_internal_command(Id, plci, rtp_connect_b3_req_command);
2707                                return false;
2708                        }
2709
2710                        if (!Info)
2711                        {
2712                                nl_req_ncci(plci, req, 0);
2713                                return 1;
2714                        }
2715                }
2716        }
2717        else Info = _WRONG_IDENTIFIER;
2718
2719        sendf(appl,
2720              _CONNECT_B3_R | CONFIRM,
2721              Id,
2722              Number,
2723              "w", Info);
2724        return false;
2725}
2726
2727static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2728                           PLCI *plci, APPL *appl, API_PARSE *parms)
2729{
2730        word ncci;
2731        API_PARSE *ncpi;
2732        byte req;
2733
2734        word w;
2735
2736
2737        API_PARSE fax_parms[9];
2738        word i;
2739        byte len;
2740
2741
2742        dbug(1, dprintf("connect_b3_res"));
2743
2744        ncci = (word)(Id >> 16);
2745        if (plci && ncci) {
2746                if (a->ncci_state[ncci] == INC_CON_PENDING) {
2747                        if (GET_WORD(&parms[0].info[0]) != 0)
2748                        {
2749                                a->ncci_state[ncci] = OUTG_REJ_PENDING;
2750                                channel_request_xon(plci, a->ncci_ch[ncci]);
2751                                channel_xmit_xon(plci);
2752                                cleanup_ncci_data(plci, ncci);
2753                                nl_req_ncci(plci, N_DISC, (byte)ncci);
2754                                return 1;
2755                        }
2756                        a->ncci_state[ncci] = INC_ACT_PENDING;
2757
2758                        req = N_CONNECT_ACK;
2759                        ncpi = &parms[1];
2760                        if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2761                        {
2762
2763                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2764                                    & (1L << PRIVATE_FAX_NONSTANDARD))
2765                                {
2766                                        if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2767                                            && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2768                                            && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2769                                        {
2770                                                len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2771                                                if (plci->fax_connect_info_length < len)
2772                                                {
2773                                                        ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2774                                                        ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2775                                                }
2776                                                if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2777                                                {
2778                                                        dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2779                                                }
2780                                                else
2781                                                {
2782                                                        if (plci->fax_connect_info_length <= len)
2783                                                                plci->fax_connect_info_buffer[len] = 0;
2784                                                        len += 1 + plci->fax_connect_info_buffer[len];
2785                                                        if (plci->fax_connect_info_length <= len)
2786                                                                plci->fax_connect_info_buffer[len] = 0;
2787                                                        len += 1 + plci->fax_connect_info_buffer[len];
2788                                                        if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2789                                                                plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2790                                                        plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2791                                                        for (i = 0; i < fax_parms[7].length; i++)
2792                                                                plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2793                                                }
2794                                                plci->fax_connect_info_length = len;
2795                                                ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2796                                                start_internal_command(Id, plci, fax_connect_ack_command);
2797                                                return false;
2798                                        }
2799                                }
2800
2801                                nl_req_ncci(plci, req, (byte)ncci);
2802                                if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2803                                    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2804                                {
2805                                        if (plci->B3_prot == 4)
2806                                                sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2807                                        else
2808                                                sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2809                                        plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2810                                }
2811                        }
2812
2813                        else if (plci->B3_prot == B3_RTP)
2814                        {
2815                                plci->internal_req_buffer[0] = ncpi->length + 1;
2816                                plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2817                                for (w = 0; w < ncpi->length; w++)
2818                                        plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2819                                start_internal_command(Id, plci, rtp_connect_b3_res_command);
2820                                return false;
2821                        }
2822
2823                        else
2824                        {
2825                                if (ncpi->length > 2) {
2826                                        if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2827                                        add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2828                                }
2829                                nl_req_ncci(plci, req, (byte)ncci);
2830                                sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2831                                if (plci->adjust_b_restore)
2832                                {
2833                                        plci->adjust_b_restore = false;
2834                                        start_internal_command(Id, plci, adjust_b_restore);
2835                                }
2836                        }
2837                        return 1;
2838                }
2839        }
2840        return false;
2841}
2842
2843static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2844                             PLCI *plci, APPL *appl, API_PARSE *parms)
2845{
2846        word ncci;
2847
2848        ncci = (word)(Id >> 16);
2849        dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2850
2851        if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2852            && (plci->State != OUTG_DIS_PENDING))
2853        {
2854                if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2855                        a->ncci_state[ncci] = CONNECTED;
2856                        if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2857                        channel_request_xon(plci, a->ncci_ch[ncci]);
2858                        channel_xmit_xon(plci);
2859                }
2860        }
2861        return false;
2862}
2863
2864static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2865                              PLCI *plci, APPL *appl, API_PARSE *parms)
2866{
2867        word Info;
2868        word ncci;
2869        API_PARSE *ncpi;
2870
2871        dbug(1, dprintf("disconnect_b3_req"));
2872
2873        Info = _WRONG_IDENTIFIER;
2874        ncci = (word)(Id >> 16);
2875        if (plci && ncci)
2876        {
2877                Info = _WRONG_STATE;
2878                if ((a->ncci_state[ncci] == CONNECTED)
2879                    || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2880                    || (a->ncci_state[ncci] == INC_CON_PENDING)
2881                    || (a->ncci_state[ncci] == INC_ACT_PENDING))
2882                {
2883                        a->ncci_state[ncci] = OUTG_DIS_PENDING;
2884                        channel_request_xon(plci, a->ncci_ch[ncci]);
2885                        channel_xmit_xon(plci);
2886
2887                        if (a->ncci[ncci].data_pending
2888                            && ((plci->B3_prot == B3_TRANSPARENT)
2889                                || (plci->B3_prot == B3_T30)
2890                                || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
2891                        {
2892                                plci->send_disc = (byte)ncci;
2893                                plci->command = 0;
2894                                return false;
2895                        }
2896                        else
2897                        {
2898                                cleanup_ncci_data(plci, ncci);
2899
2900                                if (plci->B3_prot == 2 || plci->B3_prot == 3)
2901                                {
2902                                        ncpi = &parms[0];
2903                                        if (ncpi->length > 3)
2904                                        {
2905                                                add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
2906                                        }
2907                                }
2908                                nl_req_ncci(plci, N_DISC, (byte)ncci);
2909                        }
2910                        return 1;
2911                }
2912        }
2913        sendf(appl,
2914              _DISCONNECT_B3_R | CONFIRM,
2915              Id,
2916              Number,
2917              "w", Info);
2918        return false;
2919}
2920
2921static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2922                              PLCI *plci, APPL *appl, API_PARSE *parms)
2923{
2924        word ncci;
2925        word i;
2926
2927        ncci = (word)(Id >> 16);
2928        dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
2929        if (plci && ncci) {
2930                plci->requested_options_conn = 0;
2931                plci->fax_connect_info_length = 0;
2932                plci->ncpi_state = 0x00;
2933                if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2934                    && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
2935                {
2936                        plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
2937                }
2938                for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
2939                if (i < MAX_CHANNELS_PER_PLCI) {
2940                        if (plci->channels)plci->channels--;
2941                        for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
2942                        plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
2943
2944                        ncci_free_receive_buffers(plci, ncci);
2945
2946                        if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
2947                                if (plci->State == SUSPENDING) {
2948                                        sendf(plci->appl,
2949                                              _FACILITY_I,
2950                                              Id & 0xffffL,
2951                                              0,
2952                                              "ws", (word)3, "\x03\x04\x00\x00");
2953                                        sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
2954                                }
2955                                plci_remove(plci);
2956                                plci->State = IDLE;
2957                        }
2958                }
2959                else
2960                {
2961                        if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
2962                            && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
2963                            && (a->ncci_state[ncci] == INC_DIS_PENDING))
2964                        {
2965                                ncci_free_receive_buffers(plci, ncci);
2966
2967                                nl_req_ncci(plci, N_EDATA, (byte)ncci);
2968
2969                                plci->adapter->ncci_state[ncci] = IDLE;
2970                                start_internal_command(Id, plci, fax_disconnect_command);
2971                                return 1;
2972                        }
2973                }
2974        }
2975        return false;
2976}
2977
2978static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2979                        PLCI *plci, APPL *appl, API_PARSE *parms)
2980{
2981        NCCI *ncci_ptr;
2982        DATA_B3_DESC *data;
2983        word Info;
2984        word ncci;
2985        word i;
2986
2987        dbug(1, dprintf("data_b3_req"));
2988
2989        Info = _WRONG_IDENTIFIER;
2990        ncci = (word)(Id >> 16);
2991        dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
2992
2993        if (plci && ncci)
2994        {
2995                Info = _WRONG_STATE;
2996                if ((a->ncci_state[ncci] == CONNECTED)
2997                    || (a->ncci_state[ncci] == INC_ACT_PENDING))
2998                {
2999                        /* queue data */
3000                        ncci_ptr = &(a->ncci[ncci]);
3001                        i = ncci_ptr->data_out + ncci_ptr->data_pending;
3002                        if (i >= MAX_DATA_B3)
3003                                i -= MAX_DATA_B3;
3004                        data = &(ncci_ptr->DBuffer[i]);
3005                        data->Number = Number;
3006                        if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3007                            && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3008                        {
3009
3010                                data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3011
3012                        }
3013                        else
3014                                data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3015                        data->Length = GET_WORD(parms[1].info);
3016                        data->Handle = GET_WORD(parms[2].info);
3017                        data->Flags = GET_WORD(parms[3].info);
3018                        (ncci_ptr->data_pending)++;
3019
3020                        /* check for delivery confirmation */
3021                        if (data->Flags & 0x0004)
3022                        {
3023                                i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3024                                if (i >= MAX_DATA_ACK)
3025                                        i -= MAX_DATA_ACK;
3026                                ncci_ptr->DataAck[i].Number = data->Number;
3027                                ncci_ptr->DataAck[i].Handle = data->Handle;
3028                                (ncci_ptr->data_ack_pending)++;
3029                        }
3030
3031                        send_data(plci);
3032                        return false;
3033                }
3034        }
3035        if (appl)
3036        {
3037                if (plci)
3038                {
3039                        if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3040                            && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3041                        {
3042
3043                                TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3044
3045                        }
3046                }
3047                sendf(appl,
3048                      _DATA_B3_R | CONFIRM,
3049                      Id,
3050                      Number,
3051                      "ww", GET_WORD(parms[2].info), Info);
3052        }
3053        return false;
3054}
3055
3056static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3057                        PLCI *plci, APPL *appl, API_PARSE *parms)
3058{
3059        word n;
3060        word ncci;
3061        word NCCIcode;
3062
3063        dbug(1, dprintf("data_b3_res"));
3064
3065        ncci = (word)(Id >> 16);
3066        if (plci && ncci) {
3067                n = GET_WORD(parms[0].info);
3068                dbug(1, dprintf("free(%d)", n));
3069                NCCIcode = ncci | (((word) a->Id) << 8);
3070                if (n < appl->MaxBuffer &&
3071                    appl->DataNCCI[n] == NCCIcode &&
3072                    (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3073                        dbug(1, dprintf("found"));
3074                        appl->DataNCCI[n] = 0;
3075
3076                        if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3077                                channel_request_xon(plci, a->ncci_ch[ncci]);
3078                        }
3079                        channel_xmit_xon(plci);
3080
3081                        if (appl->DataFlags[n] & 4) {
3082                                nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3083                                return 1;
3084                        }
3085                }
3086        }
3087        return false;
3088}
3089
3090static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3091                         PLCI *plci, APPL *appl, API_PARSE *parms)
3092{
3093        word Info;
3094        word ncci;
3095
3096        dbug(1, dprintf("reset_b3_req"));
3097
3098        Info = _WRONG_IDENTIFIER;
3099        ncci = (word)(Id >> 16);
3100        if (plci && ncci)
3101        {
3102                Info = _WRONG_STATE;
3103                switch (plci->B3_prot)
3104                {
3105                case B3_ISO8208:
3106                case B3_X25_DCE:
3107                        if (a->ncci_state[ncci] == CONNECTED)
3108                        {
3109                                nl_req_ncci(plci, N_RESET, (byte)ncci);
3110                                send_req(plci);
3111                                Info = GOOD;
3112                        }
3113                        break;
3114                case B3_TRANSPARENT:
3115                        if (a->ncci_state[ncci] == CONNECTED)
3116                        {
3117                                start_internal_command(Id, plci, reset_b3_command);
3118                                Info = GOOD;
3119                        }
3120                        break;
3121                }
3122        }
3123        /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3124        sendf(appl,
3125              _RESET_B3_R | CONFIRM,
3126              Id,
3127              Number,
3128              "w", Info);
3129        return false;
3130}
3131
3132static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3133                         PLCI *plci, APPL *appl, API_PARSE *parms)
3134{
3135        word ncci;
3136
3137        dbug(1, dprintf("reset_b3_res"));
3138
3139        ncci = (word)(Id >> 16);
3140        if (plci && ncci) {
3141                switch (plci->B3_prot)
3142                {
3143                case B3_ISO8208:
3144                case B3_X25_DCE:
3145                        if (a->ncci_state[ncci] == INC_RES_PENDING)
3146                        {
3147                                a->ncci_state[ncci] = CONNECTED;
3148                                nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3149                                return true;
3150                        }
3151                        break;
3152                }
3153        }
3154        return false;
3155}
3156
3157static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3158                                 PLCI *plci, APPL *appl, API_PARSE *parms)
3159{
3160        word ncci;
3161        API_PARSE *ncpi;
3162        byte req;
3163
3164        dbug(1, dprintf("connect_b3_t90_a_res"));
3165
3166        ncci = (word)(Id >> 16);
3167        if (plci && ncci) {
3168                if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3169                        a->ncci_state[ncci] = CONNECTED;
3170                }
3171                else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3172                        a->ncci_state[ncci] = CONNECTED;
3173
3174                        req = N_CONNECT_ACK;
3175
3176                        /* parms[0]==0 for CAPI original message definition! */
3177                        if (parms[0].info) {
3178                                ncpi = &parms[1];
3179                                if (ncpi->length > 2) {
3180                                        if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3181                                        add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3182                                }
3183                        }
3184                        nl_req_ncci(plci, req, (byte)ncci);
3185                        return 1;
3186                }
3187        }
3188        return false;
3189}
3190
3191
3192static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3193                         PLCI *plci, APPL *appl, API_PARSE *msg)
3194{
3195        word Info = 0;
3196        word i;
3197        byte tel;
3198        API_PARSE bp_parms[7];
3199
3200        if (!plci || !msg)
3201        {
3202                Info = _WRONG_IDENTIFIER;
3203        }
3204        else
3205        {
3206                dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3207                                msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3208                dbug(1, dprintf("PlciState=0x%x", plci->State));
3209                for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3210
3211                /* check if no channel is open, no B3 connected only */
3212                if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3213                    || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3214                {
3215                        Info = _WRONG_STATE;
3216                }
3217                /* check message format and fill bp_parms pointer */
3218                else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3219                {
3220                        Info = _WRONG_MESSAGE_FORMAT;
3221                }
3222                else
3223                {
3224                        if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3225                        {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3226                                if (Id & EXT_CONTROLLER)
3227                                {
3228                                        sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3229                                        return 0;
3230                                }
3231                                plci->State = INC_CON_CONNECTED_ALERT;
3232                                plci->appl = appl;
3233                                __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
3234                                dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
3235                                /* disconnect the other appls its quasi a connect */
3236                                for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
3237                                        sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3238                        }
3239
3240                        api_save_msg(msg, "s", &plci->saved_msg);
3241                        tel = plci->tel;
3242                        if (Id & EXT_CONTROLLER)
3243                        {
3244                                if (tel) /* external controller in use by this PLCI */
3245                                {
3246                                        if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3247                                        {
3248                                                dbug(1, dprintf("Ext_Ctrl in use 1"));
3249                                                Info = _WRONG_STATE;
3250                                        }
3251                                }
3252                                else  /* external controller NOT in use by this PLCI ? */
3253                                {
3254                                        if (a->AdvSignalPLCI)
3255                                        {
3256                                                dbug(1, dprintf("Ext_Ctrl in use 2"));
3257                                                Info = _WRONG_STATE;
3258                                        }
3259                                        else /* activate the codec */
3260                                        {
3261                                                dbug(1, dprintf("Ext_Ctrl start"));
3262                                                if (AdvCodecSupport(a, plci, appl, 0))
3263                                                {
3264                                                        dbug(1, dprintf("Error in codec procedures"));
3265                                                        Info = _WRONG_STATE;
3266                                                }
3267                                                else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3268                                                {
3269                                                        plci->spoofed_msg = AWAITING_SELECT_B;
3270                                                        plci->internal_command = BLOCK_PLCI; /* lock other commands */
3271                                                        plci->command = 0;
3272                                                        dbug(1, dprintf("continue if codec loaded"));
3273                                                        return false;
3274                                                }
3275                                        }
3276                                }
3277                        }
3278                        else /* external controller bit is OFF */
3279                        {
3280                                if (tel) /* external controller in use, need to switch off */
3281                                {
3282                                        if (a->AdvSignalAppl == appl)
3283                                        {
3284                                                CodecIdCheck(a, plci);
3285                                                plci->tel = 0;
3286                                                plci->adv_nl = 0;
3287                                                dbug(1, dprintf("Ext_Ctrl disable"));
3288                                        }
3289                                        else
3290                                        {
3291                                                dbug(1, dprintf("Ext_Ctrl not requested"));
3292                                        }
3293                                }
3294                        }
3295                        if (!Info)
3296                        {
3297                                if (plci->call_dir & CALL_DIR_OUT)
3298                                        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3299                                else if (plci->call_dir & CALL_DIR_IN)
3300                                        plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3301                                start_internal_command(Id, plci, select_b_command);
3302                                return false;
3303                        }
3304                }
3305        }
3306        sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3307        return false;
3308}
3309
3310static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3311                             PLCI *plci, APPL *appl, API_PARSE *parms)
3312{
3313        word command;
3314        word i;
3315        word ncci;
3316        API_PARSE *m;
3317        API_PARSE m_parms[5];
3318        word codec;
3319        byte req;
3320        byte ch;
3321        byte dir;
3322        static byte chi[2] = {0x01, 0x00};
3323        static byte lli[2] = {0x01, 0x00};
3324        static byte codec_cai[2] = {0x01, 0x01};
3325        static byte null_msg = {0};
3326        static API_PARSE null_parms = { 0, &null_msg };
3327        PLCI *v_plci;
3328        word Info = 0;
3329
3330        dbug(1, dprintf("manufacturer_req"));
3331        for (i = 0; i < 5; i++) m_parms[i].length = 0;
3332
3333        if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3334                Info = _WRONG_MESSAGE_FORMAT;
3335        }
3336        command = GET_WORD(parms[1].info);
3337        m = &parms[2];
3338        if (!Info)
3339        {
3340                switch (command) {
3341                case _DI_ASSIGN_PLCI:
3342                        if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3343                                Info = _WRONG_MESSAGE_FORMAT;
3344                                break;
3345                        }
3346                        codec = GET_WORD(m_parms[0].info);
3347                        ch = m_parms[1].info[0];
3348                        dir = m_parms[2].info[0];
3349                        if ((i = get_plci(a))) {
3350                                plci = &a->plci[i - 1];
3351                                plci->appl = appl;
3352                                plci->command = _MANUFACTURER_R;
3353                                plci->m_command = command;
3354                                plci->number = Number;
3355                                plci->State = LOCAL_CONNECT;
3356                                Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3357                                dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3358
3359                                if ((ch == 1 || ch == 2) && (dir <= 2)) {
3360                                        chi[1] = (byte)(0x80 | ch);
3361                                        lli[1] = 0;
3362                                        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3363                                        switch (codec)
3364                                        {
3365                                        case 0:
3366                                                Info = add_b1(plci, &m_parms[3], 0, 0);
3367                                                break;
3368                                        case 1:
3369                                                add_p(plci, CAI, codec_cai);
3370                                                break;
3371                                                /* manual 'swich on' to the codec support without signalling */
3372                                                /* first 'assign plci' with this function, then use */
3373                                        case 2:
3374                                                if (AdvCodecSupport(a, plci, appl, 0)) {
3375                                                        Info = _RESOURCE_ERROR;
3376                                                }
3377                                                else {
3378                                                        Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3379                                                        lli[1] = 0x10; /* local call codec stream */
3380                                                }
3381                                                break;
3382                                        }
3383
3384                                        plci->State = LOCAL_CONNECT;
3385                                        plci->manufacturer = true;
3386                                        plci->command = _MANUFACTURER_R;
3387                                        plci->m_command = command;
3388                                        plci->number = Number;
3389
3390                                        if (!Info)
3391                                        {
3392                                                add_p(plci, LLI, lli);
3393                                                add_p(plci, CHI, chi);
3394                                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3395                                                sig_req(plci, ASSIGN, DSIG_ID);
3396
3397                                                if (!codec)
3398                                                {
3399                                                        Info = add_b23(plci, &m_parms[3]);
3400                                                        if (!Info)
3401                                                        {
3402                                                                nl_req_ncci(plci, ASSIGN, 0);
3403                                                                send_req(plci);
3404                                                        }
3405                                                }
3406                                                if (!Info)
3407                                                {
3408                                                        dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3409                                                        if (plci->spoofed_msg == SPOOFING_REQUIRED)
3410                                                        {
3411                                                                api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3412                                                                plci->spoofed_msg = AWAITING_MANUF_CON;
3413                                                                plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3414                                                                plci->command = 0;
3415                                                                send_req(plci);
3416                                                                return false;
3417                                                        }
3418                                                        if (dir == 1) {
3419                                                                sig_req(plci, CALL_REQ, 0);
3420                                                        }
3421                                                        else if (!dir) {
3422                                                                sig_req(plci, LISTEN_REQ, 0);
3423                                                        }
3424                                                        send_req(plci);
3425                                                }
3426                                                else
3427                                                {
3428                                                        sendf(appl,
3429                                                              _MANUFACTURER_R | CONFIRM,
3430                                                              Id,
3431                                                              Number,
3432                                                              "dww", _DI_MANU_ID, command, Info);
3433                                                        return 2;
3434                                                }
3435                                        }
3436                                }
3437                        }
3438                        else  Info = _OUT_OF_PLCI;
3439                        break;
3440
3441                case _DI_IDI_CTRL:
3442                        if (!plci)
3443                        {
3444                                Info = _WRONG_IDENTIFIER;
3445                                break;
3446                        }
3447                        if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3448                                Info = _WRONG_MESSAGE_FORMAT;
3449                                break;
3450                        }
3451                        req = m_parms[0].info[0];
3452                        plci->command = _MANUFACTURER_R;
3453                        plci->m_command = command;
3454                        plci->number = Number;
3455                        if (req == CALL_REQ)
3456                        {
3457                                plci->b_channel = getChannel(&m_parms[1]);
3458                                mixer_set_bchannel_id_esc(plci, plci->b_channel);
3459                                if (plci->spoofed_msg == SPOOFING_REQUIRED)
3460                                {
3461                                        plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3462                                        plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3463                                        plci->command = 0;
3464                                        break;
3465                                }
3466                        }
3467                        else if (req == LAW_REQ)
3468                        {
3469                                plci->cr_enquiry = true;
3470                        }
3471                        add_ss(plci, FTY, &m_parms[1]);
3472                        sig_req(plci, req, 0);
3473                        send_req(plci);
3474                        if (req == HANGUP)
3475                        {
3476                                if (plci->NL.Id && !plci->nl_remove_id)
3477                                {
3478                                        if (plci->channels)
3479                                        {
3480                                                for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3481                                                {
3482                                                        if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3483                                                        {
3484                                                                a->ncci_state[ncci] = OUTG_DIS_PENDING;
3485                                                                cleanup_ncci_data(plci, ncci);
3486                                                                nl_req_ncci(plci, N_DISC, (byte)ncci);
3487                                                        }
3488                                                }
3489                                        }
3490                                        mixer_remove(plci);
3491                                        nl_req_ncci(plci, REMOVE, 0);
3492                                        send_req(plci);
3493                                }
3494                        }
3495                        break;
3496
3497                case _DI_SIG_CTRL:
3498                        /* signalling control for loop activation B-channel */
3499                        if (!plci)
3500                        {
3501                                Info = _WRONG_IDENTIFIER;
3502                                break;
3503                        }
3504                        if (m->length) {
3505                                plci->command = _MANUFACTURER_R;
3506                                plci->number = Number;
3507                                add_ss(plci, FTY, m);
3508                                sig_req(plci, SIG_CTRL, 0);
3509                                send_req(plci);
3510                        }
3511                        else Info = _WRONG_MESSAGE_FORMAT;
3512                        break;
3513
3514                case _DI_RXT_CTRL:
3515                        /* activation control for receiver/transmitter B-channel */
3516                        if (!plci)
3517                        {
3518                                Info = _WRONG_IDENTIFIER;
3519                                break;
3520                        }
3521                        if (m->length) {
3522                                plci->command = _MANUFACTURER_R;
3523                                plci->number = Number;
3524                                add_ss(plci, FTY, m);
3525                                sig_req(plci, DSP_CTRL, 0);
3526                                send_req(plci);
3527                        }
3528                        else Info = _WRONG_MESSAGE_FORMAT;
3529                        break;
3530
3531                case _DI_ADV_CODEC:
3532                case _DI_DSP_CTRL:
3533                        /* TEL_CTRL commands to support non standard adjustments: */
3534                        /* Ring on/off, Handset micro volume, external micro vol. */
3535                        /* handset+external speaker volume, receiver+transm. gain,*/
3536                        /* handsfree on (hookinfo off), set mixer command         */
3537
3538                        if (command == _DI_ADV_CODEC)
3539                        {
3540                                if (!a->AdvCodecPLCI) {
3541                                        Info = _WRONG_STATE;
3542                                        break;
3543                                }
3544                                v_plci = a->AdvCodecPLCI;
3545                        }
3546                        else
3547                        {
3548                                if (plci
3549                                    && (m->length >= 3)
3550                                    && (m->info[1] == 0x1c)
3551                                    && (m->info[2] >= 1))
3552                                {
3553                                        if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3554                                        {
3555                                                if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3556                                                {
3557                                                        Info = _WRONG_STATE;
3558                                                        break;
3559                                                }
3560                                                a->adv_voice_coef_length = m->info[2] - 1;
3561                                                if (a->adv_voice_coef_length > m->length - 3)
3562                                                        a->adv_voice_coef_length = (byte)(m->length - 3);
3563                                                if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3564                                                        a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3565                                                for (i = 0; i < a->adv_voice_coef_length; i++)
3566                                                        a->adv_voice_coef_buffer[i] = m->info[4 + i];
3567                                                if (plci->B1_facilities & B1_FACILITY_VOICE)
3568                                                        adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3569                                                break;
3570                                        }
3571                                        else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3572                                        {
3573                                                if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3574                                                {
3575                                                        Info = _FACILITY_NOT_SUPPORTED;
3576                                                        break;
3577                                                }
3578
3579                                                plci->dtmf_parameter_length = m->info[2] - 1;
3580                                                if (plci->dtmf_parameter_length > m->length - 3)
3581                                                        plci->dtmf_parameter_length = (byte)(m->length - 3);
3582                                                if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3583                                                        plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3584                                                for (i = 0; i < plci->dtmf_parameter_length; i++)
3585                                                        plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3586                                                if (plci->B1_facilities & B1_FACILITY_DTMFR)
3587                                                        dtmf_parameter_write(plci);
3588                                                break;
3589
3590                                        }
3591                                }
3592                                v_plci = plci;
3593                        }
3594
3595                        if (!v_plci)
3596                        {
3597                                Info = _WRONG_IDENTIFIER;
3598                                break;
3599                        }
3600                        if (m->length) {
3601                                add_ss(v_plci, FTY, m);
3602                                sig_req(v_plci, TEL_CTRL, 0);
3603                                send_req(v_plci);
3604                        }
3605                        else Info = _WRONG_MESSAGE_FORMAT;
3606
3607                        break;
3608
3609                case _DI_OPTIONS_REQUEST:
3610                        if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3611                                Info = _WRONG_MESSAGE_FORMAT;
3612                                break;
3613                        }
3614                        if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3615                        {
3616                                Info = _FACILITY_NOT_SUPPORTED;
3617                                break;
3618                        }
3619                        a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3620                        break;
3621
3622
3623
3624                default:
3625                        Info = _WRONG_MESSAGE_FORMAT;
3626                        break;
3627                }
3628        }
3629
3630        sendf(appl,
3631              _MANUFACTURER_R | CONFIRM,
3632              Id,
3633              Number,
3634              "dww", _DI_MANU_ID, command, Info);
3635        return false;
3636}
3637
3638
3639static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3640                             PLCI *plci, APPL *appl, API_PARSE *msg)
3641{
3642        word indication;
3643
3644        API_PARSE m_parms[3];
3645        API_PARSE *ncpi;
3646        API_PARSE fax_parms[9];
3647        word i;
3648        byte len;
3649
3650
3651        dbug(1, dprintf("manufacturer_res"));
3652
3653        if ((msg[0].length == 0)
3654            || (msg[1].length == 0)
3655            || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3656        {
3657                return false;
3658        }
3659        indication = GET_WORD(msg[1].info);
3660        switch (indication)
3661        {
3662
3663        case _DI_NEGOTIATE_B3:
3664                if (!plci)
3665                        break;
3666                if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3667                    || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3668                {
3669                        dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3670                        break;
3671                }
3672                if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3673                {
3674                        dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3675                        break;
3676                }
3677                ncpi = &m_parms[1];
3678                len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3679                if (plci->fax_connect_info_length < len)
3680                {
3681                        ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3682                        ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3683                }
3684                if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3685                {
3686                        dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3687                }
3688                else
3689                {
3690                        if (plci->fax_connect_info_length <= len)
3691                                plci->fax_connect_info_buffer[len] = 0;
3692                        len += 1 + plci->fax_connect_info_buffer[len];
3693                        if (plci->fax_connect_info_length <= len)
3694                                plci->fax_connect_info_buffer[len] = 0;
3695                        len += 1 + plci->fax_connect_info_buffer[len];
3696                        if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3697                                plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3698                        plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3699                        for (i = 0; i < fax_parms[7].length; i++)
3700                                plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3701                }
3702                plci->fax_connect_info_length = len;
3703                plci->fax_edata_ack_length = plci->fax_connect_info_length;
3704                start_internal_command(Id, plci, fax_edata_ack_command);
3705                break;
3706
3707        }
3708        return false;
3709}
3710
3711/*------------------------------------------------------------------*/
3712/* IDI callback function                                            */
3713/*------------------------------------------------------------------*/
3714
3715void callback(ENTITY *e)
3716{
3717        DIVA_CAPI_ADAPTER *a;
3718        APPL *appl;
3719        PLCI *plci;
3720        CAPI_MSG *m;
3721        word i, j;
3722        byte rc;
3723        byte ch;
3724        byte req;
3725        byte global_req;
3726        int no_cancel_rc;
3727
3728        dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3729                        (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3730
3731        a = &(adapter[(byte)e->user[0]]);
3732        plci = &(a->plci[e->user[1]]);
3733        no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3734
3735        /*
3736          If new protocol code and new XDI is used then CAPI should work
3737          fully in accordance with IDI cpec an look on callback field instead
3738          of Rc field for return codes.
3739        */
3740        if (((e->complete == 0xff) && no_cancel_rc) ||
3741            (e->Rc && !no_cancel_rc)) {
3742                rc = e->Rc;
3743                ch = e->RcCh;
3744                req = e->Req;
3745                e->Rc = 0;
3746
3747                if (e->user[0] & 0x8000)
3748                {
3749                        /*
3750                          If REMOVE request was sent then we have to wait until
3751                          return code with Id set to zero arrives.
3752                          All other return codes should be ignored.
3753                        */
3754                        if (req == REMOVE)
3755                        {
3756                                if (e->Id)
3757                                {
3758                                        dbug(1, dprintf("cancel RC in REMOVE state"));
3759                                        return;
3760                                }
3761                                channel_flow_control_remove(plci);
3762                                for (i = 0; i < 256; i++)
3763                                {
3764                                        if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3765                                                a->FlowControlIdTable[i] = 0;
3766                                }
3767                                plci->nl_remove_id = 0;
3768                                if (plci->rx_dma_descriptor > 0) {
3769                                        diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3770                                        plci->rx_dma_descriptor = 0;
3771                                }
3772                        }
3773                        if (rc == OK_FC)
3774                        {
3775                                a->FlowControlIdTable[ch] = e->Id;
3776                                a->FlowControlSkipTable[ch] = 0;
3777
3778                                a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3779                                a->ch_flow_plci[ch] = plci->Id;
3780                                plci->nl_req = 0;
3781                        }
3782                        else
3783                        {
3784                                /*
3785                                  Cancel return codes self, if feature was requested
3786                                */
3787                                if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3788                                        a->FlowControlIdTable[ch] = 0;
3789                                        if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3790                                                dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3791                                                return;
3792                                        }
3793                                }
3794
3795                                if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3796                                {
3797                                        a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3798                                        if (ch == e->ReqCh)
3799                                                plci->nl_req = 0;
3800                                }
3801                                else
3802                                        plci->nl_req = 0;
3803                        }
3804                        if (plci->nl_req)
3805                                control_rc(plci, 0, rc, ch, 0, true);
3806                        else
3807                        {
3808                                if (req == N_XON)
3809                                {
3810                                        channel_x_on(plci, ch);
3811                                        if (plci->internal_command)
3812                                                control_rc(plci, req, rc, ch, 0, true);
3813                                }
3814                                else
3815                                {
3816                                        if (plci->nl_global_req)
3817                                        {
3818                                                global_req = plci->nl_global_req;
3819                                                plci->nl_global_req = 0;
3820                                                if (rc != ASSIGN_OK) {
3821                                                        e->Id = 0;
3822                                                        if (plci->rx_dma_descriptor > 0) {
3823                                                                diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3824                                                                plci->rx_dma_descriptor = 0;
3825                                                        }
3826                                                }
3827                                                channel_xmit_xon(plci);
3828                                                control_rc(plci, 0, rc, ch, global_req, true);
3829                                        }
3830                                        else if (plci->data_sent)
3831                                        {
3832                                                channel_xmit_xon(plci);
3833                                                plci->data_sent = false;
3834                                                plci->NL.XNum = 1;
3835                                                data_rc(plci, ch);
3836                                                if (plci->internal_command)
3837                                                        control_rc(plci, req, rc, ch, 0, true);
3838                                        }
3839                                        else
3840                                        {
3841                                                channel_xmit_xon(plci);
3842                                                control_rc(plci, req, rc, ch, 0, true);
3843                                        }
3844                                }
3845                        }
3846                }
3847                else
3848                {
3849                        /*
3850                          If REMOVE request was sent then we have to wait until
3851                          return code with Id set to zero arrives.
3852                          All other return codes should be ignored.
3853                        */
3854                        if (req == REMOVE)
3855                        {
3856                                if (e->Id)
3857                                {
3858                                        dbug(1, dprintf("cancel RC in REMOVE state"));
3859                                        return;
3860                                }
3861                                plci->sig_remove_id = 0;
3862                        }
3863                        plci->sig_req = 0;
3864                        if (plci->sig_global_req)
3865                        {
3866                                global_req = plci->sig_global_req;
3867                                plci->sig_global_req = 0;
3868                                if (rc != ASSIGN_OK)
3869                                        e->Id = 0;
3870                                channel_xmit_xon(plci);
3871                                control_rc(plci, 0, rc, ch, global_req, false);
3872                        }
3873                        else
3874                        {
3875                                channel_xmit_xon(plci);
3876                                control_rc(plci, req, rc, ch, 0, false);
3877                        }
3878                }
3879                /*
3880                  Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3881                  same callback. Also if new XDI and protocol code used then jump
3882                  direct to finish.
3883                */
3884                if (no_cancel_rc) {
3885                        channel_xmit_xon(plci);
3886                        goto capi_callback_suffix;
3887                }
3888        }
3889
3890        channel_xmit_xon(plci);
3891
3892        if (e->Ind) {
3893                if (e->user[0] & 0x8000) {
3894                        byte Ind = e->Ind & 0x0f;
3895                        byte Ch = e->IndCh;
3896                        if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
3897                            (a->ch_flow_plci[Ch] == plci->Id)) {
3898                                if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
3899                                        dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
3900                                }
3901                                a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3902                        }
3903                        nl_ind(plci);
3904                        if ((e->RNR != 1) &&
3905                            (a->ch_flow_plci[Ch] == plci->Id) &&
3906                            (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
3907                                a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3908                                dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
3909                        }
3910                } else {
3911                        sig_ind(plci);
3912                }
3913                e->Ind = 0;
3914        }
3915
3916capi_callback_suffix:
3917
3918        while (!plci->req_in
3919               && !plci->internal_command
3920               && (plci->msg_in_write_pos != plci->msg_in_read_pos))
3921        {
3922                j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
3923
3924                i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
3925
3926                m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
3927                appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
3928                dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
3929                                m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
3930                if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3931                {
3932                        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3933                        plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
3934                }
3935                else
3936                {
3937                        plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
3938                }
3939                if (plci->msg_in_read_pos == plci->msg_in_write_pos)
3940                {
3941                        plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
3942                        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3943                }
3944                else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3945                {
3946                        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3947                        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3948                }
3949                i = api_put(appl, m);
3950                if (i != 0)
3951                {
3952                        if (m->header.command == _DATA_B3_R)
3953
3954                                TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
3955
3956                        dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
3957                        break;
3958                }
3959
3960                if (plci->li_notify_update)
3961                {
3962                        plci->li_notify_update = false;
3963                        mixer_notify_update(plci, false);
3964                }
3965
3966        }
3967        send_data(plci);
3968        send_req(plci);
3969}
3970
3971
3972static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
3973                       byte nl_rc)
3974{
3975        dword Id;
3976        dword rId;
3977        word Number;
3978        word Info = 0;
3979        word i;
3980        word ncci;
3981        DIVA_CAPI_ADAPTER *a;
3982        APPL *appl;
3983        PLCI *rplci;
3984        byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
3985        byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
3986
3987        if (!plci) {
3988                dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
3989                return;
3990        }
3991        dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
3992        if (plci->req_in != plci->req_out)
3993        {
3994                if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
3995                {
3996                        dbug(1, dprintf("req_1return"));
3997                        return;
3998                }
3999                /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4000        }
4001        plci->req_in = plci->req_in_start = plci->req_out = 0;
4002        dbug(1, dprintf("control_rc"));
4003
4004        appl = plci->appl;
4005        a = plci->adapter;
4006        ncci = a->ch_ncci[ch];
4007        if (appl)
4008        {
4009                Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4010                if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4011                Number = plci->number;
4012                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));
4013                dbug(1, dprintf("channels=0x%x", plci->channels));
4014                if (plci_remove_check(plci))
4015                        return;
4016                if (req == REMOVE && rc == ASSIGN_OK)
4017                {
4018                        sig_req(plci, HANGUP, 0);
4019                        sig_req(plci, REMOVE, 0);
4020                        send_req(plci);
4021                }
4022                if (plci->command)
4023                {
4024                        switch (plci->command)
4025                        {
4026                        case C_HOLD_REQ:
4027                                dbug(1, dprintf("HoldRC=0x%x", rc));
4028                                SSparms[1] = (byte)S_HOLD;
4029                                if (rc != OK)
4030                                {
4031                                        plci->SuppState = IDLE;
4032                                        Info = 0x2001;
4033                                }
4034                                sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4035                                break;
4036
4037                        case C_RETRIEVE_REQ:
4038                                dbug(1, dprintf("RetrieveRC=0x%x", rc));
4039                                SSparms[1] = (byte)S_RETRIEVE;
4040                                if (rc != OK)
4041                                {
4042                                        plci->SuppState = CALL_HELD;
4043                                        Info = 0x2001;
4044                                }
4045                                sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4046                                break;
4047
4048                        case _INFO_R:
4049                                dbug(1, dprintf("InfoRC=0x%x", rc));
4050                                if (rc != OK) Info = _WRONG_STATE;
4051                                sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4052                                break;
4053
4054                        case _CONNECT_R:
4055                                dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4056                                if (plci->State == INC_DIS_PENDING)
4057                                        break;
4058                                if (plci->Sig.Id != 0xff)
4059                                {
4060                                        if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4061                                            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4062                                        {
4063                                                dbug(1, dprintf("No more IDs/Call_Req failed"));
4064                                                sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4065                                                plci_remove(plci);
4066                                                plci->State = IDLE;
4067                                                break;
4068                                        }
4069                                        if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4070                                        sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4071                                }
4072                                else /* D-ch activation */
4073                                {
4074                                        if (rc != ASSIGN_OK)
4075                                        {
4076                                                dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4077                                                sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4078                                                plci_remove(plci);
4079                                                plci->State = IDLE;
4080                                                break;
4081                                        }
4082                                        sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4083                                        sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4084                                        plci->State = INC_ACT_PENDING;
4085                                }
4086                                break;
4087
4088                        case _CONNECT_I | RESPONSE:
4089                                if (plci->State != INC_DIS_PENDING)
4090                                        plci->State = INC_CON_ACCEPT;
4091                                break;
4092
4093                        case _DISCONNECT_R:
4094                                if (plci->State == INC_DIS_PENDING)
4095                                        break;
4096                                if (plci->Sig.Id != 0xff)
4097                                {
4098                                        plci->State = OUTG_DIS_PENDING;
4099                                        sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4100                                }
4101                                break;
4102
4103                        case SUSPEND_REQ:
4104                                break;
4105
4106                        case RESUME_REQ:
4107                                break;
4108
4109                        case _CONNECT_B3_R:
4110                                if (rc != OK)
4111                                {
4112                                        sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4113                                        break;
4114                                }
4115                                ncci = get_ncci(plci, ch, 0);
4116                                Id = (Id & 0xffff) | (((dword) ncci) << 16);
4117                                plci->channels++;
4118                                if (req == N_RESET)
4119                                {
4120                                        a->ncci_state[ncci] = INC_ACT_PENDING;
4121                                        sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4122                                        sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4123                                }
4124                                else
4125                                {
4126                                        a->ncci_state[ncci] = OUTG_CON_PENDING;
4127                                        sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4128                                }
4129                                break;
4130
4131                        case _CONNECT_B3_I | RESPONSE:
4132                                break;
4133
4134                        case _RESET_B3_R:
4135/*        sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4136                                break;
4137
4138                        case _DISCONNECT_B3_R:
4139                                sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4140                                break;
4141
4142                        case _MANUFACTURER_R:
4143                                break;
4144
4145                        case PERM_LIST_REQ:
4146                                if (rc != OK)
4147                                {
4148                                        Info = _WRONG_IDENTIFIER;
4149                                        sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4150                                        plci_remove(plci);
4151                                }
4152                                else
4153                                        sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4154                                break;
4155
4156                        default:
4157                                break;
4158                        }
4159                        plci->command = 0;
4160                }
4161                else if (plci->internal_command)
4162                {
4163                        switch (plci->internal_command)
4164                        {
4165                        case BLOCK_PLCI:
4166                                return;
4167
4168                        case GET_MWI_STATE:
4169                                if (rc == OK) /* command supported, wait for indication */
4170                                {
4171                                        return;
4172                                }
4173                                plci_remove(plci);
4174                                break;
4175
4176                                /* Get Supported Services */
4177                        case GETSERV_REQ_PEND:
4178                                if (rc == OK) /* command supported, wait for indication */
4179                                {
4180                                        break;
4181                                }
4182                                PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4183                                sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4184                                plci_remove(plci);
4185                                break;
4186
4187                        case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4188                        case INTERR_NUMBERS_REQ_PEND:
4189                        case CF_START_PEND:                  /* Call Forwarding Start pending */
4190                        case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4191                        case CCBS_REQUEST_REQ_PEND:
4192                        case CCBS_DEACTIVATE_REQ_PEND:
4193                        case CCBS_INTERROGATE_REQ_PEND:
4194                                switch (plci->internal_command)
4195                                {
4196                                case INTERR_DIVERSION_REQ_PEND:
4197                                        SSparms[1] = S_INTERROGATE_DIVERSION;
4198                                        break;
4199                                case INTERR_NUMBERS_REQ_PEND:
4200                                        SSparms[1] = S_INTERROGATE_NUMBERS;
4201                                        break;
4202                                case CF_START_PEND:
4203                                        SSparms[1] = S_CALL_FORWARDING_START;
4204                                        break;
4205                                case CF_STOP_PEND:
4206                                        SSparms[1] = S_CALL_FORWARDING_STOP;
4207                                        break;
4208                                case CCBS_REQUEST_REQ_PEND:
4209                                        SSparms[1] = S_CCBS_REQUEST;
4210                                        break;
4211                                case CCBS_DEACTIVATE_REQ_PEND:
4212                                        SSparms[1] = S_CCBS_DEACTIVATE;
4213                                        break;
4214                                case CCBS_INTERROGATE_REQ_PEND:
4215                                        SSparms[1] = S_CCBS_INTERROGATE;
4216                                        break;
4217                                }
4218                                if (global_req == ASSIGN)
4219                                {
4220                                        dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4221                                        return;
4222                                }
4223                                if (!plci->appl) break;
4224                                if (rc == ISDN_GUARD_REJ)
4225                                {
4226                                        Info = _CAPI_GUARD_ERROR;
4227                                }
4228                                else if (rc != OK)
4229                                {
4230                                        Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4231                                }
4232                                sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4233                                      plci->number, "wws", Info, (word)3, SSparms);
4234                                if (Info) plci_remove(plci);
4235                                break;
4236
4237                                /* 3pty conference pending */
4238                        case PTY_REQ_PEND:
4239                                if (!plci->relatedPTYPLCI) break;
4240                                rplci = plci->relatedPTYPLCI;
4241                                SSparms[1] = plci->ptyState;
4242                                rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4243                                if (rplci->tel) rId |= EXT_CONTROLLER;
4244                                if (rc != OK)
4245                                {
4246                                        Info = 0x300E; /* not supported */
4247                                        plci->relatedPTYPLCI = NULL;
4248                                        plci->ptyState = 0;
4249                                }
4250                                sendf(rplci->appl,
4251                                      _FACILITY_R | CONFIRM,
4252                                      rId,
4253                                      plci->number,
4254                                      "wws", Info, (word)3, SSparms);
4255                                break;
4256
4257                                /* Explicit Call Transfer pending */
4258                        case ECT_REQ_PEND:
4259                                dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4260                                if (!plci->relatedPTYPLCI) break;
4261                                rplci = plci->relatedPTYPLCI;
4262                                SSparms[1] = S_ECT;
4263                                rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4264                                if (rplci->tel) rId |= EXT_CONTROLLER;
4265                                if (rc != OK)
4266                                {
4267                                        Info = 0x300E; /* not supported */
4268                                        plci->relatedPTYPLCI = NULL;
4269                                        plci->ptyState = 0;
4270                                }
4271                                sendf(rplci->appl,
4272                                      _FACILITY_R | CONFIRM,
4273                                      rId,
4274                                      plci->number,
4275                                      "wws", Info, (word)3, SSparms);
4276                                break;
4277
4278                        case _MANUFACTURER_R:
4279                                dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4280                                if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4281                                {
4282                                        dbug(1, dprintf("No more IDs"));
4283                                        sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4284                                        plci_remove(plci);  /* after codec init, internal codec commands pending */
4285                                }
4286                                break;
4287
4288                        case _CONNECT_R:
4289                                dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4290                                if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4291                                {
4292                                        dbug(1, dprintf("No more IDs"));
4293                                        sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4294                                        plci_remove(plci);  /* after codec init, internal codec commands pending */
4295                                }
4296                                break;
4297
4298                        case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4299                                return;
4300
4301                        case PERM_COD_CALL:
4302                                dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4303                                plci->internal_command = PERM_COD_CONN_PEND;
4304                                return;
4305
4306                        case PERM_COD_ASSIGN:
4307                                dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4308                                if (rc != ASSIGN_OK) break;
4309                                sig_req(plci, CALL_REQ, 0);
4310                                send_req(plci);
4311                                plci->internal_command = PERM_COD_CALL;
4312                                return;
4313
4314                                /* Null Call Reference Request pending */
4315                        case C_NCR_FAC_REQ:
4316                                dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4317                                if (global_req == ASSIGN)
4318                                {
4319                                        if (rc == ASSIGN_OK)
4320                                        {
4321                                                return;
4322                                        }
4323                                        else
4324                                        {
4325                                                sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4326                                                appl->NullCREnable = false;
4327                                                plci_remove(plci);
4328                                        }
4329                                }
4330                                else if (req == NCR_FACILITY)
4331                                {
4332                                        if (rc == OK)
4333                                        {
4334                                                sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4335                                        }
4336                                        else
4337                                        {
4338                                                sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4339                                                appl->NullCREnable = false;
4340                                        }
4341                                        plci_remove(plci);
4342                                }
4343                                break;
4344
4345                        case HOOK_ON_REQ:
4346                                if (plci->channels)
4347                                {
4348                                        if (a->ncci_state[ncci] == CONNECTED)
4349                                        {
4350                                                a->ncci_state[ncci] = OUTG_DIS_PENDING;
4351                                                cleanup_ncci_data(plci, ncci);
4352                                                nl_req_ncci(plci, N_DISC, (byte)ncci);
4353                                        }
4354                                        break;
4355                                }
4356                                break;
4357
4358                        case HOOK_OFF_REQ:
4359                                if (plci->State == INC_DIS_PENDING)
4360                                        break;
4361                                sig_req(plci, CALL_REQ, 0);
4362                                send_req(plci);
4363                                plci->State = OUTG_CON_PENDING;
4364                                break;
4365
4366
4367                        case MWI_ACTIVATE_REQ_PEND:
4368                        case MWI_DEACTIVATE_REQ_PEND:
4369                                if (global_req == ASSIGN && rc == ASSIGN_OK)
4370                                {
4371                                        dbug(1, dprintf("MWI_REQ assigned"));
4372                                        return;
4373                                }
4374                                else if (rc != OK)
4375                                {
4376                                        if (rc == WRONG_IE)
4377                                        {
4378                                                Info = 0x2007; /* Illegal message parameter coding */
4379                                                dbug(1, dprintf("MWI_REQ invalid parameter"));
4380                                        }
4381                                        else
4382                                        {
4383                                                Info = 0x300B; /* not supported */
4384                                                dbug(1, dprintf("MWI_REQ not supported"));
4385                                        }
4386                                        /* 0x3010: Request not allowed in this state */
4387                                        PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4388
4389                                }
4390                                if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4391                                {
4392                                        PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4393                                }
4394                                else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4395
4396                                if (plci->cr_enquiry)
4397                                {
4398                                        sendf(plci->appl,
4399                                              _FACILITY_R | CONFIRM,
4400                                              Id & 0xf,
4401                                              plci->number,
4402                                              "wws", Info, (word)3, SSparms);
4403                                        if (rc != OK) plci_remove(plci);
4404                                }
4405                                else
4406                                {
4407                                        sendf(plci->appl,
4408                                              _FACILITY_R | CONFIRM,
4409                                              Id,
4410                                              plci->number,
4411                                              "wws", Info, (word)3, SSparms);
4412                                }
4413                                break;
4414
4415                        case CONF_BEGIN_REQ_PEND:
4416                        case CONF_ADD_REQ_PEND:
4417                        case CONF_SPLIT_REQ_PEND:
4418                        case CONF_DROP_REQ_PEND:
4419                        case CONF_ISOLATE_REQ_PEND:
4420                        case CONF_REATTACH_REQ_PEND:
4421                                dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4422                                if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4423                                rplci = plci;
4424                                rId = Id;
4425                                switch (plci->internal_command)
4426                                {
4427                                case CONF_BEGIN_REQ_PEND:
4428                                        SSparms[1] = S_CONF_BEGIN;
4429                                        break;
4430                                case CONF_ADD_REQ_PEND:
4431                                        SSparms[1] = S_CONF_ADD;
4432                                        rplci = plci->relatedPTYPLCI;
4433                                        rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4434                                        break;
4435                                case CONF_SPLIT_REQ_PEND:
4436                                        SSparms[1] = S_CONF_SPLIT;
4437                                        break;
4438                                case CONF_DROP_REQ_PEND:
4439                                        SSparms[1] = S_CONF_DROP;
4440                                        break;
4441                                case CONF_ISOLATE_REQ_PEND:
4442                                        SSparms[1] = S_CONF_ISOLATE;
4443                                        break;
4444                                case CONF_REATTACH_REQ_PEND:
4445                                        SSparms[1] = S_CONF_REATTACH;
4446                                        break;
4447                                }
4448
4449                                if (rc != OK)
4450                                {
4451                                        Info = 0x300E; /* not supported */
4452                                        plci->relatedPTYPLCI = NULL;
4453                                        plci->ptyState = 0;
4454                                }
4455                                sendf(rplci->appl,
4456                                      _FACILITY_R | CONFIRM,
4457                                      rId,
4458                                      plci->number,
4459                                      "wws", Info, (word)3, SSparms);
4460                                break;
4461
4462                        case VSWITCH_REQ_PEND:
4463                                if (rc != OK)
4464                                {
4465                                        if (plci->relatedPTYPLCI)
4466                                        {
4467                                                plci->relatedPTYPLCI->vswitchstate = 0;
4468                                                plci->relatedPTYPLCI->vsprot = 0;
4469                                                plci->relatedPTYPLCI->vsprotdialect = 0;
4470                                        }
4471                                        plci->vswitchstate = 0;
4472                                        plci->vsprot = 0;
4473                                        plci->vsprotdialect = 0;
4474                                }
4475                                else
4476                                {
4477                                        if (plci->relatedPTYPLCI &&
4478                                            plci->vswitchstate == 1 &&
4479                                            plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4480                                                plci->vswitchstate = 3;
4481                                }
4482                                break;
4483
4484                                /* Call Deflection Request pending (SSCT) */
4485                        case CD_REQ_PEND:
4486                                SSparms[1] = S_CALL_DEFLECTION;
4487                                if (rc != OK)
4488                                {
4489                                        Info = 0x300E; /* not supported */
4490                                        plci->appl->CDEnable = 0;
4491                                }
4492                                sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4493                                      plci->number, "wws", Info, (word)3, SSparms);
4494                                break;
4495
4496                        case RTP_CONNECT_B3_REQ_COMMAND_2:
4497                                if (rc == OK)
4498                                {
4499                                        ncci = get_ncci(plci, ch, 0);
4500                                        Id = (Id & 0xffff) | (((dword) ncci) << 16);
4501                                        plci->channels++;
4502                                        a->ncci_state[ncci] = OUTG_CON_PENDING;
4503                                }
4504                                /* fall through */
4505
4506                        default:
4507                                if (plci->internal_command_queue[0])
4508                                {
4509                                        (*(plci->internal_command_queue[0]))(Id, plci, rc);
4510                                        if (plci->internal_command)
4511                                                return;
4512                                }
4513                                break;
4514                        }
4515                        next_internal_command(Id, plci);
4516                }
4517        }
4518        else /* appl==0 */
4519        {
4520                Id = ((word)plci->Id << 8) | plci->adapter->Id;
4521                if (plci->tel) Id |= EXT_CONTROLLER;
4522
4523                switch (plci->internal_command)
4524                {
4525                case BLOCK_PLCI:
4526                        return;
4527
4528                case START_L1_SIG_ASSIGN_PEND:
4529                case REM_L1_SIG_ASSIGN_PEND:
4530                        if (global_req == ASSIGN)
4531                        {
4532                                break;
4533                        }
4534                        else
4535                        {
4536                                dbug(1, dprintf("***L1 Req rem PLCI"));
4537                                plci->internal_command = 0;
4538                                sig_req(plci, REMOVE, 0);
4539                                send_req(plci);
4540                        }
4541                        break;
4542
4543                        /* Call Deflection Request pending, just no appl ptr assigned */
4544                case CD_REQ_PEND:
4545                        SSparms[1] = S_CALL_DEFLECTION;
4546                        if (rc != OK)
4547                        {
4548                                Info = 0x300E; /* not supported */
4549                        }
4550                        for (i = 0; i < max_appl; i++)
4551                        {
4552                                if (application[i].CDEnable)
4553                                {
4554                                        if (!application[i].Id) application[i].CDEnable = 0;
4555                                        else
4556                                        {
4557                                                sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4558                                                      plci->number, "wws", Info, (word)3, SSparms);
4559                                                if (Info) application[i].CDEnable = 0;
4560                                        }
4561                                }
4562                        }
4563                        plci->internal_command = 0;
4564                        break;
4565
4566                case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4567                        return;
4568
4569                case PERM_COD_CALL:
4570                        plci->internal_command = PERM_COD_CONN_PEND;
4571                        dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4572                        return;
4573
4574                case PERM_COD_ASSIGN:
4575                        dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4576                        plci->internal_command = 0;
4577                        if (rc != ASSIGN_OK) break;
4578                        plci->internal_command = PERM_COD_CALL;
4579                        sig_req(plci, CALL_REQ, 0);
4580                        send_req(plci);
4581                        return;
4582
4583                case LISTEN_SIG_ASSIGN_PEND:
4584                        if (rc == ASSIGN_OK)
4585                        {
4586                                plci->internal_command = 0;
4587                                dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4588                                add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4589                                sig_req(plci, INDICATE_REQ, 0);
4590                                send_req(plci);
4591                        }
4592                        else
4593                        {
4594                                dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4595                                a->listen_active--;
4596                                plci_remove(plci);
4597                                plci->State = IDLE;
4598                        }
4599                        break;
4600
4601                case USELAW_REQ:
4602                        if (global_req == ASSIGN)
4603                        {
4604                                if (rc == ASSIGN_OK)
4605                                {
4606                                        sig_req(plci, LAW_REQ, 0);
4607                                        send_req(plci);
4608                                        dbug(1, dprintf("Auto-Law assigned"));
4609                                }
4610                                else
4611                                {
4612                                        dbug(1, dprintf("Auto-Law assign failed"));
4613                                        a->automatic_law = 3;
4614                                        plci->internal_command = 0;
4615                                        a->automatic_lawPLCI = NULL;
4616                                }
4617                                break;
4618                        }
4619                        else if (req == LAW_REQ && rc == OK)
4620                        {
4621                                dbug(1, dprintf("Auto-Law initiated"));
4622                                a->automatic_law = 2;
4623                                plci->internal_command = 0;
4624                        }
4625                        else
4626                        {
4627                                dbug(1, dprintf("Auto-Law not supported"));
4628                                a->automatic_law = 3;
4629                                plci->internal_command = 0;
4630                                sig_req(plci, REMOVE, 0);
4631                                send_req(plci);
4632                                a->automatic_lawPLCI = NULL;
4633                        }
4634                        break;
4635                }
4636                plci_remove_check(plci);
4637        }
4638}
4639
4640static void data_rc(PLCI *plci, byte ch)
4641{
4642        dword Id;
4643        DIVA_CAPI_ADAPTER *a;
4644        NCCI *ncci_ptr;
4645        DATA_B3_DESC *data;
4646        word ncci;
4647
4648        if (plci->appl)
4649        {
4650                TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4651                a = plci->adapter;
4652                ncci = a->ch_ncci[ch];
4653                if (ncci && (a->ncci_plci[ncci] == plci->Id))
4654                {
4655                        ncci_ptr = &(a->ncci[ncci]);
4656                        dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4657                        if (ncci_ptr->data_pending)
4658                        {
4659                                data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4660                                if (!(data->Flags & 4) && a->ncci_state[ncci])
4661                                {
4662                                        Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4663                                        if (plci->tel) Id |= EXT_CONTROLLER;
4664                                        sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4665                                              "ww", data->Handle, 0);
4666                                }
4667                                (ncci_ptr->data_out)++;
4668                                if (ncci_ptr->data_out == MAX_DATA_B3)
4669                                        ncci_ptr->data_out = 0;
4670                                (ncci_ptr->data_pending)--;
4671                        }
4672                }
4673        }
4674}
4675
4676static void data_ack(PLCI *plci, byte ch)
4677{
4678        dword Id;
4679        DIVA_CAPI_ADAPTER *a;
4680        NCCI *ncci_ptr;
4681        word ncci;
4682
4683        a = plci->adapter;
4684        ncci = a->ch_ncci[ch];
4685        ncci_ptr = &(a->ncci[ncci]);
4686        if (ncci_ptr->data_ack_pending)
4687        {
4688                if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4689                {
4690                        Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4691                        if (plci->tel) Id |= EXT_CONTROLLER;
4692                        sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4693                              "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4694                }
4695                (ncci_ptr->data_ack_out)++;
4696                if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4697                        ncci_ptr->data_ack_out = 0;
4698                (ncci_ptr->data_ack_pending)--;
4699        }
4700}
4701
4702static void sig_ind(PLCI *plci)
4703{
4704        dword x_Id;
4705        dword Id;
4706        dword rId;
4707        word i;
4708        word cip;
4709        dword cip_mask;
4710        byte *ie;
4711        DIVA_CAPI_ADAPTER *a;
4712        API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4713#define MAXPARMSIDS 31
4714        byte *parms[MAXPARMSIDS];
4715        byte *add_i[4];
4716        byte *multi_fac_parms[MAX_MULTI_IE];
4717        byte *multi_pi_parms[MAX_MULTI_IE];
4718        byte *multi_ssext_parms[MAX_MULTI_IE];
4719        byte *multi_CiPN_parms[MAX_MULTI_IE];
4720
4721        byte *multi_vswitch_parms[MAX_MULTI_IE];
4722
4723        byte ai_len;
4724        byte *esc_chi = "";
4725        byte *esc_law = "";
4726        byte *pty_cai = "";
4727        byte *esc_cr  = "";
4728        byte *esc_profile = "";
4729
4730        byte facility[256];
4731        PLCI *tplci = NULL;
4732        byte chi[] = "\x02\x18\x01";
4733        byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4734        byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4735        /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4736        /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4737        /* SMSG is situated at the end because its 0 (for compatibility reasons */
4738        /* (see Info_Mask Bit 4, first IE. then the message type)           */
4739        static const word parms_id[] =
4740                {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4741                 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4742                 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4743                 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4744        /* 14 FTY repl by ESC_CHI */
4745        /* 18 PI  repl by ESC_LAW */
4746        /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4747        static const word multi_fac_id[] = {1, FTY};
4748        static const word multi_pi_id[]  = {1, PI};
4749        static const word multi_CiPN_id[]  = {1, OAD};
4750        static const word multi_ssext_id[]  = {1, ESC_SSEXT};
4751
4752        static const word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4753
4754        byte *cau;
4755        word ncci;
4756        byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4757        byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4758        byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4759        byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4760        byte force_mt_info = false;
4761        byte dir;
4762        dword d;
4763        word w;
4764
4765        a = plci->adapter;
4766        Id = ((word)plci->Id << 8) | a->Id;
4767        PUT_WORD(&SS_Ind[4], 0x0000);
4768
4769        if (plci->sig_remove_id)
4770        {
4771                plci->Sig.RNR = 2; /* discard */
4772                dbug(1, dprintf("SIG discard while remove pending"));
4773                return;
4774        }
4775        if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4776        dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4777                        Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4778        if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4779        {
4780                plci->Sig.RNR = 1;
4781                return;
4782        }
4783        if (plci->Sig.Ind == HANGUP && plci->channels)
4784        {
4785                plci->Sig.RNR = 1;
4786                plci->hangup_flow_ctrl_timer++;
4787                /* recover the network layer after timeout */
4788                if (plci->hangup_flow_ctrl_timer == 100)
4789                {
4790                        dbug(1, dprintf("Exceptional disc"));
4791                        plci->Sig.RNR = 0;
4792                        plci->hangup_flow_ctrl_timer = 0;
4793                        for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4794                        {
4795                                if (a->ncci_plci[ncci] == plci->Id)
4796                                {
4797                                        cleanup_ncci_data(plci, ncci);
4798                                        if (plci->channels)plci->channels--;
4799                                        if (plci->appl)
4800                                                sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4801                                }
4802                        }
4803                        if (plci->appl)
4804                                sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4805                        plci_remove(plci);
4806                        plci->State = IDLE;
4807                }
4808                return;
4809        }
4810
4811        /* do first parse the info with no OAD in, because OAD will be converted */
4812        /* first the multiple facility IE, then mult. progress ind.              */
4813        /* then the parameters for the info_ind + conn_ind                       */
4814        IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4815        IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4816        IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4817
4818        IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4819
4820        IndParse(plci, parms_id, parms, 0);
4821        IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4822        esc_chi  = parms[14];
4823        esc_law  = parms[18];
4824        pty_cai  = parms[24];
4825        esc_cr   = parms[25];
4826        esc_profile = parms[27];
4827        if (esc_cr[0] && plci)
4828        {
4829                if (plci->cr_enquiry && plci->appl)
4830                {
4831                        plci->cr_enquiry = false;
4832                        /* d = MANU_ID            */
4833                        /* w = m_command          */
4834                        /* b = total length       */
4835                        /* b = indication type    */
4836                        /* b = length of all IEs  */
4837                        /* b = IE1                */
4838                        /* S = IE1 length + cont. */
4839                        /* b = IE2                */
4840                        /* S = IE2 length + cont. */
4841                        sendf(plci->appl,
4842                              _MANUFACTURER_I,
4843                              Id,
4844                              0,
4845                              "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4846                              2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4847                }
4848        }
4849        /* create the additional info structure                                  */
4850        add_i[1] = parms[15]; /* KEY of additional info */
4851        add_i[2] = parms[11]; /* UUI of additional info */
4852        ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4853
4854        /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4855        /* indication returns by the card if requested by the function           */
4856        /* AutomaticLaw() after driver init                                      */
4857        if (a->automatic_law < 4)
4858        {
4859                if (esc_law[0]) {
4860                        if (esc_law[2]) {
4861                                dbug(0, dprintf("u-Law selected"));
4862                                a->u_law = 1;
4863                        }
4864                        else {
4865                                dbug(0, dprintf("a-Law selected"));
4866                                a->u_law = 0;
4867                        }
4868                        a->automatic_law = 4;
4869                        if (plci == a->automatic_lawPLCI) {
4870                                plci->internal_command = 0;
4871                                sig_req(plci, REMOVE, 0);
4872                                send_req(plci);
4873                                a->automatic_lawPLCI = NULL;
4874                        }
4875                }
4876                if (esc_profile[0])
4877                {
4878                        dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4879                                        UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4880                                        GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4881                                        GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4882
4883                        a->profile.Global_Options &= 0x000000ffL;
4884                        a->profile.B1_Protocols &= 0x000003ffL;
4885                        a->profile.B2_Protocols &= 0x00001fdfL;
4886                        a->profile.B3_Protocols &= 0x000000b7L;
4887
4888                        a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4889                                GL_BCHANNEL_OPERATION_SUPPORTED;
4890                        a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4891                        a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4892                        a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4893                        a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4894                        a->man_profile.private_options = 0;
4895
4896                        if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4897                        {
4898                                a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4899                                a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4900                        }
4901
4902
4903                        if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4904                                a->man_profile.private_options |= 1L << PRIVATE_RTP;
4905                        a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4906                        a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4907
4908
4909                        if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4910                                a->man_profile.private_options |= 1L << PRIVATE_T38;
4911
4912
4913                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4914                                a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4915
4916
4917                        if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4918                                a->man_profile.private_options |= 1L << PRIVATE_V18;
4919
4920
4921                        if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4922                                a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4923
4924
4925                        if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4926                                a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4927
4928
4929                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4930                                a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4931
4932
4933                        if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4934                                a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4935
4936
4937                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4938                                a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4939
4940                }
4941                else
4942                {
4943                        a->profile.Global_Options &= 0x0000007fL;
4944                        a->profile.B1_Protocols &= 0x000003dfL;
4945                        a->profile.B2_Protocols &= 0x00001adfL;
4946                        a->profile.B3_Protocols &= 0x000000b7L;
4947                        a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4948                }
4949                if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4950                                                MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4951                {
4952                        a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4953                }
4954                a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4955                dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4956                                UnMapController(a->Id), a->profile.Global_Options,
4957                                a->profile.B1_Protocols, a->profile.B2_Protocols,
4958                                a->profile.B3_Protocols, a->manufacturer_features));
4959        }
4960        /* codec plci for the handset/hook state support is just an internal id  */
4961        if (plci != a->AdvCodecPLCI)
4962        {
4963                force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4964                force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4965                SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4966                SendInfo(plci, Id, parms, force_mt_info);
4967
4968                VSwitchReqInd(plci, Id, multi_vswitch_parms);
4969
4970        }
4971
4972        /* switch the codec to the b-channel                                     */
4973        if (esc_chi[0] && plci && !plci->SuppState) {
4974                plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4975                mixer_set_bchannel_id_esc(plci, plci->b_channel);
4976                dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4977                if (plci->tel == ADV_VOICE && plci->appl) {
4978                        SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4979                }
4980        }
4981
4982        if (plci->appl) plci->appl->Number++;
4983
4984        switch (plci->Sig.Ind) {
4985                /* Response to Get_Supported_Services request */
4986        case S_SUPPORTED:
4987                dbug(1, dprintf("S_Supported"));
4988                if (!plci->appl) break;
4989                if (pty_cai[0] == 4)
4990                {
4991                        PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4992                }
4993                else
4994                {
4995                        PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4996                }
4997                PUT_WORD(&CF_Ind[1], 0);
4998                PUT_WORD(&CF_Ind[4], 0);
4999                sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5000                plci_remove(plci);
5001                break;
5002
5003                /* Supplementary Service rejected */
5004        case S_SERVICE_REJ:
5005                dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5006                if (!pty_cai[0]) break;
5007                switch (pty_cai[5])
5008                {
5009                case ECT_EXECUTE:
5010                case THREE_PTY_END:
5011                case THREE_PTY_BEGIN:
5012                        if (!plci->relatedPTYPLCI) break;
5013                        tplci = plci->relatedPTYPLCI;
5014                        rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5015                        if (tplci->tel) rId |= EXT_CONTROLLER;
5016                        if (pty_cai[5] == ECT_EXECUTE)
5017                        {
5018                                PUT_WORD(&SS_Ind[1], S_ECT);
5019
5020                                plci->vswitchstate = 0;
5021                                plci->relatedPTYPLCI->vswitchstate = 0;
5022
5023                        }
5024                        else
5025                        {
5026                                PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5027                        }
5028                        if (pty_cai[2] != 0xff)
5029                        {
5030                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5031                        }
5032                        else
5033                        {
5034                                PUT_WORD(&SS_Ind[4], 0x300E);
5035                        }
5036                        plci->relatedPTYPLCI = NULL;
5037                        plci->ptyState = 0;
5038                        sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5039                        break;
5040
5041                case CALL_DEFLECTION:
5042                        if (pty_cai[2] != 0xff)
5043                        {
5044                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5045                        }
5046                        else
5047                        {
5048                                PUT_WORD(&SS_Ind[4], 0x300E);
5049                        }
5050                        PUT_WORD(&SS_Ind[1], pty_cai[5]);
5051                        for (i = 0; i < max_appl; i++)
5052                        {
5053                                if (application[i].CDEnable)
5054                                {
5055                                        if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5056                                        application[i].CDEnable = false;
5057                                }
5058                        }
5059                        break;
5060
5061                case DEACTIVATION_DIVERSION:
5062                case ACTIVATION_DIVERSION:
5063                case DIVERSION_INTERROGATE_CFU:
5064                case DIVERSION_INTERROGATE_CFB:
5065                case DIVERSION_INTERROGATE_CFNR:
5066                case DIVERSION_INTERROGATE_NUM:
5067                case CCBS_REQUEST:
5068                case CCBS_DEACTIVATE:
5069                case CCBS_INTERROGATE:
5070                        if (!plci->appl) break;
5071                        if (pty_cai[2] != 0xff)
5072                        {
5073                                PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5074                        }
5075                        else
5076                        {
5077                                PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5078                        }
5079                        switch (pty_cai[5])
5080                        {
5081                        case DEACTIVATION_DIVERSION:
5082                                dbug(1, dprintf("Deact_Div"));
5083                                Interr_Err_Ind[0] = 0x9;
5084                                Interr_Err_Ind[3] = 0x6;
5085                                PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5086                                break;
5087                        case ACTIVATION_DIVERSION:
5088                                dbug(1, dprintf("Act_Div"));
5089                                Interr_Err_Ind[0] = 0x9;
5090                                Interr_Err_Ind[3] = 0x6;
5091                                PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5092                                break;
5093                        case DIVERSION_INTERROGATE_CFU:
5094                        case DIVERSION_INTERROGATE_CFB:
5095                        case DIVERSION_INTERROGATE_CFNR:
5096                                dbug(1, dprintf("Interr_Div"));
5097                                Interr_Err_Ind[0] = 0xa;
5098                                Interr_Err_Ind[3] = 0x7;
5099                                PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5100                                break;
5101                        case DIVERSION_INTERROGATE_NUM:
5102                                dbug(1, dprintf("Interr_Num"));
5103                                Interr_Err_Ind[0] = 0xa;
5104                                Interr_Err_Ind[3] = 0x7;
5105                                PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5106                                break;
5107                        case CCBS_REQUEST:
5108                                dbug(1, dprintf("CCBS Request"));
5109                                Interr_Err_Ind[0] = 0xd;
5110                                Interr_Err_Ind[3] = 0xa;
5111                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5112                                break;
5113                        case CCBS_DEACTIVATE:
5114                                dbug(1, dprintf("CCBS Deactivate"));
5115                                Interr_Err_Ind[0] = 0x9;
5116                                Interr_Err_Ind[3] = 0x6;
5117                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5118                                break;
5119                        case CCBS_INTERROGATE:
5120                                dbug(1, dprintf("CCBS Interrogate"));
5121                                Interr_Err_Ind[0] = 0xb;
5122                                Interr_Err_Ind[3] = 0x8;
5123                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5124                                break;
5125                        }
5126                        PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5127                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5128                        plci_remove(plci);
5129                        break;
5130                case ACTIVATION_MWI:
5131                case DEACTIVATION_MWI:
5132                        if (pty_cai[5] == ACTIVATION_MWI)
5133                        {
5134                                PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5135                        }
5136                        else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5137
5138                        if (pty_cai[2] != 0xff)
5139                        {
5140                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5141                        }
5142                        else
5143                        {
5144                                PUT_WORD(&SS_Ind[4], 0x300E);
5145                        }
5146
5147                        if (plci->cr_enquiry)
5148                        {
5149                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5150                                plci_remove(plci);
5151                        }
5152                        else
5153                        {
5154                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5155                        }
5156                        break;
5157                case CONF_ADD: /* ERROR */
5158                case CONF_BEGIN:
5159                case CONF_DROP:
5160                case CONF_ISOLATE:
5161                case CONF_REATTACH:
5162                        CONF_Ind[0] = 9;
5163                        CONF_Ind[3] = 6;
5164                        switch (pty_cai[5])
5165                        {
5166                        case CONF_BEGIN:
5167                                PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5168                                plci->ptyState = 0;
5169                                break;
5170                        case CONF_DROP:
5171                                CONF_Ind[0] = 5;
5172                                CONF_Ind[3] = 2;
5173                                PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5174                                plci->ptyState = CONNECTED;
5175                                break;
5176                        case CONF_ISOLATE:
5177                                CONF_Ind[0] = 5;
5178                                CONF_Ind[3] = 2;
5179                                PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5180                                plci->ptyState = CONNECTED;
5181                                break;
5182                        case CONF_REATTACH:
5183                                CONF_Ind[0] = 5;
5184                                CONF_Ind[3] = 2;
5185                                PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5186                                plci->ptyState = CONNECTED;
5187                                break;
5188                        case CONF_ADD:
5189                                PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5190                                plci->relatedPTYPLCI = NULL;
5191                                tplci = plci->relatedPTYPLCI;
5192                                if (tplci) tplci->ptyState = CONNECTED;
5193                                plci->ptyState = CONNECTED;
5194                                break;
5195                        }
5196
5197                        if (pty_cai[2] != 0xff)
5198                        {
5199                                PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5200                        }
5201                        else
5202                        {
5203                                PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5204                                                                  within the required time */
5205                        }
5206
5207                        PUT_DWORD(&CONF_Ind[6], 0x0);
5208                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5209                        break;
5210                }
5211                break;
5212
5213                /* Supplementary Service indicates success */
5214        case S_SERVICE:
5215                dbug(1, dprintf("Service_Ind"));
5216                PUT_WORD(&CF_Ind[4], 0);
5217                switch (pty_cai[5])
5218                {
5219                case THREE_PTY_END:
5220                case THREE_PTY_BEGIN:
5221                case ECT_EXECUTE:
5222                        if (!plci->relatedPTYPLCI) break;
5223                        tplci = plci->relatedPTYPLCI;
5224                        rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5225                        if (tplci->tel) rId |= EXT_CONTROLLER;
5226                        if (pty_cai[5] == ECT_EXECUTE)
5227                        {
5228                                PUT_WORD(&SS_Ind[1], S_ECT);
5229
5230                                if (plci->vswitchstate != 3)
5231                                {
5232
5233                                        plci->ptyState = IDLE;
5234                                        plci->relatedPTYPLCI = NULL;
5235                                        plci->ptyState = 0;
5236
5237                                }
5238
5239                                dbug(1, dprintf("ECT OK"));
5240                                sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5241
5242
5243
5244                        }
5245                        else
5246                        {
5247                                switch (plci->ptyState)
5248                                {
5249                                case S_3PTY_BEGIN:
5250                                        plci->ptyState = CONNECTED;
5251                                        dbug(1, dprintf("3PTY ON"));
5252                                        break;
5253
5254                                case S_3PTY_END:
5255                                        plci->ptyState = IDLE;
5256                                        plci->relatedPTYPLCI = NULL;
5257                                        plci->ptyState = 0;
5258                                        dbug(1, dprintf("3PTY OFF"));
5259                                        break;
5260                                }
5261                                PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5262                                sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5263                        }
5264                        break;
5265
5266                case CALL_DEFLECTION:
5267                        PUT_WORD(&SS_Ind[1], pty_cai[5]);
5268                        for (i = 0; i < max_appl; i++)
5269                        {
5270                                if (application[i].CDEnable)
5271                                {
5272                                        if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5273                                        application[i].CDEnable = false;
5274                                }
5275                        }
5276                        break;
5277
5278                case DEACTIVATION_DIVERSION:
5279                case ACTIVATION_DIVERSION:
5280                        if (!plci->appl) break;
5281                        PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5282                        PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5283                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5284                        plci_remove(plci);
5285                        break;
5286
5287                case DIVERSION_INTERROGATE_CFU:
5288                case DIVERSION_INTERROGATE_CFB:
5289                case DIVERSION_INTERROGATE_CFNR:
5290                case DIVERSION_INTERROGATE_NUM:
5291                case CCBS_REQUEST:
5292                case CCBS_DEACTIVATE:
5293                case CCBS_INTERROGATE:
5294                        if (!plci->appl) break;
5295                        switch (pty_cai[5])
5296                        {
5297                        case DIVERSION_INTERROGATE_CFU:
5298                        case DIVERSION_INTERROGATE_CFB:
5299                        case DIVERSION_INTERROGATE_CFNR:
5300                                dbug(1, dprintf("Interr_Div"));
5301                                PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5302                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5303                                break;
5304                        case DIVERSION_INTERROGATE_NUM:
5305                                dbug(1, dprintf("Interr_Num"));
5306                                PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5307                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5308                                break;
5309                        case CCBS_REQUEST:
5310                                dbug(1, dprintf("CCBS Request"));
5311                                PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5312                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5313                                break;
5314                        case CCBS_DEACTIVATE:
5315                                dbug(1, dprintf("CCBS Deactivate"));
5316                                PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5317                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5318                                break;
5319                        case CCBS_INTERROGATE:
5320                                dbug(1, dprintf("CCBS Interrogate"));
5321                                PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5322                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5323                                break;
5324                        }
5325                        PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5326                        PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5327                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5328                        plci_remove(plci);
5329                        break;
5330
5331                case ACTIVATION_MWI:
5332                case DEACTIVATION_MWI:
5333                        if (pty_cai[5] == ACTIVATION_MWI)
5334                        {
5335                                PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5336                        }
5337                        else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5338                        if (plci->cr_enquiry)
5339                        {
5340                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5341                                plci_remove(plci);
5342                        }
5343                        else
5344                        {
5345                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5346                        }
5347                        break;
5348                case MWI_INDICATION:
5349                        if (pty_cai[0] >= 0x12)
5350                        {
5351                                PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5352                                pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5353                                pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5354                                if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5355                                {
5356                                        if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5357                                        {
5358                                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5359                                                plci_remove(plci);
5360                                                return;
5361                                        }
5362                                        else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5363                                        pty_cai[0] = 0;
5364                                }
5365                                else
5366                                {
5367                                        for (i = 0; i < max_appl; i++)
5368                                        {
5369                                                if (a->Notification_Mask[i]&SMASK_MWI)
5370                                                {
5371                                                        sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5372                                                        pty_cai[0] = 0;
5373                                                }
5374                                        }
5375                                }
5376
5377                                if (!pty_cai[0])
5378                                { /* acknowledge */
5379                                        facility[2] = 0; /* returncode */
5380                                }
5381                                else facility[2] = 0xff;
5382                        }
5383                        else
5384                        {
5385                                /* reject */
5386                                facility[2] = 0xff; /* returncode */
5387                        }
5388                        facility[0] = 2;
5389                        facility[1] = MWI_RESPONSE; /* Function */
5390                        add_p(plci, CAI, facility);
5391                        add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5392                        sig_req(plci, S_SERVICE, 0);
5393                        send_req(plci);
5394                        plci->command = 0;
5395                        next_internal_command(Id, plci);
5396                        break;
5397                case CONF_ADD: /* OK */
5398                case CONF_BEGIN:
5399                case CONF_DROP:
5400                case CONF_ISOLATE:
5401                case CONF_REATTACH:
5402                case CONF_PARTYDISC:
5403                        CONF_Ind[0] = 9;
5404                        CONF_Ind[3] = 6;
5405                        switch (pty_cai[5])
5406                        {
5407                        case CONF_BEGIN:
5408                                PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5409                                if (pty_cai[0] == 6)
5410                                {
5411                                        d = pty_cai[6];
5412                                        PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5413                                }
5414                                else
5415                                {
5416                                        PUT_DWORD(&CONF_Ind[6], 0x0);
5417                                }
5418                                break;
5419                        case CONF_ISOLATE:
5420                                PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5421                                CONF_Ind[0] = 5;
5422                                CONF_Ind[3] = 2;
5423                                break;
5424                        case CONF_REATTACH:
5425                                PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5426                                CONF_Ind[0] = 5;
5427                                CONF_Ind[3] = 2;
5428                                break;
5429                        case CONF_DROP:
5430                                PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5431                                CONF_Ind[0] = 5;
5432                                CONF_Ind[3] = 2;
5433                                break;
5434                        case CONF_ADD:
5435                                PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5436                                d = pty_cai[6];
5437                                PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5438                                tplci = plci->relatedPTYPLCI;
5439                                if (tplci) tplci->ptyState = CONNECTED;
5440                                break;
5441                        case CONF_PARTYDISC:
5442                                CONF_Ind[0] = 7;
5443                                CONF_Ind[3] = 4;
5444                                PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5445                                d = pty_cai[6];
5446                                PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5447                                break;
5448                        }
5449                        plci->ptyState = CONNECTED;
5450                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5451                        break;
5452                case CCBS_INFO_RETAIN:
5453                case CCBS_ERASECALLLINKAGEID:
5454                case CCBS_STOP_ALERTING:
5455                        CONF_Ind[0] = 5;
5456                        CONF_Ind[3] = 2;
5457                        switch (pty_cai[5])
5458                        {
5459                        case CCBS_INFO_RETAIN:
5460                                PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5461                                break;
5462                        case CCBS_STOP_ALERTING:
5463                                PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5464                                break;
5465                        case CCBS_ERASECALLLINKAGEID:
5466                                PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5467                                CONF_Ind[0] = 7;
5468                                CONF_Ind[3] = 4;
5469                                CONF_Ind[6] = 0;
5470                                CONF_Ind[7] = 0;
5471                                break;
5472                        }
5473                        w = pty_cai[6];
5474                        PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5475
5476                        if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5477                        {
5478                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5479                        }
5480                        else
5481                        {
5482                                for (i = 0; i < max_appl; i++)
5483                                        if (a->Notification_Mask[i] & SMASK_CCBS)
5484                                                sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5485                        }
5486                        break;
5487                }
5488                break;
5489        case CALL_HOLD_REJ:
5490                cau = parms[7];
5491                if (cau)
5492                {
5493                        i = _L3_CAUSE | cau[2];
5494                        if (cau[2] == 0) i = 0x3603;
5495                }
5496                else
5497                {
5498                        i = 0x3603;
5499                }
5500                PUT_WORD(&SS_Ind[1], S_HOLD);
5501                PUT_WORD(&SS_Ind[4], i);
5502                if (plci->SuppState == HOLD_REQUEST)
5503                {
5504                        plci->SuppState = IDLE;
5505                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5506                }
5507                break;
5508
5509        case CALL_HOLD_ACK:
5510                if (plci->SuppState == HOLD_REQUEST)
5511                {
5512                        plci->SuppState = CALL_HELD;
5513                        CodecIdCheck(a, plci);
5514                        start_internal_command(Id, plci, hold_save_command);
5515                }
5516                break;
5517
5518        case CALL_RETRIEVE_REJ:
5519                cau = parms[7];
5520                if (cau)
5521                {
5522                        i = _L3_CAUSE | cau[2];
5523                        if (cau[2] == 0) i = 0x3603;
5524                }
5525                else
5526                {
5527                        i = 0x3603;
5528                }
5529                PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5530                PUT_WORD(&SS_Ind[4], i);
5531                if (plci->SuppState == RETRIEVE_REQUEST)
5532                {
5533                        plci->SuppState = CALL_HELD;
5534                        CodecIdCheck(a, plci);
5535                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5536                }
5537                break;
5538
5539        case CALL_RETRIEVE_ACK:
5540                PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5541                if (plci->SuppState == RETRIEVE_REQUEST)
5542                {
5543                        plci->SuppState = IDLE;
5544                        plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5545                        plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5546                        if (plci->tel)
5547                        {
5548                                mixer_set_bchannel_id_esc(plci, plci->b_channel);
5549                                dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5550                                SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5551                                if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5552                                {
5553                                        dbug(1, dprintf("Get B-ch"));
5554                                        start_internal_command(Id, plci, retrieve_restore_command);
5555                                }
5556                                else
5557                                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5558                        }
5559                        else
5560                                start_internal_command(Id, plci, retrieve_restore_command);
5561                }
5562                break;
5563
5564        case INDICATE_IND:
5565                if (plci->State != LISTENING) {
5566                        sig_req(plci, HANGUP, 0);
5567                        send_req(plci);
5568                        break;
5569                }
5570                cip = find_cip(a, parms[4], parms[6]);
5571                cip_mask = 1L << cip;
5572                dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5573                bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5574                if (!remove_started && !a->adapter_disabled)
5575                {
5576                        group_optimization(a, plci);
5577                        for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5578                                if (application[i].Id
5579                                    && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5580                                    && CPN_filter_ok(parms[0], a, i)) {
5581                                        dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5582                                        __set_bit(i, plci->c_ind_mask_table);
5583                                        dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5584                                        plci->State = INC_CON_PENDING;
5585                                        plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5586                                                CALL_DIR_IN | CALL_DIR_ANSWER;
5587                                        if (esc_chi[0]) {
5588                                                plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5589                                                mixer_set_bchannel_id_esc(plci, plci->b_channel);
5590                                        }
5591                                        /* if a listen on the ext controller is done, check if hook states */
5592                                        /* are supported or if just a on board codec must be activated     */
5593                                        if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5594                                                if (a->profile.Global_Options & HANDSET)
5595                                                        plci->tel = ADV_VOICE;
5596                                                else if (a->profile.Global_Options & ON_BOARD_CODEC)
5597                                                        plci->tel = CODEC;
5598                                                if (plci->tel) Id |= EXT_CONTROLLER;
5599                                                a->codec_listen[i] = plci;
5600                                        }
5601
5602                                        sendf(&application[i], _CONNECT_I, Id, 0,
5603                                              "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5604                                              parms[0],    /* CalledPartyNumber   */
5605                                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5606                                              parms[2],    /* CalledPartySubad    */
5607                                              parms[3],    /* CallingPartySubad   */
5608                                              parms[4],    /* BearerCapability    */
5609                                              parms[5],    /* LowLC               */
5610                                              parms[6],    /* HighLC              */
5611                                              ai_len,      /* nested struct add_i */
5612                                              add_i[0],    /* B channel info    */
5613                                              add_i[1],    /* keypad facility   */
5614                                              add_i[2],    /* user user data    */
5615                                              add_i[3],    /* nested facility   */
5616                                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5617                                                );
5618                                        SendSSExtInd(&application[i],
5619                                                     plci,
5620                                                     Id,
5621                                                     multi_ssext_parms);
5622                                        SendSetupInfo(&application[i],
5623                                                      plci,
5624                                                      Id,
5625                                                      parms,
5626                                                      SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5627                                }
5628                        }
5629                        dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5630                }
5631                if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5632                        sig_req(plci, HANGUP, 0);
5633                        send_req(plci);
5634                        plci->State = IDLE;
5635                }
5636                plci->notifiedcall = 0;
5637                a->listen_active--;
5638                listen_check(a);
5639                break;
5640
5641        case CALL_PEND_NOTIFY:
5642                plci->notifiedcall = 1;
5643                listen_check(a);
5644                break;
5645
5646        case CALL_IND:
5647        case CALL_CON:
5648                if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5649                {
5650                        if (plci->internal_command == PERM_COD_CONN_PEND)
5651                        {
5652                                if (plci->State == ADVANCED_VOICE_NOSIG)
5653                                {
5654                                        dbug(1, dprintf("***Codec OK"));
5655                                        if (a->AdvSignalPLCI)
5656                                        {
5657                                                tplci = a->AdvSignalPLCI;
5658                                                if (tplci->spoofed_msg)
5659                                                {
5660                                                        dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5661                                                        tplci->command = 0;
5662                                                        tplci->internal_command = 0;
5663                                                        x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5664                                                        switch (tplci->spoofed_msg)
5665                                                        {
5666                                                        case CALL_RES:
5667                                                                tplci->command = _CONNECT_I | RESPONSE;
5668                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5669                                                                add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5670                                                                if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5671                                                                {
5672                                                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
5673                                                                        add_p(tplci, LLI, "\x01\x01");
5674                                                                }
5675                                                                add_s(tplci, CONN_NR, &saved_parms[2]);
5676                                                                add_s(tplci, LLC, &saved_parms[4]);
5677                                                                add_ai(tplci, &saved_parms[5]);
5678                                                                tplci->State = INC_CON_ACCEPT;
5679                                                                sig_req(tplci, CALL_RES, 0);
5680                                                                send_req(tplci);
5681                                                                break;
5682
5683                                                        case AWAITING_SELECT_B:
5684                                                                dbug(1, dprintf("Select_B continue"));
5685                                                                start_internal_command(x_Id, tplci, select_b_command);
5686                                                                break;
5687
5688                                                        case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5689                                                                if (!tplci->Sig.Id)
5690                                                                {
5691                                                                        dbug(1, dprintf("No SigID!"));
5692                                                                        sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5693                                                                        plci_remove(tplci);
5694                                                                        break;
5695                                                                }
5696                                                                tplci->command = _MANUFACTURER_R;
5697                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5698                                                                dir = saved_parms[2].info[0];
5699                                                                if (dir == 1) {
5700                                                                        sig_req(tplci, CALL_REQ, 0);
5701                                                                }
5702                                                                else if (!dir) {
5703                                                                        sig_req(tplci, LISTEN_REQ, 0);
5704                                                                }
5705                                                                send_req(tplci);
5706                                                                sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5707                                                                break;
5708
5709                                                        case (CALL_REQ | AWAITING_MANUF_CON):
5710                                                                sig_req(tplci, CALL_REQ, 0);
5711                                                                send_req(tplci);
5712                                                                break;
5713
5714                                                        case CALL_REQ:
5715                                                                if (!tplci->Sig.Id)
5716                                                                {
5717                                                                        dbug(1, dprintf("No SigID!"));
5718                                                                        sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5719                                                                        plci_remove(tplci);
5720                                                                        break;
5721                                                                }
5722                                                                tplci->command = _CONNECT_R;
5723                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5724                                                                add_s(tplci, CPN, &saved_parms[1]);
5725                                                                add_s(tplci, DSA, &saved_parms[3]);
5726                                                                add_ai(tplci, &saved_parms[9]);
5727                                                                sig_req(tplci, CALL_REQ, 0);
5728                                                                send_req(tplci);
5729                                                                break;
5730
5731                                                        case CALL_RETRIEVE:
5732                                                                tplci->command = C_RETRIEVE_REQ;
5733                                                                sig_req(tplci, CALL_RETRIEVE, 0);
5734                                                                send_req(tplci);
5735                                                                break;
5736                                                        }
5737                                                        tplci->spoofed_msg = 0;
5738                                                        if (tplci->internal_command == 0)
5739                                                                next_internal_command(x_Id, tplci);
5740                                                }
5741                                        }
5742                                        next_internal_command(Id, plci);
5743                                        break;
5744                                }
5745                                dbug(1, dprintf("***Codec Hook Init Req"));
5746                                plci->internal_command = PERM_COD_HOOK;
5747                                add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5748                                sig_req(plci, TEL_CTRL, 0);
5749                                send_req(plci);
5750                        }
5751                }
5752                else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5753                         && plci->State != INC_ACT_PENDING)
5754                {
5755                        mixer_set_bchannel_id_esc(plci, plci->b_channel);
5756                        if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5757                        {
5758                                chi[2] = plci->b_channel;
5759                                SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5760                        }
5761                        sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5762                        plci->State = INC_ACT_PENDING;
5763                }
5764                break;
5765
5766        case TEL_CTRL:
5767                ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5768                if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5769                        switch (ie[1] & 0x91) {
5770                        case 0x80:   /* hook off */
5771                        case 0x81:
5772                                if (plci->internal_command == PERM_COD_HOOK)
5773                                {
5774                                        dbug(1, dprintf("init:hook_off"));
5775                                        plci->hook_state = ie[1];
5776                                        next_internal_command(Id, plci);
5777                                        break;
5778                                }
5779                                else /* ignore doubled hook indications */
5780                                {
5781                                        if (((plci->hook_state) & 0xf0) == 0x80)
5782                                        {
5783                                                dbug(1, dprintf("ignore hook"));
5784                                                break;
5785                                        }
5786                                        plci->hook_state = ie[1]&0x91;
5787                                }
5788                                /* check for incoming call pending */
5789                                /* and signal '+'.Appl must decide */
5790                                /* with connect_res if call must   */
5791                                /* accepted or not                 */
5792                                for (i = 0, tplci = NULL; i < max_appl; i++) {
5793                                        if (a->codec_listen[i]
5794                                            && (a->codec_listen[i]->State == INC_CON_PENDING
5795                                                || a->codec_listen[i]->State == INC_CON_ALERT)) {
5796                                                tplci = a->codec_listen[i];
5797                                                tplci->appl = &application[i];
5798                                        }
5799                                }
5800                                /* no incoming call, do outgoing call */
5801                                /* and signal '+' if outg. setup   */
5802                                if (!a->AdvSignalPLCI && !tplci) {
5803                                        if ((i = get_plci(a))) {
5804                                                a->AdvSignalPLCI = &a->plci[i - 1];
5805                                                tplci = a->AdvSignalPLCI;
5806                                                tplci->tel  = ADV_VOICE;
5807                                                PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5808                                                if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5809                                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
5810                                                        add_p(tplci, LLI, "\x01\x01");
5811                                                }
5812                                                add_p(tplci, CAI, voice_cai);
5813                                                add_p(tplci, OAD, a->TelOAD);
5814                                                add_p(tplci, OSA, a->TelOSA);
5815                                                add_p(tplci, SHIFT | 6, NULL);
5816                                                add_p(tplci, SIN, "\x02\x01\x00");
5817                                                add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5818                                                sig_req(tplci, ASSIGN, DSIG_ID);
5819                                                a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5820                                                a->AdvSignalPLCI->command = 0;
5821                                                tplci->appl = a->AdvSignalAppl;
5822                                                tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5823                                                send_req(tplci);
5824                                        }
5825
5826                                }
5827
5828                                if (!tplci) break;
5829                                Id = ((word)tplci->Id << 8) | a->Id;
5830                                Id |= EXT_CONTROLLER;
5831                                sendf(tplci->appl,
5832                                      _FACILITY_I,
5833                                      Id,
5834                                      0,
5835                                      "ws", (word)0, "\x01+");
5836                                break;
5837
5838                        case 0x90:   /* hook on  */
5839                        case 0x91:
5840                                if (plci->internal_command == PERM_COD_HOOK)
5841                                {
5842                                        dbug(1, dprintf("init:hook_on"));
5843                                        plci->hook_state = ie[1] & 0x91;
5844                                        next_internal_command(Id, plci);
5845                                        break;
5846                                }
5847                                else /* ignore doubled hook indications */
5848                                {
5849                                        if (((plci->hook_state) & 0xf0) == 0x90) break;
5850                                        plci->hook_state = ie[1] & 0x91;
5851                                }
5852                                /* hangup the adv. voice call and signal '-' to the appl */
5853                                if (a->AdvSignalPLCI) {
5854                                        Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5855                                        if (plci->tel) Id |= EXT_CONTROLLER;
5856                                        sendf(a->AdvSignalAppl,
5857                                              _FACILITY_I,
5858                                              Id,
5859                                              0,
5860                                              "ws", (word)0, "\x01-");
5861                                        a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5862                                        a->AdvSignalPLCI->command = 0;
5863                                        sig_req(a->AdvSignalPLCI, HANGUP, 0);
5864                                        send_req(a->AdvSignalPLCI);
5865                                }
5866                                break;
5867                        }
5868                }
5869                break;
5870
5871        case RESUME:
5872                __clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5873                PUT_WORD(&resume_cau[4], GOOD);
5874                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5875                break;
5876
5877        case SUSPEND:
5878                bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5879
5880                if (plci->NL.Id && !plci->nl_remove_id) {
5881                        mixer_remove(plci);
5882                        nl_req_ncci(plci, REMOVE, 0);
5883                }
5884                if (!plci->sig_remove_id) {
5885                        plci->internal_command = 0;
5886                        sig_req(plci, REMOVE, 0);
5887                }
5888                send_req(plci);
5889                if (!plci->channels) {
5890                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5891                        sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5892                }
5893                break;
5894
5895        case SUSPEND_REJ:
5896                break;
5897
5898        case HANGUP:
5899                plci->hangup_flow_ctrl_timer = 0;
5900                if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5901                cau = parms[7];
5902                if (cau) {
5903                        i = _L3_CAUSE | cau[2];
5904                        if (cau[2] == 0) i = 0;
5905                        else if (cau[2] == 8) i = _L1_ERROR;
5906                        else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5907                        else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5908                }
5909                else {
5910                        i = _L3_ERROR;
5911                }
5912
5913                if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5914                {
5915                        for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5916                                sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5917                }
5918                else
5919                {
5920                        bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5921                }
5922                if (!plci->appl)
5923                {
5924                        if (plci->State == LISTENING)
5925                        {
5926                                plci->notifiedcall = 0;
5927                                a->listen_active--;
5928                        }
5929                        plci->State = INC_DIS_PENDING;
5930                        if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5931                        {
5932                                plci->State = IDLE;
5933                                if (plci->NL.Id && !plci->nl_remove_id)
5934                                {
5935                                        mixer_remove(plci);
5936                                        nl_req_ncci(plci, REMOVE, 0);
5937                                }
5938                                if (!plci->sig_remove_id)
5939                                {
5940                                        plci->internal_command = 0;
5941                                        sig_req(plci, REMOVE, 0);
5942                                }
5943                                send_req(plci);
5944                        }
5945                }
5946                else
5947                {
5948                        /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
5949                        /* result in a second HANGUP! Don't generate another        */
5950                        /* DISCONNECT                                               */
5951                        if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5952                        {
5953                                if (plci->State == RESUMING)
5954                                {
5955                                        PUT_WORD(&resume_cau[4], i);
5956                                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5957                                }
5958                                plci->State = INC_DIS_PENDING;
5959                                sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5960                        }
5961                }
5962                break;
5963
5964        case SSEXT_IND:
5965                SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5966                break;
5967
5968        case VSWITCH_REQ:
5969                VSwitchReqInd(plci, Id, multi_vswitch_parms);
5970                break;
5971        case VSWITCH_IND:
5972                if (plci->relatedPTYPLCI &&
5973                    plci->vswitchstate == 3 &&
5974                    plci->relatedPTYPLCI->vswitchstate == 3 &&
5975                    parms[MAXPARMSIDS - 1][0])
5976                {
5977                        add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5978                        sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5979                        send_req(plci->relatedPTYPLCI);
5980                }
5981                else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5982                break;
5983
5984        }
5985}
5986
5987
5988static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5989{
5990        word i;
5991        byte *ie;
5992        word Info_Number;
5993        byte *Info_Element;
5994        word Info_Mask = 0;
5995
5996        dbug(1, dprintf("SetupInfo"));
5997
5998        for (i = 0; i < MAXPARMSIDS; i++) {
5999                ie = parms[i];
6000                Info_Number = 0;
6001                Info_Element = ie;
6002                if (ie[0]) {
6003                        switch (i) {
6004                        case 0:
6005                                dbug(1, dprintf("CPN "));
6006                                Info_Number = 0x0070;
6007                                Info_Mask = 0x80;
6008                                Info_Sent_Flag = true;
6009                                break;
6010                        case 8:  /* display      */
6011                                dbug(1, dprintf("display(%d)", i));
6012                                Info_Number = 0x0028;
6013                                Info_Mask = 0x04;
6014                                Info_Sent_Flag = true;
6015                                break;
6016                        case 16: /* Channel Id */
6017                                dbug(1, dprintf("CHI"));
6018                                Info_Number = 0x0018;
6019                                Info_Mask = 0x100;
6020                                Info_Sent_Flag = true;
6021                                mixer_set_bchannel_id(plci, Info_Element);
6022                                break;
6023                        case 19: /* Redirected Number */
6024                                dbug(1, dprintf("RDN"));
6025                                Info_Number = 0x0074;
6026                                Info_Mask = 0x400;
6027                                Info_Sent_Flag = true;
6028                                break;
6029                        case 20: /* Redirected Number extended */
6030                                dbug(1, dprintf("RDX"));
6031                                Info_Number = 0x0073;
6032                                Info_Mask = 0x400;
6033                                Info_Sent_Flag = true;
6034                                break;
6035                        case 22: /* Redirecing Number  */
6036                                dbug(1, dprintf("RIN"));
6037                                Info_Number = 0x0076;
6038                                Info_Mask = 0x400;
6039                                Info_Sent_Flag = true;
6040                                break;
6041                        default:
6042                                Info_Number = 0;
6043                                break;
6044                        }
6045                }
6046
6047                if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6048                        Info_Number = 0x8000 | 5;
6049                        Info_Mask = 0x10;
6050                        Info_Element = "";
6051                }
6052
6053                if (Info_Sent_Flag && Info_Number) {
6054                        if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6055                                sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6056                        }
6057                }
6058        }
6059}
6060
6061
6062static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6063{
6064        word i;
6065        word j;
6066        word k;
6067        byte *ie;
6068        word Info_Number;
6069        byte *Info_Element;
6070        word Info_Mask = 0;
6071        static byte charges[5] = {4, 0, 0, 0, 0};
6072        static byte cause[] = {0x02, 0x80, 0x00};
6073        APPL *appl;
6074
6075        dbug(1, dprintf("InfoParse "));
6076
6077        if (
6078                !plci->appl
6079                && !plci->State
6080                && plci->Sig.Ind != NCR_FACILITY
6081                )
6082        {
6083                dbug(1, dprintf("NoParse "));
6084                return;
6085        }
6086        cause[2] = 0;
6087        for (i = 0; i < MAXPARMSIDS; i++) {
6088                ie = parms[i];
6089                Info_Number = 0;
6090                Info_Element = ie;
6091                if (ie[0]) {
6092                        switch (i) {
6093                        case 0:
6094                                dbug(1, dprintf("CPN "));
6095                                Info_Number = 0x0070;
6096                                Info_Mask   = 0x80;
6097                                break;
6098                        case 7: /* ESC_CAU */
6099                                dbug(1, dprintf("cau(0x%x)", ie[2]));
6100                                Info_Number = 0x0008;
6101                                Info_Mask = 0x00;
6102                                cause[2] = ie[2];
6103                                Info_Element = NULL;
6104                                break;
6105                        case 8:  /* display      */
6106                                dbug(1, dprintf("display(%d)", i));
6107                                Info_Number = 0x0028;
6108                                Info_Mask = 0x04;
6109                                break;
6110                        case 9:  /* Date display */
6111                                dbug(1, dprintf("date(%d)", i));
6112                                Info_Number = 0x0029;
6113                                Info_Mask = 0x02;
6114                                break;
6115                        case 10: /* charges */
6116                                for (j = 0; j < 4; j++) charges[1 + j] = 0;
6117                                for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6118                                for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6119                                Info_Number = 0x4000;
6120                                Info_Mask = 0x40;
6121                                Info_Element = charges;
6122                                break;
6123                        case 11: /* user user info */
6124                                dbug(1, dprintf("uui"));
6125                                Info_Number = 0x007E;
6126                                Info_Mask = 0x08;
6127                                break;
6128                        case 12: /* congestion receiver ready */
6129                                dbug(1, dprintf("clRDY"));
6130                                Info_Number = 0x00B0;
6131                                Info_Mask = 0x08;
6132                                Info_Element = "";
6133                                break;
6134                        case 13: /* congestion receiver not ready */
6135                                dbug(1, dprintf("clNRDY"));
6136                                Info_Number = 0x00BF;
6137                                Info_Mask = 0x08;
6138                                Info_Element = "";
6139                                break;
6140                        case 15: /* Keypad Facility */
6141                                dbug(1, dprintf("KEY"));
6142                                Info_Number = 0x002C;
6143                                Info_Mask = 0x20;
6144                                break;
6145                        case 16: /* Channel Id */
6146                                dbug(1, dprintf("CHI"));
6147                                Info_Number = 0x0018;
6148                                Info_Mask = 0x100;
6149                                mixer_set_bchannel_id(plci, Info_Element);
6150                                break;
6151                        case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6152                                dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6153                                if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6154                                Info_Number = 0x0008;
6155                                Info_Mask = 0x01;
6156                                if (cause[2] != ie[2]) Info_Element = cause;
6157                                break;
6158                        case 19: /* Redirected Number */
6159                                dbug(1, dprintf("RDN"));
6160                                Info_Number = 0x0074;
6161                                Info_Mask = 0x400;
6162                                break;
6163                        case 22: /* Redirecing Number  */
6164                                dbug(1, dprintf("RIN"));
6165                                Info_Number = 0x0076;
6166                                Info_Mask = 0x400;
6167                                break;
6168                        case 23: /* Notification Indicator  */
6169                                dbug(1, dprintf("NI"));
6170                                Info_Number = (word)NI;
6171                                Info_Mask = 0x210;
6172                                break;
6173                        case 26: /* Call State  */
6174                                dbug(1, dprintf("CST"));
6175                                Info_Number = (word)CST;
6176                                Info_Mask = 0x01; /* do with cause i.e. for now */
6177                                break;
6178                        case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6179                                dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6180                                Info_Number = 0x8000 | ie[3];
6181                                if (iesent) Info_Mask = 0xffff;
6182                                else  Info_Mask = 0x10;
6183                                Info_Element = "";
6184                                break;
6185                        default:
6186                                Info_Number  = 0;
6187                                Info_Mask    = 0;
6188                                Info_Element = "";
6189                                break;
6190                        }
6191                }
6192
6193                if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6194                {
6195                        for (j = 0; j < max_appl; j++)
6196                        {
6197                                appl = &application[j];
6198                                if (Info_Number
6199                                    && appl->Id
6200                                    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6201                                {
6202                                        dbug(1, dprintf("NCR_Ind"));
6203                                        iesent = true;
6204                                        sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6205                                }
6206                        }
6207                }
6208                else if (!plci->appl)
6209                { /* overlap receiving broadcast */
6210                        if (Info_Number == CPN
6211                            || Info_Number == KEY
6212                            || Info_Number == NI
6213                            || Info_Number == DSP
6214                            || Info_Number == UUI)
6215                        {
6216                                for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6217                                        dbug(1, dprintf("Ovl_Ind"));
6218                                        iesent = true;
6219                                        sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6220                                }
6221                        }
6222                }               /* all other signalling states */
6223                else if (Info_Number
6224                         && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6225                {
6226                        dbug(1, dprintf("Std_Ind"));
6227                        iesent = true;
6228                        sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6229                }
6230        }
6231}
6232
6233
6234static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6235                        dword info_mask, byte setupParse)
6236{
6237        word i;
6238        word j;
6239        byte *ie;
6240        word Info_Number;
6241        byte *Info_Element;
6242        APPL *appl;
6243        word Info_Mask = 0;
6244        byte iesent = 0;
6245
6246        if (
6247                !plci->appl
6248                && !plci->State
6249                && plci->Sig.Ind != NCR_FACILITY
6250                && !setupParse
6251                )
6252        {
6253                dbug(1, dprintf("NoM-IEParse "));
6254                return 0;
6255        }
6256        dbug(1, dprintf("M-IEParse "));
6257
6258        for (i = 0; i < MAX_MULTI_IE; i++)
6259        {
6260                ie = parms[i];
6261                Info_Number = 0;
6262                Info_Element = ie;
6263                if (ie[0])
6264                {
6265                        dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6266                        Info_Number = (word)ie_type;
6267                        Info_Mask = (word)info_mask;
6268                }
6269
6270                if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6271                {
6272                        for (j = 0; j < max_appl; j++)
6273                        {
6274                                appl = &application[j];
6275                                if (Info_Number
6276                                    && appl->Id
6277                                    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6278                                {
6279                                        iesent = true;
6280                                        dbug(1, dprintf("Mlt_NCR_Ind"));
6281                                        sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6282                                }
6283                        }
6284                }
6285                else if (!plci->appl && Info_Number)
6286                {                                        /* overlap receiving broadcast */
6287                        for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6288                                iesent = true;
6289                                dbug(1, dprintf("Mlt_Ovl_Ind"));
6290                                sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6291                        }
6292                }                                        /* all other signalling states */
6293                else if (Info_Number
6294                         && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6295                {
6296                        iesent = true;
6297                        dbug(1, dprintf("Mlt_Std_Ind"));
6298                        sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6299                }
6300        }
6301        return iesent;
6302}
6303
6304static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6305{
6306        word i;
6307        /* Format of multi_ssext_parms[i][]:
6308           0 byte length
6309           1 byte SSEXTIE
6310           2 byte SSEXT_REQ/SSEXT_IND
6311           3 byte length
6312           4 word SSExtCommand
6313           6... Params
6314        */
6315        if (
6316                plci
6317                && plci->State
6318                && plci->Sig.Ind != NCR_FACILITY
6319                )
6320                for (i = 0; i < MAX_MULTI_IE; i++)
6321                {
6322                        if (parms[i][0] < 6) continue;
6323                        if (parms[i][2] == SSEXT_REQ) continue;
6324
6325                        if (appl)
6326                        {
6327                                parms[i][0] = 0; /* kill it */
6328                                sendf(appl, _MANUFACTURER_I,
6329                                      Id,
6330                                      0,
6331                                      "dwS",
6332                                      _DI_MANU_ID,
6333                                      _DI_SSEXT_CTRL,
6334                                      &parms[i][3]);
6335                        }
6336                        else if (plci->appl)
6337                        {
6338                                parms[i][0] = 0; /* kill it */
6339                                sendf(plci->appl, _MANUFACTURER_I,
6340                                      Id,
6341                                      0,
6342                                      "dwS",
6343                                      _DI_MANU_ID,
6344                                      _DI_SSEXT_CTRL,
6345                                      &parms[i][3]);
6346                        }
6347                }
6348};
6349
6350static void nl_ind(PLCI *plci)
6351{
6352        byte ch;
6353        word ncci;
6354        dword Id;
6355        DIVA_CAPI_ADAPTER *a;
6356        word NCCIcode;
6357        APPL *APPLptr;
6358        word count;
6359        word Num;
6360        word i, ncpi_state;
6361        byte len, ncci_state;
6362        word msg;
6363        word info = 0;
6364        word fax_feature_bits;
6365        byte fax_send_edata_ack;
6366        static byte v120_header_buffer[2 + 3];
6367        static word fax_info[] = {
6368                0,                     /* T30_SUCCESS                        */
6369                _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6370                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6371                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6372                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6373                _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6374                _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6375                _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6376                _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6377                _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6378                _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6379                _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6380                _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6381                _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6382                _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6383                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6384                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6385                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6386                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6387                _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6388                _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6389                _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6390                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6391                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6392                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6393                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6394                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6395                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6396                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6397                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6398                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6399                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6400                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6401                0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6402                0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6403                0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6404                _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6405                _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6406                _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6407                _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6408                _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6409                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6410                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6411                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6412                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6413                _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6414                _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6415        };
6416
6417        byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6418
6419
6420        static word rtp_info[] = {
6421                GOOD,                  /* RTP_SUCCESS                       */
6422                0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6423        };
6424
6425        static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6426                {
6427                        0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6428                        0x00000000, 0x00000000, 0x00000000, 0x00000000
6429                };
6430
6431        ch = plci->NL.IndCh;
6432        a = plci->adapter;
6433        ncci = a->ch_ncci[ch];
6434        Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6435        if (plci->tel) Id |= EXT_CONTROLLER;
6436        APPLptr = plci->appl;
6437        dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6438                        plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6439
6440        /* in the case if no connect_active_Ind was sent to the appl we wait for */
6441
6442        if (plci->nl_remove_id)
6443        {
6444                plci->NL.RNR = 2; /* discard */
6445                dbug(1, dprintf("NL discard while remove pending"));
6446                return;
6447        }
6448        if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6449        {
6450                if (plci->State == INC_DIS_PENDING
6451                    || plci->State == OUTG_DIS_PENDING
6452                    || plci->State == IDLE)
6453                {
6454                        plci->NL.RNR = 2; /* discard */
6455                        dbug(1, dprintf("discard n_connect"));
6456                        return;
6457                }
6458                if (plci->State < INC_ACT_PENDING)
6459                {
6460                        plci->NL.RNR = 1; /* flow control */
6461                        channel_x_off(plci, ch, N_XON_CONNECT_IND);
6462                        return;
6463                }
6464        }
6465
6466        if (!APPLptr)                         /* no application or invalid data */
6467        {                                    /* while reloading the DSP        */
6468                dbug(1, dprintf("discard1"));
6469                plci->NL.RNR = 2;
6470                return;
6471        }
6472
6473        if (((plci->NL.Ind & 0x0f) == N_UDATA)
6474            && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6475                || (plci->B2_prot == 7)
6476                || (plci->B3_prot == 7)))
6477        {
6478                plci->ncpi_buffer[0] = 0;
6479
6480                ncpi_state = plci->ncpi_state;
6481                if (plci->NL.complete == 1)
6482                {
6483                        byte *data = &plci->NL.RBuffer->P[0];
6484
6485                        if ((plci->NL.RBuffer->length >= 12)
6486                            && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6487                                || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6488                        {
6489                                word conn_opt, ncpi_opt = 0x00;
6490/*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6491
6492                                if (*data == DSP_UDATA_INDICATION_DCD_ON)
6493                                        plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6494                                if (*data == DSP_UDATA_INDICATION_CTS_ON)
6495                                        plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6496
6497                                data++;    /* indication code */
6498                                data += 2; /* timestamp */
6499                                if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6500                                        ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6501                                data++;    /* connected norm */
6502                                conn_opt = GET_WORD(data);
6503                                data += 2; /* connected options */
6504
6505                                PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6506
6507                                if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6508                                {
6509                                        ncpi_opt |= MDM_NCPI_ECM_V42;
6510                                }
6511                                else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6512                                {
6513                                        ncpi_opt |= MDM_NCPI_ECM_MNP;
6514                                }
6515                                else
6516                                {
6517                                        ncpi_opt |= MDM_NCPI_TRANSPARENT;
6518                                }
6519                                if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6520                                {
6521                                        ncpi_opt |= MDM_NCPI_COMPRESSED;
6522                                }
6523                                PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6524                                plci->ncpi_buffer[0] = 4;
6525
6526                                plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6527                        }
6528                }
6529                if (plci->B3_prot == 7)
6530                {
6531                        if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6532                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6533                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6534                        {
6535                                a->ncci_state[ncci] = INC_ACT_PENDING;
6536                                sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6537                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6538                        }
6539                }
6540
6541                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6542                      & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6543                    || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6544                    || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6545
6546                {
6547                        plci->NL.RNR = 2;
6548                        return;
6549                }
6550        }
6551
6552        if (plci->NL.complete == 2)
6553        {
6554                if (((plci->NL.Ind & 0x0f) == N_UDATA)
6555                    && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6556                {
6557                        switch (plci->RData[0].P[0])
6558                        {
6559
6560                        case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6561                                if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6562                                        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6563                                break;
6564                        case DTMF_UDATA_INDICATION_ANSWER_TONE:
6565                                if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6566                                        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6567                                break;
6568                        case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6569                                dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6570                                break;
6571                        case DTMF_UDATA_INDICATION_DIGITS_SENT:
6572                                dtmf_confirmation(Id, plci);
6573                                break;
6574
6575
6576                        case UDATA_INDICATION_MIXER_TAP_DATA:
6577                                capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6578                                i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6579                                if (i != 0)
6580                                {
6581                                        dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6582                                        dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6583                                }
6584                                break;
6585
6586
6587                        case UDATA_INDICATION_MIXER_COEFS_SET:
6588                                mixer_indication_coefs_set(Id, plci);
6589                                break;
6590                        case UDATA_INDICATION_XCONNECT_FROM:
6591                                mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6592                                break;
6593                        case UDATA_INDICATION_XCONNECT_TO:
6594                                mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6595                                break;
6596
6597
6598                        case LEC_UDATA_INDICATION_DISABLE_DETECT:
6599                                ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6600                                break;
6601
6602
6603
6604                        default:
6605                                break;
6606                        }
6607                }
6608                else
6609                {
6610                        if ((plci->RData[0].PLength != 0)
6611                            && ((plci->B2_prot == B2_V120_ASYNC)
6612                                || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6613                                || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6614                        {
6615
6616                                sendf(plci->appl, _DATA_B3_I, Id, 0,
6617                                      "dwww",
6618                                      plci->RData[1].P,
6619                                      (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6620                                      plci->RNum,
6621                                      plci->RFlags);
6622
6623                        }
6624                        else
6625                        {
6626
6627                                sendf(plci->appl, _DATA_B3_I, Id, 0,
6628                                      "dwww",
6629                                      plci->RData[0].P,
6630                                      plci->RData[0].PLength,
6631                                      plci->RNum,
6632                                      plci->RFlags);
6633
6634                        }
6635                }
6636                return;
6637        }
6638
6639        fax_feature_bits = 0;
6640        if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6641            (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6642            (plci->NL.Ind & 0x0f) == N_DISC ||
6643            (plci->NL.Ind & 0x0f) == N_EDATA ||
6644            (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6645        {
6646                info = 0;
6647                plci->ncpi_buffer[0] = 0;
6648                switch (plci->B3_prot) {
6649                case  0: /*XPARENT*/
6650                case  1: /*T.90 NL*/
6651                        break;    /* no network control protocol info - jfr */
6652                case  2: /*ISO8202*/
6653                case  3: /*X25 DCE*/
6654                        for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6655                        plci->ncpi_buffer[0] = (byte)(i + 3);
6656                        plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6657                        plci->ncpi_buffer[2] = 0;
6658                        plci->ncpi_buffer[3] = 0;
6659                        break;
6660                case  4: /*T.30 - FAX*/
6661                case  5: /*T.30 - FAX*/
6662                        if (plci->NL.RLength >= sizeof(T30_INFO))
6663                        {
6664                                dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6665                                len = 9;
6666                                PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6667                                fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6668                                i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6669                                if (plci->B3_prot == 5)
6670                                {
6671                                        if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6672                                                i |= 0x8000; /* This is not an ECM connection */
6673                                        if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6674                                                i |= 0x4000; /* This is a connection with MMR compression */
6675                                        if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6676                                                i |= 0x2000; /* This is a connection with MR compression */
6677                                        if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6678                                                i |= 0x0004; /* More documents */
6679                                        if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6680                                                i |= 0x0002; /* Fax-polling indication */
6681                                }
6682                                dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6683                                PUT_WORD(&(plci->ncpi_buffer[3]), i);
6684                                PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6685                                plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6686                                plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6687                                plci->ncpi_buffer[len] = 0;
6688                                if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6689                                {
6690                                        plci->ncpi_buffer[len] = 20;
6691                                        for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6692                                                plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6693                                }
6694                                if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6695                                {
6696                                        if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6697                                                info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6698                                        else
6699                                                info = _FAX_PROTOCOL_ERROR;
6700                                }
6701
6702                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6703                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6704                                {
6705                                        i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6706                                        while (i < plci->NL.RBuffer->length)
6707                                                plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6708                                }
6709
6710                                plci->ncpi_buffer[0] = len;
6711                                fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6712                                PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6713
6714                                plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6715                                if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6716                                    || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6717                                        && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6718                                    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6719                                        && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6720                                            || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6721                                            || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6722                                {
6723                                        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6724                                }
6725                                if (((plci->NL.Ind & 0x0f) == N_DISC)
6726                                    || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6727                                    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6728                                        && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6729                                {
6730                                        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6731                                }
6732                        }
6733                        break;
6734
6735                case B3_RTP:
6736                        if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6737                        {
6738                                if (plci->NL.RLength != 0)
6739                                {
6740                                        info = rtp_info[plci->NL.RBuffer->P[0]];
6741                                        plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6742                                        for (i = 1; i < plci->NL.RLength; i++)
6743                                                plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6744                                }
6745                        }
6746                        break;
6747
6748                }
6749                plci->NL.RNR = 2;
6750        }
6751        switch (plci->NL.Ind & 0x0f) {
6752        case N_EDATA:
6753                if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6754                {
6755                        dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6756                                        ((T30_INFO *)plci->NL.RBuffer->P)->code));
6757                        fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6758
6759                        if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6760                            && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6761                            && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6762                            && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6763                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6764                            && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6765                        {
6766                                ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6767                                sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6768                                      (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6769                                plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6770                                if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6771                                        fax_send_edata_ack = false;
6772                        }
6773
6774                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6775                        {
6776                                switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6777                                {
6778                                case EDATA_T30_DIS:
6779                                        if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6780                                            && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6781                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6782                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6783                                        {
6784                                                a->ncci_state[ncci] = INC_ACT_PENDING;
6785                                                if (plci->B3_prot == 4)
6786                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6787                                                else
6788                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6789                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6790                                        }
6791                                        break;
6792
6793                                case EDATA_T30_TRAIN_OK:
6794                                        if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6795                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6796                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6797                                        {
6798                                                if (plci->B3_prot == 4)
6799                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6800                                                else
6801                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6802                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6803                                        }
6804                                        break;
6805
6806                                case EDATA_T30_EOP_CAPI:
6807                                        if (a->ncci_state[ncci] == CONNECTED)
6808                                        {
6809                                                sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6810                                                a->ncci_state[ncci] = INC_DIS_PENDING;
6811                                                plci->ncpi_state = 0;
6812                                                fax_send_edata_ack = false;
6813                                        }
6814                                        break;
6815                                }
6816                        }
6817                        else
6818                        {
6819                                switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6820                                {
6821                                case EDATA_T30_TRAIN_OK:
6822                                        if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6823                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6824                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6825                                        {
6826                                                if (plci->B3_prot == 4)
6827                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6828                                                else
6829                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6830                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6831                                        }
6832                                        break;
6833                                }
6834                        }
6835                        if (fax_send_edata_ack)
6836                        {
6837                                ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6838                                plci->fax_edata_ack_length = 1;
6839                                start_internal_command(Id, plci, fax_edata_ack_command);
6840                        }
6841                }
6842                else
6843                {
6844                        dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6845                }
6846                break;
6847        case N_CONNECT:
6848                if (!a->ch_ncci[ch])
6849                {
6850                        ncci = get_ncci(plci, ch, 0);
6851                        Id = (Id & 0xffff) | (((dword) ncci) << 16);
6852                }
6853                dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6854                                ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6855
6856                msg = _CONNECT_B3_I;
6857                if (a->ncci_state[ncci] == IDLE)
6858                        plci->channels++;
6859                else if (plci->B3_prot == 1)
6860                        msg = _CONNECT_B3_T90_ACTIVE_I;
6861
6862                a->ncci_state[ncci] = INC_CON_PENDING;
6863                if (plci->B3_prot == 4)
6864                        sendf(plci->appl, msg, Id, 0, "s", "");
6865                else
6866                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6867                break;
6868        case N_CONNECT_ACK:
6869                dbug(1, dprintf("N_connect_Ack"));
6870                if (plci->internal_command_queue[0]
6871                    && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6872                        || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6873                        || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6874                {
6875                        (*(plci->internal_command_queue[0]))(Id, plci, 0);
6876                        if (!plci->internal_command)
6877                                next_internal_command(Id, plci);
6878                        break;
6879                }
6880                msg = _CONNECT_B3_ACTIVE_I;
6881                if (plci->B3_prot == 1)
6882                {
6883                        if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6884                                msg = _CONNECT_B3_T90_ACTIVE_I;
6885                        a->ncci_state[ncci] = INC_ACT_PENDING;
6886                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6887                }
6888                else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6889                {
6890                        if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6891                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6892                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6893                        {
6894                                a->ncci_state[ncci] = INC_ACT_PENDING;
6895                                if (plci->B3_prot == 4)
6896                                        sendf(plci->appl, msg, Id, 0, "s", "");
6897                                else
6898                                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6899                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6900                        }
6901                }
6902                else
6903                {
6904                        a->ncci_state[ncci] = INC_ACT_PENDING;
6905                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6906                }
6907                if (plci->adjust_b_restore)
6908                {
6909                        plci->adjust_b_restore = false;
6910                        start_internal_command(Id, plci, adjust_b_restore);
6911                }
6912                break;
6913        case N_DISC:
6914        case N_DISC_ACK:
6915                if (plci->internal_command_queue[0]
6916                    && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6917                        || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6918                        || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6919                {
6920                        (*(plci->internal_command_queue[0]))(Id, plci, 0);
6921                        if (!plci->internal_command)
6922                                next_internal_command(Id, plci);
6923                }
6924                ncci_state = a->ncci_state[ncci];
6925                ncci_remove(plci, ncci, false);
6926
6927                /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
6928                /* channel, so we cannot store the state in ncci_state! The */
6929                /* information which channel we received a N_DISC is thus   */
6930                /* stored in the inc_dis_ncci_table buffer.                 */
6931                for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6932                plci->inc_dis_ncci_table[i] = (byte) ncci;
6933
6934                /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
6935                if (!plci->channels
6936                    && (plci->B1_resource == 16)
6937                    && (plci->State <= CONNECTED))
6938                {
6939                        len = 9;
6940                        i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6941                        PUT_WORD(&plci->ncpi_buffer[1], i);
6942                        PUT_WORD(&plci->ncpi_buffer[3], 0);
6943                        i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6944                        PUT_WORD(&plci->ncpi_buffer[5], i);
6945                        PUT_WORD(&plci->ncpi_buffer[7], 0);
6946                        plci->ncpi_buffer[len] = 0;
6947                        plci->ncpi_buffer[0] = len;
6948                        if (plci->B3_prot == 4)
6949                                sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6950                        else
6951                        {
6952
6953                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6954                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6955                                {
6956                                        plci->ncpi_buffer[++len] = 0;
6957                                        plci->ncpi_buffer[++len] = 0;
6958                                        plci->ncpi_buffer[++len] = 0;
6959                                        plci->ncpi_buffer[0] = len;
6960                                }
6961
6962                                sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6963                        }
6964                        sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6965                        plci->ncpi_state = 0;
6966                        sig_req(plci, HANGUP, 0);
6967                        send_req(plci);
6968                        plci->State = OUTG_DIS_PENDING;
6969                        /* disc here */
6970                }
6971                else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6972                         && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6973                         && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6974                {
6975                        if (ncci_state == IDLE)
6976                        {
6977                                if (plci->channels)
6978                                        plci->channels--;
6979                                if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6980                                        if (plci->State == SUSPENDING) {
6981                                                sendf(plci->appl,
6982                                                      _FACILITY_I,
6983                                                      Id & 0xffffL,
6984                                                      0,
6985                                                      "ws", (word)3, "\x03\x04\x00\x00");
6986                                                sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6987                                        }
6988                                        plci_remove(plci);
6989                                        plci->State = IDLE;
6990                                }
6991                        }
6992                }
6993                else if (plci->channels)
6994                {
6995                        sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6996                        plci->ncpi_state = 0;
6997                        if ((ncci_state == OUTG_REJ_PENDING)
6998                            && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
6999                        {
7000                                sig_req(plci, HANGUP, 0);
7001                                send_req(plci);
7002                                plci->State = OUTG_DIS_PENDING;
7003                        }
7004                }
7005                break;
7006        case N_RESET:
7007                a->ncci_state[ncci] = INC_RES_PENDING;
7008                sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7009                break;
7010        case N_RESET_ACK:
7011                a->ncci_state[ncci] = CONNECTED;
7012                sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7013                break;
7014
7015        case N_UDATA:
7016                if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7017                {
7018                        plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7019                        plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7020                        plci->NL.R = plci->RData;
7021                        plci->NL.RNum = 1;
7022                        return;
7023                }
7024                /* fall through */
7025        case N_BDATA:
7026        case N_DATA:
7027                if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7028                    || (a->ncci_state[ncci] == IDLE)
7029                    || (a->ncci_state[ncci] == INC_DIS_PENDING))
7030                {
7031                        plci->NL.RNR = 2;
7032                        break;
7033                }
7034                if ((a->ncci_state[ncci] != CONNECTED)
7035                    && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7036                    && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7037                {
7038                        dbug(1, dprintf("flow control"));
7039                        plci->NL.RNR = 1; /* flow control  */
7040                        channel_x_off(plci, ch, 0);
7041                        break;
7042                }
7043
7044                NCCIcode = ncci | (((word)a->Id) << 8);
7045
7046                /* count all buffers within the Application pool    */
7047                /* belonging to the same NCCI. If this is below the */
7048                /* number of buffers available per NCCI we accept   */
7049                /* this packet, otherwise we reject it              */
7050                count = 0;
7051                Num = 0xffff;
7052                for (i = 0; i < APPLptr->MaxBuffer; i++) {
7053                        if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7054                        if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7055                }
7056
7057                if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7058                {
7059                        dbug(3, dprintf("Flow-Control"));
7060                        plci->NL.RNR = 1;
7061                        if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7062                            (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7063                        {
7064                                plci->NL.RNR = 2;
7065                                dbug(3, dprintf("DiscardData"));
7066                        } else {
7067                                channel_x_off(plci, ch, 0);
7068                        }
7069                        break;
7070                }
7071                else
7072                {
7073                        APPLptr->NCCIDataFlowCtrlTimer = 0;
7074                }
7075
7076                plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7077                if (!plci->RData[0].P) {
7078                        plci->NL.RNR = 1;
7079                        channel_x_off(plci, ch, 0);
7080                        break;
7081                }
7082
7083                APPLptr->DataNCCI[Num] = NCCIcode;
7084                APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7085                dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7086
7087                plci->RNum = Num;
7088                plci->RFlags = plci->NL.Ind >> 4;
7089                plci->RData[0].PLength = APPLptr->MaxDataLength;
7090                plci->NL.R = plci->RData;
7091                if ((plci->NL.RLength != 0)
7092                    && ((plci->B2_prot == B2_V120_ASYNC)
7093                        || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7094                        || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7095                {
7096                        plci->RData[1].P = plci->RData[0].P;
7097                        plci->RData[1].PLength = plci->RData[0].PLength;
7098                        plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7099                        if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7100                                plci->RData[0].PLength = 1;
7101                        else
7102                                plci->RData[0].PLength = 2;
7103                        if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7104                                plci->RFlags |= 0x0010;
7105                        if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7106                                plci->RFlags |= 0x8000;
7107                        plci->NL.RNum = 2;
7108                }
7109                else
7110                {
7111                        if ((plci->NL.Ind & 0x0f) == N_UDATA)
7112                                plci->RFlags |= 0x0010;
7113
7114                        else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7115                                plci->RFlags |= 0x0001;
7116
7117                        plci->NL.RNum = 1;
7118                }
7119                break;
7120        case N_DATA_ACK:
7121                data_ack(plci, ch);
7122                break;
7123        default:
7124                plci->NL.RNR = 2;
7125                break;
7126        }
7127}
7128
7129/*------------------------------------------------------------------*/
7130/* find a free PLCI */
7131/*------------------------------------------------------------------*/
7132
7133static word get_plci(DIVA_CAPI_ADAPTER *a)
7134{
7135        word i, j;
7136        PLCI *plci;
7137
7138        for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7139        if (i == a->max_plci) {
7140                dbug(1, dprintf("get_plci: out of PLCIs"));
7141                return 0;
7142        }
7143        plci = &a->plci[i];
7144        plci->Id = (byte)(i + 1);
7145
7146        plci->Sig.Id = 0;
7147        plci->NL.Id = 0;
7148        plci->sig_req = 0;
7149        plci->nl_req = 0;
7150
7151        plci->appl = NULL;
7152        plci->relatedPTYPLCI = NULL;
7153        plci->State = IDLE;
7154        plci->SuppState = IDLE;
7155        plci->channels = 0;
7156        plci->tel = 0;
7157        plci->B1_resource = 0;
7158        plci->B2_prot = 0;
7159        plci->B3_prot = 0;
7160
7161        plci->command = 0;
7162        plci->m_command = 0;
7163        init_internal_command_queue(plci);
7164        plci->number = 0;
7165        plci->req_in_start = 0;
7166        plci->req_in = 0;
7167        plci->req_out = 0;
7168        plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7169        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7170        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7171
7172        plci->data_sent = false;
7173        plci->send_disc = 0;
7174        plci->sig_global_req = 0;
7175        plci->sig_remove_id = 0;
7176        plci->nl_global_req = 0;
7177        plci->nl_remove_id = 0;
7178        plci->adv_nl = 0;
7179        plci->manufacturer = false;
7180        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7181        plci->spoofed_msg = 0;
7182        plci->ptyState = 0;
7183        plci->cr_enquiry = false;
7184        plci->hangup_flow_ctrl_timer = 0;
7185
7186        plci->ncci_ring_list = 0;
7187        for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7188        bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7189        bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7190        plci->fax_connect_info_length = 0;
7191        plci->nsf_control_bits = 0;
7192        plci->ncpi_state = 0x00;
7193        plci->ncpi_buffer[0] = 0;
7194
7195        plci->requested_options_conn = 0;
7196        plci->requested_options = 0;
7197        plci->notifiedcall = 0;
7198        plci->vswitchstate = 0;
7199        plci->vsprot = 0;
7200        plci->vsprotdialect = 0;
7201        init_b1_config(plci);
7202        dbug(1, dprintf("get_plci(%x)", plci->Id));
7203        return i + 1;
7204}
7205
7206/*------------------------------------------------------------------*/
7207/* put a parameter in the parameter buffer                          */
7208/*------------------------------------------------------------------*/
7209
7210static void add_p(PLCI *plci, byte code, byte *p)
7211{
7212        word p_length;
7213
7214        p_length = 0;
7215        if (p) p_length = p[0];
7216        add_ie(plci, code, p, p_length);
7217}
7218
7219/*------------------------------------------------------------------*/
7220/* put a structure in the parameter buffer                          */
7221/*------------------------------------------------------------------*/
7222static void add_s(PLCI *plci, byte code, API_PARSE *p)
7223{
7224        if (p) add_ie(plci, code, p->info, (word)p->length);
7225}
7226
7227/*------------------------------------------------------------------*/
7228/* put multiple structures in the parameter buffer                  */
7229/*------------------------------------------------------------------*/
7230static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7231{
7232        byte i;
7233
7234        if (p) {
7235                dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7236                for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7237                        dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7238                        add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7239                }
7240        }
7241}
7242
7243/*------------------------------------------------------------------*/
7244/* return the channel number sent by the application in a esc_chi   */
7245/*------------------------------------------------------------------*/
7246static byte getChannel(API_PARSE *p)
7247{
7248        byte i;
7249
7250        if (p) {
7251                for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7252                        if (p->info[i] == 2) {
7253                                if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7254                        }
7255                }
7256        }
7257        return 0;
7258}
7259
7260
7261/*------------------------------------------------------------------*/
7262/* put an information element in the parameter buffer               */
7263/*------------------------------------------------------------------*/
7264
7265static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7266{
7267        word i;
7268
7269        if (!(code & 0x80) && !p_length) return;
7270
7271        if (plci->req_in == plci->req_in_start) {
7272                plci->req_in += 2;
7273        }
7274        else {
7275                plci->req_in--;
7276        }
7277        plci->RBuffer[plci->req_in++] = code;
7278
7279        if (p) {
7280                plci->RBuffer[plci->req_in++] = (byte)p_length;
7281                for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7282        }
7283
7284        plci->RBuffer[plci->req_in++] = 0;
7285}
7286
7287/*------------------------------------------------------------------*/
7288/* put a unstructured data into the buffer                          */
7289/*------------------------------------------------------------------*/
7290
7291static void add_d(PLCI *plci, word length, byte *p)
7292{
7293        word i;
7294
7295        if (plci->req_in == plci->req_in_start) {
7296                plci->req_in += 2;
7297        }
7298        else {
7299                plci->req_in--;
7300        }
7301        for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7302}
7303
7304/*------------------------------------------------------------------*/
7305/* put parameters from the Additional Info parameter in the         */
7306/* parameter buffer                                                 */
7307/*------------------------------------------------------------------*/
7308
7309static void add_ai(PLCI *plci, API_PARSE *ai)
7310{
7311        word i;
7312        API_PARSE ai_parms[5];
7313
7314        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7315
7316        if (!ai->length)
7317                return;
7318        if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7319                return;
7320
7321        add_s(plci, KEY, &ai_parms[1]);
7322        add_s(plci, UUI, &ai_parms[2]);
7323        add_ss(plci, FTY, &ai_parms[3]);
7324}
7325
7326/*------------------------------------------------------------------*/
7327/* put parameter for b1 protocol in the parameter buffer            */
7328/*------------------------------------------------------------------*/
7329
7330static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7331                   word b1_facilities)
7332{
7333        API_PARSE bp_parms[8];
7334        API_PARSE mdm_cfg[9];
7335        API_PARSE global_config[2];
7336        byte cai[256];
7337        byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7338        byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7339        word i;
7340
7341        API_PARSE mdm_cfg_v18[4];
7342        word j, n, w;
7343        dword d;
7344
7345
7346        for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7347        for (i = 0; i < 2; i++) global_config[i].length = 0;
7348
7349        dbug(1, dprintf("add_b1"));
7350        api_save_msg(bp, "s", &plci->B_protocol);
7351
7352        if (b_channel_info == 2) {
7353                plci->B1_resource = 0;
7354                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7355                add_p(plci, CAI, "\x01\x00");
7356                dbug(1, dprintf("Cai=1,0 (no resource)"));
7357                return 0;
7358        }
7359
7360        if (plci->tel == CODEC_PERMANENT) return 0;
7361        else if (plci->tel == CODEC) {
7362                plci->B1_resource = 1;
7363                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7364                add_p(plci, CAI, "\x01\x01");
7365                dbug(1, dprintf("Cai=1,1 (Codec)"));
7366                return 0;
7367        }
7368        else if (plci->tel == ADV_VOICE) {
7369                plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7370                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7371                voice_cai[1] = plci->B1_resource;
7372                PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7373                add_p(plci, CAI, voice_cai);
7374                dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7375                return 0;
7376        }
7377        plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7378        if (plci->call_dir & CALL_DIR_OUT)
7379                plci->call_dir |= CALL_DIR_ORIGINATE;
7380        else if (plci->call_dir & CALL_DIR_IN)
7381                plci->call_dir |= CALL_DIR_ANSWER;
7382
7383        if (!bp->length) {
7384                plci->B1_resource = 0x5;
7385                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7386                add_p(plci, CAI, "\x01\x05");
7387                return 0;
7388        }
7389
7390        dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7391        if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7392        if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7393        {
7394                bp_parms[6].length = 0;
7395                if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7396                {
7397                        dbug(1, dprintf("b-form.!"));
7398                        return _WRONG_MESSAGE_FORMAT;
7399                }
7400        }
7401        else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7402        {
7403                dbug(1, dprintf("b-form.!"));
7404                return _WRONG_MESSAGE_FORMAT;
7405        }
7406
7407        if (bp_parms[6].length)
7408        {
7409                if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7410                {
7411                        return _WRONG_MESSAGE_FORMAT;
7412                }
7413                switch (GET_WORD(global_config[0].info))
7414                {
7415                case 1:
7416                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7417                        break;
7418                case 2:
7419                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7420                        break;
7421                }
7422        }
7423        dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7424
7425
7426        if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7427            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7428        {
7429                plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7430                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7431                cai[1] = plci->B1_resource;
7432                cai[2] = 0;
7433                cai[3] = 0;
7434                cai[4] = 0;
7435                PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7436                for (i = 0; i < bp_parms[3].length; i++)
7437                        cai[7 + i] = bp_parms[3].info[1 + i];
7438                cai[0] = 6 + bp_parms[3].length;
7439                add_p(plci, CAI, cai);
7440                return 0;
7441        }
7442
7443
7444        if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7445            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7446        {
7447                plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7448                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7449                cai[1] = plci->B1_resource;
7450                cai[2] = 0;
7451                cai[3] = 0;
7452                cai[4] = 0;
7453                PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7454                cai[0] = 6;
7455                add_p(plci, CAI, cai);
7456                return 0;
7457        }
7458
7459
7460        if ((GET_WORD(bp_parms[0].info) >= 32)
7461            || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7462                && ((GET_WORD(bp_parms[0].info) != 3)
7463                    || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7464                    || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7465        {
7466                return _B1_NOT_SUPPORTED;
7467        }
7468        plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7469                                              (word)(b1_facilities & ~B1_FACILITY_VOICE));
7470        adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7471        cai[0] = 6;
7472        cai[1] = plci->B1_resource;
7473        for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7474
7475        if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7476            || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7477            || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7478        { /* B1 - modem */
7479                for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7480
7481                if (bp_parms[3].length)
7482                {
7483                        if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7484                        {
7485                                return (_WRONG_MESSAGE_FORMAT);
7486                        }
7487
7488                        cai[2] = 0; /* Bit rate for adaptation */
7489
7490                        dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7491
7492                        PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7493                        PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7494                        PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7495                        PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7496
7497                        cai[3] = 0; /* Async framing parameters */
7498                        switch (GET_WORD(mdm_cfg[2].info))
7499                        {       /* Parity     */
7500                        case 1: /* odd parity */
7501                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7502                                dbug(1, dprintf("MDM: odd parity"));
7503                                break;
7504
7505                        case 2: /* even parity */
7506                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7507                                dbug(1, dprintf("MDM: even parity"));
7508                                break;
7509
7510                        default:
7511                                dbug(1, dprintf("MDM: no parity"));
7512                                break;
7513                        }
7514
7515                        switch (GET_WORD(mdm_cfg[3].info))
7516                        {       /* stop bits   */
7517                        case 1: /* 2 stop bits */
7518                                cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7519                                dbug(1, dprintf("MDM: 2 stop bits"));
7520                                break;
7521
7522                        default:
7523                                dbug(1, dprintf("MDM: 1 stop bit"));
7524                                break;
7525                        }
7526
7527                        switch (GET_WORD(mdm_cfg[1].info))
7528                        {     /* char length */
7529                        case 5:
7530                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7531                                dbug(1, dprintf("MDM: 5 bits"));
7532                                break;
7533
7534                        case 6:
7535                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7536                                dbug(1, dprintf("MDM: 6 bits"));
7537                                break;
7538
7539                        case 7:
7540                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7541                                dbug(1, dprintf("MDM: 7 bits"));
7542                                break;
7543
7544                        default:
7545                                dbug(1, dprintf("MDM: 8 bits"));
7546                                break;
7547                        }
7548
7549                        cai[7] = 0; /* Line taking options */
7550                        cai[8] = 0; /* Modulation negotiation options */
7551                        cai[9] = 0; /* Modulation options */
7552
7553                        if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7554                        {
7555                                cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7556                                dbug(1, dprintf("MDM: Reverse direction"));
7557                        }
7558
7559                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7560                        {
7561                                cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7562                                dbug(1, dprintf("MDM: Disable retrain"));
7563                        }
7564
7565                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7566                        {
7567                                cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7568                                dbug(1, dprintf("MDM: Disable ring tone"));
7569                        }
7570
7571                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7572                        {
7573                                cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7574                                dbug(1, dprintf("MDM: 1800 guard tone"));
7575                        }
7576                        else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7577                        {
7578                                cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7579                                dbug(1, dprintf("MDM: 550 guard tone"));
7580                        }
7581
7582                        if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7583                        {
7584                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7585                                dbug(1, dprintf("MDM: V100"));
7586                        }
7587                        else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7588                        {
7589                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7590                                dbug(1, dprintf("MDM: IN CLASS"));
7591                        }
7592                        else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7593                        {
7594                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7595                                dbug(1, dprintf("MDM: DISABLED"));
7596                        }
7597                        cai[0] = 20;
7598
7599                        if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7600                            && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7601                        {
7602                                plci->requested_options |= 1L << PRIVATE_V18;
7603                        }
7604                        if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7605                                plci->requested_options |= 1L << PRIVATE_VOWN;
7606
7607                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7608                            & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7609                        {
7610                                if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7611                                {
7612                                        i = 27;
7613                                        if (mdm_cfg[6].length >= 4)
7614                                        {
7615                                                d = GET_DWORD(&mdm_cfg[6].info[1]);
7616                                                cai[7] |= (byte) d;          /* line taking options */
7617                                                cai[9] |= (byte)(d >> 8);    /* modulation options */
7618                                                cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7619                                                cai[++i] = (byte)(d >> 24);
7620                                                if (mdm_cfg[6].length >= 8)
7621                                                {
7622                                                        d = GET_DWORD(&mdm_cfg[6].info[5]);
7623                                                        cai[10] |= (byte) d;        /* disabled modulations mask */
7624                                                        cai[11] |= (byte)(d >> 8);
7625                                                        if (mdm_cfg[6].length >= 12)
7626                                                        {
7627                                                                d = GET_DWORD(&mdm_cfg[6].info[9]);
7628                                                                cai[12] = (byte) d;          /* enabled modulations mask */
7629                                                                cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7630                                                                cai[++i] = (byte)(d >> 16);
7631                                                                cai[++i] = (byte)(d >> 24);
7632                                                                cai[++i] = 0;
7633                                                                if (mdm_cfg[6].length >= 14)
7634                                                                {
7635                                                                        w = GET_WORD(&mdm_cfg[6].info[13]);
7636                                                                        if (w != 0)
7637                                                                                PUT_WORD(&cai[13], w);  /* min tx speed */
7638                                                                        if (mdm_cfg[6].length >= 16)
7639                                                                        {
7640                                                                                w = GET_WORD(&mdm_cfg[6].info[15]);
7641                                                                                if (w != 0)
7642                                                                                        PUT_WORD(&cai[15], w);  /* max tx speed */
7643                                                                                if (mdm_cfg[6].length >= 18)
7644                                                                                {
7645                                                                                        w = GET_WORD(&mdm_cfg[6].info[17]);
7646                                                                                        if (w != 0)
7647                                                                                                PUT_WORD(&cai[17], w);  /* min rx speed */
7648                                                                                        if (mdm_cfg[6].length >= 20)
7649                                                                                        {
7650                                                                                                w = GET_WORD(&mdm_cfg[6].info[19]);
7651                                                                                                if (w != 0)
7652                                                                                                        PUT_WORD(&cai[19], w);  /* max rx speed */
7653                                                                                                if (mdm_cfg[6].length >= 22)
7654                                                                                                {
7655                                                                                                        w = GET_WORD(&mdm_cfg[6].info[21]);
7656                                                                                                        cai[23] = (byte)(-((short) w));  /* transmit level */
7657                                                                                                        if (mdm_cfg[6].length >= 24)
7658                                                                                                        {
7659                                                                                                                w = GET_WORD(&mdm_cfg[6].info[23]);
7660                                                                                                                cai[22] |= (byte) w;        /* info options mask */
7661                                                                                                                cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7662                                                                                                        }
7663                                                                                                }
7664                                                                                        }
7665                                                                                }
7666                                                                        }
7667                                                                }
7668                                                        }
7669                                                }
7670                                        }
7671                                        cai[27] = i - 27;
7672                                        i++;
7673                                        if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7674                                        {
7675                                                if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7676                                                {
7677                                                        for (n = 0; n < 3; n++)
7678                                                        {
7679                                                                cai[i] = (byte)(mdm_cfg_v18[n].length);
7680                                                                for (j = 1; j < ((word)(cai[i] + 1)); j++)
7681                                                                        cai[i + j] = mdm_cfg_v18[n].info[j];
7682                                                                i += cai[i] + 1;
7683                                                        }
7684                                                }
7685                                        }
7686                                        cai[0] = (byte)(i - 1);
7687                                }
7688                        }
7689
7690                }
7691        }
7692        if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7693            GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7694        {
7695                if (bp_parms[3].length) {
7696                        dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7697                        switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7698                        case 0:
7699                        case 56000:
7700                                if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7701                                        dbug(1, dprintf("56k sync HSCX"));
7702                                        cai[1] = 8;
7703                                        cai[2] = 0;
7704                                        cai[3] = 0;
7705                                }
7706                                else if (GET_WORD(bp_parms[0].info) == 2) {
7707                                        dbug(1, dprintf("56k async DSP"));
7708                                        cai[2] = 9;
7709                                }
7710                                break;
7711                        case 50:     cai[2] = 1;  break;
7712                        case 75:     cai[2] = 1;  break;
7713                        case 110:    cai[2] = 1;  break;
7714                        case 150:    cai[2] = 1;  break;
7715                        case 200:    cai[2] = 1;  break;
7716                        case 300:    cai[2] = 1;  break;
7717                        case 600:    cai[2] = 1;  break;
7718                        case 1200:   cai[2] = 2;  break;
7719                        case 2400:   cai[2] = 3;  break;
7720                        case 4800:   cai[2] = 4;  break;
7721                        case 7200:   cai[2] = 10; break;
7722                        case 9600:   cai[2] = 5;  break;
7723                        case 12000:  cai[2] = 13; break;
7724                        case 24000:  cai[2] = 0;  break;
7725                        case 14400:  cai[2] = 11; break;
7726                        case 19200:  cai[2] = 6;  break;
7727                        case 28800:  cai[2] = 12; break;
7728                        case 38400:  cai[2] = 7;  break;
7729                        case 48000:  cai[2] = 8;  break;
7730                        case 76:     cai[2] = 15; break;  /* 75/1200     */
7731                        case 1201:   cai[2] = 14; break;  /* 1200/75     */
7732                        case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7733
7734                        default:
7735                                return _B1_PARM_NOT_SUPPORTED;
7736                        }
7737                        cai[3] = 0;
7738                        if (cai[1] == 13)                                        /* v.110 async */
7739                        {
7740                                if (bp_parms[3].length >= 8)
7741                                {
7742                                        switch (GET_WORD(&bp_parms[3].info[3]))
7743                                        {       /* char length */
7744                                        case 5:
7745                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7746                                                break;
7747                                        case 6:
7748                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7749                                                break;
7750                                        case 7:
7751                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7752                                                break;
7753                                        }
7754                                        switch (GET_WORD(&bp_parms[3].info[5]))
7755                                        {       /* Parity     */
7756                                        case 1: /* odd parity */
7757                                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7758                                                break;
7759                                        case 2: /* even parity */
7760                                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7761                                                break;
7762                                        }
7763                                        switch (GET_WORD(&bp_parms[3].info[7]))
7764                                        {       /* stop bits   */
7765                                        case 1: /* 2 stop bits */
7766                                                cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7767                                                break;
7768                                        }
7769                                }
7770                        }
7771                }
7772                else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7773                        dbug(1, dprintf("V.110 default 56k sync"));
7774                        cai[1] = 8;
7775                        cai[2] = 0;
7776                        cai[3] = 0;
7777                }
7778                else {
7779                        dbug(1, dprintf("V.110 default 9600 async"));
7780                        cai[2] = 5;
7781                }
7782        }
7783        PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7784        dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7785/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7786
7787        add_p(plci, CAI, cai);
7788        return 0;
7789}
7790
7791/*------------------------------------------------------------------*/
7792/* put parameter for b2 and B3  protocol in the parameter buffer    */
7793/*------------------------------------------------------------------*/
7794
7795static word add_b23(PLCI *plci, API_PARSE *bp)
7796{
7797        word i, fax_control_bits;
7798        byte pos, len;
7799        byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7800        API_PARSE bp_parms[8];
7801        API_PARSE *b1_config;
7802        API_PARSE *b2_config;
7803        API_PARSE b2_config_parms[8];
7804        API_PARSE *b3_config;
7805        API_PARSE b3_config_parms[6];
7806        API_PARSE global_config[2];
7807
7808        static byte llc[3] = {2,0,0};
7809        static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7810        static byte nlc[256];
7811        static byte lli[12] = {1,1};
7812
7813        const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7814        const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7815
7816        const byte llc3[] = {4,3,2,2,6,6,0};
7817        const byte header[] = {0,2,3,3,0,0,0};
7818
7819        for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7820        for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7821        for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7822
7823        lli[0] = 1;
7824        lli[1] = 1;
7825        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7826                lli[1] |= 2;
7827        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7828                lli[1] |= 4;
7829
7830        if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7831                lli[1] |= 0x10;
7832                if (plci->rx_dma_descriptor <= 0) {
7833                        plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7834                        if (plci->rx_dma_descriptor >= 0)
7835                                plci->rx_dma_descriptor++;
7836                }
7837                if (plci->rx_dma_descriptor > 0) {
7838                        lli[0] = 6;
7839                        lli[1] |= 0x40;
7840                        lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7841                        lli[3] = (byte)plci->rx_dma_magic;
7842                        lli[4] = (byte)(plci->rx_dma_magic >>  8);
7843                        lli[5] = (byte)(plci->rx_dma_magic >> 16);
7844                        lli[6] = (byte)(plci->rx_dma_magic >> 24);
7845                }
7846        }
7847
7848        if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7849                lli[1] |= 0x20;
7850        }
7851
7852        dbug(1, dprintf("add_b23"));
7853        api_save_msg(bp, "s", &plci->B_protocol);
7854
7855        if (!bp->length && plci->tel)
7856        {
7857                plci->adv_nl = true;
7858                dbug(1, dprintf("Default adv.Nl"));
7859                add_p(plci, LLI, lli);
7860                plci->B2_prot = 1 /*XPARENT*/;
7861                plci->B3_prot = 0 /*XPARENT*/;
7862                llc[1] = 2;
7863                llc[2] = 4;
7864                add_p(plci, LLC, llc);
7865                dlc[0] = 2;
7866                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7867                add_p(plci, DLC, dlc);
7868                return 0;
7869        }
7870
7871        if (!bp->length) /*default*/
7872        {
7873                dbug(1, dprintf("ret default"));
7874                add_p(plci, LLI, lli);
7875                plci->B2_prot = 0 /*X.75   */;
7876                plci->B3_prot = 0 /*XPARENT*/;
7877                llc[1] = 1;
7878                llc[2] = 4;
7879                add_p(plci, LLC, llc);
7880                dlc[0] = 2;
7881                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7882                add_p(plci, DLC, dlc);
7883                return 0;
7884        }
7885        dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7886        if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
7887
7888        if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7889        {
7890                bp_parms[6].length = 0;
7891                if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7892                {
7893                        dbug(1, dprintf("b-form.!"));
7894                        return _WRONG_MESSAGE_FORMAT;
7895                }
7896        }
7897        else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7898        {
7899                dbug(1, dprintf("b-form.!"));
7900                return _WRONG_MESSAGE_FORMAT;
7901        }
7902
7903        if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
7904        {
7905                if (GET_WORD(bp_parms[1].info) != 1
7906                    || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7907                plci->adv_nl = true;
7908        }
7909        else if (plci->tel) return _B2_NOT_SUPPORTED;
7910
7911
7912        if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7913            && (GET_WORD(bp_parms[2].info) == B3_RTP)
7914            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7915        {
7916                add_p(plci, LLI, lli);
7917                plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7918                plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7919                llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7920                llc[2] = 4;
7921                add_p(plci, LLC, llc);
7922                dlc[0] = 2;
7923                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7924                dlc[3] = 3; /* Addr A */
7925                dlc[4] = 1; /* Addr B */
7926                dlc[5] = 7; /* modulo mode */
7927                dlc[6] = 7; /* window size */
7928                dlc[7] = 0; /* XID len Lo  */
7929                dlc[8] = 0; /* XID len Hi  */
7930                for (i = 0; i < bp_parms[4].length; i++)
7931                        dlc[9 + i] = bp_parms[4].info[1 + i];
7932                dlc[0] = (byte)(8 + bp_parms[4].length);
7933                add_p(plci, DLC, dlc);
7934                for (i = 0; i < bp_parms[5].length; i++)
7935                        nlc[1 + i] = bp_parms[5].info[1 + i];
7936                nlc[0] = (byte)(bp_parms[5].length);
7937                add_p(plci, NLC, nlc);
7938                return 0;
7939        }
7940
7941
7942
7943        if ((GET_WORD(bp_parms[1].info) >= 32)
7944            || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7945                && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7946                    || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7947
7948        {
7949                return _B2_NOT_SUPPORTED;
7950        }
7951        if ((GET_WORD(bp_parms[2].info) >= 32)
7952            || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7953        {
7954                return _B3_NOT_SUPPORTED;
7955        }
7956        if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7957            && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7958                || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7959                || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7960        {
7961                return (add_modem_b23(plci, bp_parms));
7962        }
7963
7964        add_p(plci, LLI, lli);
7965
7966        plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7967        plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7968        if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
7969
7970        if (bp_parms[6].length)
7971        {
7972                if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7973                {
7974                        return _WRONG_MESSAGE_FORMAT;
7975                }
7976                switch (GET_WORD(global_config[0].info))
7977                {
7978                case 1:
7979                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7980                        break;
7981                case 2:
7982                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7983                        break;
7984                }
7985        }
7986        dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7987
7988
7989        if (plci->B2_prot == B2_PIAFS)
7990                llc[1] = PIAFS_CRC;
7991        else
7992/* IMPLEMENT_PIAFS */
7993        {
7994                llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7995                        llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7996        }
7997        llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7998
7999        add_p(plci, LLC, llc);
8000
8001        dlc[0] = 2;
8002        PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8003                 header[GET_WORD(bp_parms[2].info)]);
8004
8005        b1_config = &bp_parms[3];
8006        nlc[0] = 0;
8007        if (plci->B3_prot == 4
8008            || plci->B3_prot == 5)
8009        {
8010                for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8011                nlc[0] = sizeof(T30_INFO);
8012                if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8013                        ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8014                ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8015                if (b1_config->length >= 2)
8016                {
8017                        ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8018                }
8019        }
8020        b2_config = &bp_parms[4];
8021
8022
8023        if (llc[1] == PIAFS_CRC)
8024        {
8025                if (plci->B3_prot != B3_TRANSPARENT)
8026                {
8027                        return _B_STACK_NOT_SUPPORTED;
8028                }
8029                if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8030                        return _WRONG_MESSAGE_FORMAT;
8031                }
8032                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8033                dlc[3] = 0; /* Addr A */
8034                dlc[4] = 0; /* Addr B */
8035                dlc[5] = 0; /* modulo mode */
8036                dlc[6] = 0; /* window size */
8037                if (b2_config->length >= 7) {
8038                        dlc[7] = 7;
8039                        dlc[8] = 0;
8040                        dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8041                        dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8042                        dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8043                        dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8044                        dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8045                        dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8046                        dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8047                        dlc[0] = 15;
8048                        if (b2_config->length >= 8) { /* PIAFS control abilities */
8049                                dlc[7] = 10;
8050                                dlc[16] = 2; /* Length of PIAFS extension */
8051                                dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8052                                dlc[18] = b2_config_parms[4].info[0]; /* value */
8053                                dlc[0] = 18;
8054                        }
8055                }
8056                else /* default values, 64K, variable, no compression */
8057                {
8058                        dlc[7] = 7;
8059                        dlc[8] = 0;
8060                        dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8061                        dlc[10] = 0x03; /* V.42bis P0 */
8062                        dlc[11] = 0;    /* V.42bis P0 */
8063                        dlc[12] = 0;    /* V.42bis P1 */
8064                        dlc[13] = 0;    /* V.42bis P1 */
8065                        dlc[14] = 0;    /* V.42bis P2 */
8066                        dlc[15] = 0;    /* V.42bis P2 */
8067                        dlc[0] = 15;
8068                }
8069                add_p(plci, DLC, dlc);
8070        }
8071        else
8072
8073                if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8074                {
8075                        if (plci->B3_prot != B3_TRANSPARENT)
8076                                return _B_STACK_NOT_SUPPORTED;
8077
8078                        dlc[0] = 6;
8079                        PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8080                        dlc[3] = 0x08;
8081                        dlc[4] = 0x01;
8082                        dlc[5] = 127;
8083                        dlc[6] = 7;
8084                        if (b2_config->length != 0)
8085                        {
8086                                if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8087                                        return _WRONG_MESSAGE_FORMAT;
8088                                }
8089                                dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8090                                dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8091                                if (b2_config->info[3] != 128)
8092                                {
8093                                        dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8094                                        return _B2_PARM_NOT_SUPPORTED;
8095                                }
8096                                dlc[5] = (byte)(b2_config->info[3] - 1);
8097                                dlc[6] = b2_config->info[4];
8098                                if (llc[1] == V120_V42BIS) {
8099                                        if (b2_config->length >= 10) {
8100                                                dlc[7] = 6;
8101                                                dlc[8] = 0;
8102                                                dlc[9] = b2_config_parms[4].info[0];
8103                                                dlc[10] = b2_config_parms[4].info[1];
8104                                                dlc[11] = b2_config_parms[5].info[0];
8105                                                dlc[12] = b2_config_parms[5].info[1];
8106                                                dlc[13] = b2_config_parms[6].info[0];
8107                                                dlc[14] = b2_config_parms[6].info[1];
8108                                                dlc[0] = 14;
8109                                                dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8110                                                dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8111                                                dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8112                                        }
8113                                        else {
8114                                                dlc[6] = 14;
8115                                        }
8116                                }
8117                        }
8118                }
8119                else
8120                {
8121                        if (b2_config->length)
8122                        {
8123                                dbug(1, dprintf("B2-Config"));
8124                                if (llc[1] == X75_V42BIS) {
8125                                        if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8126                                        {
8127                                                return _WRONG_MESSAGE_FORMAT;
8128                                        }
8129                                }
8130                                else {
8131                                        if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8132                                        {
8133                                                return _WRONG_MESSAGE_FORMAT;
8134                                        }
8135                                }
8136                                /* if B2 Protocol is LAPD, b2_config structure is different */
8137                                if (llc[1] == 6)
8138                                {
8139                                        dlc[0] = 4;
8140                                        if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8141                                        else dlc[2] = 0x01;
8142                                        if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8143                                        {
8144                                                SAPI = b2_config->info[2];    /* SAPI */
8145                                        }
8146                                        dlc[1] = SAPI;
8147                                        if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8148                                        {
8149                                                dlc[3] = 127;      /* Mode */
8150                                        }
8151                                        else
8152                                        {
8153                                                dlc[3] = 7;        /* Mode */
8154                                        }
8155
8156                                        if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8157                                        else dlc[4] = 1;
8158                                        dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8159                                        if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8160                                }
8161                                else
8162                                {
8163                                        dlc[0] = (byte)(b2_config_parms[4].length + 6);
8164                                        dlc[3] = b2_config->info[1];
8165                                        dlc[4] = b2_config->info[2];
8166                                        if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8167                                                dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8168                                                return _B2_PARM_NOT_SUPPORTED;
8169                                        }
8170
8171                                        dlc[5] = (byte)(b2_config->info[3] - 1);
8172                                        dlc[6] = b2_config->info[4];
8173                                        if (dlc[6] > dlc[5]) {
8174                                                dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8175                                                return _B2_PARM_NOT_SUPPORTED;
8176                                        }
8177
8178                                        if (llc[1] == X75_V42BIS) {
8179                                                if (b2_config->length >= 10) {
8180                                                        dlc[7] = 6;
8181                                                        dlc[8] = 0;
8182                                                        dlc[9] = b2_config_parms[4].info[0];
8183                                                        dlc[10] = b2_config_parms[4].info[1];
8184                                                        dlc[11] = b2_config_parms[5].info[0];
8185                                                        dlc[12] = b2_config_parms[5].info[1];
8186                                                        dlc[13] = b2_config_parms[6].info[0];
8187                                                        dlc[14] = b2_config_parms[6].info[1];
8188                                                        dlc[0] = 14;
8189                                                        dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8190                                                        dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8191                                                        dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8192                                                }
8193                                                else {
8194                                                        dlc[6] = 14;
8195                                                }
8196
8197                                        }
8198                                        else {
8199                                                PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8200                                                for (i = 0; i < b2_config_parms[4].length; i++)
8201                                                        dlc[11 + i] = b2_config_parms[4].info[1 + i];
8202                                        }
8203                                }
8204                        }
8205                }
8206        add_p(plci, DLC, dlc);
8207
8208        b3_config = &bp_parms[5];
8209        if (b3_config->length)
8210        {
8211                if (plci->B3_prot == 4
8212                    || plci->B3_prot == 5)
8213                {
8214                        if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8215                        {
8216                                return _WRONG_MESSAGE_FORMAT;
8217                        }
8218                        i = GET_WORD((byte *)(b3_config_parms[0].info));
8219                        ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8220                                                                    ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8221                        ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8222                        fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8223                        if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8224                                fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8225                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8226                        {
8227
8228                                if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8229                                    & (1L << PRIVATE_FAX_PAPER_FORMATS))
8230                                {
8231                                        ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8232                                                T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8233                                                T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8234                                }
8235
8236                                ((T30_INFO *)&nlc[1])->recording_properties =
8237                                        T30_RECORDING_WIDTH_ISO_A3 |
8238                                        (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8239                                        (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8240                        }
8241                        if (plci->B3_prot == 5)
8242                        {
8243                                if (i & 0x0002) /* Accept incoming fax-polling requests */
8244                                        fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8245                                if (i & 0x2000) /* Do not use MR compression */
8246                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8247                                if (i & 0x4000) /* Do not use MMR compression */
8248                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8249                                if (i & 0x8000) /* Do not use ECM */
8250                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8251                                if (plci->fax_connect_info_length != 0)
8252                                {
8253                                        ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8254                                        ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8255                                        ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8256                                        fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8257                                                (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8258                                }
8259                        }
8260                        /* copy station id to NLC */
8261                        for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8262                        {
8263                                if (i < b3_config_parms[2].length)
8264                                {
8265                                        ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8266                                }
8267                                else
8268                                {
8269                                        ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8270                                }
8271                        }
8272                        ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8273                        /* copy head line to NLC */
8274                        if (b3_config_parms[3].length)
8275                        {
8276
8277                                pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8278                                if (pos != 0)
8279                                {
8280                                        if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8281                                                pos = 0;
8282                                        else
8283                                        {
8284                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8285                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8286                                                len = (byte)b3_config_parms[2].length;
8287                                                if (len > 20)
8288                                                        len = 20;
8289                                                if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8290                                                {
8291                                                        for (i = 0; i < len; i++)
8292                                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8293                                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8294                                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8295                                                }
8296                                        }
8297                                }
8298
8299                                len = (byte)b3_config_parms[3].length;
8300                                if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8301                                        len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8302                                ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8303                                nlc[0] += (byte)(pos + len);
8304                                for (i = 0; i < len; i++)
8305                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8306                        } else
8307                                ((T30_INFO *)&nlc[1])->head_line_len = 0;
8308
8309                        plci->nsf_control_bits = 0;
8310                        if (plci->B3_prot == 5)
8311                        {
8312                                if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8313                                    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8314                                {
8315                                        plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8316                                }
8317                                if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8318                                    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8319                                {
8320                                        plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8321                                }
8322                                if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8323                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8324                                {
8325                                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8326                                            & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8327                                        {
8328                                                fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8329                                                if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8330                                                        fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8331                                        }
8332                                        len = nlc[0];
8333                                        pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8334                                        if (pos < plci->fax_connect_info_length)
8335                                        {
8336                                                for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8337                                                        nlc[++len] = plci->fax_connect_info_buffer[pos++];
8338                                        }
8339                                        else
8340                                                nlc[++len] = 0;
8341                                        if (pos < plci->fax_connect_info_length)
8342                                        {
8343                                                for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8344                                                        nlc[++len] = plci->fax_connect_info_buffer[pos++];
8345                                        }
8346                                        else
8347                                                nlc[++len] = 0;
8348                                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8349                                            & (1L << PRIVATE_FAX_NONSTANDARD))
8350                                        {
8351                                                if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8352                                                {
8353                                                        if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8354                                                                plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8355                                                        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8356                                                                nlc[++len] = plci->fax_connect_info_buffer[pos++];
8357                                                }
8358                                                else
8359                                                {
8360                                                        if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8361                                                        {
8362                                                                dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8363                                                                nlc[++len] = 0;
8364                                                        }
8365                                                        else
8366                                                        {
8367                                                                if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8368                                                                        plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8369                                                                nlc[++len] = (byte)(b3_config_parms[4].length);
8370                                                                for (i = 0; i < b3_config_parms[4].length; i++)
8371                                                                        nlc[++len] = b3_config_parms[4].info[1 + i];
8372                                                        }
8373                                                }
8374                                        }
8375                                        nlc[0] = len;
8376                                        if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8377                                            && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8378                                        {
8379                                                ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8380                                        }
8381                                }
8382                        }
8383
8384                        PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8385                        len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8386                        for (i = 0; i < len; i++)
8387                                plci->fax_connect_info_buffer[i] = nlc[1 + i];
8388                        ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8389                        i += ((T30_INFO *)&nlc[1])->head_line_len;
8390                        while (i < nlc[0])
8391                                plci->fax_connect_info_buffer[len++] = nlc[++i];
8392                        plci->fax_connect_info_length = len;
8393                }
8394                else
8395                {
8396                        nlc[0] = 14;
8397                        if (b3_config->length != 16)
8398                                return _B3_PARM_NOT_SUPPORTED;
8399                        for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8400                        if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8401                                return _B3_PARM_NOT_SUPPORTED;
8402                        nlc[13] = b3_config->info[13];
8403                        if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8404                                return _B3_PARM_NOT_SUPPORTED;
8405                        nlc[14] = b3_config->info[15];
8406                }
8407        }
8408        else
8409        {
8410                if (plci->B3_prot == 4
8411                    || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8412        }
8413        add_p(plci, NLC, nlc);
8414        return 0;
8415}
8416
8417/*----------------------------------------------------------------*/
8418/*      make the same as add_b23, but only for the modem related  */
8419/*      L2 and L3 B-Chan protocol.                                */
8420/*                                                                */
8421/*      Enabled L2 and L3 Configurations:                         */
8422/*        If L1 == Modem all negotiation                          */
8423/*          only L2 == Modem with full negotiation is allowed     */
8424/*        If L1 == Modem async or sync                            */
8425/*          only L2 == Transparent is allowed                     */
8426/*        L3 == Modem or L3 == Transparent are allowed            */
8427/*      B2 Configuration for modem:                               */
8428/*          word : enable/disable compression, bitoptions         */
8429/*      B3 Configuration for modem:                               */
8430/*          empty                                                 */
8431/*----------------------------------------------------------------*/
8432static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8433{
8434        static byte lli[12] = {1,1};
8435        static byte llc[3] = {2,0,0};
8436        static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8437        API_PARSE mdm_config[2];
8438        word i;
8439        word b2_config = 0;
8440
8441        for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8442        for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8443
8444        if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8445             && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8446            || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8447                && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8448        {
8449                return (_B_STACK_NOT_SUPPORTED);
8450        }
8451        if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8452            && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8453        {
8454                return (_B_STACK_NOT_SUPPORTED);
8455        }
8456
8457        plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8458        plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8459
8460        if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8461        {
8462                if (api_parse(&bp_parms[4].info[1],
8463                              (word)bp_parms[4].length, "w",
8464                              mdm_config))
8465                {
8466                        return (_WRONG_MESSAGE_FORMAT);
8467                }
8468                b2_config = GET_WORD(mdm_config[0].info);
8469        }
8470
8471        /* OK, L2 is modem */
8472
8473        lli[0] = 1;
8474        lli[1] = 1;
8475        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8476                lli[1] |= 2;
8477        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8478                lli[1] |= 4;
8479
8480        if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8481                lli[1] |= 0x10;
8482                if (plci->rx_dma_descriptor <= 0) {
8483                        plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8484                        if (plci->rx_dma_descriptor >= 0)
8485                                plci->rx_dma_descriptor++;
8486                }
8487                if (plci->rx_dma_descriptor > 0) {
8488                        lli[1] |= 0x40;
8489                        lli[0] = 6;
8490                        lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8491                        lli[3] = (byte)plci->rx_dma_magic;
8492                        lli[4] = (byte)(plci->rx_dma_magic >>  8);
8493                        lli[5] = (byte)(plci->rx_dma_magic >> 16);
8494                        lli[6] = (byte)(plci->rx_dma_magic >> 24);
8495                }
8496        }
8497
8498        if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8499                lli[1] |= 0x20;
8500        }
8501
8502        llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8503                /*V42*/ 10 : /*V42_IN*/ 9;
8504        llc[2] = 4;                      /* pass L3 always transparent */
8505        add_p(plci, LLI, lli);
8506        add_p(plci, LLC, llc);
8507        i =  1;
8508        PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8509        i += 2;
8510        if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8511        {
8512                if (bp_parms[4].length)
8513                {
8514                        dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8515                        dlc[i++] = 3; /* Addr A */
8516                        dlc[i++] = 1; /* Addr B */
8517                        dlc[i++] = 7; /* modulo mode */
8518                        dlc[i++] = 7; /* window size */
8519                        dlc[i++] = 0; /* XID len Lo  */
8520                        dlc[i++] = 0; /* XID len Hi  */
8521
8522                        if (b2_config & MDM_B2_DISABLE_V42bis)
8523                        {
8524                                dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8525                        }
8526                        if (b2_config & MDM_B2_DISABLE_MNP)
8527                        {
8528                                dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8529                        }
8530                        if (b2_config & MDM_B2_DISABLE_TRANS)
8531                        {
8532                                dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8533                        }
8534                        if (b2_config & MDM_B2_DISABLE_V42)
8535                        {
8536                                dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8537                        }
8538                        if (b2_config & MDM_B2_DISABLE_COMP)
8539                        {
8540                                dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8541                        }
8542                        i++;
8543                }
8544        }
8545        else
8546        {
8547                dlc[i++] = 3; /* Addr A */
8548                dlc[i++] = 1; /* Addr B */
8549                dlc[i++] = 7; /* modulo mode */
8550                dlc[i++] = 7; /* window size */
8551                dlc[i++] = 0; /* XID len Lo  */
8552                dlc[i++] = 0; /* XID len Hi  */
8553                dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8554                        DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8555                        DLC_MODEMPROT_DISABLE_V42_DETECT |
8556                        DLC_MODEMPROT_DISABLE_COMPRESSION;
8557        }
8558        dlc[0] = (byte)(i - 1);
8559/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8560        add_p(plci, DLC, dlc);
8561        return (0);
8562}
8563
8564
8565/*------------------------------------------------------------------*/
8566/* send a request for the signaling entity                          */
8567/*------------------------------------------------------------------*/
8568
8569static void sig_req(PLCI *plci, byte req, byte Id)
8570{
8571        if (!plci) return;
8572        if (plci->adapter->adapter_disabled) return;
8573        dbug(1, dprintf("sig_req(%x)", req));
8574        if (req == REMOVE)
8575                plci->sig_remove_id = plci->Sig.Id;
8576        if (plci->req_in == plci->req_in_start) {
8577                plci->req_in += 2;
8578                plci->RBuffer[plci->req_in++] = 0;
8579        }
8580        PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8581        plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8582        plci->RBuffer[plci->req_in++] = req;  /* request */
8583        plci->RBuffer[plci->req_in++] = 0;    /* channel */
8584        plci->req_in_start = plci->req_in;
8585}
8586
8587/*------------------------------------------------------------------*/
8588/* send a request for the network layer entity                      */
8589/*------------------------------------------------------------------*/
8590
8591static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8592{
8593        if (!plci) return;
8594        if (plci->adapter->adapter_disabled) return;
8595        dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8596        if (req == REMOVE)
8597        {
8598                plci->nl_remove_id = plci->NL.Id;
8599                ncci_remove(plci, 0, (byte)(ncci != 0));
8600                ncci = 0;
8601        }
8602        if (plci->req_in == plci->req_in_start) {
8603                plci->req_in += 2;
8604                plci->RBuffer[plci->req_in++] = 0;
8605        }
8606        PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8607        plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8608        plci->RBuffer[plci->req_in++] = req;  /* request */
8609        plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8610        plci->req_in_start = plci->req_in;
8611}
8612
8613static void send_req(PLCI *plci)
8614{
8615        ENTITY *e;
8616        word l;
8617/*  word i; */
8618
8619        if (!plci) return;
8620        if (plci->adapter->adapter_disabled) return;
8621        channel_xmit_xon(plci);
8622
8623        /* if nothing to do, return */
8624        if (plci->req_in == plci->req_out) return;
8625        dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8626
8627        if (plci->nl_req || plci->sig_req) return;
8628
8629        l = GET_WORD(&plci->RBuffer[plci->req_out]);
8630        plci->req_out += 2;
8631        plci->XData[0].P = &plci->RBuffer[plci->req_out];
8632        plci->req_out += l;
8633        if (plci->RBuffer[plci->req_out] == 1)
8634        {
8635                e = &plci->NL;
8636                plci->req_out++;
8637                e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8638                e->ReqCh = plci->RBuffer[plci->req_out++];
8639                if (!(e->Id & 0x1f))
8640                {
8641                        e->Id = NL_ID;
8642                        plci->RBuffer[plci->req_out - 4] = CAI;
8643                        plci->RBuffer[plci->req_out - 3] = 1;
8644                        plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8645                        plci->RBuffer[plci->req_out - 1] = 0;
8646                        l += 3;
8647                        plci->nl_global_req = plci->nl_req;
8648                }
8649                dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8650        }
8651        else
8652        {
8653                e = &plci->Sig;
8654                if (plci->RBuffer[plci->req_out])
8655                        e->Id = plci->RBuffer[plci->req_out];
8656                plci->req_out++;
8657                e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8658                e->ReqCh = plci->RBuffer[plci->req_out++];
8659                if (!(e->Id & 0x1f))
8660                        plci->sig_global_req = plci->sig_req;
8661                dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8662        }
8663        plci->XData[0].PLength = l;
8664        e->X = plci->XData;
8665        plci->adapter->request(e);
8666        dbug(1, dprintf("send_ok"));
8667}
8668
8669static void send_data(PLCI *plci)
8670{
8671        DIVA_CAPI_ADAPTER *a;
8672        DATA_B3_DESC *data;
8673        NCCI   *ncci_ptr;
8674        word ncci;
8675
8676        if (!plci->nl_req && plci->ncci_ring_list)
8677        {
8678                a = plci->adapter;
8679                ncci = plci->ncci_ring_list;
8680                do
8681                {
8682                        ncci = a->ncci_next[ncci];
8683                        ncci_ptr = &(a->ncci[ncci]);
8684                        if (!(a->ncci_ch[ncci]
8685                              && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8686                        {
8687                                if (ncci_ptr->data_pending)
8688                                {
8689                                        if ((a->ncci_state[ncci] == CONNECTED)
8690                                            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8691                                            || (plci->send_disc == ncci))
8692                                        {
8693                                                data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8694                                                if ((plci->B2_prot == B2_V120_ASYNC)
8695                                                    || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8696                                                    || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8697                                                {
8698                                                        plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8699                                                        plci->NData[1].PLength = data->Length;
8700                                                        if (data->Flags & 0x10)
8701                                                                plci->NData[0].P = v120_break_header;
8702                                                        else
8703                                                                plci->NData[0].P = v120_default_header;
8704                                                        plci->NData[0].PLength = 1;
8705                                                        plci->NL.XNum = 2;
8706                                                        plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8707                                                }
8708                                                else
8709                                                {
8710                                                        plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8711                                                        plci->NData[0].PLength = data->Length;
8712                                                        if (data->Flags & 0x10)
8713                                                                plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8714
8715                                                        else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8716                                                                plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8717
8718                                                        else
8719                                                                plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8720                                                }
8721                                                plci->NL.X = plci->NData;
8722                                                plci->NL.ReqCh = a->ncci_ch[ncci];
8723                                                dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8724                                                plci->data_sent = true;
8725                                                plci->data_sent_ptr = data->P;
8726                                                a->request(&plci->NL);
8727                                        }
8728                                        else {
8729                                                cleanup_ncci_data(plci, ncci);
8730                                        }
8731                                }
8732                                else if (plci->send_disc == ncci)
8733                                {
8734                                        /* dprintf("N_DISC"); */
8735                                        plci->NData[0].PLength = 0;
8736                                        plci->NL.ReqCh = a->ncci_ch[ncci];
8737                                        plci->NL.Req = plci->nl_req = N_DISC;
8738                                        a->request(&plci->NL);
8739                                        plci->command = _DISCONNECT_B3_R;
8740                                        plci->send_disc = 0;
8741                                }
8742                        }
8743                } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8744                plci->ncci_ring_list = ncci;
8745        }
8746}
8747
8748static void listen_check(DIVA_CAPI_ADAPTER *a)
8749{
8750        word i, j;
8751        PLCI *plci;
8752        byte activnotifiedcalls = 0;
8753
8754        dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8755        if (!remove_started && !a->adapter_disabled)
8756        {
8757                for (i = 0; i < a->max_plci; i++)
8758                {
8759                        plci = &(a->plci[i]);
8760                        if (plci->notifiedcall) activnotifiedcalls++;
8761                }
8762                dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8763
8764                for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8765                        if ((j = get_plci(a))) {
8766                                a->listen_active++;
8767                                plci = &a->plci[j - 1];
8768                                plci->State = LISTENING;
8769
8770                                add_p(plci, OAD, "\x01\xfd");
8771
8772                                add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8773
8774                                add_p(plci, CAI, "\x01\xc0");
8775                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8776                                add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8777                                add_p(plci, SHIFT | 6, NULL);
8778                                add_p(plci, SIN, "\x02\x00\x00");
8779                                plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8780                                sig_req(plci, ASSIGN, DSIG_ID);
8781                                send_req(plci);
8782                        }
8783                }
8784        }
8785}
8786
8787/*------------------------------------------------------------------*/
8788/* functions for all parameters sent in INDs                        */
8789/*------------------------------------------------------------------*/
8790
8791static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8792{
8793        word ploc;            /* points to current location within packet */
8794        byte w;
8795        byte wlen;
8796        byte codeset, lock;
8797        byte *in;
8798        word i;
8799        word code;
8800        word mIEindex = 0;
8801        ploc = 0;
8802        codeset = 0;
8803        lock = 0;
8804
8805        in = plci->Sig.RBuffer->P;
8806        for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8807        {                            /* element but parms array is larger      */
8808                parms[i] = (byte *)"";
8809        }
8810        for (i = 0; i < multiIEsize; i++)
8811        {
8812                parms[i] = (byte *)"";
8813        }
8814
8815        while (ploc < plci->Sig.RBuffer->length - 1) {
8816
8817                /* read information element id and length                   */
8818                w = in[ploc];
8819
8820                if (w & 0x80) {
8821/*    w &=0xf0; removed, cannot detect congestion levels */
8822/*    upper 4 bit masked with w==SHIFT now               */
8823                        wlen = 0;
8824                }
8825                else {
8826                        wlen = (byte)(in[ploc + 1] + 1);
8827                }
8828                /* check if length valid (not exceeding end of packet)      */
8829                if ((ploc + wlen) > 270) return;
8830                if (lock & 0x80) lock &= 0x7f;
8831                else codeset = lock;
8832
8833                if ((w & 0xf0) == SHIFT) {
8834                        codeset = in[ploc];
8835                        if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8836                        codeset &= 7;
8837                        lock |= 0x80;
8838                }
8839                else {
8840                        if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8841                        else code = w;
8842                        code |= (codeset << 8);
8843
8844                        for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8845
8846                        if (i < parms_id[0] + 1) {
8847                                if (!multiIEsize) { /* with multiIEs use next field index,          */
8848                                        mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8849                                }
8850
8851                                parms[mIEindex] = &in[ploc + 1];
8852                                dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8853                                if (parms_id[i] == OAD
8854                                    || parms_id[i] == CONN_NR
8855                                    || parms_id[i] == CAD) {
8856                                        if (in[ploc + 2] & 0x80) {
8857                                                in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8858                                                in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8859                                                in[ploc + 2] = 0x80;
8860                                                parms[mIEindex] = &in[ploc];
8861                                        }
8862                                }
8863                                mIEindex++;       /* effects multiIEs only */
8864                        }
8865                }
8866
8867                ploc += (wlen + 1);
8868        }
8869        return;
8870}
8871
8872/*------------------------------------------------------------------*/
8873/* try to match a cip from received BC and HLC                      */
8874/*------------------------------------------------------------------*/
8875
8876static byte ie_compare(byte *ie1, byte *ie2)
8877{
8878        word i;
8879        if (!ie1 || !ie2) return false;
8880        if (!ie1[0]) return false;
8881        for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8882        return true;
8883}
8884
8885static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8886{
8887        word i;
8888        word j;
8889
8890        for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8891
8892        for (j = 16; j < 29 &&
8893                     (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8894        if (j == 29) return i;
8895        return j;
8896}
8897
8898
8899static byte AddInfo(byte **add_i,
8900                    byte **fty_i,
8901                    byte *esc_chi,
8902                    byte *facility)
8903{
8904        byte i;
8905        byte j;
8906        byte k;
8907        byte flen;
8908        byte len = 0;
8909        /* facility is a nested structure */
8910        /* FTY can be more than once      */
8911
8912        if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8913        {
8914                add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
8915        }
8916
8917        else
8918        {
8919                add_i[0] = (byte *)"";
8920        }
8921        if (!fty_i[0][0])
8922        {
8923                add_i[3] = (byte *)"";
8924        }
8925        else
8926        {    /* facility array found  */
8927                for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8928                {
8929                        dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8930                        len += fty_i[i][0];
8931                        len += 2;
8932                        flen = fty_i[i][0];
8933                        facility[j++] = 0x1c; /* copy fac IE */
8934                        for (k = 0; k <= flen; k++, j++)
8935                        {
8936                                facility[j] = fty_i[i][k];
8937/*      dbug(1, dprintf("%x ",facility[j])); */
8938                        }
8939                }
8940                facility[0] = len;
8941                add_i[3] = facility;
8942        }
8943/*  dbug(1, dprintf("FacArrLen=%d ",len)); */
8944        len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8945        len += 4;                          /* calculate length of all */
8946        return (len);
8947}
8948
8949/*------------------------------------------------------------------*/
8950/* voice and codec features                                         */
8951/*------------------------------------------------------------------*/
8952
8953static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8954{
8955        byte voice_chi[] = "\x02\x18\x01";
8956        byte channel;
8957
8958        channel = chi[chi[0]] & 0x3;
8959        dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8960        voice_chi[2] = (channel) ? channel : 1;
8961        add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
8962        add_p(plci, ESC, voice_chi);                  /* Channel */
8963        sig_req(plci, TEL_CTRL, 0);
8964        send_req(plci);
8965        if (a->AdvSignalPLCI)
8966        {
8967                adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8968        }
8969}
8970
8971static void VoiceChannelOff(PLCI *plci)
8972{
8973        dbug(1, dprintf("ExtDevOFF"));
8974        add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
8975        sig_req(plci, TEL_CTRL, 0);
8976        send_req(plci);
8977        if (plci->adapter->AdvSignalPLCI)
8978        {
8979                adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8980        }
8981}
8982
8983
8984static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8985                            byte hook_listen)
8986{
8987        word j;
8988        PLCI *splci;
8989
8990        /* check if hardware supports handset with hook states (adv.codec) */
8991        /* or if just a on board codec is supported                        */
8992        /* the advanced codec plci is just for internal use                */
8993
8994        /* diva Pro with on-board codec:                                   */
8995        if (a->profile.Global_Options & HANDSET)
8996        {
8997                /* new call, but hook states are already signalled */
8998                if (a->AdvCodecFLAG)
8999                {
9000                        if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9001                        {
9002                                dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9003                                return 0x2001; /* codec in use by another application */
9004                        }
9005                        if (plci != NULL)
9006                        {
9007                                a->AdvSignalPLCI = plci;
9008                                plci->tel = ADV_VOICE;
9009                        }
9010                        return 0;                      /* adv codec still used */
9011                }
9012                if ((j = get_plci(a)))
9013                {
9014                        splci = &a->plci[j - 1];
9015                        splci->tel = CODEC_PERMANENT;
9016                        /* hook_listen indicates if a facility_req with handset/hook support */
9017                        /* was sent. Otherwise if just a call on an external device was made */
9018                        /* the codec will be used but the hook info will be discarded (just  */
9019                        /* the external controller is in use                                 */
9020                        if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9021                        else
9022                        {
9023                                splci->State = ADVANCED_VOICE_NOSIG;
9024                                if (plci)
9025                                {
9026                                        plci->spoofed_msg = SPOOFING_REQUIRED;
9027                                }
9028                                /* indicate D-ch connect if  */
9029                        }                                        /* codec is connected OK     */
9030                        if (plci != NULL)
9031                        {
9032                                a->AdvSignalPLCI = plci;
9033                                plci->tel = ADV_VOICE;
9034                        }
9035                        a->AdvSignalAppl = appl;
9036                        a->AdvCodecFLAG = true;
9037                        a->AdvCodecPLCI = splci;
9038                        add_p(splci, CAI, "\x01\x15");
9039                        add_p(splci, LLI, "\x01\x00");
9040                        add_p(splci, ESC, "\x02\x18\x00");
9041                        add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9042                        splci->internal_command = PERM_COD_ASSIGN;
9043                        dbug(1, dprintf("Codec Assign"));
9044                        sig_req(splci, ASSIGN, DSIG_ID);
9045                        send_req(splci);
9046                }
9047                else
9048                {
9049                        return 0x2001; /* wrong state, no more plcis */
9050                }
9051        }
9052        else if (a->profile.Global_Options & ON_BOARD_CODEC)
9053        {
9054                if (hook_listen) return 0x300B;               /* Facility not supported */
9055                /* no hook with SCOM      */
9056                if (plci != NULL) plci->tel = CODEC;
9057                dbug(1, dprintf("S/SCOM codec"));
9058                /* first time we use the scom-s codec we must shut down the internal   */
9059                /* handset application of the card. This can be done by an assign with */
9060                /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9061                if (!a->scom_appl_disable) {
9062                        if ((j = get_plci(a))) {
9063                                splci = &a->plci[j - 1];
9064                                add_p(splci, CAI, "\x01\x80");
9065                                add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9066                                sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9067                                send_req(splci);
9068                                a->scom_appl_disable = true;
9069                        }
9070                        else{
9071                                return 0x2001; /* wrong state, no more plcis */
9072                        }
9073                }
9074        }
9075        else return 0x300B;               /* Facility not supported */
9076
9077        return 0;
9078}
9079
9080
9081static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9082{
9083
9084        dbug(1, dprintf("CodecIdCheck"));
9085
9086        if (a->AdvSignalPLCI == plci)
9087        {
9088                dbug(1, dprintf("PLCI owns codec"));
9089                VoiceChannelOff(a->AdvCodecPLCI);
9090                if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9091                {
9092                        dbug(1, dprintf("remove temp codec PLCI"));
9093                        plci_remove(a->AdvCodecPLCI);
9094                        a->AdvCodecFLAG  = 0;
9095                        a->AdvCodecPLCI  = NULL;
9096                        a->AdvSignalAppl = NULL;
9097                }
9098                a->AdvSignalPLCI = NULL;
9099        }
9100}
9101
9102/* -------------------------------------------------------------------
9103   Ask for physical address of card on PCI bus
9104   ------------------------------------------------------------------- */
9105static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9106                                       IDI_SYNC_REQ *preq) {
9107        a->sdram_bar = 0;
9108        if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9109                ENTITY *e = (ENTITY *)preq;
9110
9111                e->user[0] = a->Id - 1;
9112                preq->xdi_sdram_bar.info.bar    = 0;
9113                preq->xdi_sdram_bar.Req         = 0;
9114                preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9115
9116                (*(a->request))(e);
9117
9118                a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9119                dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9120        }
9121}
9122
9123/* -------------------------------------------------------------------
9124   Ask XDI about extended features
9125   ------------------------------------------------------------------- */
9126static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9127        IDI_SYNC_REQ *preq;
9128        char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9129
9130        char features[4];
9131        preq = (IDI_SYNC_REQ *)&buffer[0];
9132
9133        if (!diva_xdi_extended_features) {
9134                ENTITY *e = (ENTITY *)preq;
9135                diva_xdi_extended_features |= 0x80000000;
9136
9137                e->user[0] = a->Id - 1;
9138                preq->xdi_extended_features.Req = 0;
9139                preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9140                preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9141                preq->xdi_extended_features.info.features = &features[0];
9142
9143                (*(a->request))(e);
9144
9145                if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9146                        /*
9147                          Check features located in the byte '0'
9148                        */
9149                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9150                                diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9151                        }
9152                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9153                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9154                                dbug(1, dprintf("XDI provides RxDMA"));
9155                        }
9156                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9157                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9158                        }
9159                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9160                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9161                                dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9162                        }
9163
9164                }
9165        }
9166
9167        diva_ask_for_xdi_sdram_bar(a, preq);
9168}
9169
9170/*------------------------------------------------------------------*/
9171/* automatic law                                                    */
9172/*------------------------------------------------------------------*/
9173/* called from OS specific part after init time to get the Law              */
9174/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9175void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9176{
9177        word j;
9178        PLCI *splci;
9179
9180        if (a->automatic_law) {
9181                return;
9182        }
9183        if ((j = get_plci(a))) {
9184                diva_get_extended_adapter_features(a);
9185                splci = &a->plci[j - 1];
9186                a->automatic_lawPLCI = splci;
9187                a->automatic_law = 1;
9188                add_p(splci, CAI, "\x01\x80");
9189                add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9190                splci->internal_command = USELAW_REQ;
9191                splci->command = 0;
9192                splci->number = 0;
9193                sig_req(splci, ASSIGN, DSIG_ID);
9194                send_req(splci);
9195        }
9196}
9197
9198/* called from OS specific part if an application sends an Capi20Release */
9199word CapiRelease(word Id)
9200{
9201        word i, j, appls_found;
9202        PLCI *plci;
9203        APPL   *this;
9204        DIVA_CAPI_ADAPTER *a;
9205
9206        if (!Id)
9207        {
9208                dbug(0, dprintf("A: CapiRelease(Id==0)"));
9209                return (_WRONG_APPL_ID);
9210        }
9211
9212        this = &application[Id - 1];               /* get application pointer */
9213
9214        for (i = 0, appls_found = 0; i < max_appl; i++)
9215        {
9216                if (application[i].Id)       /* an application has been found        */
9217                {
9218                        appls_found++;
9219                }
9220        }
9221
9222        for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9223        {
9224                a = &adapter[i];
9225                if (a->request)
9226                {
9227                        a->Info_Mask[Id - 1] = 0;
9228                        a->CIP_Mask[Id - 1] = 0;
9229                        a->Notification_Mask[Id - 1] = 0;
9230                        a->codec_listen[Id - 1] = NULL;
9231                        a->requested_options_table[Id - 1] = 0;
9232                        for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9233                        {                                      /* with this application   */
9234                                plci = &a->plci[j];
9235                                if (plci->Id)                         /* if plci owns no application */
9236                                {                                    /* it may be not jet connected */
9237                                        if (plci->State == INC_CON_PENDING
9238                                            || plci->State == INC_CON_ALERT)
9239                                        {
9240                                                if (test_bit(Id - 1, plci->c_ind_mask_table))
9241                                                {
9242                                                        __clear_bit(Id - 1, plci->c_ind_mask_table);
9243                                                        if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9244                                                        {
9245                                                                sig_req(plci, HANGUP, 0);
9246                                                                send_req(plci);
9247                                                                plci->State = OUTG_DIS_PENDING;
9248                                                        }
9249                                                }
9250                                        }
9251                                        if (test_bit(Id - 1, plci->c_ind_mask_table))
9252                                        {
9253                                                __clear_bit(Id - 1, plci->c_ind_mask_table);
9254                                                if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9255                                                {
9256                                                        if (!plci->appl)
9257                                                        {
9258                                                                plci_remove(plci);
9259                                                                plci->State = IDLE;
9260                                                        }
9261                                                }
9262                                        }
9263                                        if (plci->appl == this)
9264                                        {
9265                                                plci->appl = NULL;
9266                                                plci_remove(plci);
9267                                                plci->State = IDLE;
9268                                        }
9269                                }
9270                        }
9271                        listen_check(a);
9272
9273                        if (a->flag_dynamic_l1_down)
9274                        {
9275                                if (appls_found == 1)            /* last application does a capi release */
9276                                {
9277                                        if ((j = get_plci(a)))
9278                                        {
9279                                                plci = &a->plci[j - 1];
9280                                                plci->command = 0;
9281                                                add_p(plci, OAD, "\x01\xfd");
9282                                                add_p(plci, CAI, "\x01\x80");
9283                                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9284                                                add_p(plci, SHIFT | 6, NULL);
9285                                                add_p(plci, SIN, "\x02\x00\x00");
9286                                                plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9287                                                sig_req(plci, ASSIGN, DSIG_ID);
9288                                                add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9289                                                sig_req(plci, SIG_CTRL, 0);
9290                                                send_req(plci);
9291                                        }
9292                                }
9293                        }
9294                        if (a->AdvSignalAppl == this)
9295                        {
9296                                this->NullCREnable = false;
9297                                if (a->AdvCodecPLCI)
9298                                {
9299                                        plci_remove(a->AdvCodecPLCI);
9300                                        a->AdvCodecPLCI->tel = 0;
9301                                        a->AdvCodecPLCI->adv_nl = 0;
9302                                }
9303                                a->AdvSignalAppl = NULL;
9304                                a->AdvSignalPLCI = NULL;
9305                                a->AdvCodecFLAG = 0;
9306                                a->AdvCodecPLCI = NULL;
9307                        }
9308                }
9309        }
9310
9311        this->Id = 0;
9312
9313        return GOOD;
9314}
9315
9316static word plci_remove_check(PLCI *plci)
9317{
9318        if (!plci) return true;
9319        if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9320        {
9321                if (plci->Sig.Id == 0xff)
9322                        plci->Sig.Id = 0;
9323                if (!plci->Sig.Id)
9324                {
9325                        dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9326                        dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9327                        if (plci->Id)
9328                        {
9329                                CodecIdCheck(plci->adapter, plci);
9330                                clear_b1_config(plci);
9331                                ncci_remove(plci, 0, false);
9332                                plci_free_msg_in_queue(plci);
9333                                channel_flow_control_remove(plci);
9334                                plci->Id = 0;
9335                                plci->State = IDLE;
9336                                plci->channels = 0;
9337                                plci->appl = NULL;
9338                                plci->notifiedcall = 0;
9339                        }
9340                        listen_check(plci->adapter);
9341                        return true;
9342                }
9343        }
9344        return false;
9345}
9346
9347
9348/*------------------------------------------------------------------*/
9349
9350static byte plci_nl_busy(PLCI *plci)
9351{
9352        /* only applicable for non-multiplexed protocols */
9353        return (plci->nl_req
9354                || (plci->ncci_ring_list
9355                    && plci->adapter->ncci_ch[plci->ncci_ring_list]
9356                    && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9357}
9358
9359
9360/*------------------------------------------------------------------*/
9361/* DTMF facilities                                                  */
9362/*------------------------------------------------------------------*/
9363
9364
9365static struct
9366{
9367        byte send_mask;
9368        byte listen_mask;
9369        byte character;
9370        byte code;
9371} dtmf_digit_map[] =
9372{
9373        { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9374        { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9375        { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9376        { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9377        { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9378        { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9379        { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9380        { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9381        { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9382        { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9383        { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9384        { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9385        { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9386        { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9387        { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9388        { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9389        { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9390        { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9391        { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9392        { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9393
9394        { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9395        { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9396        { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9397        { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9398        { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9399        { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9400        { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9401        { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9402        { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9403        { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9404        { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9405        { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9406        { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9407        { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9408        { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9409        { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9410        { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9411        { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9412        { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9413        { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9414        { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9415        { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9416        { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9417        { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9418        { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9419        { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9420        { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9421        { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9422        { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9423        { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9424        { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9425        { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9426        { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9427        { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9428        { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9429        { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9430        { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9431        { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9432        { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9433        { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9434        { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9435        { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9436        { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9437        { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9438        { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9439        { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9440        { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9441        { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9442        { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9443        { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9444        { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9445        { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9446
9447};
9448
9449#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9450
9451
9452static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9453{
9454        word min_digit_duration, min_gap_duration;
9455
9456        dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9457                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9458                        (char *)(FILE_), __LINE__, enable_mask));
9459
9460        if (enable_mask != 0)
9461        {
9462                min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9463                min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9464                plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9465                PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9466                PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9467                plci->NData[0].PLength = 5;
9468
9469                PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9470                plci->NData[0].PLength += 2;
9471                capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9472
9473        }
9474        else
9475        {
9476                plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9477                plci->NData[0].PLength = 1;
9478
9479                capidtmf_recv_disable(&(plci->capidtmf_state));
9480
9481        }
9482        plci->NData[0].P = plci->internal_req_buffer;
9483        plci->NL.X = plci->NData;
9484        plci->NL.ReqCh = 0;
9485        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9486        plci->adapter->request(&plci->NL);
9487}
9488
9489
9490static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9491{
9492        word w, i;
9493
9494        dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9495                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9496                        (char *)(FILE_), __LINE__, digit_count));
9497
9498        plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9499        w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9500        PUT_WORD(&plci->internal_req_buffer[1], w);
9501        w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9502        PUT_WORD(&plci->internal_req_buffer[3], w);
9503        for (i = 0; i < digit_count; i++)
9504        {
9505                w = 0;
9506                while ((w < DTMF_DIGIT_MAP_ENTRIES)
9507                       && (digit_buffer[i] != dtmf_digit_map[w].character))
9508                {
9509                        w++;
9510                }
9511                plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9512                        dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9513        }
9514        plci->NData[0].PLength = 5 + digit_count;
9515        plci->NData[0].P = plci->internal_req_buffer;
9516        plci->NL.X = plci->NData;
9517        plci->NL.ReqCh = 0;
9518        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9519        plci->adapter->request(&plci->NL);
9520}
9521
9522
9523static void dtmf_rec_clear_config(PLCI *plci)
9524{
9525
9526        dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9527                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9528                        (char *)(FILE_), __LINE__));
9529
9530        plci->dtmf_rec_active = 0;
9531        plci->dtmf_rec_pulse_ms = 0;
9532        plci->dtmf_rec_pause_ms = 0;
9533
9534        capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9535
9536}
9537
9538
9539static void dtmf_send_clear_config(PLCI *plci)
9540{
9541
9542        dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9543                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9544                        (char *)(FILE_), __LINE__));
9545
9546        plci->dtmf_send_requests = 0;
9547        plci->dtmf_send_pulse_ms = 0;
9548        plci->dtmf_send_pause_ms = 0;
9549}
9550
9551
9552static void dtmf_prepare_switch(dword Id, PLCI *plci)
9553{
9554
9555        dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9556                        UnMapId(Id), (char *)(FILE_), __LINE__));
9557
9558        while (plci->dtmf_send_requests != 0)
9559                dtmf_confirmation(Id, plci);
9560}
9561
9562
9563static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9564{
9565
9566        dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9567                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9568
9569        return (GOOD);
9570}
9571
9572
9573static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9574{
9575        word Info;
9576
9577        dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9578                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9579
9580        Info = GOOD;
9581        if (plci->B1_facilities & B1_FACILITY_DTMFR)
9582        {
9583                switch (plci->adjust_b_state)
9584                {
9585                case ADJUST_B_RESTORE_DTMF_1:
9586                        plci->internal_command = plci->adjust_b_command;
9587                        if (plci_nl_busy(plci))
9588                        {
9589                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9590                                break;
9591                        }
9592                        dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9593                        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9594                        break;
9595                case ADJUST_B_RESTORE_DTMF_2:
9596                        if ((Rc != OK) && (Rc != OK_FC))
9597                        {
9598                                dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9599                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9600                                Info = _WRONG_STATE;
9601                                break;
9602                        }
9603                        break;
9604                }
9605        }
9606        return (Info);
9607}
9608
9609
9610static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9611{
9612        word internal_command, Info;
9613        byte mask;
9614        byte result[4];
9615
9616        dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9617                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9618                        plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9619                        plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9620
9621        Info = GOOD;
9622        result[0] = 2;
9623        PUT_WORD(&result[1], DTMF_SUCCESS);
9624        internal_command = plci->internal_command;
9625        plci->internal_command = 0;
9626        mask = 0x01;
9627        switch (plci->dtmf_cmd)
9628        {
9629
9630        case DTMF_LISTEN_TONE_START:
9631                mask <<= 1; /* fall through */
9632        case DTMF_LISTEN_MF_START:
9633                mask <<= 1; /* fall through */
9634
9635        case DTMF_LISTEN_START:
9636                switch (internal_command)
9637                {
9638                default:
9639                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9640                                                                  B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9641                        /* fall through */
9642                case DTMF_COMMAND_1:
9643                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9644                        {
9645                                dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9646                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9647                                Info = _FACILITY_NOT_SUPPORTED;
9648                                break;
9649                        }
9650                        if (plci->internal_command)
9651                                return;
9652                        /* fall through */
9653                case DTMF_COMMAND_2:
9654                        if (plci_nl_busy(plci))
9655                        {
9656                                plci->internal_command = DTMF_COMMAND_2;
9657                                return;
9658                        }
9659                        plci->internal_command = DTMF_COMMAND_3;
9660                        dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9661                        return;
9662                case DTMF_COMMAND_3:
9663                        if ((Rc != OK) && (Rc != OK_FC))
9664                        {
9665                                dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9666                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9667                                Info = _FACILITY_NOT_SUPPORTED;
9668                                break;
9669                        }
9670
9671                        plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9672
9673                        plci->dtmf_rec_active |= mask;
9674                        break;
9675                }
9676                break;
9677
9678
9679        case DTMF_LISTEN_TONE_STOP:
9680                mask <<= 1; /* fall through */
9681        case DTMF_LISTEN_MF_STOP:
9682                mask <<= 1; /* fall through */
9683
9684        case DTMF_LISTEN_STOP:
9685                switch (internal_command)
9686                {
9687                default:
9688                        plci->dtmf_rec_active &= ~mask;
9689                        if (plci->dtmf_rec_active)
9690                                break;
9691/*
9692  case DTMF_COMMAND_1:
9693  if (plci->dtmf_rec_active)
9694  {
9695  if (plci_nl_busy (plci))
9696  {
9697  plci->internal_command = DTMF_COMMAND_1;
9698  return;
9699  }
9700  plci->dtmf_rec_active &= ~mask;
9701  plci->internal_command = DTMF_COMMAND_2;
9702  dtmf_enable_receiver (plci, false);
9703  return;
9704  }
9705  Rc = OK;
9706  case DTMF_COMMAND_2:
9707  if ((Rc != OK) && (Rc != OK_FC))
9708  {
9709  dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9710  UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9711  Info = _FACILITY_NOT_SUPPORTED;
9712  break;
9713  }
9714*/
9715                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9716                                                                  ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9717                        /* fall through */
9718                case DTMF_COMMAND_3:
9719                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9720                        {
9721                                dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9722                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9723                                Info = _FACILITY_NOT_SUPPORTED;
9724                                break;
9725                        }
9726                        if (plci->internal_command)
9727                                return;
9728                        break;
9729                }
9730                break;
9731
9732
9733        case DTMF_SEND_TONE:
9734                mask <<= 1; /* fall through */
9735        case DTMF_SEND_MF:
9736                mask <<= 1; /* fall through */
9737
9738        case DTMF_DIGITS_SEND:
9739                switch (internal_command)
9740                {
9741                default:
9742                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9743                                                                  ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9744                                           DTMF_COMMAND_1);
9745                        /* fall through */
9746                case DTMF_COMMAND_1:
9747                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9748                        {
9749                                dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9750                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9751                                Info = _FACILITY_NOT_SUPPORTED;
9752                                break;
9753                        }
9754                        if (plci->internal_command)
9755                                return;
9756                        /* fall through */
9757                case DTMF_COMMAND_2:
9758                        if (plci_nl_busy(plci))
9759                        {
9760                                plci->internal_command = DTMF_COMMAND_2;
9761                                return;
9762                        }
9763                        plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9764                        plci->internal_command = DTMF_COMMAND_3;
9765                        dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9766                        return;
9767                case DTMF_COMMAND_3:
9768                        if ((Rc != OK) && (Rc != OK_FC))
9769                        {
9770                                dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9771                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9772                                if (plci->dtmf_send_requests != 0)
9773                                        (plci->dtmf_send_requests)--;
9774                                Info = _FACILITY_NOT_SUPPORTED;
9775                                break;
9776                        }
9777                        return;
9778                }
9779                break;
9780        }
9781        sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9782              "wws", Info, SELECTOR_DTMF, result);
9783}
9784
9785
9786static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9787{
9788        word Info;
9789        word i, j;
9790        byte mask;
9791        API_PARSE dtmf_parms[5];
9792        byte result[40];
9793
9794        dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9795                        UnMapId(Id), (char *)(FILE_), __LINE__));
9796
9797        Info = GOOD;
9798        result[0] = 2;
9799        PUT_WORD(&result[1], DTMF_SUCCESS);
9800        if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9801        {
9802                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9803                                UnMapId(Id), (char *)(FILE_), __LINE__));
9804                Info = _FACILITY_NOT_SUPPORTED;
9805        }
9806        else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9807        {
9808                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9809                                UnMapId(Id), (char *)(FILE_), __LINE__));
9810                Info = _WRONG_MESSAGE_FORMAT;
9811        }
9812
9813        else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9814                 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9815        {
9816                if (!((a->requested_options_table[appl->Id - 1])
9817                      & (1L << PRIVATE_DTMF_TONE)))
9818                {
9819                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9820                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9821                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9822                }
9823                else
9824                {
9825                        for (i = 0; i < 32; i++)
9826                                result[4 + i] = 0;
9827                        if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9828                        {
9829                                for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9830                                {
9831                                        if (dtmf_digit_map[i].listen_mask != 0)
9832                                                result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9833                                }
9834                        }
9835                        else
9836                        {
9837                                for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9838                                {
9839                                        if (dtmf_digit_map[i].send_mask != 0)
9840                                                result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9841                                }
9842                        }
9843                        result[0] = 3 + 32;
9844                        result[3] = 32;
9845                }
9846        }
9847
9848        else if (plci == NULL)
9849        {
9850                dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9851                                UnMapId(Id), (char *)(FILE_), __LINE__));
9852                Info = _WRONG_IDENTIFIER;
9853        }
9854        else
9855        {
9856                if (!plci->State
9857                    || !plci->NL.Id || plci->nl_remove_id)
9858                {
9859                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9860                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9861                        Info = _WRONG_STATE;
9862                }
9863                else
9864                {
9865                        plci->command = 0;
9866                        plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9867                        mask = 0x01;
9868                        switch (plci->dtmf_cmd)
9869                        {
9870
9871                        case DTMF_LISTEN_TONE_START:
9872                        case DTMF_LISTEN_TONE_STOP:
9873                                mask <<= 1; /* fall through */
9874                        case DTMF_LISTEN_MF_START:
9875                        case DTMF_LISTEN_MF_STOP:
9876                                mask <<= 1;
9877                                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9878                                      & (1L << PRIVATE_DTMF_TONE)))
9879                                {
9880                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9881                                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9882                                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9883                                        break;
9884                                }
9885                                /* fall through */
9886
9887                        case DTMF_LISTEN_START:
9888                        case DTMF_LISTEN_STOP:
9889                                if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9890                                    && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9891                                {
9892                                        dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9893                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9894                                        Info = _FACILITY_NOT_SUPPORTED;
9895                                        break;
9896                                }
9897                                if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9898                                {
9899                                        if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9900                                        {
9901                                                plci->dtmf_rec_pulse_ms = 0;
9902                                                plci->dtmf_rec_pause_ms = 0;
9903                                        }
9904                                        else
9905                                        {
9906                                                plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9907                                                plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9908                                        }
9909                                }
9910                                start_internal_command(Id, plci, dtmf_command);
9911                                return (false);
9912
9913
9914                        case DTMF_SEND_TONE:
9915                                mask <<= 1; /* fall through */
9916                        case DTMF_SEND_MF:
9917                                mask <<= 1;
9918                                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9919                                      & (1L << PRIVATE_DTMF_TONE)))
9920                                {
9921                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9922                                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9923                                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9924                                        break;
9925                                }
9926                                /* fall through */
9927
9928                        case DTMF_DIGITS_SEND:
9929                                if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9930                                {
9931                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9932                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9933                                        Info = _WRONG_MESSAGE_FORMAT;
9934                                        break;
9935                                }
9936                                if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9937                                {
9938                                        plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9939                                        plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9940                                }
9941                                i = 0;
9942                                j = 0;
9943                                while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9944                                {
9945                                        j = 0;
9946                                        while ((j < DTMF_DIGIT_MAP_ENTRIES)
9947                                               && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9948                                                   || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9949                                        {
9950                                                j++;
9951                                        }
9952                                        i++;
9953                                }
9954                                if (j == DTMF_DIGIT_MAP_ENTRIES)
9955                                {
9956                                        dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9957                                                        UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9958                                        PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9959                                        break;
9960                                }
9961                                if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9962                                {
9963                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9964                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9965                                        Info = _WRONG_STATE;
9966                                        break;
9967                                }
9968                                api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9969                                start_internal_command(Id, plci, dtmf_command);
9970                                return (false);
9971
9972                        default:
9973                                dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9974                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9975                                PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9976                        }
9977                }
9978        }
9979        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9980              "wws", Info, SELECTOR_DTMF, result);
9981        return (false);
9982}
9983
9984
9985static void dtmf_confirmation(dword Id, PLCI *plci)
9986{
9987        word i;
9988        byte result[4];
9989
9990        dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9991                        UnMapId(Id), (char *)(FILE_), __LINE__));
9992
9993        result[0] = 2;
9994        PUT_WORD(&result[1], DTMF_SUCCESS);
9995        if (plci->dtmf_send_requests != 0)
9996        {
9997                sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9998                      "wws", GOOD, SELECTOR_DTMF, result);
9999                (plci->dtmf_send_requests)--;
10000                for (i = 0; i < plci->dtmf_send_requests; i++)
10001                        plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10002        }
10003}
10004
10005
10006static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10007{
10008        word i, j, n;
10009
10010        dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10011                        UnMapId(Id), (char *)(FILE_), __LINE__));
10012
10013        n = 0;
10014        for (i = 1; i < length; i++)
10015        {
10016                j = 0;
10017                while ((j < DTMF_DIGIT_MAP_ENTRIES)
10018                       && ((msg[i] != dtmf_digit_map[j].code)
10019                           || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10020                {
10021                        j++;
10022                }
10023                if (j < DTMF_DIGIT_MAP_ENTRIES)
10024                {
10025
10026                        if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10027                            && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10028                            && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10029                        {
10030                                if (n + 1 == i)
10031                                {
10032                                        for (i = length; i > n + 1; i--)
10033                                                msg[i] = msg[i - 1];
10034                                        length++;
10035                                        i++;
10036                                }
10037                                msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10038                        }
10039                        plci->tone_last_indication_code = dtmf_digit_map[j].character;
10040
10041                        msg[++n] = dtmf_digit_map[j].character;
10042                }
10043        }
10044        if (n != 0)
10045        {
10046                msg[0] = (byte) n;
10047                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10048        }
10049}
10050
10051
10052/*------------------------------------------------------------------*/
10053/* DTMF parameters                                                  */
10054/*------------------------------------------------------------------*/
10055
10056static void dtmf_parameter_write(PLCI *plci)
10057{
10058        word i;
10059        byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10060
10061        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10062                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10063                        (char *)(FILE_), __LINE__));
10064
10065        parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10066        parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10067        for (i = 0; i < plci->dtmf_parameter_length; i++)
10068                parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10069        add_p(plci, FTY, parameter_buffer);
10070        sig_req(plci, TEL_CTRL, 0);
10071        send_req(plci);
10072}
10073
10074
10075static void dtmf_parameter_clear_config(PLCI *plci)
10076{
10077
10078        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10079                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10080                        (char *)(FILE_), __LINE__));
10081
10082        plci->dtmf_parameter_length = 0;
10083}
10084
10085
10086static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10087{
10088
10089        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10090                        UnMapId(Id), (char *)(FILE_), __LINE__));
10091
10092}
10093
10094
10095static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10096{
10097
10098        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10099                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10100
10101        return (GOOD);
10102}
10103
10104
10105static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10106{
10107        word Info;
10108
10109        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10110                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10111
10112        Info = GOOD;
10113        if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10114            && (plci->dtmf_parameter_length != 0))
10115        {
10116                switch (plci->adjust_b_state)
10117                {
10118                case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10119                        plci->internal_command = plci->adjust_b_command;
10120                        if (plci->sig_req)
10121                        {
10122                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10123                                break;
10124                        }
10125                        dtmf_parameter_write(plci);
10126                        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10127                        break;
10128                case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10129                        if ((Rc != OK) && (Rc != OK_FC))
10130                        {
10131                                dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10132                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10133                                Info = _WRONG_STATE;
10134                                break;
10135                        }
10136                        break;
10137                }
10138        }
10139        return (Info);
10140}
10141
10142
10143/*------------------------------------------------------------------*/
10144/* Line interconnect facilities                                     */
10145/*------------------------------------------------------------------*/
10146
10147
10148LI_CONFIG   *li_config_table;
10149word li_total_channels;
10150
10151
10152/*------------------------------------------------------------------*/
10153/* translate a CHI information element to a channel number          */
10154/* returns 0xff - any channel                                       */
10155/*         0xfe - chi wrong coding                                  */
10156/*         0xfd - D-channel                                         */
10157/*         0x00 - no channel                                        */
10158/*         else channel number / PRI: timeslot                      */
10159/* if channels is provided we accept more than one channel.         */
10160/*------------------------------------------------------------------*/
10161
10162static byte chi_to_channel(byte *chi, dword *pchannelmap)
10163{
10164        int p;
10165        int i;
10166        dword map;
10167        byte excl;
10168        byte ofs;
10169        byte ch;
10170
10171        if (pchannelmap) *pchannelmap = 0;
10172        if (!chi[0]) return 0xff;
10173        excl = 0;
10174
10175        if (chi[1] & 0x20) {
10176                if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10177                for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10178                if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10179                if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10180                if (chi[1] & 0x08) excl = 0x40;
10181
10182                /* int. id present */
10183                if (chi[1] & 0x40) {
10184                        p = i + 1;
10185                        for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10186                        if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10187                }
10188
10189                /* coding standard, Number/Map, Channel Type */
10190                p = i + 1;
10191                for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10192                if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10193                if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10194
10195                /* Number/Map */
10196                if (chi[p] & 0x10) {
10197
10198                        /* map */
10199                        if ((chi[0] - p) == 4) ofs = 0;
10200                        else if ((chi[0] - p) == 3) ofs = 1;
10201                        else return 0xfe;
10202                        ch = 0;
10203                        map = 0;
10204                        for (i = 0; i < 4 && p < chi[0]; i++) {
10205                                p++;
10206                                ch += 8;
10207                                map <<= 8;
10208                                if (chi[p]) {
10209                                        for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10210                                        map |= chi[p];
10211                                }
10212                        }
10213                        ch += ofs;
10214                        map <<= ofs;
10215                }
10216                else {
10217
10218                        /* number */
10219                        p = i + 1;
10220                        ch = chi[p] & 0x3f;
10221                        if (pchannelmap) {
10222                                if ((byte)(chi[0] - p) > 30) return 0xfe;
10223                                map = 0;
10224                                for (i = p; i <= chi[0]; i++) {
10225                                        if ((chi[i] & 0x7f) > 31) return 0xfe;
10226                                        map |= (1L << (chi[i] & 0x7f));
10227                                }
10228                        }
10229                        else {
10230                                if (p != chi[0]) return 0xfe;
10231                                if (ch > 31) return 0xfe;
10232                                map = (1L << ch);
10233                        }
10234                        if (chi[p] & 0x40) return 0xfe;
10235                }
10236                if (pchannelmap) *pchannelmap = map;
10237                else if (map != ((dword)(1L << ch))) return 0xfe;
10238                return (byte)(excl | ch);
10239        }
10240        else {  /* not PRI */
10241                for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10242                if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10243                if (chi[1] & 0x08) excl = 0x40;
10244
10245                switch (chi[1] | 0x98) {
10246                case 0x98: return 0;
10247                case 0x99:
10248                        if (pchannelmap) *pchannelmap = 2;
10249                        return excl | 1;
10250                case 0x9a:
10251                        if (pchannelmap) *pchannelmap = 4;
10252                        return excl | 2;
10253                case 0x9b: return 0xff;
10254                case 0x9c: return 0xfd; /* d-ch */
10255                default: return 0xfe;
10256                }
10257        }
10258}
10259
10260
10261static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10262{
10263        DIVA_CAPI_ADAPTER *a;
10264        PLCI *splci;
10265        byte old_id;
10266
10267        a = plci->adapter;
10268        old_id = plci->li_bchannel_id;
10269        if (a->li_pri)
10270        {
10271                if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10272                        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10273                plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10274                if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10275                        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10276        }
10277        else
10278        {
10279                if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10280                {
10281                        if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10282                                li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10283                        plci->li_bchannel_id = bchannel_id & 0x03;
10284                        if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10285                        {
10286                                splci = a->AdvSignalPLCI;
10287                                if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10288                                {
10289                                        if ((splci->li_bchannel_id != 0)
10290                                            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10291                                        {
10292                                                li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10293                                        }
10294                                        splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10295                                        li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10296                                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10297                                                        (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10298                                                        (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10299                                }
10300                        }
10301                        if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10302                                li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10303                }
10304        }
10305        if ((old_id == 0) && (plci->li_bchannel_id != 0)
10306            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10307        {
10308                mixer_clear_config(plci);
10309        }
10310        dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10311                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10312                        (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10313}
10314
10315
10316static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10317{
10318        DIVA_CAPI_ADAPTER *a;
10319        PLCI *splci;
10320        byte ch, old_id;
10321
10322        a = plci->adapter;
10323        old_id = plci->li_bchannel_id;
10324        ch = chi_to_channel(chi, NULL);
10325        if (!(ch & 0x80))
10326        {
10327                if (a->li_pri)
10328                {
10329                        if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10330                                li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10331                        plci->li_bchannel_id = (ch & 0x1f) + 1;
10332                        if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10333                                li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10334                }
10335                else
10336                {
10337                        if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10338                        {
10339                                if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10340                                        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10341                                plci->li_bchannel_id = ch & 0x1f;
10342                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10343                                {
10344                                        splci = a->AdvSignalPLCI;
10345                                        if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10346                                        {
10347                                                if ((splci->li_bchannel_id != 0)
10348                                                    && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10349                                                {
10350                                                        li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10351                                                }
10352                                                splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10353                                                li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10354                                                dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10355                                                                (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10356                                                                (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10357                                        }
10358                                }
10359                                if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10360                                        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10361                        }
10362                }
10363        }
10364        if ((old_id == 0) && (plci->li_bchannel_id != 0)
10365            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10366        {
10367                mixer_clear_config(plci);
10368        }
10369        dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10370                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10371                        (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10372}
10373
10374
10375#define MIXER_MAX_DUMP_CHANNELS 34
10376
10377static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10378{
10379        word n, i, j;
10380        char *p;
10381        char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10382
10383        dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10384                        (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10385
10386        for (i = 0; i < li_total_channels; i++)
10387        {
10388                li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10389                if (li_config_table[i].chflags != 0)
10390                        li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10391                else
10392                {
10393                        for (j = 0; j < li_total_channels; j++)
10394                        {
10395                                if (((li_config_table[i].flag_table[j]) != 0)
10396                                    || ((li_config_table[j].flag_table[i]) != 0))
10397                                {
10398                                        li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10399                                }
10400                                if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10401                                    || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10402                                {
10403                                        li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10404                                }
10405                        }
10406                }
10407        }
10408        for (i = 0; i < li_total_channels; i++)
10409        {
10410                for (j = 0; j < li_total_channels; j++)
10411                {
10412                        li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10413                        if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10414                                li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10415                }
10416        }
10417        for (n = 0; n < li_total_channels; n++)
10418        {
10419                if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10420                {
10421                        for (i = 0; i < li_total_channels; i++)
10422                        {
10423                                if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10424                                {
10425                                        for (j = 0; j < li_total_channels; j++)
10426                                        {
10427                                                li_config_table[i].coef_table[j] |=
10428                                                        li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10429                                        }
10430                                }
10431                        }
10432                }
10433        }
10434        for (i = 0; i < li_total_channels; i++)
10435        {
10436                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10437                {
10438                        li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10439                        for (j = 0; j < li_total_channels; j++)
10440                        {
10441                                if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10442                                        li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10443                        }
10444                        if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10445                                li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10446                }
10447        }
10448        for (i = 0; i < li_total_channels; i++)
10449        {
10450                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10451                {
10452                        for (j = 0; j < li_total_channels; j++)
10453                        {
10454                                if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10455                                        li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10456                                if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10457                                        li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10458                                if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10459                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10460                                if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10461                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10462                        }
10463                        if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10464                        {
10465                                for (j = 0; j < li_total_channels; j++)
10466                                {
10467                                        if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10468                                        {
10469                                                li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10470                                                if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10471                                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10472                                        }
10473                                }
10474                        }
10475                        if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10476                        {
10477                                for (j = 0; j < li_total_channels; j++)
10478                                {
10479                                        if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10480                                                li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10481                                }
10482                        }
10483                        if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10484                        {
10485                                for (j = 0; j < li_total_channels; j++)
10486                                {
10487                                        if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10488                                        {
10489                                                for (n = 0; n < li_total_channels; n++)
10490                                                {
10491                                                        if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10492                                                        {
10493                                                                li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10494                                                                if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10495                                                                {
10496                                                                        li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10497                                                                        if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10498                                                                                li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10499                                                                }
10500                                                                else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10501                                                                        li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10502                                                        }
10503                                                }
10504                                        }
10505                                }
10506                        }
10507                }
10508        }
10509        for (i = 0; i < li_total_channels; i++)
10510        {
10511                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10512                {
10513                        if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10514                                li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10515                        if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10516                                li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10517                        if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10518                                li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10519                        for (j = 0; j < li_total_channels; j++)
10520                        {
10521                                if ((li_config_table[i].flag_table[j] &
10522                                     (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10523                                    || (li_config_table[j].flag_table[i] &
10524                                        (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10525                                {
10526                                        li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10527                                }
10528                                if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10529                                        li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10530                                if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10531                                        li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10532                        }
10533                        if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10534                        {
10535                                li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10536                                li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10537                        }
10538                }
10539        }
10540        for (i = 0; i < li_total_channels; i++)
10541        {
10542                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10543                {
10544                        j = 0;
10545                        while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10546                                j++;
10547                        if (j < li_total_channels)
10548                        {
10549                                for (j = 0; j < li_total_channels; j++)
10550                                {
10551                                        li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10552                                        if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10553                                                li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10554                                }
10555                        }
10556                }
10557        }
10558        n = li_total_channels;
10559        if (n > MIXER_MAX_DUMP_CHANNELS)
10560                n = MIXER_MAX_DUMP_CHANNELS;
10561
10562        p = hex_line;
10563        for (j = 0; j < n; j++)
10564        {
10565                if ((j & 0x7) == 0)
10566                        *(p++) = ' ';
10567                p = hex_byte_pack(p, li_config_table[j].curchnl);
10568        }
10569        *p = '\0';
10570        dbug(1, dprintf("[%06lx] CURRENT %s",
10571                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10572        p = hex_line;
10573        for (j = 0; j < n; j++)
10574        {
10575                if ((j & 0x7) == 0)
10576                        *(p++) = ' ';
10577                p = hex_byte_pack(p, li_config_table[j].channel);
10578        }
10579        *p = '\0';
10580        dbug(1, dprintf("[%06lx] CHANNEL %s",
10581                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10582        p = hex_line;
10583        for (j = 0; j < n; j++)
10584        {
10585                if ((j & 0x7) == 0)
10586                        *(p++) = ' ';
10587                p = hex_byte_pack(p, li_config_table[j].chflags);
10588        }
10589        *p = '\0';
10590        dbug(1, dprintf("[%06lx] CHFLAG  %s",
10591                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10592        for (i = 0; i < n; i++)
10593        {
10594                p = hex_line;
10595                for (j = 0; j < n; j++)
10596                {
10597                        if ((j & 0x7) == 0)
10598                                *(p++) = ' ';
10599                        p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10600                }
10601                *p = '\0';
10602                dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10603                                (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10604        }
10605        for (i = 0; i < n; i++)
10606        {
10607                p = hex_line;
10608                for (j = 0; j < n; j++)
10609                {
10610                        if ((j & 0x7) == 0)
10611                                *(p++) = ' ';
10612                        p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10613                }
10614                *p = '\0';
10615                dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10616                                (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10617        }
10618}
10619
10620
10621static struct
10622{
10623        byte mask;
10624        byte line_flags;
10625} mixer_write_prog_pri[] =
10626{
10627        { LI_COEF_CH_CH, 0 },
10628        { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10629        { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10630        { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10631};
10632
10633static struct
10634{
10635        byte from_ch;
10636        byte to_ch;
10637        byte mask;
10638        byte xconnect_override;
10639} mixer_write_prog_bri[] =
10640{
10641        { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10642        { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10643        { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10644        { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10645        { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10646        { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10647        { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10648        { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10649        { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10650        { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10651        { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10652        { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10653        { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10654        { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10655        { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10656        { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10657        { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10658        { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10659        { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10660        { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10661        { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10662        { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10663        { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10664        { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10665        { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10666        { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10667        { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10668        { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10669        { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10670        { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10671        { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10672        { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10673        { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10674        { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10675        { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10676        { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10677};
10678
10679static byte mixer_swapped_index_bri[] =
10680{
10681        18,  /* B      to B      */
10682        19,  /* Alt B  to B      */
10683        20,  /* PC     to B      */
10684        21,  /* Alt PC to B      */
10685        22,  /* IC     to B      */
10686        23,  /* Alt IC to B      */
10687        24,  /* B      to PC     */
10688        25,  /* Alt B  to PC     */
10689        26,  /* PC     to PC     */
10690        27,  /* Alt PC to PC     */
10691        28,  /* IC     to PC     */
10692        29,  /* Alt IC to PC     */
10693        30,  /* B      to IC     */
10694        31,  /* Alt B  to IC     */
10695        32,  /* PC     to IC     */
10696        33,  /* Alt PC to IC     */
10697        34,  /* IC     to IC     */
10698        35,  /* Alt IC to IC     */
10699        0,   /* Alt B  to Alt B  */
10700        1,   /* B      to Alt B  */
10701        2,   /* Alt PC to Alt B  */
10702        3,   /* PC     to Alt B  */
10703        4,   /* Alt IC to Alt B  */
10704        5,   /* IC     to Alt B  */
10705        6,   /* Alt B  to Alt PC */
10706        7,   /* B      to Alt PC */
10707        8,   /* Alt PC to Alt PC */
10708        9,   /* PC     to Alt PC */
10709        10,  /* Alt IC to Alt PC */
10710        11,  /* IC     to Alt PC */
10711        12,  /* Alt B  to Alt IC */
10712        13,  /* B      to Alt IC */
10713        14,  /* Alt PC to Alt IC */
10714        15,  /* PC     to Alt IC */
10715        16,  /* Alt IC to Alt IC */
10716        17   /* IC     to Alt IC */
10717};
10718
10719static struct
10720{
10721        byte mask;
10722        byte from_pc;
10723        byte to_pc;
10724} xconnect_write_prog[] =
10725{
10726        { LI_COEF_CH_CH, false, false },
10727        { LI_COEF_CH_PC, false, true },
10728        { LI_COEF_PC_CH, true, false },
10729        { LI_COEF_PC_PC, true, true }
10730};
10731
10732
10733static void xconnect_query_addresses(PLCI *plci)
10734{
10735        DIVA_CAPI_ADAPTER *a;
10736        word w, ch;
10737        byte *p;
10738
10739        dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10740                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10741                        (char *)(FILE_), __LINE__));
10742
10743        a = plci->adapter;
10744        if (a->li_pri && ((plci->li_bchannel_id == 0)
10745                          || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10746        {
10747                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10748                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10749                                (char *)(FILE_), __LINE__));
10750                return;
10751        }
10752        p = plci->internal_req_buffer;
10753        ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10754        *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10755        w = ch;
10756        *(p++) = (byte) w;
10757        *(p++) = (byte)(w >> 8);
10758        w = ch | XCONNECT_CHANNEL_PORT_PC;
10759        *(p++) = (byte) w;
10760        *(p++) = (byte)(w >> 8);
10761        plci->NData[0].P = plci->internal_req_buffer;
10762        plci->NData[0].PLength = p - plci->internal_req_buffer;
10763        plci->NL.X = plci->NData;
10764        plci->NL.ReqCh = 0;
10765        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10766        plci->adapter->request(&plci->NL);
10767}
10768
10769
10770static void xconnect_write_coefs(PLCI *plci, word internal_command)
10771{
10772
10773        dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10774                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10775                        (char *)(FILE_), __LINE__, internal_command));
10776
10777        plci->li_write_command = internal_command;
10778        plci->li_write_channel = 0;
10779}
10780
10781
10782static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10783{
10784        DIVA_CAPI_ADAPTER *a;
10785        word w, n, i, j, r, s, to_ch;
10786        dword d;
10787        byte *p;
10788        struct xconnect_transfer_address_s   *transfer_address;
10789        byte ch_map[MIXER_CHANNELS_BRI];
10790
10791        dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10792                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10793
10794        a = plci->adapter;
10795        if ((plci->li_bchannel_id == 0)
10796            || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10797        {
10798                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10799                                UnMapId(Id), (char *)(FILE_), __LINE__));
10800                return (true);
10801        }
10802        i = a->li_base + (plci->li_bchannel_id - 1);
10803        j = plci->li_write_channel;
10804        p = plci->internal_req_buffer;
10805        if (j != 0)
10806        {
10807                if ((Rc != OK) && (Rc != OK_FC))
10808                {
10809                        dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10810                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10811                        return (false);
10812                }
10813        }
10814        if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10815        {
10816                r = 0;
10817                s = 0;
10818                if (j < li_total_channels)
10819                {
10820                        if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10821                        {
10822                                s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10823                                     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10824                                        ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10825                                         (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10826                        }
10827                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10828                        while ((j < li_total_channels)
10829                               && ((r == 0)
10830                                   || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10831                                   || (!li_config_table[j].adapter->li_pri
10832                                       && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10833                                   || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10834                                        || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10835                                       && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10836                                           || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10837                                   || ((li_config_table[j].adapter->li_base != a->li_base)
10838                                       && !(r & s &
10839                                            ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10840                                             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10841                                            ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10842                                             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10843                        {
10844                                j++;
10845                                if (j < li_total_channels)
10846                                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10847                        }
10848                }
10849                if (j < li_total_channels)
10850                {
10851                        plci->internal_command = plci->li_write_command;
10852                        if (plci_nl_busy(plci))
10853                                return (true);
10854                        to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10855                        *(p++) = UDATA_REQUEST_XCONNECT_TO;
10856                        do
10857                        {
10858                                if (li_config_table[j].adapter->li_base != a->li_base)
10859                                {
10860                                        r &= s &
10861                                                ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10862                                                 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10863                                                ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10864                                                 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10865                                }
10866                                n = 0;
10867                                do
10868                                {
10869                                        if (r & xconnect_write_prog[n].mask)
10870                                        {
10871                                                if (xconnect_write_prog[n].from_pc)
10872                                                        transfer_address = &(li_config_table[j].send_pc);
10873                                                else
10874                                                        transfer_address = &(li_config_table[j].send_b);
10875                                                d = transfer_address->card_address.low;
10876                                                *(p++) = (byte) d;
10877                                                *(p++) = (byte)(d >> 8);
10878                                                *(p++) = (byte)(d >> 16);
10879                                                *(p++) = (byte)(d >> 24);
10880                                                d = transfer_address->card_address.high;
10881                                                *(p++) = (byte) d;
10882                                                *(p++) = (byte)(d >> 8);
10883                                                *(p++) = (byte)(d >> 16);
10884                                                *(p++) = (byte)(d >> 24);
10885                                                d = transfer_address->offset;
10886                                                *(p++) = (byte) d;
10887                                                *(p++) = (byte)(d >> 8);
10888                                                *(p++) = (byte)(d >> 16);
10889                                                *(p++) = (byte)(d >> 24);
10890                                                w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10891                                                *(p++) = (byte) w;
10892                                                *(p++) = (byte)(w >> 8);
10893                                                w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10894                                                        (li_config_table[i].adapter->u_law ?
10895                                                         (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10896                                                         (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10897                                                *(p++) = (byte) w;
10898                                                *(p++) = (byte) 0;
10899                                                li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10900                                        }
10901                                        n++;
10902                                } while ((n < ARRAY_SIZE(xconnect_write_prog))
10903                                         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10904                                if (n == ARRAY_SIZE(xconnect_write_prog))
10905                                {
10906                                        do
10907                                        {
10908                                                j++;
10909                                                if (j < li_total_channels)
10910                                                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10911                                        } while ((j < li_total_channels)
10912                                                 && ((r == 0)
10913                                                     || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10914                                                     || (!li_config_table[j].adapter->li_pri
10915                                                         && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10916                                                     || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10917                                                          || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10918                                                         && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10919                                                             || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10920                                                     || ((li_config_table[j].adapter->li_base != a->li_base)
10921                                                         && !(r & s &
10922                                                              ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10923                                                               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10924                                                              ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10925                                                               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10926                                }
10927                        } while ((j < li_total_channels)
10928                                 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10929                }
10930                else if (j == li_total_channels)
10931                {
10932                        plci->internal_command = plci->li_write_command;
10933                        if (plci_nl_busy(plci))
10934                                return (true);
10935                        if (a->li_pri)
10936                        {
10937                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10938                                w = 0;
10939                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10940                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
10941                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10942                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
10943                                *(p++) = (byte) w;
10944                                *(p++) = (byte)(w >> 8);
10945                        }
10946                        else
10947                        {
10948                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10949                                w = 0;
10950                                if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10951                                    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10952                                {
10953                                        w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10954                                }
10955                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10956                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
10957                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10958                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
10959                                *(p++) = (byte) w;
10960                                *(p++) = (byte)(w >> 8);
10961                                for (j = 0; j < sizeof(ch_map); j += 2)
10962                                {
10963                                        if (plci->li_bchannel_id == 2)
10964                                        {
10965                                                ch_map[j] = (byte)(j + 1);
10966                                                ch_map[j + 1] = (byte) j;
10967                                        }
10968                                        else
10969                                        {
10970                                                ch_map[j] = (byte) j;
10971                                                ch_map[j + 1] = (byte)(j + 1);
10972                                        }
10973                                }
10974                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10975                                {
10976                                        i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10977                                        j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10978                                        if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10979                                        {
10980                                                *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10981                                                        mixer_write_prog_bri[n].xconnect_override :
10982                                                        ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10983                                                if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10984                                                {
10985                                                        w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10986                                                        li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10987                                                }
10988                                        }
10989                                        else
10990                                        {
10991                                                *p = 0x00;
10992                                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10993                                                {
10994                                                        w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10995                                                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10996                                                                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10997                                                }
10998                                        }
10999                                        p++;
11000                                }
11001                        }
11002                        j = li_total_channels + 1;
11003                }
11004        }
11005        else
11006        {
11007                if (j <= li_total_channels)
11008                {
11009                        plci->internal_command = plci->li_write_command;
11010                        if (plci_nl_busy(plci))
11011                                return (true);
11012                        if (j < a->li_base)
11013                                j = a->li_base;
11014                        if (a->li_pri)
11015                        {
11016                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11017                                w = 0;
11018                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11019                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
11020                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11021                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
11022                                *(p++) = (byte) w;
11023                                *(p++) = (byte)(w >> 8);
11024                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11025                                {
11026                                        *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11027                                        for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11028                                        {
11029                                                w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11030                                                if (w & mixer_write_prog_pri[n].mask)
11031                                                {
11032                                                        *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11033                                                        li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11034                                                }
11035                                                else
11036                                                        *(p++) = 0x00;
11037                                        }
11038                                        *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11039                                        for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11040                                        {
11041                                                w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11042                                                if (w & mixer_write_prog_pri[n].mask)
11043                                                {
11044                                                        *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11045                                                        li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11046                                                }
11047                                                else
11048                                                        *(p++) = 0x00;
11049                                        }
11050                                }
11051                        }
11052                        else
11053                        {
11054                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11055                                w = 0;
11056                                if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11057                                    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11058                                {
11059                                        w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11060                                }
11061                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11062                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
11063                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11064                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
11065                                *(p++) = (byte) w;
11066                                *(p++) = (byte)(w >> 8);
11067                                for (j = 0; j < sizeof(ch_map); j += 2)
11068                                {
11069                                        if (plci->li_bchannel_id == 2)
11070                                        {
11071                                                ch_map[j] = (byte)(j + 1);
11072                                                ch_map[j + 1] = (byte) j;
11073                                        }
11074                                        else
11075                                        {
11076                                                ch_map[j] = (byte) j;
11077                                                ch_map[j + 1] = (byte)(j + 1);
11078                                        }
11079                                }
11080                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11081                                {
11082                                        i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11083                                        j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11084                                        if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11085                                        {
11086                                                *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11087                                                w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11088                                                li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11089                                        }
11090                                        else
11091                                        {
11092                                                *p = 0x00;
11093                                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11094                                                {
11095                                                        w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11096                                                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11097                                                                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11098                                                }
11099                                        }
11100                                        p++;
11101                                }
11102                        }
11103                        j = li_total_channels + 1;
11104                }
11105        }
11106        plci->li_write_channel = j;
11107        if (p != plci->internal_req_buffer)
11108        {
11109                plci->NData[0].P = plci->internal_req_buffer;
11110                plci->NData[0].PLength = p - plci->internal_req_buffer;
11111                plci->NL.X = plci->NData;
11112                plci->NL.ReqCh = 0;
11113                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11114                plci->adapter->request(&plci->NL);
11115        }
11116        return (true);
11117}
11118
11119
11120static void mixer_notify_update(PLCI *plci, byte others)
11121{
11122        DIVA_CAPI_ADAPTER *a;
11123        word i, w;
11124        PLCI *notify_plci;
11125        byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11126
11127        dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11128                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11129                        (char *)(FILE_), __LINE__, others));
11130
11131        a = plci->adapter;
11132        if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11133        {
11134                if (others)
11135                        plci->li_notify_update = true;
11136                i = 0;
11137                do
11138                {
11139                        notify_plci = NULL;
11140                        if (others)
11141                        {
11142                                while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11143                                        i++;
11144                                if (i < li_total_channels)
11145                                        notify_plci = li_config_table[i++].plci;
11146                        }
11147                        else
11148                        {
11149                                if ((plci->li_bchannel_id != 0)
11150                                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11151                                {
11152                                        notify_plci = plci;
11153                                }
11154                        }
11155                        if ((notify_plci != NULL)
11156                            && !notify_plci->li_notify_update
11157                            && (notify_plci->appl != NULL)
11158                            && (notify_plci->State)
11159                            && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11160                        {
11161                                notify_plci->li_notify_update = true;
11162                                ((CAPI_MSG *) msg)->header.length = 18;
11163                                ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11164                                ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11165                                ((CAPI_MSG *) msg)->header.number = 0;
11166                                ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11167                                ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11168                                ((CAPI_MSG *) msg)->header.ncci = 0;
11169                                ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11170                                ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11171                                ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11172                                ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11173                                ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11174                                w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11175                                if (w != _QUEUE_FULL)
11176                                {
11177                                        if (w != 0)
11178                                        {
11179                                                dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11180                                                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11181                                                                (char *)(FILE_), __LINE__,
11182                                                                (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11183                                        }
11184                                        notify_plci->li_notify_update = false;
11185                                }
11186                        }
11187                } while (others && (notify_plci != NULL));
11188                if (others)
11189                        plci->li_notify_update = false;
11190        }
11191}
11192
11193
11194static void mixer_clear_config(PLCI *plci)
11195{
11196        DIVA_CAPI_ADAPTER *a;
11197        word i, j;
11198
11199        dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11200                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11201                        (char *)(FILE_), __LINE__));
11202
11203        plci->li_notify_update = false;
11204        plci->li_plci_b_write_pos = 0;
11205        plci->li_plci_b_read_pos = 0;
11206        plci->li_plci_b_req_pos = 0;
11207        a = plci->adapter;
11208        if ((plci->li_bchannel_id != 0)
11209            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11210        {
11211                i = a->li_base + (plci->li_bchannel_id - 1);
11212                li_config_table[i].curchnl = 0;
11213                li_config_table[i].channel = 0;
11214                li_config_table[i].chflags = 0;
11215                for (j = 0; j < li_total_channels; j++)
11216                {
11217                        li_config_table[j].flag_table[i] = 0;
11218                        li_config_table[i].flag_table[j] = 0;
11219                        li_config_table[i].coef_table[j] = 0;
11220                        li_config_table[j].coef_table[i] = 0;
11221                }
11222                if (!a->li_pri)
11223                {
11224                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11225                        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11226                        {
11227                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11228                                li_config_table[i].curchnl = 0;
11229                                li_config_table[i].channel = 0;
11230                                li_config_table[i].chflags = 0;
11231                                for (j = 0; j < li_total_channels; j++)
11232                                {
11233                                        li_config_table[i].flag_table[j] = 0;
11234                                        li_config_table[j].flag_table[i] = 0;
11235                                        li_config_table[i].coef_table[j] = 0;
11236                                        li_config_table[j].coef_table[i] = 0;
11237                                }
11238                                if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11239                                {
11240                                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11241                                        li_config_table[i].curchnl = 0;
11242                                        li_config_table[i].channel = 0;
11243                                        li_config_table[i].chflags = 0;
11244                                        for (j = 0; j < li_total_channels; j++)
11245                                        {
11246                                                li_config_table[i].flag_table[j] = 0;
11247                                                li_config_table[j].flag_table[i] = 0;
11248                                                li_config_table[i].coef_table[j] = 0;
11249                                                li_config_table[j].coef_table[i] = 0;
11250                                        }
11251                                }
11252                        }
11253                }
11254        }
11255}
11256
11257
11258static void mixer_prepare_switch(dword Id, PLCI *plci)
11259{
11260
11261        dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11262                        UnMapId(Id), (char *)(FILE_), __LINE__));
11263
11264        do
11265        {
11266                mixer_indication_coefs_set(Id, plci);
11267        } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11268}
11269
11270
11271static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11272{
11273        DIVA_CAPI_ADAPTER *a;
11274        word i, j;
11275
11276        dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11277                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11278
11279        a = plci->adapter;
11280        if ((plci->li_bchannel_id != 0)
11281            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11282        {
11283                i = a->li_base + (plci->li_bchannel_id - 1);
11284                for (j = 0; j < li_total_channels; j++)
11285                {
11286                        li_config_table[i].coef_table[j] &= 0xf;
11287                        li_config_table[j].coef_table[i] &= 0xf;
11288                }
11289                if (!a->li_pri)
11290                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11291        }
11292        return (GOOD);
11293}
11294
11295
11296static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11297{
11298        DIVA_CAPI_ADAPTER *a;
11299        word Info;
11300
11301        dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11302                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11303
11304        Info = GOOD;
11305        a = plci->adapter;
11306        if ((plci->B1_facilities & B1_FACILITY_MIXER)
11307            && (plci->li_bchannel_id != 0)
11308            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11309        {
11310                switch (plci->adjust_b_state)
11311                {
11312                case ADJUST_B_RESTORE_MIXER_1:
11313                        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11314                        {
11315                                plci->internal_command = plci->adjust_b_command;
11316                                if (plci_nl_busy(plci))
11317                                {
11318                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11319                                        break;
11320                                }
11321                                xconnect_query_addresses(plci);
11322                                plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11323                                break;
11324                        }
11325                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11326                        Rc = OK;
11327                        /* fall through */
11328                case ADJUST_B_RESTORE_MIXER_2:
11329                case ADJUST_B_RESTORE_MIXER_3:
11330                case ADJUST_B_RESTORE_MIXER_4:
11331                        if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11332                        {
11333                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11334                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11335                                Info = _WRONG_STATE;
11336                                break;
11337                        }
11338                        if (Rc == OK)
11339                        {
11340                                if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11341                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11342                                else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11343                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11344                        }
11345                        else if (Rc == 0)
11346                        {
11347                                if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11348                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11349                                else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11350                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11351                        }
11352                        if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11353                        {
11354                                plci->internal_command = plci->adjust_b_command;
11355                                break;
11356                        }
11357                        /* fall through */
11358                case ADJUST_B_RESTORE_MIXER_5:
11359                        xconnect_write_coefs(plci, plci->adjust_b_command);
11360                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11361                        Rc = OK;
11362                        /* fall through */
11363                case ADJUST_B_RESTORE_MIXER_6:
11364                        if (!xconnect_write_coefs_process(Id, plci, Rc))
11365                        {
11366                                dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11367                                                UnMapId(Id), (char *)(FILE_), __LINE__));
11368                                Info = _FACILITY_NOT_SUPPORTED;
11369                                break;
11370                        }
11371                        if (plci->internal_command)
11372                                break;
11373                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11374                case ADJUST_B_RESTORE_MIXER_7:
11375                        break;
11376                }
11377        }
11378        return (Info);
11379}
11380
11381
11382static void mixer_command(dword Id, PLCI *plci, byte Rc)
11383{
11384        DIVA_CAPI_ADAPTER *a;
11385        word i, internal_command;
11386
11387        dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11388                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11389                        plci->li_cmd));
11390
11391        a = plci->adapter;
11392        internal_command = plci->internal_command;
11393        plci->internal_command = 0;
11394        switch (plci->li_cmd)
11395        {
11396        case LI_REQ_CONNECT:
11397        case LI_REQ_DISCONNECT:
11398        case LI_REQ_SILENT_UPDATE:
11399                switch (internal_command)
11400                {
11401                default:
11402                        if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11403                        {
11404                                adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11405                                                                          B1_FACILITY_MIXER), MIXER_COMMAND_1);
11406                        }
11407                        /* fall through */
11408                case MIXER_COMMAND_1:
11409                        if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11410                        {
11411                                if (adjust_b_process(Id, plci, Rc) != GOOD)
11412                                {
11413                                        dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11414                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11415                                        break;
11416                                }
11417                                if (plci->internal_command)
11418                                        return;
11419                        }
11420                        plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11421                        if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11422                            || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11423                                && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11424                                                                                      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11425                        {
11426                                xconnect_write_coefs(plci, MIXER_COMMAND_2);
11427                        }
11428                        else
11429                        {
11430                                do
11431                                {
11432                                        mixer_indication_coefs_set(Id, plci);
11433                                } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11434                        }
11435                        /* fall through */
11436                case MIXER_COMMAND_2:
11437                        if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11438                            || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11439                                && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11440                                                                                      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11441                        {
11442                                if (!xconnect_write_coefs_process(Id, plci, Rc))
11443                                {
11444                                        dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11445                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11446                                        if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11447                                        {
11448                                                do
11449                                                {
11450                                                        plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11451                                                                LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11452                                                        i = (plci->li_plci_b_write_pos == 0) ?
11453                                                                LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11454                                                } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11455                                                         && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11456                                        }
11457                                        break;
11458                                }
11459                                if (plci->internal_command)
11460                                        return;
11461                        }
11462                        if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11463                        {
11464                                adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11465                                                                          ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11466                        }
11467                        /* fall through */
11468                case MIXER_COMMAND_3:
11469                        if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11470                        {
11471                                if (adjust_b_process(Id, plci, Rc) != GOOD)
11472                                {
11473                                        dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11474                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11475                                        break;
11476                                }
11477                                if (plci->internal_command)
11478                                        return;
11479                        }
11480                        break;
11481                }
11482                break;
11483        }
11484        if ((plci->li_bchannel_id == 0)
11485            || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11486        {
11487                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11488                                UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11489        }
11490        else
11491        {
11492                i = a->li_base + (plci->li_bchannel_id - 1);
11493                li_config_table[i].curchnl = plci->li_channel_bits;
11494                if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11495                {
11496                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11497                        li_config_table[i].curchnl = plci->li_channel_bits;
11498                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11499                        {
11500                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11501                                li_config_table[i].curchnl = plci->li_channel_bits;
11502                        }
11503                }
11504        }
11505}
11506
11507
11508static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11509                              dword plci_b_id, byte connect, dword li_flags)
11510{
11511        word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11512        PLCI *plci_b;
11513        DIVA_CAPI_ADAPTER *a_b;
11514
11515        a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11516        plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11517        ch_a = a->li_base + (plci->li_bchannel_id - 1);
11518        if (!a->li_pri && (plci->tel == ADV_VOICE)
11519            && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11520        {
11521                ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11522                ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11523                        a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11524        }
11525        else
11526        {
11527                ch_a_v = ch_a;
11528                ch_a_s = ch_a;
11529        }
11530        ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11531        if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11532            && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11533        {
11534                ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11535                ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11536                        a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11537        }
11538        else
11539        {
11540                ch_b_v = ch_b;
11541                ch_b_s = ch_b;
11542        }
11543        if (connect)
11544        {
11545                li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11546                li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11547                li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11548                li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11549        }
11550        li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11551        li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11552        li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11553        li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11554        if (ch_a_v == ch_b_v)
11555        {
11556                li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11557                li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11558        }
11559        else
11560        {
11561                if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11562                {
11563                        for (i = 0; i < li_total_channels; i++)
11564                        {
11565                                if (i != ch_a_v)
11566                                        li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11567                        }
11568                }
11569                if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11570                {
11571                        for (i = 0; i < li_total_channels; i++)
11572                        {
11573                                if (i != ch_a_s)
11574                                        li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11575                        }
11576                }
11577                if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11578                {
11579                        for (i = 0; i < li_total_channels; i++)
11580                        {
11581                                if (i != ch_a_v)
11582                                        li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11583                        }
11584                }
11585                if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11586                {
11587                        for (i = 0; i < li_total_channels; i++)
11588                        {
11589                                if (i != ch_a_s)
11590                                        li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11591                        }
11592                }
11593        }
11594        if (li_flags & LI_FLAG_CONFERENCE_A_B)
11595        {
11596                li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11597                li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11598                li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11599                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11600        }
11601        if (li_flags & LI_FLAG_CONFERENCE_B_A)
11602        {
11603                li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11604                li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11605                li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11606                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11607        }
11608        if (li_flags & LI_FLAG_MONITOR_A)
11609        {
11610                li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11611                li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11612        }
11613        if (li_flags & LI_FLAG_MONITOR_B)
11614        {
11615                li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11616                li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11617        }
11618        if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11619        {
11620                li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11621                li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11622        }
11623        if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11624        {
11625                li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11626                li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11627        }
11628        if (li_flags & LI_FLAG_MIX_A)
11629        {
11630                li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11631                li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11632        }
11633        if (li_flags & LI_FLAG_MIX_B)
11634        {
11635                li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11636                li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11637        }
11638        if (ch_a_v != ch_a_s)
11639        {
11640                li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11641                li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11642        }
11643        if (ch_b_v != ch_b_s)
11644        {
11645                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11646                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11647        }
11648}
11649
11650
11651static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11652                               dword plci_b_id, byte connect, dword li_flags)
11653{
11654        word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11655        PLCI *plci_b;
11656        DIVA_CAPI_ADAPTER *a_b;
11657
11658        a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11659        plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11660        ch_a = a->li_base + (plci->li_bchannel_id - 1);
11661        if (!a->li_pri && (plci->tel == ADV_VOICE)
11662            && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11663        {
11664                ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11665                ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11666                        a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11667        }
11668        else
11669        {
11670                ch_a_v = ch_a;
11671                ch_a_s = ch_a;
11672        }
11673        ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11674        if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11675            && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11676        {
11677                ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11678                ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11679                        a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11680        }
11681        else
11682        {
11683                ch_b_v = ch_b;
11684                ch_b_s = ch_b;
11685        }
11686        if (connect)
11687        {
11688                li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11689                li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11690                li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11691                li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11692                li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11693                li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11694        }
11695        li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11696        li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11697        li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11698        li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11699        li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11700        li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11701        li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11702        li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11703        if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11704        {
11705                li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11706                li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11707                li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11708                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11709        }
11710        if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11711        {
11712                li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11713                li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11714                li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11715                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11716        }
11717        if (li_flags & LI2_FLAG_MONITOR_B)
11718        {
11719                li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11720                li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11721        }
11722        if (li_flags & LI2_FLAG_MIX_B)
11723        {
11724                li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11725                li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11726        }
11727        if (li_flags & LI2_FLAG_MONITOR_X)
11728                li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11729        if (li_flags & LI2_FLAG_MIX_X)
11730                li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11731        if (li_flags & LI2_FLAG_LOOP_B)
11732        {
11733                li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11734                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11735                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11736                li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11737        }
11738        if (li_flags & LI2_FLAG_LOOP_PC)
11739                li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11740        if (li_flags & LI2_FLAG_LOOP_X)
11741                li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11742        if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11743                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11744        if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11745                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11746        if (ch_a_v != ch_a_s)
11747        {
11748                li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11749                li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11750        }
11751        if (ch_b_v != ch_b_s)
11752        {
11753                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11754                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11755        }
11756}
11757
11758
11759static word li_check_main_plci(dword Id, PLCI *plci)
11760{
11761        if (plci == NULL)
11762        {
11763                dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11764                                UnMapId(Id), (char *)(FILE_), __LINE__));
11765                return (_WRONG_IDENTIFIER);
11766        }
11767        if (!plci->State
11768            || !plci->NL.Id || plci->nl_remove_id
11769            || (plci->li_bchannel_id == 0))
11770        {
11771                dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11772                                UnMapId(Id), (char *)(FILE_), __LINE__));
11773                return (_WRONG_STATE);
11774        }
11775        li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11776        return (GOOD);
11777}
11778
11779
11780static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11781                             dword plci_b_id, word plci_b_write_pos, byte *p_result)
11782{
11783        byte ctlr_b;
11784        PLCI *plci_b;
11785
11786        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11787             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11788        {
11789                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11790                                UnMapId(Id), (char *)(FILE_), __LINE__));
11791                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11792                return (NULL);
11793        }
11794        ctlr_b = 0;
11795        if ((plci_b_id & 0x7f) != 0)
11796        {
11797                ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11798                if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11799                        ctlr_b = 0;
11800        }
11801        if ((ctlr_b == 0)
11802            || (((plci_b_id >> 8) & 0xff) == 0)
11803            || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11804        {
11805                dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11806                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11807                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11808                return (NULL);
11809        }
11810        plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11811        if (!plci_b->State
11812            || !plci_b->NL.Id || plci_b->nl_remove_id
11813            || (plci_b->li_bchannel_id == 0))
11814        {
11815                dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11816                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11817                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11818                return (NULL);
11819        }
11820        li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11821        if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11822            ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11823            && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11824                || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11825        {
11826                dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11827                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11828                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11829                return (NULL);
11830        }
11831        if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11832                                                          (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11833        {
11834                dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11835                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11836                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11837                return (NULL);
11838        }
11839        return (plci_b);
11840}
11841
11842
11843static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11844                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11845{
11846        byte ctlr_b;
11847        PLCI *plci_b;
11848
11849        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11850             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11851        {
11852                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11853                                UnMapId(Id), (char *)(FILE_), __LINE__));
11854                PUT_WORD(p_result, _WRONG_STATE);
11855                return (NULL);
11856        }
11857        ctlr_b = 0;
11858        if ((plci_b_id & 0x7f) != 0)
11859        {
11860                ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11861                if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11862                        ctlr_b = 0;
11863        }
11864        if ((ctlr_b == 0)
11865            || (((plci_b_id >> 8) & 0xff) == 0)
11866            || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11867        {
11868                dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11869                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11870                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11871                return (NULL);
11872        }
11873        plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11874        if (!plci_b->State
11875            || !plci_b->NL.Id || plci_b->nl_remove_id
11876            || (plci_b->li_bchannel_id == 0)
11877            || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11878        {
11879                dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11880                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11881                PUT_WORD(p_result, _WRONG_STATE);
11882                return (NULL);
11883        }
11884        if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11885            ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11886            && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11887                || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11888        {
11889                dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11890                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11891                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11892                return (NULL);
11893        }
11894        if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11895                                                          (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11896        {
11897                dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11898                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11899                PUT_WORD(p_result, _WRONG_STATE);
11900                return (NULL);
11901        }
11902        return (plci_b);
11903}
11904
11905
11906static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
11907{
11908        word Info;
11909        word i;
11910        dword d, li_flags, plci_b_id;
11911        PLCI *plci_b;
11912        API_PARSE li_parms[3];
11913        API_PARSE li_req_parms[3];
11914        API_PARSE li_participant_struct[2];
11915        API_PARSE li_participant_parms[3];
11916        word participant_parms_pos;
11917        byte result_buffer[32];
11918        byte *result;
11919        word result_pos;
11920        word plci_b_write_pos;
11921
11922        dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11923                        UnMapId(Id), (char *)(FILE_), __LINE__));
11924
11925        Info = GOOD;
11926        result = result_buffer;
11927        result_buffer[0] = 0;
11928        if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11929        {
11930                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11931                                UnMapId(Id), (char *)(FILE_), __LINE__));
11932                Info = _FACILITY_NOT_SUPPORTED;
11933        }
11934        else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11935        {
11936                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11937                                UnMapId(Id), (char *)(FILE_), __LINE__));
11938                Info = _WRONG_MESSAGE_FORMAT;
11939        }
11940        else
11941        {
11942                result_buffer[0] = 3;
11943                PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11944                result_buffer[3] = 0;
11945                switch (GET_WORD(li_parms[0].info))
11946                {
11947                case LI_GET_SUPPORTED_SERVICES:
11948                        if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11949                        {
11950                                result_buffer[0] = 17;
11951                                result_buffer[3] = 14;
11952                                PUT_WORD(&result_buffer[4], GOOD);
11953                                d = 0;
11954                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11955                                        d |= LI_CONFERENCING_SUPPORTED;
11956                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11957                                        d |= LI_MONITORING_SUPPORTED;
11958                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11959                                        d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11960                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11961                                        d |= LI_CROSS_CONTROLLER_SUPPORTED;
11962                                PUT_DWORD(&result_buffer[6], d);
11963                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11964                                {
11965                                        d = 0;
11966                                        for (i = 0; i < li_total_channels; i++)
11967                                        {
11968                                                if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11969                                                    && (li_config_table[i].adapter->li_pri
11970                                                        || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11971                                                {
11972                                                        d++;
11973                                                }
11974                                        }
11975                                }
11976                                else
11977                                {
11978                                        d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11979                                }
11980                                PUT_DWORD(&result_buffer[10], d / 2);
11981                                PUT_DWORD(&result_buffer[14], d);
11982                        }
11983                        else
11984                        {
11985                                result_buffer[0] = 25;
11986                                result_buffer[3] = 22;
11987                                PUT_WORD(&result_buffer[4], GOOD);
11988                                d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11989                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11990                                        d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11991                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11992                                        d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11993                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11994                                        d |= LI2_PC_LOOPING_SUPPORTED;
11995                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11996                                        d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11997                                PUT_DWORD(&result_buffer[6], d);
11998                                d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11999                                PUT_DWORD(&result_buffer[10], d / 2);
12000                                PUT_DWORD(&result_buffer[14], d - 1);
12001                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12002                                {
12003                                        d = 0;
12004                                        for (i = 0; i < li_total_channels; i++)
12005                                        {
12006                                                if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12007                                                    && (li_config_table[i].adapter->li_pri
12008                                                        || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12009                                                {
12010                                                        d++;
12011                                                }
12012                                        }
12013                                }
12014                                PUT_DWORD(&result_buffer[18], d / 2);
12015                                PUT_DWORD(&result_buffer[22], d - 1);
12016                        }
12017                        break;
12018
12019                case LI_REQ_CONNECT:
12020                        if (li_parms[1].length == 8)
12021                        {
12022                                appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12023                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12024                                {
12025                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12026                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12027                                        Info = _WRONG_MESSAGE_FORMAT;
12028                                        break;
12029                                }
12030                                plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12031                                li_flags = GET_DWORD(li_req_parms[1].info);
12032                                Info = li_check_main_plci(Id, plci);
12033                                result_buffer[0] = 9;
12034                                result_buffer[3] = 6;
12035                                PUT_DWORD(&result_buffer[4], plci_b_id);
12036                                PUT_WORD(&result_buffer[8], GOOD);
12037                                if (Info != GOOD)
12038                                        break;
12039                                result = plci->saved_msg.info;
12040                                for (i = 0; i <= result_buffer[0]; i++)
12041                                        result[i] = result_buffer[i];
12042                                plci_b_write_pos = plci->li_plci_b_write_pos;
12043                                plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12044                                if (plci_b == NULL)
12045                                        break;
12046                                li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12047                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12048                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12049                                plci->li_plci_b_write_pos = plci_b_write_pos;
12050                        }
12051                        else
12052                        {
12053                                appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12054                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12055                                {
12056                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12057                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12058                                        Info = _WRONG_MESSAGE_FORMAT;
12059                                        break;
12060                                }
12061                                li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12062                                Info = li_check_main_plci(Id, plci);
12063                                result_buffer[0] = 7;
12064                                result_buffer[3] = 4;
12065                                PUT_WORD(&result_buffer[4], Info);
12066                                result_buffer[6] = 0;
12067                                if (Info != GOOD)
12068                                        break;
12069                                result = plci->saved_msg.info;
12070                                for (i = 0; i <= result_buffer[0]; i++)
12071                                        result[i] = result_buffer[i];
12072                                plci_b_write_pos = plci->li_plci_b_write_pos;
12073                                participant_parms_pos = 0;
12074                                result_pos = 7;
12075                                li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12076                                while (participant_parms_pos < li_req_parms[1].length)
12077                                {
12078                                        result[result_pos] = 6;
12079                                        result_pos += 7;
12080                                        PUT_DWORD(&result[result_pos - 6], 0);
12081                                        PUT_WORD(&result[result_pos - 2], GOOD);
12082                                        if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12083                                                      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12084                                        {
12085                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12086                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12087                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12088                                                break;
12089                                        }
12090                                        if (api_parse(&li_participant_struct[0].info[1],
12091                                                      li_participant_struct[0].length, "dd", li_participant_parms))
12092                                        {
12093                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12094                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12095                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12096                                                break;
12097                                        }
12098                                        plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12099                                        li_flags = GET_DWORD(li_participant_parms[1].info);
12100                                        PUT_DWORD(&result[result_pos - 6], plci_b_id);
12101                                        if (sizeof(result) - result_pos < 7)
12102                                        {
12103                                                dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12104                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12105                                                PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12106                                                break;
12107                                        }
12108                                        plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12109                                        if (plci_b != NULL)
12110                                        {
12111                                                li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12112                                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12113                                                        ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12114                                                                      LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12115                                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12116                                        }
12117                                        participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12118                                                                       (&li_req_parms[1].info[1]));
12119                                }
12120                                result[0] = (byte)(result_pos - 1);
12121                                result[3] = (byte)(result_pos - 4);
12122                                result[6] = (byte)(result_pos - 7);
12123                                i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12124                                if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12125                                    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12126                                {
12127                                        plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12128                                        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12129                                }
12130                                else
12131                                        plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12132                                plci->li_plci_b_write_pos = plci_b_write_pos;
12133                        }
12134                        mixer_calculate_coefs(a);
12135                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12136                        mixer_notify_update(plci, true);
12137                        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12138                              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12139                        plci->command = 0;
12140                        plci->li_cmd = GET_WORD(li_parms[0].info);
12141                        start_internal_command(Id, plci, mixer_command);
12142                        return (false);
12143
12144                case LI_REQ_DISCONNECT:
12145                        if (li_parms[1].length == 4)
12146                        {
12147                                appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12148                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12149                                {
12150                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12151                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12152                                        Info = _WRONG_MESSAGE_FORMAT;
12153                                        break;
12154                                }
12155                                plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12156                                Info = li_check_main_plci(Id, plci);
12157                                result_buffer[0] = 9;
12158                                result_buffer[3] = 6;
12159                                PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12160                                PUT_WORD(&result_buffer[8], GOOD);
12161                                if (Info != GOOD)
12162                                        break;
12163                                result = plci->saved_msg.info;
12164                                for (i = 0; i <= result_buffer[0]; i++)
12165                                        result[i] = result_buffer[i];
12166                                plci_b_write_pos = plci->li_plci_b_write_pos;
12167                                plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12168                                if (plci_b == NULL)
12169                                        break;
12170                                li_update_connect(Id, a, plci, plci_b_id, false, 0);
12171                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12172                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12173                                plci->li_plci_b_write_pos = plci_b_write_pos;
12174                        }
12175                        else
12176                        {
12177                                appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12178                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12179                                {
12180                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12181                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12182                                        Info = _WRONG_MESSAGE_FORMAT;
12183                                        break;
12184                                }
12185                                Info = li_check_main_plci(Id, plci);
12186                                result_buffer[0] = 7;
12187                                result_buffer[3] = 4;
12188                                PUT_WORD(&result_buffer[4], Info);
12189                                result_buffer[6] = 0;
12190                                if (Info != GOOD)
12191                                        break;
12192                                result = plci->saved_msg.info;
12193                                for (i = 0; i <= result_buffer[0]; i++)
12194                                        result[i] = result_buffer[i];
12195                                plci_b_write_pos = plci->li_plci_b_write_pos;
12196                                participant_parms_pos = 0;
12197                                result_pos = 7;
12198                                while (participant_parms_pos < li_req_parms[0].length)
12199                                {
12200                                        result[result_pos] = 6;
12201                                        result_pos += 7;
12202                                        PUT_DWORD(&result[result_pos - 6], 0);
12203                                        PUT_WORD(&result[result_pos - 2], GOOD);
12204                                        if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12205                                                      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12206                                        {
12207                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12208                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12209                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210                                                break;
12211                                        }
12212                                        if (api_parse(&li_participant_struct[0].info[1],
12213                                                      li_participant_struct[0].length, "d", li_participant_parms))
12214                                        {
12215                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12217                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218                                                break;
12219                                        }
12220                                        plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12221                                        PUT_DWORD(&result[result_pos - 6], plci_b_id);
12222                                        if (sizeof(result) - result_pos < 7)
12223                                        {
12224                                                dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12225                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12226                                                PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12227                                                break;
12228                                        }
12229                                        plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12230                                        if (plci_b != NULL)
12231                                        {
12232                                                li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12233                                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12234                                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12235                                        }
12236                                        participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12237                                                                       (&li_req_parms[0].info[1]));
12238                                }
12239                                result[0] = (byte)(result_pos - 1);
12240                                result[3] = (byte)(result_pos - 4);
12241                                result[6] = (byte)(result_pos - 7);
12242                                i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12243                                if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12244                                    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12245                                {
12246                                        plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12247                                        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12248                                }
12249                                else
12250                                        plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12251                                plci->li_plci_b_write_pos = plci_b_write_pos;
12252                        }
12253                        mixer_calculate_coefs(a);
12254                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12255                        mixer_notify_update(plci, true);
12256                        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12257                              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12258                        plci->command = 0;
12259                        plci->li_cmd = GET_WORD(li_parms[0].info);
12260                        start_internal_command(Id, plci, mixer_command);
12261                        return (false);
12262
12263                case LI_REQ_SILENT_UPDATE:
12264                        if (!plci || !plci->State
12265                            || !plci->NL.Id || plci->nl_remove_id
12266                            || (plci->li_bchannel_id == 0)
12267                            || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12268                        {
12269                                dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12270                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12271                                return (false);
12272                        }
12273                        plci_b_write_pos = plci->li_plci_b_write_pos;
12274                        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12275                             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12276                        {
12277                                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12278                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12279                                return (false);
12280                        }
12281                        i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12282                        if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12283                            || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12284                        {
12285                                plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12286                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12287                        }
12288                        else
12289                                plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12290                        plci->li_plci_b_write_pos = plci_b_write_pos;
12291                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12292                        plci->command = 0;
12293                        plci->li_cmd = GET_WORD(li_parms[0].info);
12294                        start_internal_command(Id, plci, mixer_command);
12295                        return (false);
12296
12297                default:
12298                        dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12299                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12300                        Info = _FACILITY_NOT_SUPPORTED;
12301                }
12302        }
12303        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12304              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12305        return (false);
12306}
12307
12308
12309static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12310{
12311        dword d;
12312        byte result[12];
12313
12314        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12315                        UnMapId(Id), (char *)(FILE_), __LINE__));
12316
12317        if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12318        {
12319                do
12320                {
12321                        d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12322                        if (!(d & LI_PLCI_B_SKIP_FLAG))
12323                        {
12324                                if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12325                                {
12326                                        if (d & LI_PLCI_B_DISC_FLAG)
12327                                        {
12328                                                result[0] = 5;
12329                                                PUT_WORD(&result[1], LI_IND_DISCONNECT);
12330                                                result[3] = 2;
12331                                                PUT_WORD(&result[4], _LI_USER_INITIATED);
12332                                        }
12333                                        else
12334                                        {
12335                                                result[0] = 7;
12336                                                PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12337                                                result[3] = 4;
12338                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12339                                        }
12340                                }
12341                                else
12342                                {
12343                                        if (d & LI_PLCI_B_DISC_FLAG)
12344                                        {
12345                                                result[0] = 9;
12346                                                PUT_WORD(&result[1], LI_IND_DISCONNECT);
12347                                                result[3] = 6;
12348                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12349                                                PUT_WORD(&result[8], _LI_USER_INITIATED);
12350                                        }
12351                                        else
12352                                        {
12353                                                result[0] = 7;
12354                                                PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12355                                                result[3] = 4;
12356                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12357                                        }
12358                                }
12359                                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12360                                      "ws", SELECTOR_LINE_INTERCONNECT, result);
12361                        }
12362                        plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12363                                0 : plci->li_plci_b_read_pos + 1;
12364                } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12365        }
12366}
12367
12368
12369static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12370{
12371        word i, j, ch;
12372        struct xconnect_transfer_address_s s,   *p;
12373        DIVA_CAPI_ADAPTER *a;
12374
12375        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12376                        UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12377
12378        a = plci->adapter;
12379        i = 1;
12380        for (i = 1; i < length; i += 16)
12381        {
12382                s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12383                s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12384                s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12385                ch = msg[i + 12] | (msg[i + 13] << 8);
12386                j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12387                if (!a->li_pri && (plci->li_bchannel_id == 2))
12388                        j = 1 - j;
12389                j += a->li_base;
12390                if (ch & XCONNECT_CHANNEL_PORT_PC)
12391                        p = &(li_config_table[j].send_pc);
12392                else
12393                        p = &(li_config_table[j].send_b);
12394                p->card_address.low = s.card_address.low;
12395                p->card_address.high = s.card_address.high;
12396                p->offset = s.offset;
12397                li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12398        }
12399        if (plci->internal_command_queue[0]
12400            && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12401                || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12402                || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12403        {
12404                (*(plci->internal_command_queue[0]))(Id, plci, 0);
12405                if (!plci->internal_command)
12406                        next_internal_command(Id, plci);
12407        }
12408        mixer_notify_update(plci, true);
12409}
12410
12411
12412static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12413{
12414
12415        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12416                        UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12417
12418}
12419
12420
12421static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12422{
12423        word plci_b_write_pos;
12424
12425        plci_b_write_pos = plci->li_plci_b_write_pos;
12426        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12427             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12428        {
12429                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12430                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12431                                (char *)(FILE_), __LINE__));
12432                return (false);
12433        }
12434        plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12435        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12436        plci->li_plci_b_write_pos = plci_b_write_pos;
12437        return (true);
12438}
12439
12440
12441static void mixer_remove(PLCI *plci)
12442{
12443        DIVA_CAPI_ADAPTER *a;
12444        PLCI *notify_plci;
12445        dword plci_b_id;
12446        word i, j;
12447
12448        dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12449                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12450                        (char *)(FILE_), __LINE__));
12451
12452        a = plci->adapter;
12453        plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12454        if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12455        {
12456                if ((plci->li_bchannel_id != 0)
12457                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12458                {
12459                        i = a->li_base + (plci->li_bchannel_id - 1);
12460                        if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12461                        {
12462                                for (j = 0; j < li_total_channels; j++)
12463                                {
12464                                        if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12465                                            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12466                                        {
12467                                                notify_plci = li_config_table[j].plci;
12468                                                if ((notify_plci != NULL)
12469                                                    && (notify_plci != plci)
12470                                                    && (notify_plci->appl != NULL)
12471                                                    && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12472                                                    && (notify_plci->State)
12473                                                    && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12474                                                {
12475                                                        mixer_notify_source_removed(notify_plci, plci_b_id);
12476                                                }
12477                                        }
12478                                }
12479                                mixer_clear_config(plci);
12480                                mixer_calculate_coefs(a);
12481                                mixer_notify_update(plci, true);
12482                        }
12483                        li_config_table[i].plci = NULL;
12484                        plci->li_bchannel_id = 0;
12485                }
12486        }
12487}
12488
12489
12490/*------------------------------------------------------------------*/
12491/* Echo canceller facilities                                        */
12492/*------------------------------------------------------------------*/
12493
12494
12495static void ec_write_parameters(PLCI *plci)
12496{
12497        word w;
12498        byte parameter_buffer[6];
12499
12500        dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12501                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12502                        (char *)(FILE_), __LINE__));
12503
12504        parameter_buffer[0] = 5;
12505        parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12506        PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12507        plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12508        w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12509        PUT_WORD(&parameter_buffer[4], w);
12510        add_p(plci, FTY, parameter_buffer);
12511        sig_req(plci, TEL_CTRL, 0);
12512        send_req(plci);
12513}
12514
12515
12516static void ec_clear_config(PLCI *plci)
12517{
12518
12519        dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12520                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12521                        (char *)(FILE_), __LINE__));
12522
12523        plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12524                LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12525        plci->ec_tail_length = 0;
12526}
12527
12528
12529static void ec_prepare_switch(dword Id, PLCI *plci)
12530{
12531
12532        dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12533                        UnMapId(Id), (char *)(FILE_), __LINE__));
12534
12535}
12536
12537
12538static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12539{
12540
12541        dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12542                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12543
12544        return (GOOD);
12545}
12546
12547
12548static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12549{
12550        word Info;
12551
12552        dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12553                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12554
12555        Info = GOOD;
12556        if (plci->B1_facilities & B1_FACILITY_EC)
12557        {
12558                switch (plci->adjust_b_state)
12559                {
12560                case ADJUST_B_RESTORE_EC_1:
12561                        plci->internal_command = plci->adjust_b_command;
12562                        if (plci->sig_req)
12563                        {
12564                                plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12565                                break;
12566                        }
12567                        ec_write_parameters(plci);
12568                        plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12569                        break;
12570                case ADJUST_B_RESTORE_EC_2:
12571                        if ((Rc != OK) && (Rc != OK_FC))
12572                        {
12573                                dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12574                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12575                                Info = _WRONG_STATE;
12576                                break;
12577                        }
12578                        break;
12579                }
12580        }
12581        return (Info);
12582}
12583
12584
12585static void ec_command(dword Id, PLCI *plci, byte Rc)
12586{
12587        word internal_command, Info;
12588        byte result[8];
12589
12590        dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12591                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12592                        plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12593
12594        Info = GOOD;
12595        if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12596        {
12597                result[0] = 2;
12598                PUT_WORD(&result[1], EC_SUCCESS);
12599        }
12600        else
12601        {
12602                result[0] = 5;
12603                PUT_WORD(&result[1], plci->ec_cmd);
12604                result[3] = 2;
12605                PUT_WORD(&result[4], GOOD);
12606        }
12607        internal_command = plci->internal_command;
12608        plci->internal_command = 0;
12609        switch (plci->ec_cmd)
12610        {
12611        case EC_ENABLE_OPERATION:
12612        case EC_FREEZE_COEFFICIENTS:
12613        case EC_RESUME_COEFFICIENT_UPDATE:
12614        case EC_RESET_COEFFICIENTS:
12615                switch (internal_command)
12616                {
12617                default:
12618                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12619                                                                  B1_FACILITY_EC), EC_COMMAND_1);
12620                        /* fall through */
12621                case EC_COMMAND_1:
12622                        if (adjust_b_process(Id, plci, Rc) != GOOD)
12623                        {
12624                                dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12625                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12626                                Info = _FACILITY_NOT_SUPPORTED;
12627                                break;
12628                        }
12629                        if (plci->internal_command)
12630                                return;
12631                        /* fall through */
12632                case EC_COMMAND_2:
12633                        if (plci->sig_req)
12634                        {
12635                                plci->internal_command = EC_COMMAND_2;
12636                                return;
12637                        }
12638                        plci->internal_command = EC_COMMAND_3;
12639                        ec_write_parameters(plci);
12640                        return;
12641                case EC_COMMAND_3:
12642                        if ((Rc != OK) && (Rc != OK_FC))
12643                        {
12644                                dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12645                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12646                                Info = _FACILITY_NOT_SUPPORTED;
12647                                break;
12648                        }
12649                        break;
12650                }
12651                break;
12652
12653        case EC_DISABLE_OPERATION:
12654                switch (internal_command)
12655                {
12656                default:
12657                case EC_COMMAND_1:
12658                        if (plci->B1_facilities & B1_FACILITY_EC)
12659                        {
12660                                if (plci->sig_req)
12661                                {
12662                                        plci->internal_command = EC_COMMAND_1;
12663                                        return;
12664                                }
12665                                plci->internal_command = EC_COMMAND_2;
12666                                ec_write_parameters(plci);
12667                                return;
12668                        }
12669                        Rc = OK;
12670                        /* fall through */
12671                case EC_COMMAND_2:
12672                        if ((Rc != OK) && (Rc != OK_FC))
12673                        {
12674                                dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12675                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12676                                Info = _FACILITY_NOT_SUPPORTED;
12677                                break;
12678                        }
12679                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12680                                                                  ~B1_FACILITY_EC), EC_COMMAND_3);
12681                        /* fall through */
12682                case EC_COMMAND_3:
12683                        if (adjust_b_process(Id, plci, Rc) != GOOD)
12684                        {
12685                                dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12686                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12687                                Info = _FACILITY_NOT_SUPPORTED;
12688                                break;
12689                        }
12690                        if (plci->internal_command)
12691                                return;
12692                        break;
12693                }
12694                break;
12695        }
12696        sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12697              "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12698              PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12699}
12700
12701
12702static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12703{
12704        word Info;
12705        word opt;
12706        API_PARSE ec_parms[3];
12707        byte result[16];
12708
12709        dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12710                        UnMapId(Id), (char *)(FILE_), __LINE__));
12711
12712        Info = GOOD;
12713        result[0] = 0;
12714        if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12715        {
12716                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12717                                UnMapId(Id), (char *)(FILE_), __LINE__));
12718                Info = _FACILITY_NOT_SUPPORTED;
12719        }
12720        else
12721        {
12722                if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12723                {
12724                        if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12725                        {
12726                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12727                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12728                                Info = _WRONG_MESSAGE_FORMAT;
12729                        }
12730                        else
12731                        {
12732                                if (plci == NULL)
12733                                {
12734                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12735                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12736                                        Info = _WRONG_IDENTIFIER;
12737                                }
12738                                else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12739                                {
12740                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12741                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12742                                        Info = _WRONG_STATE;
12743                                }
12744                                else
12745                                {
12746                                        plci->command = 0;
12747                                        plci->ec_cmd = GET_WORD(ec_parms[0].info);
12748                                        plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12749                                        result[0] = 2;
12750                                        PUT_WORD(&result[1], EC_SUCCESS);
12751                                        if (msg[1].length >= 4)
12752                                        {
12753                                                opt = GET_WORD(&ec_parms[0].info[2]);
12754                                                plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12755                                                                          LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12756                                                if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12757                                                        plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12758                                                if (opt & EC_DETECT_DISABLE_TONE)
12759                                                        plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12760                                                if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12761                                                        plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12762                                                if (msg[1].length >= 6)
12763                                                {
12764                                                        plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12765                                                }
12766                                        }
12767                                        switch (plci->ec_cmd)
12768                                        {
12769                                        case EC_ENABLE_OPERATION:
12770                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12771                                                start_internal_command(Id, plci, ec_command);
12772                                                return (false);
12773
12774                                        case EC_DISABLE_OPERATION:
12775                                                plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12776                                                        LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12777                                                        LEC_RESET_COEFFICIENTS;
12778                                                start_internal_command(Id, plci, ec_command);
12779                                                return (false);
12780
12781                                        case EC_FREEZE_COEFFICIENTS:
12782                                                plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12783                                                start_internal_command(Id, plci, ec_command);
12784                                                return (false);
12785
12786                                        case EC_RESUME_COEFFICIENT_UPDATE:
12787                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12788                                                start_internal_command(Id, plci, ec_command);
12789                                                return (false);
12790
12791                                        case EC_RESET_COEFFICIENTS:
12792                                                plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12793                                                start_internal_command(Id, plci, ec_command);
12794                                                return (false);
12795
12796                                        default:
12797                                                dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12798                                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12799                                                PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12800                                        }
12801                                }
12802                        }
12803                }
12804                else
12805                {
12806                        if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12807                        {
12808                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12809                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12810                                Info = _WRONG_MESSAGE_FORMAT;
12811                        }
12812                        else
12813                        {
12814                                if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12815                                {
12816                                        result[0] = 11;
12817                                        PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12818                                        result[3] = 8;
12819                                        PUT_WORD(&result[4], GOOD);
12820                                        PUT_WORD(&result[6], 0x0007);
12821                                        PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12822                                        PUT_WORD(&result[10], 0);
12823                                }
12824                                else if (plci == NULL)
12825                                {
12826                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12827                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12828                                        Info = _WRONG_IDENTIFIER;
12829                                }
12830                                else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12831                                {
12832                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12833                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12834                                        Info = _WRONG_STATE;
12835                                }
12836                                else
12837                                {
12838                                        plci->command = 0;
12839                                        plci->ec_cmd = GET_WORD(ec_parms[0].info);
12840                                        plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12841                                        result[0] = 5;
12842                                        PUT_WORD(&result[1], plci->ec_cmd);
12843                                        result[3] = 2;
12844                                        PUT_WORD(&result[4], GOOD);
12845                                        plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12846                                                                  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12847                                        plci->ec_tail_length = 0;
12848                                        if (ec_parms[1].length >= 2)
12849                                        {
12850                                                opt = GET_WORD(&ec_parms[1].info[1]);
12851                                                if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12852                                                        plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12853                                                if (opt & EC_DETECT_DISABLE_TONE)
12854                                                        plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12855                                                if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12856                                                        plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12857                                                if (ec_parms[1].length >= 4)
12858                                                {
12859                                                        plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12860                                                }
12861                                        }
12862                                        switch (plci->ec_cmd)
12863                                        {
12864                                        case EC_ENABLE_OPERATION:
12865                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12866                                                start_internal_command(Id, plci, ec_command);
12867                                                return (false);
12868
12869                                        case EC_DISABLE_OPERATION:
12870                                                plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12871                                                        LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12872                                                        LEC_RESET_COEFFICIENTS;
12873                                                start_internal_command(Id, plci, ec_command);
12874                                                return (false);
12875
12876                                        default:
12877                                                dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12878                                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12879                                                PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12880                                        }
12881                                }
12882                        }
12883                }
12884        }
12885        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12886              "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12887              PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12888        return (false);
12889}
12890
12891
12892static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12893{
12894        byte result[8];
12895
12896        dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12897                        UnMapId(Id), (char *)(FILE_), __LINE__));
12898
12899        if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12900        {
12901                if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12902                {
12903                        result[0] = 2;
12904                        PUT_WORD(&result[1], 0);
12905                        switch (msg[1])
12906                        {
12907                        case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908                                PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12909                                break;
12910                        case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911                                PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12912                                break;
12913                        case LEC_DISABLE_RELEASED:
12914                                PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12915                                break;
12916                        }
12917                }
12918                else
12919                {
12920                        result[0] = 5;
12921                        PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12922                        result[3] = 2;
12923                        PUT_WORD(&result[4], 0);
12924                        switch (msg[1])
12925                        {
12926                        case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12927                                PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12928                                break;
12929                        case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12930                                PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12931                                break;
12932                        case LEC_DISABLE_RELEASED:
12933                                PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12934                                break;
12935                        }
12936                }
12937                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12938                      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12939        }
12940}
12941
12942
12943
12944/*------------------------------------------------------------------*/
12945/* Advanced voice                                                   */
12946/*------------------------------------------------------------------*/
12947
12948static void adv_voice_write_coefs(PLCI *plci, word write_command)
12949{
12950        DIVA_CAPI_ADAPTER *a;
12951        word i;
12952        byte *p;
12953
12954        word w, n, j, k;
12955        byte ch_map[MIXER_CHANNELS_BRI];
12956
12957        byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12958
12959        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12960                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12961                        (char *)(FILE_), __LINE__, write_command));
12962
12963        a = plci->adapter;
12964        p = coef_buffer + 1;
12965        *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12966        i = 0;
12967        while (i + sizeof(word) <= a->adv_voice_coef_length)
12968        {
12969                PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12970                p += 2;
12971                i += 2;
12972        }
12973        while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12974        {
12975                PUT_WORD(p, 0x8000);
12976                p += 2;
12977                i += 2;
12978        }
12979
12980        if (!a->li_pri && (plci->li_bchannel_id == 0))
12981        {
12982                if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12983                {
12984                        plci->li_bchannel_id = 1;
12985                        li_config_table[a->li_base].plci = plci;
12986                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12987                                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12988                                        (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12989                }
12990                else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12991                {
12992                        plci->li_bchannel_id = 2;
12993                        li_config_table[a->li_base + 1].plci = plci;
12994                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12995                                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12996                                        (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12997                }
12998        }
12999        if (!a->li_pri && (plci->li_bchannel_id != 0)
13000            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13001        {
13002                i = a->li_base + (plci->li_bchannel_id - 1);
13003                switch (write_command)
13004                {
13005                case ADV_VOICE_WRITE_ACTIVATION:
13006                        j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13007                        k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13008                        if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13009                        {
13010                                li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13011                                li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13012                        }
13013                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13014                        {
13015                                li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13016                                li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13017                                li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13018                                li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13019                        }
13020                        mixer_calculate_coefs(a);
13021                        li_config_table[i].curchnl = li_config_table[i].channel;
13022                        li_config_table[j].curchnl = li_config_table[j].channel;
13023                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13024                                li_config_table[k].curchnl = li_config_table[k].channel;
13025                        break;
13026
13027                case ADV_VOICE_WRITE_DEACTIVATION:
13028                        for (j = 0; j < li_total_channels; j++)
13029                        {
13030                                li_config_table[i].flag_table[j] = 0;
13031                                li_config_table[j].flag_table[i] = 0;
13032                        }
13033                        k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13034                        for (j = 0; j < li_total_channels; j++)
13035                        {
13036                                li_config_table[k].flag_table[j] = 0;
13037                                li_config_table[j].flag_table[k] = 0;
13038                        }
13039                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13040                        {
13041                                k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13042                                for (j = 0; j < li_total_channels; j++)
13043                                {
13044                                        li_config_table[k].flag_table[j] = 0;
13045                                        li_config_table[j].flag_table[k] = 0;
13046                                }
13047                        }
13048                        mixer_calculate_coefs(a);
13049                        break;
13050                }
13051                if (plci->B1_facilities & B1_FACILITY_MIXER)
13052                {
13053                        w = 0;
13054                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13055                                w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13056                        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13057                                w |= MIXER_FEATURE_ENABLE_TX_DATA;
13058                        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13059                                w |= MIXER_FEATURE_ENABLE_RX_DATA;
13060                        *(p++) = (byte) w;
13061                        *(p++) = (byte)(w >> 8);
13062                        for (j = 0; j < sizeof(ch_map); j += 2)
13063                        {
13064                                ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13065                                ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13066                        }
13067                        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13068                        {
13069                                i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13070                                j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13071                                if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13072                                {
13073                                        *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13074                                        w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13075                                        li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13076                                }
13077                                else
13078                                {
13079                                        *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13080                                                a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13081                                }
13082                        }
13083                }
13084                else
13085                {
13086                        for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13087                                *(p++) = a->adv_voice_coef_buffer[i];
13088                }
13089        }
13090        else
13091
13092        {
13093                for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13094                        *(p++) = a->adv_voice_coef_buffer[i];
13095        }
13096        coef_buffer[0] = (p - coef_buffer) - 1;
13097        add_p(plci, FTY, coef_buffer);
13098        sig_req(plci, TEL_CTRL, 0);
13099        send_req(plci);
13100}
13101
13102
13103static void adv_voice_clear_config(PLCI *plci)
13104{
13105        DIVA_CAPI_ADAPTER *a;
13106
13107        word i, j;
13108
13109
13110        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13111                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13112                        (char *)(FILE_), __LINE__));
13113
13114        a = plci->adapter;
13115        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13116        {
13117                a->adv_voice_coef_length = 0;
13118
13119                if (!a->li_pri && (plci->li_bchannel_id != 0)
13120                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13121                {
13122                        i = a->li_base + (plci->li_bchannel_id - 1);
13123                        li_config_table[i].curchnl = 0;
13124                        li_config_table[i].channel = 0;
13125                        li_config_table[i].chflags = 0;
13126                        for (j = 0; j < li_total_channels; j++)
13127                        {
13128                                li_config_table[i].flag_table[j] = 0;
13129                                li_config_table[j].flag_table[i] = 0;
13130                                li_config_table[i].coef_table[j] = 0;
13131                                li_config_table[j].coef_table[i] = 0;
13132                        }
13133                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13134                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13135                        li_config_table[i].curchnl = 0;
13136                        li_config_table[i].channel = 0;
13137                        li_config_table[i].chflags = 0;
13138                        for (j = 0; j < li_total_channels; j++)
13139                        {
13140                                li_config_table[i].flag_table[j] = 0;
13141                                li_config_table[j].flag_table[i] = 0;
13142                                li_config_table[i].coef_table[j] = 0;
13143                                li_config_table[j].coef_table[i] = 0;
13144                        }
13145                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13146                        {
13147                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13148                                li_config_table[i].curchnl = 0;
13149                                li_config_table[i].channel = 0;
13150                                li_config_table[i].chflags = 0;
13151                                for (j = 0; j < li_total_channels; j++)
13152                                {
13153                                        li_config_table[i].flag_table[j] = 0;
13154                                        li_config_table[j].flag_table[i] = 0;
13155                                        li_config_table[i].coef_table[j] = 0;
13156                                        li_config_table[j].coef_table[i] = 0;
13157                                }
13158                        }
13159                }
13160
13161        }
13162}
13163
13164
13165static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13166{
13167
13168        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13169                        UnMapId(Id), (char *)(FILE_), __LINE__));
13170
13171}
13172
13173
13174static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13175{
13176
13177        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13178                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13179
13180        return (GOOD);
13181}
13182
13183
13184static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13185{
13186        DIVA_CAPI_ADAPTER *a;
13187        word Info;
13188
13189        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13190                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13191
13192        Info = GOOD;
13193        a = plci->adapter;
13194        if ((plci->B1_facilities & B1_FACILITY_VOICE)
13195            && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13196        {
13197                switch (plci->adjust_b_state)
13198                {
13199                case ADJUST_B_RESTORE_VOICE_1:
13200                        plci->internal_command = plci->adjust_b_command;
13201                        if (plci->sig_req)
13202                        {
13203                                plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13204                                break;
13205                        }
13206                        adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13207                        plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13208                        break;
13209                case ADJUST_B_RESTORE_VOICE_2:
13210                        if ((Rc != OK) && (Rc != OK_FC))
13211                        {
13212                                dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13213                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13214                                Info = _WRONG_STATE;
13215                                break;
13216                        }
13217                        break;
13218                }
13219        }
13220        return (Info);
13221}
13222
13223
13224
13225
13226/*------------------------------------------------------------------*/
13227/* B1 resource switching                                            */
13228/*------------------------------------------------------------------*/
13229
13230static byte b1_facilities_table[] =
13231{
13232        0x00,  /* 0  No bchannel resources      */
13233        0x00,  /* 1  Codec (automatic law)      */
13234        0x00,  /* 2  Codec (A-law)              */
13235        0x00,  /* 3  Codec (y-law)              */
13236        0x00,  /* 4  HDLC for X.21              */
13237        0x00,  /* 5  HDLC                       */
13238        0x00,  /* 6  External Device 0          */
13239        0x00,  /* 7  External Device 1          */
13240        0x00,  /* 8  HDLC 56k                   */
13241        0x00,  /* 9  Transparent                */
13242        0x00,  /* 10 Loopback to network        */
13243        0x00,  /* 11 Test pattern to net        */
13244        0x00,  /* 12 Rate adaptation sync       */
13245        0x00,  /* 13 Rate adaptation async      */
13246        0x00,  /* 14 R-Interface                */
13247        0x00,  /* 15 HDLC 128k leased line      */
13248        0x00,  /* 16 FAX                        */
13249        0x00,  /* 17 Modem async                */
13250        0x00,  /* 18 Modem sync HDLC            */
13251        0x00,  /* 19 V.110 async HDLC           */
13252        0x12,  /* 20 Adv voice (Trans,mixer)    */
13253        0x00,  /* 21 Codec connected to IC      */
13254        0x0c,  /* 22 Trans,DTMF                 */
13255        0x1e,  /* 23 Trans,DTMF+mixer           */
13256        0x1f,  /* 24 Trans,DTMF+mixer+local     */
13257        0x13,  /* 25 Trans,mixer+local          */
13258        0x12,  /* 26 HDLC,mixer                 */
13259        0x12,  /* 27 HDLC 56k,mixer             */
13260        0x2c,  /* 28 Trans,LEC+DTMF             */
13261        0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13262        0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13263        0x2c,  /* 31 RTP,LEC+DTMF               */
13264        0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13265        0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13266        0x00,  /* 34 Signaling task             */
13267        0x00,  /* 35 PIAFS                      */
13268        0x0c,  /* 36 Trans,DTMF+TONE            */
13269        0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13270        0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13271};
13272
13273
13274static word get_b1_facilities(PLCI *plci, byte b1_resource)
13275{
13276        word b1_facilities;
13277
13278        b1_facilities = b1_facilities_table[b1_resource];
13279        if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13280        {
13281
13282                if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13283                      || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13284
13285                {
13286                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13287                                b1_facilities |= B1_FACILITY_DTMFX;
13288                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13289                                b1_facilities |= B1_FACILITY_DTMFR;
13290                }
13291        }
13292        if ((b1_resource == 17) || (b1_resource == 18))
13293        {
13294                if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13295                        b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13296        }
13297/*
13298  dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13299  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13300  (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13301*/
13302        return (b1_facilities);
13303}
13304
13305
13306static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13307{
13308        byte b;
13309
13310        switch (b1_resource)
13311        {
13312        case 5:
13313        case 26:
13314                if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13315                        b = 26;
13316                else
13317                        b = 5;
13318                break;
13319
13320        case 8:
13321        case 27:
13322                if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13323                        b = 27;
13324                else
13325                        b = 8;
13326                break;
13327
13328        case 9:
13329        case 20:
13330        case 22:
13331        case 23:
13332        case 24:
13333        case 25:
13334        case 28:
13335        case 29:
13336        case 30:
13337        case 36:
13338        case 37:
13339        case 38:
13340                if (b1_facilities & B1_FACILITY_EC)
13341                {
13342                        if (b1_facilities & B1_FACILITY_LOCAL)
13343                                b = 30;
13344                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13345                                b = 29;
13346                        else
13347                                b = 28;
13348                }
13349
13350                else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13351                         && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13352                             || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13353                {
13354                        if (b1_facilities & B1_FACILITY_LOCAL)
13355                                b = 38;
13356                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13357                                b = 37;
13358                        else
13359                                b = 36;
13360                }
13361
13362                else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13363                          && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13364                         || ((b1_facilities & B1_FACILITY_DTMFR)
13365                             && ((b1_facilities & B1_FACILITY_MIXER)
13366                                 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13367                         || ((b1_facilities & B1_FACILITY_DTMFX)
13368                             && ((b1_facilities & B1_FACILITY_MIXER)
13369                                 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13370                {
13371                        if (b1_facilities & B1_FACILITY_LOCAL)
13372                                b = 24;
13373                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13374                                b = 23;
13375                        else
13376                                b = 22;
13377                }
13378                else
13379                {
13380                        if (b1_facilities & B1_FACILITY_LOCAL)
13381                                b = 25;
13382                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13383                                b = 20;
13384                        else
13385                                b = 9;
13386                }
13387                break;
13388
13389        case 31:
13390        case 32:
13391        case 33:
13392                if (b1_facilities & B1_FACILITY_LOCAL)
13393                        b = 33;
13394                else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13395                        b = 32;
13396                else
13397                        b = 31;
13398                break;
13399
13400        default:
13401                b = b1_resource;
13402        }
13403        dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13404                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13405                        (char *)(FILE_), __LINE__,
13406                        b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13407        return (b);
13408}
13409
13410
13411static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13412{
13413        word removed_facilities;
13414
13415        dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13416                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13417                        (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13418                        new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13419
13420        new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13421        removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13422
13423        if (removed_facilities & B1_FACILITY_EC)
13424                ec_clear_config(plci);
13425
13426
13427        if (removed_facilities & B1_FACILITY_DTMFR)
13428        {
13429                dtmf_rec_clear_config(plci);
13430                dtmf_parameter_clear_config(plci);
13431        }
13432        if (removed_facilities & B1_FACILITY_DTMFX)
13433                dtmf_send_clear_config(plci);
13434
13435
13436        if (removed_facilities & B1_FACILITY_MIXER)
13437                mixer_clear_config(plci);
13438
13439        if (removed_facilities & B1_FACILITY_VOICE)
13440                adv_voice_clear_config(plci);
13441        plci->B1_facilities = new_b1_facilities;
13442}
13443
13444
13445static void adjust_b_clear(PLCI *plci)
13446{
13447
13448        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13449                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13450                        (char *)(FILE_), __LINE__));
13451
13452        plci->adjust_b_restore = false;
13453}
13454
13455
13456static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13457{
13458        word Info;
13459        byte b1_resource;
13460        NCCI *ncci_ptr;
13461        API_PARSE bp[2];
13462
13463        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13464                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13465
13466        Info = GOOD;
13467        switch (plci->adjust_b_state)
13468        {
13469        case ADJUST_B_START:
13470                if ((plci->adjust_b_parms_msg == NULL)
13471                    && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13472                    && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13473                                                 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13474                {
13475                        b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13476                                0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13477                        if (b1_resource == plci->B1_resource)
13478                        {
13479                                adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13480                                break;
13481                        }
13482                        if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13483                        {
13484                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13485                                                UnMapId(Id), (char *)(FILE_), __LINE__,
13486                                                plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13487                                Info = _WRONG_STATE;
13488                                break;
13489                        }
13490                }
13491                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13492                {
13493
13494                        mixer_prepare_switch(Id, plci);
13495
13496
13497                        dtmf_prepare_switch(Id, plci);
13498                        dtmf_parameter_prepare_switch(Id, plci);
13499
13500
13501                        ec_prepare_switch(Id, plci);
13502
13503                        adv_voice_prepare_switch(Id, plci);
13504                }
13505                plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13506                Rc = OK;
13507                /* fall through */
13508        case ADJUST_B_SAVE_MIXER_1:
13509                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13510                {
13511
13512                        Info = mixer_save_config(Id, plci, Rc);
13513                        if ((Info != GOOD) || plci->internal_command)
13514                                break;
13515
13516                }
13517                plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13518                Rc = OK;
13519                /* fall through */
13520        case ADJUST_B_SAVE_DTMF_1:
13521                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13522                {
13523
13524                        Info = dtmf_save_config(Id, plci, Rc);
13525                        if ((Info != GOOD) || plci->internal_command)
13526                                break;
13527
13528                }
13529                plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13530                /* fall through */
13531        case ADJUST_B_REMOVE_L23_1:
13532                if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13533                    && plci->NL.Id && !plci->nl_remove_id)
13534                {
13535                        plci->internal_command = plci->adjust_b_command;
13536                        if (plci->adjust_b_ncci != 0)
13537                        {
13538                                ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13539                                while (ncci_ptr->data_pending)
13540                                {
13541                                        plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13542                                        data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13543                                }
13544                                while (ncci_ptr->data_ack_pending)
13545                                        data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13546                        }
13547                        nl_req_ncci(plci, REMOVE,
13548                                    (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13549                        send_req(plci);
13550                        plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13551                        break;
13552                }
13553                plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13554                Rc = OK;
13555                /* fall through */
13556        case ADJUST_B_REMOVE_L23_2:
13557                if ((Rc != OK) && (Rc != OK_FC))
13558                {
13559                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13560                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13561                        Info = _WRONG_STATE;
13562                        break;
13563                }
13564                if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13565                {
13566                        if (plci_nl_busy(plci))
13567                        {
13568                                plci->internal_command = plci->adjust_b_command;
13569                                break;
13570                        }
13571                }
13572                plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13573                Rc = OK;
13574                /* fall through */
13575        case ADJUST_B_SAVE_EC_1:
13576                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13577                {
13578
13579                        Info = ec_save_config(Id, plci, Rc);
13580                        if ((Info != GOOD) || plci->internal_command)
13581                                break;
13582
13583                }
13584                plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13585                Rc = OK;
13586                /* fall through */
13587        case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13588                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13589                {
13590
13591                        Info = dtmf_parameter_save_config(Id, plci, Rc);
13592                        if ((Info != GOOD) || plci->internal_command)
13593                                break;
13594
13595                }
13596                plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13597                Rc = OK;
13598                /* fall through */
13599        case ADJUST_B_SAVE_VOICE_1:
13600                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13601                {
13602                        Info = adv_voice_save_config(Id, plci, Rc);
13603                        if ((Info != GOOD) || plci->internal_command)
13604                                break;
13605                }
13606                plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13607                /* fall through */
13608        case ADJUST_B_SWITCH_L1_1:
13609                if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13610                {
13611                        if (plci->sig_req)
13612                        {
13613                                plci->internal_command = plci->adjust_b_command;
13614                                break;
13615                        }
13616                        if (plci->adjust_b_parms_msg != NULL)
13617                                api_load_msg(plci->adjust_b_parms_msg, bp);
13618                        else
13619                                api_load_msg(&plci->B_protocol, bp);
13620                        Info = add_b1(plci, bp,
13621                                      (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13622                                      plci->adjust_b_facilities);
13623                        if (Info != GOOD)
13624                        {
13625                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13626                                                UnMapId(Id), (char *)(FILE_), __LINE__,
13627                                                plci->B1_resource, plci->adjust_b_facilities));
13628                                break;
13629                        }
13630                        plci->internal_command = plci->adjust_b_command;
13631                        sig_req(plci, RESOURCES, 0);
13632                        send_req(plci);
13633                        plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13634                        break;
13635                }
13636                plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13637                Rc = OK;
13638                /* fall through */
13639        case ADJUST_B_SWITCH_L1_2:
13640                if ((Rc != OK) && (Rc != OK_FC))
13641                {
13642                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13643                                        UnMapId(Id), (char *)(FILE_), __LINE__,
13644                                        Rc, plci->B1_resource, plci->adjust_b_facilities));
13645                        Info = _WRONG_STATE;
13646                        break;
13647                }
13648                plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13649                Rc = OK;
13650                /* fall through */
13651        case ADJUST_B_RESTORE_VOICE_1:
13652        case ADJUST_B_RESTORE_VOICE_2:
13653                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13654                {
13655                        Info = adv_voice_restore_config(Id, plci, Rc);
13656                        if ((Info != GOOD) || plci->internal_command)
13657                                break;
13658                }
13659                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13660                Rc = OK;
13661                /* fall through */
13662        case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13663        case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13664                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13665                {
13666
13667                        Info = dtmf_parameter_restore_config(Id, plci, Rc);
13668                        if ((Info != GOOD) || plci->internal_command)
13669                                break;
13670
13671                }
13672                plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13673                Rc = OK;
13674                /* fall through */
13675        case ADJUST_B_RESTORE_EC_1:
13676        case ADJUST_B_RESTORE_EC_2:
13677                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13678                {
13679
13680                        Info = ec_restore_config(Id, plci, Rc);
13681                        if ((Info != GOOD) || plci->internal_command)
13682                                break;
13683
13684                }
13685                plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13686                /* fall through */
13687        case ADJUST_B_ASSIGN_L23_1:
13688                if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13689                {
13690                        if (plci_nl_busy(plci))
13691                        {
13692                                plci->internal_command = plci->adjust_b_command;
13693                                break;
13694                        }
13695                        if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13696                                plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13697                        if (plci->adjust_b_parms_msg != NULL)
13698                                api_load_msg(plci->adjust_b_parms_msg, bp);
13699                        else
13700                                api_load_msg(&plci->B_protocol, bp);
13701                        Info = add_b23(plci, bp);
13702                        if (Info != GOOD)
13703                        {
13704                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13705                                                UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13706                                break;
13707                        }
13708                        plci->internal_command = plci->adjust_b_command;
13709                        nl_req_ncci(plci, ASSIGN, 0);
13710                        send_req(plci);
13711                        plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13712                        break;
13713                }
13714                plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13715                Rc = ASSIGN_OK;
13716                /* fall through */
13717        case ADJUST_B_ASSIGN_L23_2:
13718                if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13719                {
13720                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13721                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13722                        Info = _WRONG_STATE;
13723                        break;
13724                }
13725                if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13726                {
13727                        if (Rc != ASSIGN_OK)
13728                        {
13729                                plci->internal_command = plci->adjust_b_command;
13730                                break;
13731                        }
13732                }
13733                if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13734                {
13735                        plci->adjust_b_restore = true;
13736                        break;
13737                }
13738                plci->adjust_b_state = ADJUST_B_CONNECT_1;
13739                /* fall through */
13740        case ADJUST_B_CONNECT_1:
13741                if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13742                {
13743                        plci->internal_command = plci->adjust_b_command;
13744                        if (plci_nl_busy(plci))
13745                                break;
13746                        nl_req_ncci(plci, N_CONNECT, 0);
13747                        send_req(plci);
13748                        plci->adjust_b_state = ADJUST_B_CONNECT_2;
13749                        break;
13750                }
13751                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13752                Rc = OK;
13753                /* fall through */
13754        case ADJUST_B_CONNECT_2:
13755        case ADJUST_B_CONNECT_3:
13756        case ADJUST_B_CONNECT_4:
13757                if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13758                {
13759                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13760                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13761                        Info = _WRONG_STATE;
13762                        break;
13763                }
13764                if (Rc == OK)
13765                {
13766                        if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13767                        {
13768                                get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13769                                Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13770                        }
13771                        if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13772                                plci->adjust_b_state = ADJUST_B_CONNECT_3;
13773                        else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13774                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13775                }
13776                else if (Rc == 0)
13777                {
13778                        if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13779                                plci->adjust_b_state = ADJUST_B_CONNECT_4;
13780                        else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13781                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13782                }
13783                if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13784                {
13785                        plci->internal_command = plci->adjust_b_command;
13786                        break;
13787                }
13788                Rc = OK;
13789                /* fall through */
13790        case ADJUST_B_RESTORE_DTMF_1:
13791        case ADJUST_B_RESTORE_DTMF_2:
13792                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13793                {
13794
13795                        Info = dtmf_restore_config(Id, plci, Rc);
13796                        if ((Info != GOOD) || plci->internal_command)
13797                                break;
13798
13799                }
13800                plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13801                Rc = OK;
13802                /* fall through */
13803        case ADJUST_B_RESTORE_MIXER_1:
13804        case ADJUST_B_RESTORE_MIXER_2:
13805        case ADJUST_B_RESTORE_MIXER_3:
13806        case ADJUST_B_RESTORE_MIXER_4:
13807        case ADJUST_B_RESTORE_MIXER_5:
13808        case ADJUST_B_RESTORE_MIXER_6:
13809        case ADJUST_B_RESTORE_MIXER_7:
13810                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13811                {
13812
13813                        Info = mixer_restore_config(Id, plci, Rc);
13814                        if ((Info != GOOD) || plci->internal_command)
13815                                break;
13816
13817                }
13818                plci->adjust_b_state = ADJUST_B_END;
13819        case ADJUST_B_END:
13820                break;
13821        }
13822        return (Info);
13823}
13824
13825
13826static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13827{
13828
13829        dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13830                        UnMapId(Id), (char *)(FILE_), __LINE__,
13831                        plci->B1_resource, b1_facilities));
13832
13833        plci->adjust_b_parms_msg = bp_msg;
13834        plci->adjust_b_facilities = b1_facilities;
13835        plci->adjust_b_command = internal_command;
13836        plci->adjust_b_ncci = (word)(Id >> 16);
13837        if ((bp_msg == NULL) && (plci->B1_resource == 0))
13838                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13839        else
13840                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13841        plci->adjust_b_state = ADJUST_B_START;
13842        dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13843                        UnMapId(Id), (char *)(FILE_), __LINE__,
13844                        plci->B1_resource, b1_facilities));
13845}
13846
13847
13848static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13849{
13850        word internal_command;
13851
13852        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13853                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13854
13855        internal_command = plci->internal_command;
13856        plci->internal_command = 0;
13857        switch (internal_command)
13858        {
13859        default:
13860                plci->command = 0;
13861                if (plci->req_in != 0)
13862                {
13863                        plci->internal_command = ADJUST_B_RESTORE_1;
13864                        break;
13865                }
13866                Rc = OK;
13867                /* fall through */
13868        case ADJUST_B_RESTORE_1:
13869                if ((Rc != OK) && (Rc != OK_FC))
13870                {
13871                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13872                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13873                }
13874                plci->adjust_b_parms_msg = NULL;
13875                plci->adjust_b_facilities = plci->B1_facilities;
13876                plci->adjust_b_command = ADJUST_B_RESTORE_2;
13877                plci->adjust_b_ncci = (word)(Id >> 16);
13878                plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13879                plci->adjust_b_state = ADJUST_B_START;
13880                dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13881                                UnMapId(Id), (char *)(FILE_), __LINE__));
13882                /* fall through */
13883        case ADJUST_B_RESTORE_2:
13884                if (adjust_b_process(Id, plci, Rc) != GOOD)
13885                {
13886                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13887                                        UnMapId(Id), (char *)(FILE_), __LINE__));
13888                }
13889                if (plci->internal_command)
13890                        break;
13891                break;
13892        }
13893}
13894
13895
13896static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13897{
13898        word Info;
13899        word internal_command;
13900
13901        dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13902                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13903
13904        Info = GOOD;
13905        internal_command = plci->internal_command;
13906        plci->internal_command = 0;
13907        switch (internal_command)
13908        {
13909        default:
13910                plci->command = 0;
13911                plci->adjust_b_parms_msg = NULL;
13912                plci->adjust_b_facilities = plci->B1_facilities;
13913                plci->adjust_b_command = RESET_B3_COMMAND_1;
13914                plci->adjust_b_ncci = (word)(Id >> 16);
13915                plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13916                plci->adjust_b_state = ADJUST_B_START;
13917                dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13918                                UnMapId(Id), (char *)(FILE_), __LINE__));
13919                /* fall through */
13920        case RESET_B3_COMMAND_1:
13921                Info = adjust_b_process(Id, plci, Rc);
13922                if (Info != GOOD)
13923                {
13924                        dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13925                                        UnMapId(Id), (char *)(FILE_), __LINE__));
13926                        break;
13927                }
13928                if (plci->internal_command)
13929                        return;
13930                break;
13931        }
13932/*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
13933        sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13934}
13935
13936
13937static void select_b_command(dword Id, PLCI *plci, byte Rc)
13938{
13939        word Info;
13940        word internal_command;
13941        byte esc_chi[3];
13942
13943        dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13944                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13945
13946        Info = GOOD;
13947        internal_command = plci->internal_command;
13948        plci->internal_command = 0;
13949        switch (internal_command)
13950        {
13951        default:
13952                plci->command = 0;
13953                plci->adjust_b_parms_msg = &plci->saved_msg;
13954                if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13955                        plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13956                else
13957                        plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13958                plci->adjust_b_command = SELECT_B_COMMAND_1;
13959                plci->adjust_b_ncci = (word)(Id >> 16);
13960                if (plci->saved_msg.parms[0].length == 0)
13961                {
13962                        plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13963                                ADJUST_B_MODE_NO_RESOURCE;
13964                }
13965                else
13966                {
13967                        plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13968                                ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13969                }
13970                plci->adjust_b_state = ADJUST_B_START;
13971                dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13972                                UnMapId(Id), (char *)(FILE_), __LINE__));
13973                /* fall through */
13974        case SELECT_B_COMMAND_1:
13975                Info = adjust_b_process(Id, plci, Rc);
13976                if (Info != GOOD)
13977                {
13978                        dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13979                                        UnMapId(Id), (char *)(FILE_), __LINE__));
13980                        break;
13981                }
13982                if (plci->internal_command)
13983                        return;
13984                if (plci->tel == ADV_VOICE)
13985                {
13986                        esc_chi[0] = 0x02;
13987                        esc_chi[1] = 0x18;
13988                        esc_chi[2] = plci->b_channel;
13989                        SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13990                }
13991                break;
13992        }
13993        sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13994}
13995
13996
13997static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13998{
13999        word internal_command;
14000
14001        dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14002                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14003
14004        internal_command = plci->internal_command;
14005        plci->internal_command = 0;
14006        switch (internal_command)
14007        {
14008        default:
14009                plci->command = 0; /* fall through */
14010        case FAX_CONNECT_ACK_COMMAND_1:
14011                if (plci_nl_busy(plci))
14012                {
14013                        plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14014                        return;
14015                }
14016                plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14017                plci->NData[0].P = plci->fax_connect_info_buffer;
14018                plci->NData[0].PLength = plci->fax_connect_info_length;
14019                plci->NL.X = plci->NData;
14020                plci->NL.ReqCh = 0;
14021                plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14022                plci->adapter->request(&plci->NL);
14023                return;
14024        case FAX_CONNECT_ACK_COMMAND_2:
14025                if ((Rc != OK) && (Rc != OK_FC))
14026                {
14027                        dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14028                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14029                        break;
14030                }
14031        }
14032        if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14033            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14034        {
14035                if (plci->B3_prot == 4)
14036                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14037                else
14038                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14039                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14040        }
14041}
14042
14043
14044static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14045{
14046        word internal_command;
14047
14048        dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14049                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14050
14051        internal_command = plci->internal_command;
14052        plci->internal_command = 0;
14053        switch (internal_command)
14054        {
14055        default:
14056                plci->command = 0;
14057                /* fall through */
14058        case FAX_EDATA_ACK_COMMAND_1:
14059                if (plci_nl_busy(plci))
14060                {
14061                        plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14062                        return;
14063                }
14064                plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14065                plci->NData[0].P = plci->fax_connect_info_buffer;
14066                plci->NData[0].PLength = plci->fax_edata_ack_length;
14067                plci->NL.X = plci->NData;
14068                plci->NL.ReqCh = 0;
14069                plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14070                plci->adapter->request(&plci->NL);
14071                return;
14072        case FAX_EDATA_ACK_COMMAND_2:
14073                if ((Rc != OK) && (Rc != OK_FC))
14074                {
14075                        dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14076                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14077                        break;
14078                }
14079        }
14080}
14081
14082
14083static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14084{
14085        word Info;
14086        word internal_command;
14087
14088        dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14089                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14090
14091        Info = GOOD;
14092        internal_command = plci->internal_command;
14093        plci->internal_command = 0;
14094        switch (internal_command)
14095        {
14096        default:
14097                plci->command = 0; /* fall through */
14098        case FAX_CONNECT_INFO_COMMAND_1:
14099                if (plci_nl_busy(plci))
14100                {
14101                        plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14102                        return;
14103                }
14104                plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14105                plci->NData[0].P = plci->fax_connect_info_buffer;
14106                plci->NData[0].PLength = plci->fax_connect_info_length;
14107                plci->NL.X = plci->NData;
14108                plci->NL.ReqCh = 0;
14109                plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14110                plci->adapter->request(&plci->NL);
14111                return;
14112        case FAX_CONNECT_INFO_COMMAND_2:
14113                if ((Rc != OK) && (Rc != OK_FC))
14114                {
14115                        dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14116                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14117                        Info = _WRONG_STATE;
14118                        break;
14119                }
14120                if (plci_nl_busy(plci))
14121                {
14122                        plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14123                        return;
14124                }
14125                plci->command = _CONNECT_B3_R;
14126                nl_req_ncci(plci, N_CONNECT, 0);
14127                send_req(plci);
14128                return;
14129        }
14130        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14131}
14132
14133
14134static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14135{
14136        word Info;
14137        word internal_command;
14138
14139        dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14140                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14141
14142        Info = GOOD;
14143        internal_command = plci->internal_command;
14144        plci->internal_command = 0;
14145        switch (internal_command)
14146        {
14147        default:
14148                plci->command = 0;
14149                plci->adjust_b_parms_msg = NULL;
14150                plci->adjust_b_facilities = plci->B1_facilities;
14151                plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14152                plci->adjust_b_ncci = (word)(Id >> 16);
14153                plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14154                plci->adjust_b_state = ADJUST_B_START;
14155                dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14156                                UnMapId(Id), (char *)(FILE_), __LINE__));
14157                /* fall through */
14158        case FAX_ADJUST_B23_COMMAND_1:
14159                Info = adjust_b_process(Id, plci, Rc);
14160                if (Info != GOOD)
14161                {
14162                        dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14163                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14164                        break;
14165                }
14166                if (plci->internal_command)
14167                        return;
14168                /* fall through */
14169        case FAX_ADJUST_B23_COMMAND_2:
14170                if (plci_nl_busy(plci))
14171                {
14172                        plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14173                        return;
14174                }
14175                plci->command = _CONNECT_B3_R;
14176                nl_req_ncci(plci, N_CONNECT, 0);
14177                send_req(plci);
14178                return;
14179        }
14180        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14181}
14182
14183
14184static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14185{
14186        word internal_command;
14187
14188        dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14189                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14190
14191        internal_command = plci->internal_command;
14192        plci->internal_command = 0;
14193        switch (internal_command)
14194        {
14195        default:
14196                plci->command = 0;
14197                plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14198                return;
14199        case FAX_DISCONNECT_COMMAND_1:
14200        case FAX_DISCONNECT_COMMAND_2:
14201        case FAX_DISCONNECT_COMMAND_3:
14202                if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14203                {
14204                        dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14205                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14206                        break;
14207                }
14208                if (Rc == OK)
14209                {
14210                        if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14211                            || (internal_command == FAX_DISCONNECT_COMMAND_2))
14212                        {
14213                                plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14214                        }
14215                }
14216                else if (Rc == 0)
14217                {
14218                        if (internal_command == FAX_DISCONNECT_COMMAND_1)
14219                                plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14220                }
14221                return;
14222        }
14223}
14224
14225
14226
14227static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14228{
14229        word Info;
14230        word internal_command;
14231
14232        dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14233                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14234
14235        Info = GOOD;
14236        internal_command = plci->internal_command;
14237        plci->internal_command = 0;
14238        switch (internal_command)
14239        {
14240        default:
14241                plci->command = 0; /* fall through */
14242        case RTP_CONNECT_B3_REQ_COMMAND_1:
14243                if (plci_nl_busy(plci))
14244                {
14245                        plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14246                        return;
14247                }
14248                plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14249                nl_req_ncci(plci, N_CONNECT, 0);
14250                send_req(plci);
14251                return;
14252        case RTP_CONNECT_B3_REQ_COMMAND_2:
14253                if ((Rc != OK) && (Rc != OK_FC))
14254                {
14255                        dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14256                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14257                        Info = _WRONG_STATE;
14258                        break;
14259                }
14260                if (plci_nl_busy(plci))
14261                {
14262                        plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14263                        return;
14264                }
14265                plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14266                plci->NData[0].PLength = plci->internal_req_buffer[0];
14267                plci->NData[0].P = plci->internal_req_buffer + 1;
14268                plci->NL.X = plci->NData;
14269                plci->NL.ReqCh = 0;
14270                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14271                plci->adapter->request(&plci->NL);
14272                break;
14273        case RTP_CONNECT_B3_REQ_COMMAND_3:
14274                return;
14275        }
14276        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14277}
14278
14279
14280static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14281{
14282        word internal_command;
14283
14284        dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14285                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14286
14287        internal_command = plci->internal_command;
14288        plci->internal_command = 0;
14289        switch (internal_command)
14290        {
14291        default:
14292                plci->command = 0; /* fall through */
14293        case RTP_CONNECT_B3_RES_COMMAND_1:
14294                if (plci_nl_busy(plci))
14295                {
14296                        plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14297                        return;
14298                }
14299                plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14300                nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14301                send_req(plci);
14302                return;
14303        case RTP_CONNECT_B3_RES_COMMAND_2:
14304                if ((Rc != OK) && (Rc != OK_FC))
14305                {
14306                        dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14307                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14308                        break;
14309                }
14310                if (plci_nl_busy(plci))
14311                {
14312                        plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14313                        return;
14314                }
14315                sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14316                plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14317                plci->NData[0].PLength = plci->internal_req_buffer[0];
14318                plci->NData[0].P = plci->internal_req_buffer + 1;
14319                plci->NL.X = plci->NData;
14320                plci->NL.ReqCh = 0;
14321                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14322                plci->adapter->request(&plci->NL);
14323                return;
14324        case RTP_CONNECT_B3_RES_COMMAND_3:
14325                return;
14326        }
14327}
14328
14329
14330
14331static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14332{
14333        byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14334        word Info;
14335        word internal_command;
14336
14337        dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14338                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14339
14340        Info = GOOD;
14341        internal_command = plci->internal_command;
14342        plci->internal_command = 0;
14343        switch (internal_command)
14344        {
14345        default:
14346                if (!plci->NL.Id)
14347                        break;
14348                plci->command = 0;
14349                plci->adjust_b_parms_msg = NULL;
14350                plci->adjust_b_facilities = plci->B1_facilities;
14351                plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14352                plci->adjust_b_ncci = (word)(Id >> 16);
14353                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14354                plci->adjust_b_state = ADJUST_B_START;
14355                dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14356                                UnMapId(Id), (char *)(FILE_), __LINE__));
14357                /* fall through */
14358        case HOLD_SAVE_COMMAND_1:
14359                Info = adjust_b_process(Id, plci, Rc);
14360                if (Info != GOOD)
14361                {
14362                        dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14363                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14364                        break;
14365                }
14366                if (plci->internal_command)
14367                        return;
14368        }
14369        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14370}
14371
14372
14373static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14374{
14375        byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14376        word Info;
14377        word internal_command;
14378
14379        dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14380                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14381
14382        Info = GOOD;
14383        internal_command = plci->internal_command;
14384        plci->internal_command = 0;
14385        switch (internal_command)
14386        {
14387        default:
14388                plci->command = 0;
14389                plci->adjust_b_parms_msg = NULL;
14390                plci->adjust_b_facilities = plci->B1_facilities;
14391                plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14392                plci->adjust_b_ncci = (word)(Id >> 16);
14393                plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14394                plci->adjust_b_state = ADJUST_B_START;
14395                dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14396                                UnMapId(Id), (char *)(FILE_), __LINE__));
14397                /* fall through */
14398        case RETRIEVE_RESTORE_COMMAND_1:
14399                Info = adjust_b_process(Id, plci, Rc);
14400                if (Info != GOOD)
14401                {
14402                        dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14403                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14404                        break;
14405                }
14406                if (plci->internal_command)
14407                        return;
14408        }
14409        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14410}
14411
14412
14413static void init_b1_config(PLCI *plci)
14414{
14415
14416        dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14417                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14418                        (char *)(FILE_), __LINE__));
14419
14420        plci->B1_resource = 0;
14421        plci->B1_facilities = 0;
14422
14423        plci->li_bchannel_id = 0;
14424        mixer_clear_config(plci);
14425
14426
14427        ec_clear_config(plci);
14428
14429
14430        dtmf_rec_clear_config(plci);
14431        dtmf_send_clear_config(plci);
14432        dtmf_parameter_clear_config(plci);
14433
14434        adv_voice_clear_config(plci);
14435        adjust_b_clear(plci);
14436}
14437
14438
14439static void clear_b1_config(PLCI *plci)
14440{
14441
14442        dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14443                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14444                        (char *)(FILE_), __LINE__));
14445
14446        adv_voice_clear_config(plci);
14447        adjust_b_clear(plci);
14448
14449        ec_clear_config(plci);
14450
14451
14452        dtmf_rec_clear_config(plci);
14453        dtmf_send_clear_config(plci);
14454        dtmf_parameter_clear_config(plci);
14455
14456
14457        if ((plci->li_bchannel_id != 0)
14458            && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14459        {
14460                mixer_clear_config(plci);
14461                li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14462                plci->li_bchannel_id = 0;
14463        }
14464
14465        plci->B1_resource = 0;
14466        plci->B1_facilities = 0;
14467}
14468
14469
14470/* -----------------------------------------------------------------
14471   XON protocol local helpers
14472   ----------------------------------------------------------------- */
14473static void channel_flow_control_remove(PLCI *plci) {
14474        DIVA_CAPI_ADAPTER *a = plci->adapter;
14475        word i;
14476        for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14477                if (a->ch_flow_plci[i] == plci->Id) {
14478                        a->ch_flow_plci[i] = 0;
14479                        a->ch_flow_control[i] = 0;
14480                }
14481        }
14482}
14483
14484static void channel_x_on(PLCI *plci, byte ch) {
14485        DIVA_CAPI_ADAPTER *a = plci->adapter;
14486        if (a->ch_flow_control[ch] & N_XON_SENT) {
14487                a->ch_flow_control[ch] &= ~N_XON_SENT;
14488        }
14489}
14490
14491static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14492        DIVA_CAPI_ADAPTER *a = plci->adapter;
14493        if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14494                a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14495                a->ch_flow_plci[ch] = plci->Id;
14496                a->ch_flow_control_pending++;
14497        }
14498}
14499
14500static void channel_request_xon(PLCI *plci, byte ch) {
14501        DIVA_CAPI_ADAPTER *a = plci->adapter;
14502
14503        if (a->ch_flow_control[ch] & N_CH_XOFF) {
14504                a->ch_flow_control[ch] |= N_XON_REQ;
14505                a->ch_flow_control[ch] &= ~N_CH_XOFF;
14506                a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14507        }
14508}
14509
14510static void channel_xmit_extended_xon(PLCI *plci) {
14511        DIVA_CAPI_ADAPTER *a;
14512        int max_ch = ARRAY_SIZE(a->ch_flow_control);
14513        int i, one_requested = 0;
14514
14515        if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14516                return;
14517        }
14518
14519        for (i = 0; i < max_ch; i++) {
14520                if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14521                    (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14522                    (plci->Id == a->ch_flow_plci[i])) {
14523                        channel_request_xon(plci, (byte)i);
14524                        one_requested = 1;
14525                }
14526        }
14527
14528        if (one_requested) {
14529                channel_xmit_xon(plci);
14530        }
14531}
14532
14533/*
14534  Try to xmit next X_ON
14535*/
14536static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14537        int max_ch = ARRAY_SIZE(a->ch_flow_control);
14538        int i;
14539
14540        if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14541                return (0);
14542        }
14543
14544        if (a->last_flow_control_ch >= max_ch) {
14545                a->last_flow_control_ch = 1;
14546        }
14547        for (i = a->last_flow_control_ch; i < max_ch; i++) {
14548                if ((a->ch_flow_control[i] & N_XON_REQ) &&
14549                    (plci->Id == a->ch_flow_plci[i])) {
14550                        a->last_flow_control_ch = i + 1;
14551                        return (i);
14552                }
14553        }
14554
14555        for (i = 1; i < a->last_flow_control_ch; i++) {
14556                if ((a->ch_flow_control[i] & N_XON_REQ) &&
14557                    (plci->Id == a->ch_flow_plci[i])) {
14558                        a->last_flow_control_ch = i + 1;
14559                        return (i);
14560                }
14561        }
14562
14563        return (0);
14564}
14565
14566static void channel_xmit_xon(PLCI *plci) {
14567        DIVA_CAPI_ADAPTER *a = plci->adapter;
14568        byte ch;
14569
14570        if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14571                return;
14572        }
14573        if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14574                return;
14575        }
14576        a->ch_flow_control[ch] &= ~N_XON_REQ;
14577        a->ch_flow_control[ch] |= N_XON_SENT;
14578
14579        plci->NL.Req = plci->nl_req = (byte)N_XON;
14580        plci->NL.ReqCh         = ch;
14581        plci->NL.X             = plci->NData;
14582        plci->NL.XNum          = 1;
14583        plci->NData[0].P       = &plci->RBuffer[0];
14584        plci->NData[0].PLength = 0;
14585
14586        plci->adapter->request(&plci->NL);
14587}
14588
14589static int channel_can_xon(PLCI *plci, byte ch) {
14590        APPL *APPLptr;
14591        DIVA_CAPI_ADAPTER *a;
14592        word NCCIcode;
14593        dword count;
14594        word Num;
14595        word i;
14596
14597        APPLptr = plci->appl;
14598        a = plci->adapter;
14599
14600        if (!APPLptr)
14601                return (0);
14602
14603        NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14604
14605        /* count all buffers within the Application pool    */
14606        /* belonging to the same NCCI. XON if a first is    */
14607        /* used.                                            */
14608        count = 0;
14609        Num = 0xffff;
14610        for (i = 0; i < APPLptr->MaxBuffer; i++) {
14611                if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14612                if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14613        }
14614        if ((count > 2) || (Num == 0xffff)) {
14615                return (0);
14616        }
14617        return (1);
14618}
14619
14620
14621/*------------------------------------------------------------------*/
14622
14623static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14624{
14625        return 1;
14626}
14627
14628
14629
14630/**********************************************************************************/
14631/* function groups the listening applications according to the CIP mask and the   */
14632/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14633/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14634/* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14635/* function must be enabled by setting "a->group_optimization_enabled" from the   */
14636/* OS specific part (per adapter).                                                */
14637/**********************************************************************************/
14638static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14639{
14640        word i, j, k, busy, group_found;
14641        dword info_mask_group[MAX_CIP_TYPES];
14642        dword cip_mask_group[MAX_CIP_TYPES];
14643        word appl_number_group_type[MAX_APPL];
14644        PLCI *auxplci;
14645
14646        /* all APPLs within this inc. call are allowed to dial in */
14647        bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14648
14649        if (!a->group_optimization_enabled)
14650        {
14651                dbug(1, dprintf("No group optimization"));
14652                return;
14653        }
14654
14655        dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14656
14657        for (i = 0; i < MAX_CIP_TYPES; i++)
14658        {
14659                info_mask_group[i] = 0;
14660                cip_mask_group[i] = 0;
14661        }
14662        for (i = 0; i < MAX_APPL; i++)
14663        {
14664                appl_number_group_type[i] = 0;
14665        }
14666        for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14667        {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14668                if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14669                {
14670                        dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14671                        return; /* allow good application unfiltered access */
14672                }
14673        }
14674        for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14675        {
14676                if (application[i].Id && a->CIP_Mask[i])
14677                {
14678                        for (k = 0, busy = false; k < a->max_plci; k++)
14679                        {
14680                                if (a->plci[k].Id)
14681                                {
14682                                        auxplci = &a->plci[k];
14683                                        if (auxplci->appl == &application[i]) {
14684                                                /* application has a busy PLCI */
14685                                                busy = true;
14686                                                dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14687                                        } else if (test_bit(i, plci->c_ind_mask_table)) {
14688                                                /* application has an incoming call pending */
14689                                                busy = true;
14690                                                dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14691                                        }
14692                                }
14693                        }
14694
14695                        for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14696                        {
14697                                if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14698                                {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14699                                        appl_number_group_type[i] = MAX_CIP_TYPES;
14700                                        group_found = true;
14701                                        dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14702                                }
14703                                else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14704                                {                                      /* is group already present ?                  */
14705                                        appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14706                                        group_found = true;
14707                                        dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14708                                }
14709                                else if (!info_mask_group[j])
14710                                {                                      /* establish a new group                       */
14711                                        appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14712                                        info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14713                                        cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14714                                        group_found = true;
14715                                        dbug(1, dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14716                                }
14717                        }
14718                }
14719        }
14720
14721        for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14722        {
14723                if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14724                {
14725                        if (appl_number_group_type[i] == MAX_CIP_TYPES)
14726                        {
14727                                dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14728                        }
14729                        else
14730                        {
14731                                dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14732                                for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14733                                {
14734                                        if (appl_number_group_type[i] == appl_number_group_type[j])
14735                                        {
14736                                                dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14737                                                /* disable call on other group members */
14738                                                __clear_bit(j, plci->group_optimization_mask_table);
14739                                                appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14740                                        }
14741                                }
14742                        }
14743                }
14744                else                                                 /* application should not get a call */
14745                {
14746                        __clear_bit(i, plci->group_optimization_mask_table);
14747                }
14748        }
14749
14750}
14751
14752
14753
14754/* OS notifies the driver about a application Capi_Register */
14755word CapiRegister(word id)
14756{
14757        word i, j, appls_found;
14758
14759        PLCI *plci;
14760        DIVA_CAPI_ADAPTER *a;
14761
14762        for (i = 0, appls_found = 0; i < max_appl; i++)
14763        {
14764                if (application[i].Id && (application[i].Id != id))
14765                {
14766                        appls_found++;                       /* an application has been found */
14767                }
14768        }
14769
14770        if (appls_found) return true;
14771        for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14772        {
14773                a = &adapter[i];
14774                if (a->request)
14775                {
14776                        if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14777                        {
14778                                if (!appls_found)           /* first application does a capi register   */
14779                                {
14780                                        if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14781                                        {
14782                                                plci = &a->plci[j - 1];
14783                                                plci->command = 0;
14784                                                add_p(plci, OAD, "\x01\xfd");
14785                                                add_p(plci, CAI, "\x01\x80");
14786                                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14787                                                add_p(plci, SHIFT | 6, NULL);
14788                                                add_p(plci, SIN, "\x02\x00\x00");
14789                                                plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14790                                                sig_req(plci, ASSIGN, DSIG_ID);
14791                                                add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14792                                                sig_req(plci, SIG_CTRL, 0);
14793                                                send_req(plci);
14794                                        }
14795                                }
14796                        }
14797                }
14798        }
14799        return false;
14800}
14801
14802/*------------------------------------------------------------------*/
14803
14804/* Functions for virtual Switching e.g. Transfer by join, Conference */
14805
14806static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14807{
14808        word i;
14809        /* Format of vswitch_t:
14810           0 byte length
14811           1 byte VSWITCHIE
14812           2 byte VSWITCH_REQ/VSWITCH_IND
14813           3 byte reserved
14814           4 word VSwitchcommand
14815           6 word returnerror
14816           8... Params
14817        */
14818        if (!plci ||
14819            !plci->appl ||
14820            !plci->State ||
14821            plci->Sig.Ind == NCR_FACILITY
14822                )
14823                return;
14824
14825        for (i = 0; i < MAX_MULTI_IE; i++)
14826        {
14827                if (!parms[i][0]) continue;
14828                if (parms[i][0] < 7)
14829                {
14830                        parms[i][0] = 0; /* kill it */
14831                        continue;
14832                }
14833                dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14834                switch (parms[i][4])
14835                {
14836                case VSJOIN:
14837                        if (!plci->relatedPTYPLCI ||
14838                            (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14839                        { /* Error */
14840                                break;
14841                        }
14842                        /* remember all necessary informations */
14843                        if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14844                        {
14845                                break;
14846                        }
14847                        if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14848                        {   /* first indication after ECT-Request on Consultation Call */
14849                                plci->vswitchstate = parms[i][9];
14850                                parms[i][9] = 2; /* State */
14851                                /* now ask first Call to join */
14852                        }
14853                        else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14854                        { /* Answer of VSWITCH_REQ from first Call */
14855                                plci->vswitchstate = parms[i][9];
14856                                /* tell consultation call to join
14857                                   and the protocol capabilities of the first call */
14858                        }
14859                        else
14860                        { /* Error */
14861                                break;
14862                        }
14863                        plci->vsprot = parms[i][10]; /* protocol */
14864                        plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14865                        /* send join request to related PLCI */
14866                        parms[i][1] = VSWITCHIE;
14867                        parms[i][2] = VSWITCH_REQ;
14868
14869                        plci->relatedPTYPLCI->command = 0;
14870                        plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14871                        add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14872                        sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14873                        send_req(plci->relatedPTYPLCI);
14874                        break;
14875                case VSTRANSPORT:
14876                default:
14877                        if (plci->relatedPTYPLCI &&
14878                            plci->vswitchstate == 3 &&
14879                            plci->relatedPTYPLCI->vswitchstate == 3)
14880                        {
14881                                add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14882                                sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14883                                send_req(plci->relatedPTYPLCI);
14884                        }
14885                        break;
14886                }
14887                parms[i][0] = 0; /* kill it */
14888        }
14889}
14890
14891
14892/*------------------------------------------------------------------*/
14893
14894static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14895        ENTITY e;
14896        IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14897
14898        if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14899                return (-1);
14900        }
14901
14902        pReq->xdi_dma_descriptor_operation.Req = 0;
14903        pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14904
14905        pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14906        pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14907        pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14908        pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14909
14910        e.user[0] = plci->adapter->Id - 1;
14911        plci->adapter->request((ENTITY *)pReq);
14912
14913        if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14914            (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14915            pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14916                *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14917                dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14918                                plci->adapter->Id,
14919                                pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14920                                *dma_magic));
14921                return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14922        } else {
14923                dbug(1, dprintf("dma_alloc failed"));
14924                return (-1);
14925        }
14926}
14927
14928static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14929        ENTITY e;
14930        IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14931
14932        if (nr < 0) {
14933                return;
14934        }
14935
14936        pReq->xdi_dma_descriptor_operation.Req = 0;
14937        pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14938
14939        pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14940        pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
14941        pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14942        pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14943
14944        e.user[0] = plci->adapter->Id - 1;
14945        plci->adapter->request((ENTITY *)pReq);
14946
14947        if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14948                dbug(1, dprintf("dma_free(%d)", nr));
14949        } else {
14950                dbug(1, dprintf("dma_free failed (%d)", nr));
14951        }
14952}
14953
14954/*------------------------------------------------------------------*/
14955